diff --git a/plugins/embeddedjsp/pom.xml b/plugins/embeddedjsp/pom.xml index cba2e1ced..9e69fcad7 100644 --- a/plugins/embeddedjsp/pom.xml +++ b/plugins/embeddedjsp/pom.xml @@ -68,7 +68,7 @@ org.apache.tomcat - juli + tomcat-juli taglibs @@ -82,7 +82,7 @@ org.apache.tomcat - jasper + tomcat-jasper provided diff --git a/plugins/embeddedjsp/src/main/java/org/apache/struts2/JSPLoader.java b/plugins/embeddedjsp/src/main/java/org/apache/struts2/JSPLoader.java index e1c048cc9..713fcb848 100644 --- a/plugins/embeddedjsp/src/main/java/org/apache/struts2/JSPLoader.java +++ b/plugins/embeddedjsp/src/main/java/org/apache/struts2/JSPLoader.java @@ -23,6 +23,8 @@ import com.opensymphony.xwork2.FileManagerFactory; import com.opensymphony.xwork2.util.finder.ClassLoaderInterface; import com.opensymphony.xwork2.util.finder.ClassLoaderInterfaceDelegate; import com.opensymphony.xwork2.util.finder.UrlSet; +import com.opensymphony.xwork2.util.fs.DefaultFileManager; +import com.opensymphony.xwork2.util.fs.DefaultFileManagerFactory; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.apache.commons.io.FileUtils; @@ -172,8 +174,6 @@ public class JSPLoader { List optionList = new ArrayList(); Set classPath = new HashSet(); - FileManager fileManager = ServletActionContext.getContext().getInstance(FileManagerFactory.class).getFileManager(); - //find available jars ClassLoaderInterface classLoaderInterface = getClassLoaderInterface(); UrlSet urlSet = new UrlSet(classLoaderInterface); @@ -181,11 +181,19 @@ public class JSPLoader { //find jars List urls = urlSet.getUrls(); - for (URL url : urls) { - URL normalizedUrl = fileManager.normalizeToFileProtocol(url); - File file = FileUtils.toFile(ObjectUtils.defaultIfNull(normalizedUrl, url)); - if (file.exists()) - classPath.add(file.getAbsolutePath()); + if (urls != null && urls.size() > 0) { + final FileManagerFactory fileManagerFactoryGetInstance = ServletActionContext.getContext().getInstance(FileManagerFactory.class); + final FileManagerFactory contextFileManagerFactory = (fileManagerFactoryGetInstance != null ? fileManagerFactoryGetInstance : (FileManagerFactory) ServletActionContext.getContext().get(StrutsConstants.STRUTS_FILE_MANAGER_FACTORY)); + final FileManagerFactory fileManagerFactory = (contextFileManagerFactory != null ? contextFileManagerFactory : new DefaultFileManagerFactory()); + final FileManager fileManagerGetInstance = fileManagerFactory.getFileManager(); + final FileManager contextFileManager = (fileManagerGetInstance != null ? fileManagerGetInstance : (FileManager) ServletActionContext.getContext().get(StrutsConstants.STRUTS_FILE_MANAGER)); + final FileManager fileManager = (contextFileManager != null ? contextFileManager : new DefaultFileManager()); + for (URL url : urls) { + URL normalizedUrl = fileManager.normalizeToFileProtocol(url); + File file = FileUtils.toFile(ObjectUtils.defaultIfNull(normalizedUrl, url)); + if (file.exists()) + classPath.add(file.getAbsolutePath()); + } } //these should be in the list already, but I am feeling paranoid @@ -197,8 +205,8 @@ public class JSPLoader { classPath.add(getJarUrl(JspPage.class)); try { - Class annotationsProcessor = Class.forName("org.apache.AnnotationProcessor"); - classPath.add(getJarUrl(annotationsProcessor)); + Class instanceManager = Class.forName("org.apache.tomcat.InstanceManager"); + classPath.add(getJarUrl(instanceManager)); } catch (ClassNotFoundException e) { //ok ignore } diff --git a/plugins/embeddedjsp/src/main/java/org/apache/struts2/JSPRuntime.java b/plugins/embeddedjsp/src/main/java/org/apache/struts2/JSPRuntime.java index ab9152846..1a47a4d00 100644 --- a/plugins/embeddedjsp/src/main/java/org/apache/struts2/JSPRuntime.java +++ b/plugins/embeddedjsp/src/main/java/org/apache/struts2/JSPRuntime.java @@ -29,6 +29,7 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.jsp.HttpJspPage; import java.util.HashMap; import java.util.Map; +import org.apache.struts2.views.util.DefaultUrlHelper; /** * Maintains a cache of jsp locations -> servlet instances for those jsps. When a jsp is requested @@ -49,11 +50,13 @@ public abstract class JSPRuntime { public static void handle(String location, boolean flush) throws Exception { final HttpServletResponse response = ServletActionContext.getResponse(); final HttpServletRequest request = ServletActionContext.getRequest(); - final UrlHelper urlHelper = ServletActionContext.getContext().getInstance(UrlHelper.class); int i = location.indexOf("?"); if (i > 0) { //extract params from the url and add them to the request + final UrlHelper urlHelperGetInstance = ServletActionContext.getContext().getInstance(UrlHelper.class); + final UrlHelper contextUrlHelper = (urlHelperGetInstance != null ? urlHelperGetInstance : (UrlHelper) ServletActionContext.getContext().get(StrutsConstants.STRUTS_URL_HELPER)); + final UrlHelper urlHelper = (contextUrlHelper != null ? contextUrlHelper : new DefaultUrlHelper()); String query = location.substring(i + 1); Map queryParams = urlHelper.parseQueryString(query, true); if (queryParams != null && !queryParams.isEmpty()) { diff --git a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/Generator.java b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/Generator.java index 6a8ab7272..5327afcc8 100644 --- a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/Generator.java +++ b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/Generator.java @@ -76,8 +76,8 @@ class Generator { private static final String VAR_EXPRESSIONFACTORY = System.getProperty("org.apache.struts2.jasper.compiler.Generator.VAR_EXPRESSIONFACTORY", "_el_expressionfactory"); - private static final String VAR_ANNOTATIONPROCESSOR = - System.getProperty("org.apache.struts2.jasper.compiler.Generator.VAR_ANNOTATIONPROCESSOR", "_jsp_annotationprocessor"); + private static final String VAR_INSTANCEMANAGER = + System.getProperty("org.apache.struts2.jasper.compiler.Generator.VAR_INSTANCEMANAGER", "_jsp_instancemanager"); private ServletWriter out; @@ -421,15 +421,14 @@ class Generator { out.print("getServletConfig()"); } out.println(".getServletContext()).getExpressionFactory();"); - - out.printin(VAR_ANNOTATIONPROCESSOR); - out.print(" = (org.apache.AnnotationProcessor) "); + out.printin(VAR_INSTANCEMANAGER); + out.print(" = (org.apache.tomcat.InstanceManager) "); if (ctxt.isTagFile()) { out.print("config"); } else { out.print("getServletConfig()"); } - out.println(".getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName());"); + out.println(".getServletContext().getAttribute(org.apache.tomcat.InstanceManager.class.getName());"); out.popIndent(); out.printil("}"); @@ -533,8 +532,8 @@ class Generator { out.printin("private javax.el.ExpressionFactory "); out.print(VAR_EXPRESSIONFACTORY); out.println(";"); - out.printin("private org.apache.AnnotationProcessor "); - out.print(VAR_ANNOTATIONPROCESSOR); + out.printin("private org.apache.tomcat.InstanceManager "); + out.print(VAR_INSTANCEMANAGER); out.println(";"); out.println(); } @@ -2210,8 +2209,8 @@ class Generator { out.print("new "); out.print(tagHandlerClassName); out.println("();"); - out.printin("org.apache.struts2.jasper.runtime.AnnotationHelper.postConstruct("); - out.print(VAR_ANNOTATIONPROCESSOR); + out.printin("org.apache.struts2.jasper.runtime.InstanceHelper.postConstruct("); + out.print(VAR_INSTANCEMANAGER); out.print(", "); out.print(tagHandlerVar); out.println(");"); @@ -2360,8 +2359,8 @@ class Generator { } else { out.printin(tagHandlerVar); out.println(".release();"); - out.printin("org.apache.struts2.jasper.runtime.AnnotationHelper.preDestroy("); - out.print(VAR_ANNOTATIONPROCESSOR); + out.printin("org.apache.struts2.jasper.runtime.InstanceHelper.preDestroy("); + out.print(VAR_INSTANCEMANAGER); out.print(", "); out.print(tagHandlerVar); out.println(");"); @@ -2407,8 +2406,8 @@ class Generator { } else { out.printin(tagHandlerVar); out.println(".release();"); - out.printin("org.apache.struts2.jasper.runtime.AnnotationHelper.preDestroy("); - out.print(VAR_ANNOTATIONPROCESSOR); + out.printin("org.apache.struts2.jasper.runtime.InstanceHelper.preDestroy("); + out.print(VAR_INSTANCEMANAGER); out.print(", "); out.print(tagHandlerVar); out.println(");"); @@ -2452,8 +2451,8 @@ class Generator { out.println("();"); // Resource injection - out.printin("org.apache.struts2.jasper.runtime.AnnotationHelper.postConstruct("); - out.print(VAR_ANNOTATIONPROCESSOR); + out.printin("org.apache.struts2.jasper.runtime.InstanceHelper.postConstruct("); + out.print(VAR_INSTANCEMANAGER); out.print(", "); out.print(tagHandlerVar); out.println(");"); @@ -2510,8 +2509,8 @@ class Generator { syncScriptingVars(n, VariableInfo.AT_END); // Resource injection - out.printin("org.apache.struts2.jasper.runtime.AnnotationHelper.preDestroy("); - out.print(VAR_ANNOTATIONPROCESSOR); + out.printin("org.apache.struts2.jasper.runtime.InstanceHelper.preDestroy("); + out.print(VAR_INSTANCEMANAGER); out.print(", "); out.print(tagHandlerVar); out.println(");"); diff --git a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/AnnotationHelper.java b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/AnnotationHelper.java deleted file mode 100644 index 709d3c400..000000000 --- a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/AnnotationHelper.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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.jasper.runtime; - -import java.lang.reflect.InvocationTargetException; - -import javax.naming.NamingException; - -import org.apache.AnnotationProcessor; - - -/** - * Verify the annotation and Process it. - * - * @author Fabien Carrion - * @author Remy Maucherat - * @version $Revision: 467222 $, $Date: 2006-10-24 05:17:11 +0200 (Tue, 24 Oct 2006) $ - */ -public class AnnotationHelper { - - - /** - * Call postConstruct method on the specified instance. Note: In Jasper, this - * calls naming resources injection as well. - * - * @param processor annotation processor - * @param instance object instance - * - * @throws IllegalAccessException on error - * @throws InvocationTargetException on error - * @throws NamingException on error - */ - public static void postConstruct(AnnotationProcessor processor, Object instance) - throws IllegalAccessException, InvocationTargetException, NamingException { - if (processor != null) { - processor.processAnnotations(instance); - processor.postConstruct(instance); - } - } - - - /** - * Call preDestroy method on the specified instance. - * - * @param processor annotation processor - * @param instance object instance - * - * @throws IllegalAccessException on error - * @throws InvocationTargetException on error - */ - public static void preDestroy(AnnotationProcessor processor, Object instance) - throws IllegalAccessException, InvocationTargetException { - if (processor != null) { - processor.preDestroy(instance); - } - } - - -} diff --git a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/InstanceHelper.java b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/InstanceHelper.java new file mode 100644 index 000000000..7be48a920 --- /dev/null +++ b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/InstanceHelper.java @@ -0,0 +1,191 @@ +/* + * 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.jasper.runtime; + +import java.lang.reflect.InvocationTargetException; +import java.util.Collections; +import java.util.Map; +import java.util.WeakHashMap; + +import javax.naming.NamingException; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; + +import org.apache.tomcat.InstanceManager; +import org.apache.tomcat.SimpleInstanceManager; + + +/** + * A helper module for processing instance objects using InstanceManager instances. + * + * Since AnnotationProcessor was removed in Tomcat 7+, this module performs a similar purpose using + * InstanceManager processing (the effective replacement). This module's logic is a blending + * of the original Struts 2 AnnotationHelper and logic ideas from an old Geronimo update + * (https://issues.apache.org/jira/browse/GERONIMO-3010) + * + * Original AnnotationHelper: Verify the annotation and Process it (@author Fabien Carrion, @author Remy Maucherat) + */ +public class InstanceHelper { + + private static final Map INSTANCE_MANAGERS = + Collections.synchronizedMap(new WeakHashMap()); + + + /** + * Private constructor (all methods static, no instance required) + */ + private InstanceHelper() {} + + /** + * Get the {@link InstanceManager} instance manager for a given + * {@link ServletConfig}. + * + * For any non-null servletConfig with a non-null {@link ServletContext}, + * if no instance manager is defined, this method will produce a + * {@link SimpleInstanceManager} and associate it with that + * {@link ServletConfig} and its {@link ClassLoader}. + * + * @param servletConfig + * + * @return + */ + public static InstanceManager getServletInstanceManager(ServletConfig servletConfig) { + if (servletConfig == null) { + return null; + } + final ServletContext servletContext = servletConfig.getServletContext(); + if (servletContext == null) { + return null; + } + final ClassLoader classLoader = servletContext.getClassLoader(); + final Object potentialInstanceManager = servletContext.getAttribute(InstanceManager.class.getName()); + InstanceManager instanceManager; + if (potentialInstanceManager == null) { + instanceManager = new SimpleInstanceManager(); + setClassLoaderInstanceManager(classLoader, instanceManager); + servletContext.setAttribute(InstanceManager.class.getName(), instanceManager); + return instanceManager; + } + else { + instanceManager = getClassLoaderInstanceManager(classLoader); + if (instanceManager == null || ! instanceManager.equals(potentialInstanceManager) ) { + if (potentialInstanceManager instanceof InstanceManager) { + instanceManager = (InstanceManager) potentialInstanceManager; + setClassLoaderInstanceManager(classLoader, instanceManager); + return instanceManager; + } else { + return null; + } + } else { + return instanceManager; + } + } + } + + /** + * Get the {@link InstanceManager} instance manager for a given + * {@link ClassLoader} instance, stored within the + * {@link InstanceHelper} {@link Map}. + * + * For any non-null classLoader, if no instance manager is defined, + * this method will produce a {@link SimpleInstanceManager} + * and associate it with that {@link ClassLoader}. + * + * @param classLoader + * + * @return + */ + public static InstanceManager getClassLoaderInstanceManager(ClassLoader classLoader) { + if (classLoader == null) { + return null; + } + InstanceManager instanceManager = INSTANCE_MANAGERS.get(classLoader); + if (instanceManager == null) { + instanceManager = new SimpleInstanceManager(); + setClassLoaderInstanceManager(classLoader, instanceManager); + } + return instanceManager; + } + + /** + * Set the {@link InstanceManager} instance manager for a given + * {@link ClassLoader} instance, stored within the + * {@link InstanceHelper} {@link Map}. + * + * @param classLoader + * @param instanceManager + */ + protected static void setClassLoaderInstanceManager(ClassLoader classLoader, InstanceManager instanceManager) { + if (classLoader != null) { + INSTANCE_MANAGERS.put(classLoader, instanceManager); + } + } + + /** + * Post-construct an instance of the specified {@link Object} using + * the provided {@link InstanceManager}. + * + * Note: This method replaces the old postContruct method in the AnnotationHelper. + * Note: In Jasper, this calls naming resources injection as well. + * + * @param instanceManager + * @param instance + * + * @throws IllegalAccessException + * @throws IllegalArgumentException + * @throws InvocationTargetException + * @throws NamingException + */ + public static void postConstruct(InstanceManager instanceManager, Object instance) + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, + NamingException { + if (instanceManager == null) { + throw new IllegalArgumentException("postConstruct - instanceManager is null"); + } else if (instance == null) { + throw new IllegalArgumentException("postConstruct - instanceClass is null"); + } else { + instanceManager.newInstance(instance); + } + } + + /** + * Pre-destroy an instance {@link Object} previously post-constructed + * with the provided {@link InstanceManager}. + * + * Note: This method replaces the old preDestroy method in the AnnotationHelper. + * + * @param instanceManager instance manager + * @param instance object instance + * + * @throws IllegalAccessException + * @throws IllegalArgumentException + * @throws InvocationTargetException + */ + public static void preDestroy(InstanceManager instanceManager, Object instance) + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + if (instanceManager == null) { + throw new IllegalArgumentException("preDestroy - instanceManager is null"); + } else if (instance == null) { + throw new IllegalArgumentException("preDestroy - instance is null"); + } else { + instanceManager.destroyInstance(instance); + } + } + +} diff --git a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/TagHandlerPool.java b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/TagHandlerPool.java index 2cc506f5e..c93de922c 100644 --- a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/TagHandlerPool.java +++ b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/TagHandlerPool.java @@ -22,10 +22,10 @@ import javax.servlet.ServletConfig; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.Tag; -import org.apache.AnnotationProcessor; import org.apache.struts2.jasper.Constants; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.InstanceManager; /** * Pool of tag handlers that can be reused. @@ -43,7 +43,7 @@ public class TagHandlerPool { // index of next available tag handler private int current; - protected AnnotationProcessor annotationProcessor = null; + protected InstanceManager instanceManager = null; public static TagHandlerPool getTagHandlerPool( ServletConfig config) { TagHandlerPool result=null; @@ -79,8 +79,7 @@ public class TagHandlerPool { } this.handlers = new Tag[maxSize]; this.current = -1; - this.annotationProcessor = - (AnnotationProcessor) config.getServletContext().getAttribute(AnnotationProcessor.class.getName()); + this.instanceManager = InstanceHelper.getServletInstanceManager(config); } /** @@ -124,8 +123,10 @@ public class TagHandlerPool { // Out of sync block - there is no need for other threads to // wait for us to construct a tag for this thread. try { - Tag instance = (Tag) handlerClass.newInstance(); - AnnotationHelper.postConstruct(annotationProcessor, instance); + final Tag instance = (Tag) handlerClass.newInstance(); + if (instanceManager != null) { + InstanceHelper.postConstruct(instanceManager, instance); + } return instance; } catch (Exception e) { throw new JspException(e.getMessage(), e); @@ -148,9 +149,9 @@ public class TagHandlerPool { } // There is no need for other threads to wait for us to release handler.release(); - if (annotationProcessor != null) { + if (instanceManager != null) { try { - AnnotationHelper.preDestroy(annotationProcessor, handler); + InstanceHelper.preDestroy(instanceManager, handler); } catch (Exception e) { log.warn("Error processing preDestroy on tag instance of " + handler.getClass().getName(), e); @@ -165,9 +166,9 @@ public class TagHandlerPool { public synchronized void release() { for (int i = current; i >= 0; i--) { handlers[i].release(); - if (annotationProcessor != null) { + if (instanceManager != null) { try { - AnnotationHelper.preDestroy(annotationProcessor, handlers[i]); + InstanceHelper.preDestroy(instanceManager, handlers[i]); } catch (Exception e) { log.warn("Error processing preDestroy on tag instance of " + handlers[i].getClass().getName(), e); diff --git a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/servlet/JspCServletContext.java b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/servlet/JspCServletContext.java index cfbcd81f9..94fee5469 100644 --- a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/servlet/JspCServletContext.java +++ b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/servlet/JspCServletContext.java @@ -28,15 +28,23 @@ import java.io.PrintWriter; import java.net.MalformedURLException; import java.net.URL; import java.util.Enumeration; +import java.util.EventListener; import java.util.HashSet; import java.util.Hashtable; +import java.util.Map; import java.util.Set; import java.util.Vector; +import javax.servlet.Filter; +import javax.servlet.FilterRegistration; import javax.servlet.RequestDispatcher; import javax.servlet.Servlet; import javax.servlet.ServletContext; import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; +import javax.servlet.SessionCookieConfig; +import javax.servlet.SessionTrackingMode; +import javax.servlet.descriptor.JspConfigDescriptor; import org.apache.struts2.ServletActionContext; @@ -421,6 +429,139 @@ public class JspCServletContext implements ServletContext { } + @Override + public int getEffectiveMajorVersion() { + return (2); + } + @Override + public int getEffectiveMinorVersion() { + return (3); + } + + @Override + public boolean setInitParameter(String arg0, String arg1) { + return (false); + } + + @Override + public ServletRegistration.Dynamic addServlet(String arg0, String arg1) { + return (null); + } + + @Override + public ServletRegistration.Dynamic addServlet(String arg0, Servlet arg1) { + return (null); + } + + @Override + public ServletRegistration.Dynamic addServlet(String arg0, Class arg1) { + return (null); + } + + @Override + public T createServlet(Class arg0) throws ServletException { + return (null); + } + + @Override + public ServletRegistration getServletRegistration(String arg0) { + return (null); + } + + @Override + public Map getServletRegistrations() { + return (null); + } + + @Override + public FilterRegistration.Dynamic addFilter(String arg0, String arg1) { + return (null); + } + + @Override + public FilterRegistration.Dynamic addFilter(String arg0, Filter arg1) { + return (null); + } + + @Override + public FilterRegistration.Dynamic addFilter(String arg0, Class arg1) { + return (null); + } + + @Override + public T createFilter(Class arg0) throws ServletException { + return (null); + } + + @Override + public FilterRegistration getFilterRegistration(String arg0) { + return (null); + } + + @Override + public Map getFilterRegistrations() { + return (null); + } + + @Override + public SessionCookieConfig getSessionCookieConfig() { + return (null); + } + + @Override + public void setSessionTrackingModes(Set arg0) { + return; + } + + @Override + public Set getDefaultSessionTrackingModes() { + return (null); + } + + @Override + public Set getEffectiveSessionTrackingModes() { + return (null); + } + + @Override + public void addListener(String arg0) { + return; + } + + @Override + public void addListener(T arg0) { + return; + } + + @Override + public void addListener(Class arg0) { + return; + } + + @Override + public T createListener(Class arg0) throws ServletException { + return (null); + } + + @Override + public JspConfigDescriptor getJspConfigDescriptor() { + return (null); + } + + @Override + public ClassLoader getClassLoader() { + return (null); + } + + @Override + public void declareRoles(String... arg0) { + return; + } + + @Override + public String getVirtualServerName() { + return ("JspCServletContext_VirtualServer"); + } } diff --git a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/servlet/JspServlet.java b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/servlet/JspServlet.java index 40ebac90c..fbe23424b 100644 --- a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/servlet/JspServlet.java +++ b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/servlet/JspServlet.java @@ -37,7 +37,7 @@ import org.apache.struts2.jasper.compiler.Localizer; import org.apache.struts2.jasper.security.SecurityUtil; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; -import org.apache.PeriodicEventListener; +import org.apache.tomcat.PeriodicEventListener; /** * The JSP engine (a.k.a Jasper). diff --git a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/servlet/JspServletWrapper.java b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/servlet/JspServletWrapper.java index 9e118cbc7..8a04b2eea 100644 --- a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/servlet/JspServletWrapper.java +++ b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/servlet/JspServletWrapper.java @@ -32,7 +32,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.jsp.tagext.TagInfo; -import org.apache.AnnotationProcessor; import org.apache.struts2.jasper.JasperException; import org.apache.struts2.jasper.JspCompilationContext; import org.apache.struts2.jasper.Options; @@ -41,8 +40,10 @@ import org.apache.struts2.jasper.compiler.JavacErrorDetail; import org.apache.struts2.jasper.compiler.JspRuntimeContext; import org.apache.struts2.jasper.compiler.Localizer; import org.apache.struts2.jasper.runtime.JspSourceDependent; +import org.apache.struts2.jasper.runtime.InstanceHelper; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.InstanceManager; /** * The JSP engine (a.k.a Jasper). @@ -144,10 +145,9 @@ public class JspServletWrapper { try { servletClass = ctxt.load(); servlet = (Servlet) servletClass.newInstance(); - AnnotationProcessor annotationProcessor = (AnnotationProcessor) config.getServletContext().getAttribute(AnnotationProcessor.class.getName()); - if (annotationProcessor != null) { - annotationProcessor.processAnnotations(servlet); - annotationProcessor.postConstruct(servlet); + final InstanceManager instanceManager = InstanceHelper.getServletInstanceManager(config); + if (instanceManager != null) { + InstanceHelper.postConstruct(instanceManager, servlet); } } catch (IllegalAccessException e) { throw new JasperException(e); @@ -424,10 +424,10 @@ public class JspServletWrapper { public void destroy() { if (theServlet != null) { theServlet.destroy(); - AnnotationProcessor annotationProcessor = (AnnotationProcessor) config.getServletContext().getAttribute(AnnotationProcessor.class.getName()); - if (annotationProcessor != null) { + final InstanceManager instanceManager = InstanceHelper.getServletInstanceManager(config); + if (instanceManager != null) { try { - annotationProcessor.preDestroy(theServlet); + InstanceHelper.preDestroy(instanceManager, theServlet); } catch (Exception e) { // Log any exception, since it can't be passed along log.error(Localizer.getMessage("jsp.error.file.not.found", diff --git a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/Util.java b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/Util.java index 8ba6b66e9..4896a2fae 100644 --- a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/Util.java +++ b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/Util.java @@ -28,6 +28,7 @@ import java.io.UnsupportedEncodingException; import java.util.Locale; import javax.servlet.ServletOutputStream; +import javax.servlet.WriteListener; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; @@ -283,6 +284,16 @@ public class Util { public void write(int b) throws IOException { bos.write(b); } + + @Override + public boolean isReady() { + return (true); + } + + @Override + public void setWriteListener(WriteListener arg0) { + return; + } }; private boolean isWriterUsed; private boolean isStreamUsed; diff --git a/plugins/embeddedjsp/src/test/java/org/apache/struts2/EmbeddedJSPResultTest.java b/plugins/embeddedjsp/src/test/java/org/apache/struts2/EmbeddedJSPResultTest.java index dbc807011..7d96f9ba2 100644 --- a/plugins/embeddedjsp/src/test/java/org/apache/struts2/EmbeddedJSPResultTest.java +++ b/plugins/embeddedjsp/src/test/java/org/apache/struts2/EmbeddedJSPResultTest.java @@ -34,11 +34,15 @@ import com.opensymphony.xwork2.util.fs.DefaultFileManager; import junit.framework.TestCase; import org.apache.commons.lang3.StringUtils; import org.apache.struts2.dispatcher.HttpParameters; +import org.apache.struts2.jasper.runtime.InstanceHelper; import org.apache.struts2.views.util.DefaultUrlHelper; import org.apache.struts2.views.util.UrlHelper; +import org.apache.tomcat.InstanceManager; import org.easymock.EasyMock; import org.easymock.IAnswer; +import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.mock.web.MockServletConfig; import org.springframework.mock.web.MockServletContext; import javax.servlet.Servlet; @@ -49,10 +53,12 @@ import java.util.*; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; + public class EmbeddedJSPResultTest extends TestCase { private HttpServletRequest request; private MockHttpServletResponse response; private MockServletContext context; + private MockServletConfig config; private EmbeddedJSPResult result; public void testScriptlet() throws Exception { @@ -241,6 +247,56 @@ public class EmbeddedJSPResultTest extends TestCase { } } + public void testComplex() throws Exception { + result.setLocation("org/apache/struts2/complex0.jsp"); + result.execute(null); + + String responseString = response.getContentAsString(); + assertNotNull("result is null?", responseString); + int titleIndex = responseString.indexOf("Struts2 Embedded JSP Plugin - Complex Test Page"); + int responseLength = responseString.length(); + int testValue1Index = responseString.indexOf("testvalue1 set/if worked."); + int testValue5Index = responseString.indexOf("testvalue5 set/if worked."); + int lastGroupIndex = responseString.indexOf("End include tests
"); + int lastHtmlIndex = responseString.indexOf(""); + assertTrue("Did not find title ?", titleIndex > 0); + assertTrue("Test value 1 not present or index not > title index ?", testValue1Index > titleIndex); + assertTrue("Test value 5 not present or index not > test value 1 index ?", testValue5Index > testValue1Index); + assertTrue("Last group index not present or index not > test value 5 index ?", lastGroupIndex > testValue5Index); + assertTrue("Last html index not present or index not > last group index ?", lastHtmlIndex > lastGroupIndex); + assertTrue("Response not at least length: 3400 ?", responseLength > 3400); + } + + public void testInstanceHelper() throws Exception { + InstanceManager instanceManagerServlet = InstanceHelper.getServletInstanceManager(config); + InstanceManager instanceManagerClassLoader = InstanceHelper.getClassLoaderInstanceManager(context.getClassLoader()); + assertNotNull("instanceManager (servlet) is null ?", instanceManagerServlet); + assertNotNull("instanceManager (classloader) is null ?", instanceManagerClassLoader); + assertEquals("instanceManager (servlet) is not equal to instanceManager (classloader) ?", instanceManagerServlet, instanceManagerClassLoader); + final Double instanceDouble = new Double(0); + final Long instanceLong = new Long(0); + final Object instanceObject = new Object(); + final String instanceString = new String("test string"); + final MockHttpServletRequest intanceMockHttpServletRequest = new MockHttpServletRequest(); + intanceMockHttpServletRequest.setContextPath("context path"); + InstanceHelper.postConstruct(instanceManagerServlet, instanceDouble); + InstanceHelper.postConstruct(instanceManagerServlet, instanceLong); + InstanceHelper.postConstruct(instanceManagerServlet, instanceObject); + InstanceHelper.postConstruct(instanceManagerServlet, instanceString); + InstanceHelper.postConstruct(instanceManagerServlet, intanceMockHttpServletRequest); + assertEquals("test string value changed after postConstruct ?", instanceString, "test string"); + assertEquals("mock servlet request context path value changed after postConstruct ?", + intanceMockHttpServletRequest.getContextPath(), "context path"); + InstanceHelper.preDestroy(instanceManagerServlet, instanceDouble); + InstanceHelper.preDestroy(instanceManagerServlet, instanceLong); + InstanceHelper.preDestroy(instanceManagerServlet, instanceObject); + InstanceHelper.preDestroy(instanceManagerServlet, instanceString); + InstanceHelper.preDestroy(instanceManagerServlet, intanceMockHttpServletRequest); + assertEquals("test string value changed after preDestroy ?", instanceString, "test string"); + assertEquals("mock servlet request context path value changed after preDestroy ?", + intanceMockHttpServletRequest.getContextPath(), "context path"); + } + @Override protected void setUp() throws Exception { super.setUp(); @@ -250,6 +306,7 @@ public class EmbeddedJSPResultTest extends TestCase { request = EasyMock.createNiceMock(HttpServletRequest.class); response = new MockHttpServletResponse(); context = new MockServletContext(); + config = new MockServletConfig(context); final Map params = new HashMap(); diff --git a/plugins/embeddedjsp/src/test/resources/org/apache/struts2/complex0.jsp b/plugins/embeddedjsp/src/test/resources/org/apache/struts2/complex0.jsp new file mode 100644 index 000000000..263a1421e --- /dev/null +++ b/plugins/embeddedjsp/src/test/resources/org/apache/struts2/complex0.jsp @@ -0,0 +1,221 @@ +<%-- +/* +* 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. +*/ +--%> + +<%@ page import="org.apache.commons.lang3.StringUtils" %> +<%@ page import="com.opensymphony.xwork2.util.AnnotationUtils" %> +<%@ page import="com.opensymphony.xwork2.util.ClassLoaderUtil" %> +<%@ page import="com.opensymphony.xwork2.util.ProxyUtil" %> +<%@ page import="com.opensymphony.xwork2.util.ResolverUtil" %> +<%@ page import="com.opensymphony.xwork2.util.TextParseUtil" %> +<%@ page import="com.opensymphony.xwork2.util.WildcardUtil" %> +<%@ page import="org.apache.struts2.StrutsConstants" %> +<%@ page import="org.apache.struts2.StrutsConstants" %> +<%@ page import="org.apache.struts2.util.ComponentUtils" %> +<%@ page import="org.apache.struts2.util.ContainUtil" %> +<%@ page import="org.apache.struts2.util.StrutsUtil" %> +<%@ page import="org.apache.struts2.util.URLDecoderUtil" %> +<%@ page import="org.apache.struts2.util.VelocityStrutsUtil" %> +<%@ taglib prefix="r" uri="http://jakarta.apache.org/taglibs/request-1.0" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + Struts2 Embedded JSP Plugin - Complex Test Page + + +
+

Embedded JSP - Test JSTL Set/If Tag - Borrows structure from Struts 2 Showcase

+
+
+
+
+

+ This is a jsp to test the JSTL If/Choose Tags. There's a few combination being tested. + The characters in bold an non-bold should be the same. +

+ 1 - Foo - + + Foo + + + Bar + +
+ 2 - Bar - + + + Foo + + + Bar + + +
+ 3 - FooFooFoo - + + + Foo + + + FooFoo + + + BarBar + + + + + Bar + + +
+ 4 - FooBarBar - + + + Foo + + + FooFoo + + + BarBar + + + + + Bar + + +
+ 5 - BarFooFoo - + + + Foo + + + Bar + + + FooFoo + + + BarBar + + + + +
+ 6 - BarBarBar - + + + Foo + + + Bar + + + FooFoo + + + BarBar + + + + +
+
+
+
+
+ Request headers:
+ + = + +
+ User-Agent:
+ + User-Agent= + + + No User-Agent + +
+ Request parameters:
+ + = + +
+ Request attributes:
+ + = + +
+
+
+ Start set/out/if tests
+ + + + + + All test values:
+ testvalue1:
+ testvalue2:
+ testvalue3:
+ testvalue4:
+ testvalue5:
+ + testvalue1 set/if worked.
+
+ + testvalue2 set/if worked.
+
+ + testvalue3 set/if worked.
+
+ + testvalue4 set/if worked.
+
+ + testvalue5 set/if worked.
+
+
+ End set/out/if tests
+
+
+
+ Start include tests
+ + + + + + <%@ include file="org/apache/struts2/simple0.jsp" %> + + + + + +
+
+ End include tests
+
+ + diff --git a/pom.xml b/pom.xml index 15bce6232..99a88a7de 100644 --- a/pom.xml +++ b/pom.xml @@ -759,8 +759,15 @@ org.apache.tomcat - jasper - 6.0.53 + tomcat-jasper + 8.5.37 + provided + + + + org.apache.tomcat + tomcat-api + 8.5.37 provided @@ -836,8 +843,8 @@ org.apache.tomcat - juli - 6.0.53 + tomcat-juli + 8.5.37