This is an automated email from the ASF dual-hosted git repository.
jamesyong pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git The following commit(s) were added to refs/heads/trunk by this push: new 803f7fa Improved: <script-template> widget tag (OFBIZ-11686) 803f7fa is described below commit 803f7fa06048baa5c4246c80ff249cba2edb9451 Author: James Yong <[hidden email]> AuthorDate: Wed May 13 20:19:05 2020 +0800 Improved: <script-template> widget tag (OFBIZ-11686) The new tag allows us to render a freemarker template containing javascript, as external script in html instead of inline script. This helps to reduce CSP errors. --- applications/order/template/order/FindOrders.ftl | 74 ----------------- .../order/template/order/FindOrders.js.ftl | 86 ++++++++++++++++++++ .../order/widget/ordermgr/OrderViewScreens.xml | 5 +- .../java/org/apache/ofbiz/common/CommonEvents.java | 25 ++++++ .../common/webcommon/WEB-INF/common-controller.xml | 11 +++ .../webapp/ftl/ScriptTemplateListTransform.java | 81 +++++++++++++++++++ .../ofbiz/webapp/freemarkerTransforms.properties | 1 + framework/widget/dtd/widget-screen.xsd | 8 ++ .../widget/artifact/ArtifactInfoGatherer.java | 5 ++ .../org/apache/ofbiz/widget/model/HtmlWidget.java | 72 +++++++++++++++++ .../ofbiz/widget/model/ModelWidgetVisitor.java | 2 + .../ofbiz/widget/model/ScriptTemplateUtil.java | 92 ++++++++++++++++++++++ .../ofbiz/widget/model/XmlWidgetVisitor.java | 9 +++ .../widget/renderer/html/HtmlWidgetRenderer.java | 4 + themes/flatgrey/template/Footer.ftl | 1 + themes/rainbowstone/template/includes/Footer.ftl | 1 + themes/tomahawk/template/Footer.ftl | 1 + 17 files changed, 403 insertions(+), 75 deletions(-) diff --git a/applications/order/template/order/FindOrders.ftl b/applications/order/template/order/FindOrders.ftl index cb2c338..0d1923d 100644 --- a/applications/order/template/order/FindOrders.ftl +++ b/applications/order/template/order/FindOrders.ftl @@ -17,80 +17,6 @@ specific language governing permissions and limitations under the License. --> -<script type="application/javascript"> -<!-- // -function lookupOrders(click) { - orderIdValue = document.lookuporder.orderId.value; - if (orderIdValue.length > 1) { - document.lookuporder.action = "<@ofbizUrl>orderview</@ofbizUrl>"; - document.lookuporder.method = "get"; - } else { - document.lookuporder.action = "<@ofbizUrl>searchorders</@ofbizUrl>"; - } - - if (click) { - document.lookuporder.submit(); - } - return true; -} -function toggleOrderId(master) { - var form = document.massOrderChangeForm; - var orders = form.elements.length; - for (var i = 0; i < orders; i++) { - var element = form.elements[i]; - if ("orderIdList" == element.name) { - element.checked = master.checked; - } - } - toggleOrderIdList(); -} -function setServiceName(selection) { - document.massOrderChangeForm.action = selection.value; -} -function runAction() { - var form = document.massOrderChangeForm; - form.submit(); -} - -function toggleOrderIdList() { - var form = document.massOrderChangeForm; - var orders = form.elements.length; - var isAllSelected = true; - var isSingle = true; - for (var i = 0; i < orders; i++) { - var element = form.elements[i]; - if ("orderIdList" == element.name) { - if (element.checked) { - isSingle = false; - } else { - isAllSelected = false; - } - } - } - if (isAllSelected) { - jQuery('#checkAllOrders').attr('checked', true); - } else { - jQuery('#checkAllOrders').attr('checked', false); - } - jQuery('#checkAllOrders').attr("checked", isAllSelected); - if (!isSingle && jQuery('#serviceName').val() != "") { - jQuery('#submitButton').removeAttr("disabled"); - } else { - jQuery('#submitButton').attr('disabled', true); - } -} - -// --> - - function paginateOrderList(viewSize, viewIndex, hideFields) { - document.paginationForm.viewSize.value = viewSize; - document.paginationForm.viewIndex.value = viewIndex; - document.paginationForm.hideFields.value = hideFields; - document.paginationForm.submit(); - } - -</script> - <#if security.hasEntityPermission("ORDERMGR", "_VIEW", session)> <#if parameters.hideFields?has_content> <form name='lookupandhidefields${requestParameters.hideFields?default("Y")}' method="post" action="<@ofbizUrl>searchorders</@ofbizUrl>"> diff --git a/applications/order/template/order/FindOrders.js.ftl b/applications/order/template/order/FindOrders.js.ftl new file mode 100644 index 0000000..0b98270 --- /dev/null +++ b/applications/order/template/order/FindOrders.js.ftl @@ -0,0 +1,86 @@ +/*********************************************** +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. +***********************************************/ + +function lookupOrders(click) { + orderIdValue = document.lookuporder.orderId.value; + if (orderIdValue.length > 1) { + document.lookuporder.action = "<@ofbizUrl>orderview</@ofbizUrl>"; + document.lookuporder.method = "get"; + } else { + document.lookuporder.action = "<@ofbizUrl>searchorders</@ofbizUrl>"; + } + + if (click) { + document.lookuporder.submit(); + } + return true; +} +function toggleOrderId(master) { + var form = document.massOrderChangeForm; + var orders = form.elements.length; + for (var i = 0; i < orders; i++) { + var element = form.elements[i]; + if ("orderIdList" == element.name) { + element.checked = master.checked; + } + } + toggleOrderIdList(); +} +function setServiceName(selection) { + document.massOrderChangeForm.action = selection.value; +} +function runAction() { + var form = document.massOrderChangeForm; + form.submit(); +} + +function toggleOrderIdList() { + var form = document.massOrderChangeForm; + var orders = form.elements.length; + var isAllSelected = true; + var isSingle = true; + for (var i = 0; i < orders; i++) { + var element = form.elements[i]; + if ("orderIdList" == element.name) { + if (element.checked) { + isSingle = false; + } else { + isAllSelected = false; + } + } + } + if (isAllSelected) { + jQuery('#checkAllOrders').attr('checked', true); + } else { + jQuery('#checkAllOrders').attr('checked', false); + } + jQuery('#checkAllOrders').attr("checked", isAllSelected); + if (!isSingle && jQuery('#serviceName').val() != "") { + jQuery('#submitButton').removeAttr("disabled"); + } else { + jQuery('#submitButton').attr('disabled', true); + } +} + +function paginateOrderList(viewSize, viewIndex, hideFields) { + document.paginationForm.viewSize.value = viewSize; + document.paginationForm.viewIndex.value = viewIndex; + document.paginationForm.hideFields.value = hideFields; + document.paginationForm.submit(); +} \ No newline at end of file diff --git a/applications/order/widget/ordermgr/OrderViewScreens.xml b/applications/order/widget/ordermgr/OrderViewScreens.xml index 80c99db..7d0667c 100644 --- a/applications/order/widget/ordermgr/OrderViewScreens.xml +++ b/applications/order/widget/ordermgr/OrderViewScreens.xml @@ -266,7 +266,10 @@ under the License. <decorator-section name="body"> <platform-specific><html><html-template location="component://common-theme/template/includes/SetMultipleSelectJs.ftl"/></html></platform-specific> <platform-specific> - <html><html-template location="component://order/template/order/FindOrders.ftl"/></html> + <html> + <script-template location="component://order/template/order/FindOrders.js.ftl"/> + <html-template location="component://order/template/order/FindOrders.ftl"/> + </html> </platform-specific> </decorator-section> </decorator-screen> diff --git a/framework/common/src/main/java/org/apache/ofbiz/common/CommonEvents.java b/framework/common/src/main/java/org/apache/ofbiz/common/CommonEvents.java index 76aa710..c97fa36 100644 --- a/framework/common/src/main/java/org/apache/ofbiz/common/CommonEvents.java +++ b/framework/common/src/main/java/org/apache/ofbiz/common/CommonEvents.java @@ -53,6 +53,7 @@ import org.apache.ofbiz.entity.GenericValue; import org.apache.ofbiz.entity.util.EntityUtilProperties; import org.apache.ofbiz.webapp.control.JWTManager; import org.apache.ofbiz.webapp.control.LoginWorker; +import org.apache.ofbiz.widget.model.ScriptTemplateUtil; import org.apache.ofbiz.widget.model.ThemeFactory; import org.apache.ofbiz.widget.renderer.VisualTheme; @@ -176,6 +177,30 @@ public class CommonEvents { return "success"; } + public static String jsResponseFromRequest(HttpServletRequest request, HttpServletResponse response) { + + String fileName = request.getParameter("name"); + String script = ScriptTemplateUtil.getScriptFromSession(request.getSession(), fileName); + + // return the JS String + Writer out; + try { + + // set the JS content type + response.setContentType("application/javascript"); + // script.length is not reliable for unicode characters + response.setContentLength(script.getBytes("UTF8").length); + + out = response.getWriter(); + out.write(script); + out.flush(); + } catch (IOException e) { + Debug.logError(e, MODULE); + return "error"; + } + return "success"; + } + public static String jsonResponseFromRequestAttributes(HttpServletRequest request, HttpServletResponse response) { // pull out the service response from the request attribute diff --git a/framework/common/webcommon/WEB-INF/common-controller.xml b/framework/common/webcommon/WEB-INF/common-controller.xml index 46fa551..e6f9394 100644 --- a/framework/common/webcommon/WEB-INF/common-controller.xml +++ b/framework/common/webcommon/WEB-INF/common-controller.xml @@ -324,6 +324,17 @@ under the License. <response name="error" type="request" value="json"/> </request-map> + <request-map uri="getJs" method="get"> + <security https="false" auth="false"/> + <response name="success" type="request" value="js"/> + <response name="error" type="request" value="js"/> + </request-map> + <request-map uri="js"> + <security direct-request="false"/> + <event type="java" path="org.apache.ofbiz.common.CommonEvents" invoke="jsResponseFromRequest"/> + <response name="success" type="none"/> + </request-map> + <!--========================== AJAX events =====================--> <!-- View Mappings --> diff --git a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/ftl/ScriptTemplateListTransform.java b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/ftl/ScriptTemplateListTransform.java new file mode 100644 index 0000000..c749c87 --- /dev/null +++ b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/ftl/ScriptTemplateListTransform.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * 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.apache.ofbiz.webapp.ftl; + +import java.io.IOException; +import java.io.Writer; +import java.util.Map; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.ofbiz.widget.model.ScriptTemplateUtil; + +import freemarker.core.Environment; +import freemarker.ext.beans.BeanModel; +import freemarker.template.TemplateModelException; +import freemarker.template.TemplateTransformModel; + +/** + * Render the script tags collected from the <script-template/> + */ +public class ScriptTemplateListTransform implements TemplateTransformModel { + + public static final String MODULE = CsrfTokenAjaxTransform.class.getName(); + + @Override + public Writer getWriter(Writer out, @SuppressWarnings("rawtypes") Map args) + throws TemplateModelException, IOException { + + return new Writer(out) { + + @Override + public void close() throws IOException { + try { + Environment env = Environment.getCurrentEnvironment(); + BeanModel req = (BeanModel) env.getVariable("request"); + if (req != null) { + HttpServletRequest request = (HttpServletRequest) req.getWrappedObject(); + Set<String> scriptSrcSet = ScriptTemplateUtil.getScriptSrcLinksFromRequest(request); + if (scriptSrcSet!=null) { + String srcList = ""; + for (String scriptSrc : scriptSrcSet) { + srcList += ("<script src=\"" + scriptSrc + "\" type=\"application/javascript\"></script>\n"); + } + out.write(srcList); + } + } + return; + } catch (Exception e) { + throw new IOException(e.getMessage()); + } + } + + @Override + public void flush() throws IOException { + out.flush(); + } + + @Override + public void write(char cbuf[], int off, int len) { + } + }; + + } +} diff --git a/framework/webapp/src/main/resources/org/apache/ofbiz/webapp/freemarkerTransforms.properties b/framework/webapp/src/main/resources/org/apache/ofbiz/webapp/freemarkerTransforms.properties index 65cf04e..b4f4d8b 100644 --- a/framework/webapp/src/main/resources/org/apache/ofbiz/webapp/freemarkerTransforms.properties +++ b/framework/webapp/src/main/resources/org/apache/ofbiz/webapp/freemarkerTransforms.properties @@ -31,3 +31,4 @@ renderWrappedText=org.apache.ofbiz.webapp.ftl.RenderWrappedTextTransform setContextField=org.apache.ofbiz.webapp.ftl.SetContextFieldTransform csrfTokenAjax=org.apache.ofbiz.webapp.ftl.CsrfTokenAjaxTransform csrfTokenPair=org.apache.ofbiz.webapp.ftl.CsrfTokenPairNonAjaxTransform +scriptTemplateList=org.apache.ofbiz.webapp.ftl.ScriptTemplateListTransform diff --git a/framework/widget/dtd/widget-screen.xsd b/framework/widget/dtd/widget-screen.xsd index 7165f41..62ffc03 100644 --- a/framework/widget/dtd/widget-screen.xsd +++ b/framework/widget/dtd/widget-screen.xsd @@ -544,6 +544,14 @@ under the License. <xs:attribute type="xs:string" name="name" use="required" /> </xs:complexType> </xs:element> + <xs:element name="script-template" substitutionGroup="HtmlWidgets"> + <xs:complexType> + <xs:attributeGroup ref="attlist.script-template" /> + </xs:complexType> + </xs:element> + <xs:attributeGroup name="attlist.script-template"> + <xs:attribute type="xs:string" name="location" use="required" /> + </xs:attributeGroup> <!-- ============== Swing Specific Elements =============== --> <xs:element name="swing"> <xs:complexType /> diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/artifact/ArtifactInfoGatherer.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/artifact/ArtifactInfoGatherer.java index 0ea3393..3c96f1e 100644 --- a/framework/widget/src/main/java/org/apache/ofbiz/widget/artifact/ArtifactInfoGatherer.java +++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/artifact/ArtifactInfoGatherer.java @@ -38,6 +38,7 @@ import org.apache.ofbiz.widget.model.HtmlWidget; import org.apache.ofbiz.widget.model.HtmlWidget.HtmlTemplate; import org.apache.ofbiz.widget.model.HtmlWidget.HtmlTemplateDecorator; import org.apache.ofbiz.widget.model.HtmlWidget.HtmlTemplateDecoratorSection; +import org.apache.ofbiz.widget.model.HtmlWidget.ScriptTemplate; import org.apache.ofbiz.widget.model.IterateSectionWidget; import org.apache.ofbiz.widget.model.ModelAction; import org.apache.ofbiz.widget.model.ModelActionVisitor; @@ -356,6 +357,10 @@ public final class ArtifactInfoGatherer implements ModelWidgetVisitor, ModelActi } @Override + public void visit(ScriptTemplate scriptTemplate) throws Exception { + } + + @Override public void visit(Section section) throws Exception { for (ModelAction action : section.getActions()) { action.accept(this); diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/HtmlWidget.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/HtmlWidget.java index b39ec2d..b5afc68 100644 --- a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/HtmlWidget.java +++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/HtmlWidget.java @@ -19,6 +19,7 @@ package org.apache.ofbiz.widget.model; import java.io.IOException; +import java.io.StringWriter; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -120,6 +121,8 @@ public class HtmlWidget extends ModelScreenWidget { subWidgets.add(new HtmlTemplate(modelScreen, childElement)); } else if ("html-template-decorator".equals(childElement.getNodeName())) { subWidgets.add(new HtmlTemplateDecorator(modelScreen, childElement)); + } else if ("script-template".equals(childElement.getNodeName())) { + subWidgets.add(new ScriptTemplate(modelScreen, childElement)); } else { throw new IllegalArgumentException("Tag not supported under the platform-specific -> html tag with name: " + childElement.getNodeName()); @@ -175,6 +178,36 @@ public class HtmlWidget extends ModelScreenWidget { } } + public static void renderScriptTemplate(Appendable writer, FlexibleStringExpander locationExdr, Map<String, Object> context) { + String location = locationExdr.expandString(context); + + if (UtilValidate.isEmpty(location)) { + throw new IllegalArgumentException("Template location is empty with search string location " + locationExdr.getOriginal()); + } + + if (location.endsWith(".ftl")) { + try { + boolean insertWidgetBoundaryComments = ModelWidget.widgetBoundaryCommentsEnabled(context); + if (insertWidgetBoundaryComments) { + writer.append(HtmlWidgetRenderer.formatBoundaryJsComment("Begin", "Template", location)); + } + + Template template = FreeMarkerWorker.getTemplate(location, specialTemplateCache, specialConfig); + FreeMarkerWorker.renderTemplate(template, context, writer); + + if (insertWidgetBoundaryComments) { + writer.append(HtmlWidgetRenderer.formatBoundaryJsComment("End", "Template", location)); + } + } catch (IllegalArgumentException | TemplateException | 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 { @@ -288,6 +321,45 @@ public class HtmlWidget extends ModelScreenWidget { } } + public static class ScriptTemplate extends ModelScreenWidget { + protected FlexibleStringExpander locationExdr; + + public ScriptTemplate(ModelScreen modelScreen, Element htmlTemplateElement) { + super(modelScreen, htmlTemplateElement); + this.locationExdr = FlexibleStringExpander.getInstance(htmlTemplateElement.getAttribute("location")); + } + + public String getLocation(Map<String, Object> context) { + return locationExdr.expandString(context); + } + + @Override + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws IOException { + StringWriter stringWriter = new StringWriter(); + renderScriptTemplate(stringWriter, this.locationExdr, context); + String data = stringWriter.toString(); + stringWriter.close(); + + String fileName = this.getLocation(context); + fileName = fileName.substring(fileName.lastIndexOf("/")+1); + // remove ".ftl" + fileName = fileName.substring(0, fileName.length()-4); + ScriptTemplateUtil.putScriptInSession(context, fileName, data); + + String webappName = (String)context.get("webappName"); + ScriptTemplateUtil.addScriptSrcToRequest(context, "/"+webappName+"/control/getJs?name="+fileName); + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + + public FlexibleStringExpander getLocationExdr() { + return locationExdr; + } + } + @Override public void accept(ModelWidgetVisitor visitor) throws Exception { visitor.visit(this); diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelWidgetVisitor.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelWidgetVisitor.java index f081f98..a1f89bb 100644 --- a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelWidgetVisitor.java +++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelWidgetVisitor.java @@ -32,6 +32,8 @@ public interface ModelWidgetVisitor { void visit(HtmlWidget.HtmlTemplateDecoratorSection htmlTemplateDecoratorSection) throws Exception; + void visit(HtmlWidget.ScriptTemplate scriptTemplate) throws Exception; + void visit(IterateSectionWidget iterateSectionWidget) throws Exception; void visit(ModelSingleForm modelForm) throws Exception; diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ScriptTemplateUtil.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ScriptTemplateUtil.java new file mode 100644 index 0000000..d6d16a2 --- /dev/null +++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ScriptTemplateUtil.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * 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.apache.ofbiz.widget.model; + +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.apache.ofbiz.base.util.UtilGenerics; +import org.apache.ofbiz.webapp.ftl.ScriptTemplateListTransform; + +public class ScriptTemplateUtil { + + private static String sessionKey = "ScriptTemplateMap"; + private static String requestKey = "ScriptTemplateList"; + private static int maxNumOfScriptInCache = 10; + + /** + * add script src link for use by @see {@link ScriptTemplateListTransform} + * @param context + * @param filePath + */ + public static void addScriptSrcToRequest(Map<String, Object> context, String filePath){ + HttpServletRequest request = (HttpServletRequest)context.get("request"); + Set<String> scriptTemplates = UtilGenerics.cast(request.getAttribute(requestKey)); + if (scriptTemplates==null){ + // use of LinkedHashSet to maintain insertion order + scriptTemplates = new LinkedHashSet<String>(); + request.setAttribute(requestKey, scriptTemplates); + } + scriptTemplates.add(filePath); + } + + /** + * get the script src links collected from the <script-template/> tags + * @param request + * @return + */ + public static Set<String> getScriptSrcLinksFromRequest(HttpServletRequest request){ + Set<String> scriptTemplates = UtilGenerics.cast(request.getAttribute(requestKey)); + return scriptTemplates; + } + + public static void putScriptInSession(Map<String, Object> context, String fileName, String fileContent){ + HttpSession session = (HttpSession)context.get("session"); + Map<String,String> scriptTemplateMap = UtilGenerics.cast(session.getAttribute(sessionKey)); + if (scriptTemplateMap==null){ + synchronized (session) { + scriptTemplateMap = UtilGenerics.cast(session.getAttribute(sessionKey)); + if (scriptTemplateMap==null){ + // use of LinkedHashMap to limit size of the map + scriptTemplateMap = new LinkedHashMap<String, String>() { + private static final long serialVersionUID = 1L; + protected boolean removeEldestEntry(Map.Entry<String, String> eldest) { + return size() > maxNumOfScriptInCache; + } + }; + session.setAttribute(sessionKey, scriptTemplateMap); + } + } + } + scriptTemplateMap.put(fileName, fileContent); + } + + public static String getScriptFromSession(HttpSession session, String fileName){ + Map<String,String> scriptTemplateMap = UtilGenerics.cast(session.getAttribute(sessionKey)); + if (scriptTemplateMap!=null){ + return scriptTemplateMap.get(fileName); + } + return null; + } +} diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/XmlWidgetVisitor.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/XmlWidgetVisitor.java index 193a45a..737ced1 100644 --- a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/XmlWidgetVisitor.java +++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/XmlWidgetVisitor.java @@ -24,6 +24,7 @@ import java.util.Map; import org.apache.ofbiz.widget.model.HtmlWidget.HtmlTemplate; import org.apache.ofbiz.widget.model.HtmlWidget.HtmlTemplateDecorator; import org.apache.ofbiz.widget.model.HtmlWidget.HtmlTemplateDecoratorSection; +import org.apache.ofbiz.widget.model.HtmlWidget.ScriptTemplate; import org.apache.ofbiz.widget.model.ModelScreenWidget.Column; import org.apache.ofbiz.widget.model.ModelScreenWidget.ColumnContainer; import org.apache.ofbiz.widget.model.ModelScreenWidget.Container; @@ -405,6 +406,14 @@ public class XmlWidgetVisitor extends XmlAbstractWidgetVisitor implements ModelW } @Override + public void visit(ScriptTemplate scriptTemplate) throws Exception { + writer.append("<script-template"); + visitModelWidget(scriptTemplate); + visitAttribute("location", scriptTemplate.getLocationExdr()); + writer.append("/>"); + } + + @Override public void visit(ModelScreen modelScreen) throws Exception { writer.append("<screen"); visitModelWidget(modelScreen); diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/html/HtmlWidgetRenderer.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/html/HtmlWidgetRenderer.java index 62cb643..047037e 100644 --- a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/html/HtmlWidgetRenderer.java +++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/html/HtmlWidgetRenderer.java @@ -60,6 +60,10 @@ public class HtmlWidgetRenderer { return "<!-- " + boundaryType + " " + widgetType + " " + widgetName + " -->" + whiteSpace; } + public static String formatBoundaryJsComment(String boundaryType, String widgetType, String widgetName) { + return "// " + boundaryType + " " + widgetType + " " + widgetName + whiteSpace; + } + /** * Renders the beginning boundary comment string. * @param writer The writer to write to diff --git a/themes/flatgrey/template/Footer.ftl b/themes/flatgrey/template/Footer.ftl index 517c1b0..3a65a83 100644 --- a/themes/flatgrey/template/Footer.ftl +++ b/themes/flatgrey/template/Footer.ftl @@ -42,4 +42,5 @@ under the License. </#list> </#if> </body> +<@scriptTemplateList/> </html> diff --git a/themes/rainbowstone/template/includes/Footer.ftl b/themes/rainbowstone/template/includes/Footer.ftl index 164b5aa..057ad23 100644 --- a/themes/rainbowstone/template/includes/Footer.ftl +++ b/themes/rainbowstone/template/includes/Footer.ftl @@ -34,4 +34,5 @@ under the License. </#list> </#if> </body> +<@scriptTemplateList/> </html> diff --git a/themes/tomahawk/template/Footer.ftl b/themes/tomahawk/template/Footer.ftl index cc26dd7..baf94a8 100644 --- a/themes/tomahawk/template/Footer.ftl +++ b/themes/tomahawk/template/Footer.ftl @@ -42,4 +42,5 @@ under the License. </div> </body> +<@scriptTemplateList/> </html> |
Free forum by Nabble | Edit this page |