diff --git a/.github/workflows/scorecards-analysis.yaml b/.github/workflows/scorecards-analysis.yaml index e5ce47978..163cb2c44 100644 --- a/.github/workflows/scorecards-analysis.yaml +++ b/.github/workflows/scorecards-analysis.yaml @@ -58,7 +58,7 @@ jobs: publish_results: true - name: "Upload artifact" - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # 4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # 4.3.1 with: name: SARIF file path: results.sarif diff --git a/core/src/main/java/org/apache/struts2/components/File.java b/core/src/main/java/org/apache/struts2/components/File.java index adef610f0..ffe8e227c 100644 --- a/core/src/main/java/org/apache/struts2/components/File.java +++ b/core/src/main/java/org/apache/struts2/components/File.java @@ -99,4 +99,10 @@ public class File extends UIBean { public void setSize(String size) { this.size = size; } + + @Override + @StrutsTagAttribute(description="Ignored during file upload") + public void setValue(String value) { + // ignores provided value + } } diff --git a/core/src/site/resources/tags/file-attributes.html b/core/src/site/resources/tags/file-attributes.html index 5f51badb6..e23f5dca5 100644 --- a/core/src/site/resources/tags/file-attributes.html +++ b/core/src/site/resources/tags/file-attributes.html @@ -371,6 +371,6 @@
This is a SiteMesh Velocity view servlet.
- * - *It overrides the SiteMesh servlet to rely on the - * Velocity Manager in Struts instead of creating it's - * own manager
- */ -public class VelocityDecoratorServlet extends VelocityViewServlet { - - private static final Logger LOG = LogManager.getLogger(VelocityDecoratorServlet.class); - - private static final long serialVersionUID = -6731485159371716918L; - - protected VelocityManager velocityManager; - protected String defaultContentType; - - /** - *Initializes servlet, toolbox and Velocity template engine. - * Called by the servlet container on loading.
- * - *NOTE: If no charset is specified in the default.contentType - * property (in your velocity.properties) and you have specified - * an output.encoding property, then that will be used as the - * charset for the default content-type of pages served by this - * servlet.
- * - * @param config servlet configuration - */ - public void init(ServletConfig config) throws ServletException { - super.init(config); - Dispatcher dispatcher = Dispatcher.getInstance(getServletContext()); - if (dispatcher == null) { - throw new IllegalStateException("Unable to find the Dispatcher in the Servlet Context. Is '" + StrutsListener.class.getName() + "' missing in web.xml?"); - } - velocityManager = dispatcher.getContainer().getInstance(VelocityManager.class); - velocityManager.init(config.getServletContext()); - - // do whatever we have to do to init Velocity - getVelocityView().setVelocityEngine(velocityManager.getVelocityEngine()); - // toolboxManager = velocityManager.getToolboxManager(); - - - // we can get these now that velocity is initialized - defaultContentType = getVelocityProperty(VelocityView.CONTENT_TYPE_KEY, VelocityView.DEFAULT_CONTENT_TYPE); - - String encoding = getVelocityProperty(RuntimeConstants.ENCODING_DEFAULT, VelocityView.DEFAULT_OUTPUT_ENCODING); - - // For non Latin-1 encodings, ensure that the charset is - // included in the Content-Type header. - if (!VelocityView.DEFAULT_OUTPUT_ENCODING.equalsIgnoreCase(encoding)) { - int index = defaultContentType.lastIndexOf("charset"); - if (index < 0) { - // the charset specifier is not yet present in header. - // append character encoding to default content-type - defaultContentType += "; charset=" + encoding; - } else { - // The user may have configuration issues. - getVelocityView().getVelocityEngine().getLog().warn("VelocityViewServlet: Charset was already " + "specified in the Content-Type property. " + "Output encoding property will be ignored."); - } - } - - getVelocityView().getVelocityEngine().getLog().info("VelocityViewServlet: Default content-type is: " + defaultContentType); - } - - public Template handleRequest(HttpServletRequest request, HttpServletResponse response, Context context) { - HTMLPage htmlPage = (HTMLPage) request.getAttribute(RequestConstants.PAGE); - String template; - - context.put("base", request.getContextPath()); - // For backwards compatibility with apps that used the old VelocityDecoratorServlet - // that extended VelocityServlet instead of VelocityViewServlet - context.put("req", request); - context.put("res", response); - - if (htmlPage == null) { - context.put("title", "Title?"); - context.put("body", "Body?
"); - context.put("head", ""); - template = request.getServletPath(); - } else { - try { - context.put("title", OutputConverter.convert(htmlPage.getTitle())); - { - StringWriter buffer = new StringWriter(); - htmlPage.writeBody(OutputConverter.getWriter(buffer)); - context.put("body", buffer.toString()); - } - { - StringWriter buffer = new StringWriter(); - htmlPage.writeHead(OutputConverter.getWriter(buffer)); - context.put("head", buffer.toString()); - } - } catch (IOException e) { - LOG.error("IOException handle request template", e); - } - context.put("page", htmlPage); - DecoratorMapper decoratorMapper = getDecoratorMapper(); - Decorator decorator = decoratorMapper.getDecorator(request, htmlPage); - template = decorator.getPage(); - } - - return getTemplate(template); - } - - private DecoratorMapper getDecoratorMapper() { - Factory factory = Factory.getInstance(new Config(getServletConfig())); - return factory.getDecoratorMapper(); - } - - /** - *Creates and returns an initialized Velocity context.
- * - * @param request servlet request from client - * @param response servlet reponse to client - */ - protected Context createContext(HttpServletRequest request, HttpServletResponse response) { - Context context = (Context) request.getAttribute(VelocityManager.KEY_VELOCITY_STRUTS_CONTEXT); - if (context == null) { - ActionContext ctx = ServletActionContext.getActionContext(request); - context = velocityManager.createContext(ctx.getValueStack(), request, response); - } - return context; - } - - /** - *- * Sets the content type of the response. This is available to be overridden - * by a derived class. - *
- *The default implementation is:
- *- * - * response.setContentType(defaultContentType); - * - *- *
- * where defaultContentType is set to the value of the default.contentType - * property, or "text/html" if that is not set.
- * - * @param request servlet request from client - * @param response servlet reponse to client - */ - protected void setContentType(HttpServletRequest request, HttpServletResponse response) { - response.setContentType(defaultContentType); - } - -} +/* + * 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.struts2.sitemesh; + + +import com.opensymphony.module.sitemesh.Config; +import com.opensymphony.module.sitemesh.Decorator; +import com.opensymphony.module.sitemesh.DecoratorMapper; +import com.opensymphony.module.sitemesh.Factory; +import com.opensymphony.module.sitemesh.HTMLPage; +import com.opensymphony.module.sitemesh.RequestConstants; +import com.opensymphony.module.sitemesh.util.OutputConverter; +import com.opensymphony.xwork2.ActionContext; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.struts2.ServletActionContext; +import org.apache.struts2.dispatcher.Dispatcher; +import org.apache.struts2.dispatcher.listener.StrutsListener; +import org.apache.struts2.views.velocity.VelocityManager; +import org.apache.struts2.views.velocity.VelocityManagerInterface; +import org.apache.velocity.Template; +import org.apache.velocity.context.Context; +import org.apache.velocity.runtime.RuntimeConstants; +import org.apache.velocity.tools.view.VelocityView; +import org.apache.velocity.tools.view.VelocityViewServlet; + +import jakarta.servlet.ServletConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import java.io.IOException; +import java.io.StringWriter; + +/** + *This is a SiteMesh Velocity view servlet.
+ * + *It overrides the SiteMesh servlet to rely on the + * Velocity Manager in Struts instead of creating it's + * own manager
+ */ +public class VelocityDecoratorServlet extends VelocityViewServlet { + + private static final Logger LOG = LogManager.getLogger(VelocityDecoratorServlet.class); + + private static final long serialVersionUID = -6731485159371716918L; + + protected VelocityManagerInterface velocityManager; + protected String defaultContentType; + + /** + *Initializes servlet, toolbox and Velocity template engine. + * Called by the servlet container on loading.
+ * + *NOTE: If no charset is specified in the default.contentType + * property (in your velocity.properties) and you have specified + * an output.encoding property, then that will be used as the + * charset for the default content-type of pages served by this + * servlet.
+ * + * @param config servlet configuration + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); + Dispatcher dispatcher = Dispatcher.getInstance(getServletContext()); + if (dispatcher == null) { + throw new IllegalStateException("Unable to find the Dispatcher in the Servlet Context. Is '" + StrutsListener.class.getName() + "' missing in web.xml?"); + } + velocityManager = dispatcher.getContainer().getInstance(VelocityManagerInterface.class); + velocityManager.init(config.getServletContext()); + + // do whatever we have to do to init Velocity + getVelocityView().setVelocityEngine(velocityManager.getVelocityEngine()); + // toolboxManager = velocityManager.getToolboxManager(); + + + // we can get these now that velocity is initialized + defaultContentType = getVelocityProperty(VelocityView.CONTENT_TYPE_KEY, VelocityView.DEFAULT_CONTENT_TYPE); + + String encoding = getVelocityProperty(RuntimeConstants.ENCODING_DEFAULT, VelocityView.DEFAULT_OUTPUT_ENCODING); + + // For non Latin-1 encodings, ensure that the charset is + // included in the Content-Type header. + if (!VelocityView.DEFAULT_OUTPUT_ENCODING.equalsIgnoreCase(encoding)) { + int index = defaultContentType.lastIndexOf("charset"); + if (index < 0) { + // the charset specifier is not yet present in header. + // append character encoding to default content-type + defaultContentType += "; charset=" + encoding; + } else { + // The user may have configuration issues. + getVelocityView().getVelocityEngine().getLog().warn("VelocityViewServlet: Charset was already " + "specified in the Content-Type property. " + "Output encoding property will be ignored."); + } + } + + getVelocityView().getVelocityEngine().getLog().info("VelocityViewServlet: Default content-type is: " + defaultContentType); + } + + public Template handleRequest(HttpServletRequest request, HttpServletResponse response, Context context) { + HTMLPage htmlPage = (HTMLPage) request.getAttribute(RequestConstants.PAGE); + String template; + + context.put("base", request.getContextPath()); + // For backwards compatibility with apps that used the old VelocityDecoratorServlet + // that extended VelocityServlet instead of VelocityViewServlet + context.put("req", request); + context.put("res", response); + + if (htmlPage == null) { + context.put("title", "Title?"); + context.put("body", "Body?
"); + context.put("head", ""); + template = request.getServletPath(); + } else { + try { + context.put("title", OutputConverter.convert(htmlPage.getTitle())); + { + StringWriter buffer = new StringWriter(); + htmlPage.writeBody(OutputConverter.getWriter(buffer)); + context.put("body", buffer.toString()); + } + { + StringWriter buffer = new StringWriter(); + htmlPage.writeHead(OutputConverter.getWriter(buffer)); + context.put("head", buffer.toString()); + } + } catch (IOException e) { + LOG.error("IOException handle request template", e); + } + context.put("page", htmlPage); + DecoratorMapper decoratorMapper = getDecoratorMapper(); + Decorator decorator = decoratorMapper.getDecorator(request, htmlPage); + template = decorator.getPage(); + } + + return getTemplate(template); + } + + private DecoratorMapper getDecoratorMapper() { + Factory factory = Factory.getInstance(new Config(getServletConfig())); + return factory.getDecoratorMapper(); + } + + /** + *Creates and returns an initialized Velocity context.
+ * + * @param request servlet request from client + * @param response servlet reponse to client + */ + protected Context createContext(HttpServletRequest request, HttpServletResponse response) { + Context context = (Context) request.getAttribute(VelocityManager.KEY_VELOCITY_STRUTS_CONTEXT); + if (context == null) { + ActionContext ctx = ServletActionContext.getActionContext(request); + context = velocityManager.createContext(ctx.getValueStack(), request, response); + } + return context; + } + + /** + *+ * Sets the content type of the response. This is available to be overridden + * by a derived class. + *
+ *The default implementation is:
+ *+ * + * response.setContentType(defaultContentType); + * + *+ *
+ * where defaultContentType is set to the value of the default.contentType + * property, or "text/html" if that is not set.
+ * + * @param request servlet request from client + * @param response servlet reponse to client + */ + protected void setContentType(HttpServletRequest request, HttpServletResponse response) { + response.setContentType(defaultContentType); + } + +} diff --git a/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/VelocityPageFilter.java b/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/VelocityPageFilter.java index fa309ea27..71e04b329 100644 --- a/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/VelocityPageFilter.java +++ b/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/VelocityPageFilter.java @@ -18,27 +18,35 @@ */ package org.apache.struts2.sitemesh; -import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext; -import com.opensymphony.sitemesh.webapp.SiteMeshFilter; -import com.opensymphony.sitemesh.DecoratorSelector; -import com.opensymphony.module.sitemesh.Factory; import com.opensymphony.module.sitemesh.Config; +import com.opensymphony.module.sitemesh.Factory; +import com.opensymphony.sitemesh.DecoratorSelector; +import com.opensymphony.sitemesh.webapp.SiteMeshFilter; +import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext; import com.opensymphony.xwork2.inject.Inject; +import org.apache.struts2.views.velocity.VelocityManager; +import org.apache.struts2.views.velocity.VelocityManagerInterface; import jakarta.servlet.*; -import org.apache.struts2.views.velocity.VelocityManager; - /** * Core Filter for integrating SiteMesh into a Java web application. */ public class VelocityPageFilter extends SiteMeshFilter { @Inject(required=false) - public static void setVelocityManager(VelocityManager mgr) { + public static void setVelocityManager(VelocityManagerInterface mgr) { OldDecorator2NewStrutsVelocityDecorator.setVelocityManager(mgr); } + /** + * @deprecated since 6.4.0 + */ + @Deprecated + public static void setVelocityManager(VelocityManager mgr) { + setVelocityManager((VelocityManagerInterface) mgr); + } + private FilterConfig filterConfig; public void init(FilterConfig filterConfig) { diff --git a/plugins/velocity/src/main/java/org/apache/struts2/views/velocity/VelocityBeanSelectionProvider.java b/plugins/velocity/src/main/java/org/apache/struts2/views/velocity/VelocityBeanSelectionProvider.java index f53ec6607..d2c195b0f 100644 --- a/plugins/velocity/src/main/java/org/apache/struts2/views/velocity/VelocityBeanSelectionProvider.java +++ b/plugins/velocity/src/main/java/org/apache/struts2/views/velocity/VelocityBeanSelectionProvider.java @@ -49,7 +49,7 @@ public class VelocityBeanSelectionProvider extends AbstractBeanSelectionProvider @Override public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException { - alias(VelocityManager.class, VelocityConstants.STRUTS_VELOCITY_MANAGER_CLASSNAME, builder, props); + alias(VelocityManagerInterface.class, VelocityConstants.STRUTS_VELOCITY_MANAGER_CLASSNAME, builder, props); } } diff --git a/plugins/velocity/src/main/java/org/apache/struts2/views/velocity/VelocityManager.java b/plugins/velocity/src/main/java/org/apache/struts2/views/velocity/VelocityManager.java index deed524cd..cc4a20057 100644 --- a/plugins/velocity/src/main/java/org/apache/struts2/views/velocity/VelocityManager.java +++ b/plugins/velocity/src/main/java/org/apache/struts2/views/velocity/VelocityManager.java @@ -62,7 +62,7 @@ import static org.apache.struts2.views.util.ContextUtil.STRUTS; /** * Manages the environment for Velocity result types */ -public class VelocityManager { +public class VelocityManager implements VelocityManagerInterface { private static final Logger LOG = LogManager.getLogger(VelocityManager.class); @@ -105,6 +105,7 @@ public class VelocityManager { * @return a reference to the VelocityEngine used by all Struts Velocity results except directly * accessed *.vm pages (unless otherwise configured) */ + @Override public VelocityEngine getVelocityEngine() { return velocityEngine; } @@ -117,6 +118,7 @@ public class VelocityManager { * @param res the current HttpServletResponse * @return a new StrutsVelocityContext */ + @Override public Context createContext(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { Context context = buildToolContext(); if (context == null) { @@ -182,6 +184,7 @@ public class VelocityManager { * * @param context the current servlet context */ + @Override public synchronized void init(ServletContext context) { if (velocityEngine == null) { velocityEngine = newVelocityEngine(context); diff --git a/plugins/velocity/src/main/java/org/apache/struts2/views/velocity/VelocityManagerInterface.java b/plugins/velocity/src/main/java/org/apache/struts2/views/velocity/VelocityManagerInterface.java new file mode 100644 index 000000000..4e6b7b69a --- /dev/null +++ b/plugins/velocity/src/main/java/org/apache/struts2/views/velocity/VelocityManagerInterface.java @@ -0,0 +1,38 @@ +/* + * 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.struts2.views.velocity; + +import com.opensymphony.xwork2.util.ValueStack; +import jakarta.servlet.ServletContext; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.context.Context; + +/** + * @since 6.4.0 + */ +public interface VelocityManagerInterface { + + Context createContext(ValueStack stack, HttpServletRequest req, HttpServletResponse res); + + VelocityEngine getVelocityEngine(); + + void init(ServletContext context); +} diff --git a/plugins/velocity/src/main/java/org/apache/struts2/views/velocity/result/VelocityResult.java b/plugins/velocity/src/main/java/org/apache/struts2/views/velocity/result/VelocityResult.java index 1af1ef739..cb7a1f56d 100644 --- a/plugins/velocity/src/main/java/org/apache/struts2/views/velocity/result/VelocityResult.java +++ b/plugins/velocity/src/main/java/org/apache/struts2/views/velocity/result/VelocityResult.java @@ -29,6 +29,7 @@ import org.apache.struts2.StrutsConstants; import org.apache.struts2.result.StrutsResultSupport; import org.apache.struts2.views.JspSupportServlet; import org.apache.struts2.views.velocity.VelocityManager; +import org.apache.struts2.views.velocity.VelocityManagerInterface; import org.apache.velocity.Template; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.context.Context; @@ -85,9 +86,9 @@ public class VelocityResult extends StrutsResultSupport { private static final long serialVersionUID = 7268830767762559424L; private static final Logger LOG = LogManager.getLogger(VelocityResult.class); - + private String defaultEncoding; - private VelocityManager velocityManager; + private transient VelocityManagerInterface velocityManager; private JspFactory jspFactory = JspFactory.getDefaultFactory(); public VelocityResult() { @@ -97,17 +98,25 @@ public class VelocityResult extends StrutsResultSupport { public VelocityResult(String location) { super(location); } - + @Inject(StrutsConstants.STRUTS_I18N_ENCODING) public void setDefaultEncoding(String val) { defaultEncoding = val; } - + @Inject - public void setVelocityManager(VelocityManager mgr) { + public void setVelocityManager(VelocityManagerInterface mgr) { this.velocityManager = mgr; } + /** + * @deprecated since 6.4.0 + */ + @Deprecated + public void setVelocityManager(VelocityManager mgr) { + setVelocityManager((VelocityManagerInterface) mgr); + } + /** * Creates a Velocity context from the action, loads a Velocity template and executes the * template. Output is written to the servlet output stream. @@ -232,7 +241,23 @@ public class VelocityResult extends StrutsResultSupport { * @param location the name of the template that is being used * @return the a minted Velocity context. */ - protected Context createContext(VelocityManager velocityManager, ValueStack stack, HttpServletRequest request, HttpServletResponse response, String location) { + protected Context createContext(VelocityManagerInterface velocityManager, + ValueStack stack, + HttpServletRequest request, + HttpServletResponse response, + String location) { return velocityManager.createContext(stack, request, response); } + + /** + * @deprecated since 6.4.0 + */ + @Deprecated + protected Context createContext(VelocityManager velocityManager, + ValueStack stack, + HttpServletRequest request, + HttpServletResponse response, + String location) { + return createContext((VelocityManagerInterface) velocityManager, stack, request, response, location); + } } diff --git a/plugins/velocity/src/main/java/org/apache/struts2/views/velocity/template/VelocityTemplateEngine.java b/plugins/velocity/src/main/java/org/apache/struts2/views/velocity/template/VelocityTemplateEngine.java index 6788e0217..f6e0481f8 100644 --- a/plugins/velocity/src/main/java/org/apache/struts2/views/velocity/template/VelocityTemplateEngine.java +++ b/plugins/velocity/src/main/java/org/apache/struts2/views/velocity/template/VelocityTemplateEngine.java @@ -26,6 +26,7 @@ import org.apache.struts2.components.template.BaseTemplateEngine; import org.apache.struts2.components.template.Template; import org.apache.struts2.components.template.TemplateRenderingContext; import org.apache.struts2.views.velocity.VelocityManager; +import org.apache.struts2.views.velocity.VelocityManagerInterface; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.context.Context; @@ -41,14 +42,22 @@ import java.util.Map; */ public class VelocityTemplateEngine extends BaseTemplateEngine { private static final Logger LOG = LogManager.getLogger(VelocityTemplateEngine.class); - - private VelocityManager velocityManager; - + + private VelocityManagerInterface velocityManager; + @Inject - public void setVelocityManager(VelocityManager mgr) { + public void setVelocityManager(VelocityManagerInterface mgr) { this.velocityManager = mgr; } + /** + * @deprecated since 6.4.0 + */ + @Deprecated + public void setVelocityManager(VelocityManager mgr) { + setVelocityManager((VelocityManagerInterface) mgr); + } + public void renderTemplate(TemplateRenderingContext templateContext) throws Exception { // get the various items required from the stack Map actionContext = templateContext.getStack().getContext(); diff --git a/plugins/velocity/src/main/resources/struts-plugin.xml b/plugins/velocity/src/main/resources/struts-plugin.xml index 7630d41e3..b19aec9f2 100644 --- a/plugins/velocity/src/main/resources/struts-plugin.xml +++ b/plugins/velocity/src/main/resources/struts-plugin.xml @@ -25,6 +25,10 @@