You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2022/12/04 11:49:52 UTC

[struts] 01/01: WW-5264 Moves XSLT result into a dedicated plugin

This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch WW-5264-xslt
in repository https://gitbox.apache.org/repos/asf/struts.git

commit ebd0d4827efcc1de4685b40829512975f61191a4
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Sun Dec 4 12:49:44 2022 +0100

    WW-5264 Moves XSLT result into a dedicated plugin
---
 apps/showcase/pom.xml                              |   5 +
 bom/pom.xml                                        |   5 +
 .../java/org/apache/struts2/StrutsConstants.java   |   3 -
 .../struts2/config/entities/ConstantConfig.java    |   1 -
 core/src/main/resources/struts-default.xml         |   2 +-
 plugins/pom.xml                                    |   1 +
 plugins/xslt/README.md                             |   3 +
 plugins/{ => xslt}/pom.xml                         |  62 +++--------
 .../result}/xslt/AbstractAdapterElement.java       |  28 ++---
 .../struts2/result}/xslt/AbstractAdapterNode.java  |  49 ++++----
 .../struts2/result}/xslt/AdapterFactory.java       |  25 ++---
 .../apache/struts2/result}/xslt/AdapterNode.java   |   2 +-
 .../apache/struts2/result}/xslt/ArrayAdapter.java  |   6 +-
 .../apache/struts2/result}/xslt/BeanAdapter.java   |  49 ++++----
 .../struts2/result}/xslt/CollectionAdapter.java    |  12 +-
 .../apache/struts2/result}/xslt/MapAdapter.java    |  25 ++---
 .../struts2/result}/xslt/ProxyAttrAdapter.java     |  12 +-
 .../struts2/result}/xslt/ProxyElementAdapter.java  |  17 +--
 .../struts2/result}/xslt/ProxyNamedNodeMap.java    |  10 +-
 .../struts2/result}/xslt/ProxyNodeAdapter.java     |  39 ++++---
 .../struts2/result}/xslt/ProxyTextNodeAdapter.java |   2 +-
 .../struts2/result}/xslt/ServletURIResolver.java   |  27 ++---
 .../result}/xslt/SimpleAdapterDocument.java        |  29 +++--
 .../struts2/result}/xslt/SimpleNodeList.java       |  16 +--
 .../struts2/result}/xslt/SimpleTextNode.java       |   2 +-
 .../apache/struts2/result}/xslt/StringAdapter.java |   9 +-
 .../apache/struts2/result}/xslt/XSLTResult.java    |   6 +-
 .../apache/struts2/result/xslt/XsltConstants.java  |  22 ++--
 .../org/apache/struts2/result}/xslt/package.html   |   0
 .../xslt/src/main/resources/struts-plugin.xml      |  21 ++--
 .../struts2/result}/xslt/XSLTResultTest.java       | 124 ++++++++++-----------
 .../src/test/resources/XSLTResultTest-val.xml      |   0
 .../resources/XSLTResultTest.bad.character.xsl     |   0
 .../xslt}/src/test/resources/XSLTResultTest.xsl    |   0
 .../xslt}/src/test/resources/XSLTResultTest2.xsl   |   0
 .../xslt}/src/test/resources/XSLTResultTest3.xsl   |   0
 .../test/resources/XSLTResultTest4.badinclude.xsl  |   0
 .../xslt}/src/test/resources/XSLTResultTest4.xsl   |   0
 .../xslt}/src/test/resources/XSLTResultTest5.xsl   |   0
 .../xslt}/src/test/resources/XSLTResultTest6.xsl   |   0
 pom.xml                                            |  45 +++++---
 41 files changed, 317 insertions(+), 342 deletions(-)

diff --git a/apps/showcase/pom.xml b/apps/showcase/pom.xml
index add8be9a5..cc6d51d5e 100644
--- a/apps/showcase/pom.xml
+++ b/apps/showcase/pom.xml
@@ -99,6 +99,11 @@
             <artifactId>struts2-velocity-plugin</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.struts</groupId>
+            <artifactId>struts2-xslt-plugin</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>javax.servlet</groupId>
             <artifactId>javax.servlet-api</artifactId>
diff --git a/bom/pom.xml b/bom/pom.xml
index f1db01489..289e83b02 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -181,6 +181,11 @@
                 <artifactId>struts2-velocity-plugin</artifactId>
                 <version>${struts-version.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.apache.struts</groupId>
+                <artifactId>struts2-xslt-plugin</artifactId>
+                <version>${struts-version.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
diff --git a/core/src/main/java/org/apache/struts2/StrutsConstants.java b/core/src/main/java/org/apache/struts2/StrutsConstants.java
index c75ff3d54..9a1920f02 100644
--- a/core/src/main/java/org/apache/struts2/StrutsConstants.java
+++ b/core/src/main/java/org/apache/struts2/StrutsConstants.java
@@ -177,9 +177,6 @@ public final class StrutsConstants {
     @Deprecated
     public static final String STRUTS_OBJECTFACTORY_SPRING_ENABLE_AOP_SUPPORT = "struts.objectFactory.spring.enableAopSupport";
 
-    /** Whether or not XSLT templates should not be cached */
-    public static final String STRUTS_XSLT_NOCACHE = "struts.xslt.nocache";
-
     /** Location of additional configuration properties files to load */
     public static final String STRUTS_CUSTOM_PROPERTIES = "struts.custom.properties";
 
diff --git a/core/src/main/java/org/apache/struts2/config/entities/ConstantConfig.java b/core/src/main/java/org/apache/struts2/config/entities/ConstantConfig.java
index 63c30ce2f..0fe1e300c 100644
--- a/core/src/main/java/org/apache/struts2/config/entities/ConstantConfig.java
+++ b/core/src/main/java/org/apache/struts2/config/entities/ConstantConfig.java
@@ -204,7 +204,6 @@ public class ConstantConfig {
         map.put(StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE_ALWAYS_RESPECT, Objects.toString(objectFactorySpringAutoWireAlwaysRespect, null));
         map.put(StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_USE_CLASS_CACHE, Objects.toString(objectFactorySpringUseClassCache, null));
         map.put(StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_ENABLE_AOP_SUPPORT, Objects.toString(objectFactorySpringEnableAopSupport, null));
-        map.put(StrutsConstants.STRUTS_XSLT_NOCACHE, Objects.toString(xsltNocache, null));
         map.put(StrutsConstants.STRUTS_CUSTOM_PROPERTIES, StringUtils.join(customProperties, ','));
         map.put(StrutsConstants.STRUTS_CUSTOM_I18N_RESOURCES, StringUtils.join(customI18nResources, ','));
         map.put(StrutsConstants.STRUTS_MAPPER_CLASS, beanConfToString(mapperClass));
diff --git a/core/src/main/resources/struts-default.xml b/core/src/main/resources/struts-default.xml
index 0bb197b56..7b81e9013 100644
--- a/core/src/main/resources/struts-default.xml
+++ b/core/src/main/resources/struts-default.xml
@@ -331,7 +331,7 @@
             <result-type name="redirect" class="org.apache.struts2.result.ServletRedirectResult"/>
             <result-type name="redirectAction" class="org.apache.struts2.result.ServletActionRedirectResult"/>
             <result-type name="stream" class="org.apache.struts2.result.StreamResult"/>
-            <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
+            <result-type name="xslt" class="org.apache.struts2.result.xslt.XSLTResult"/>
             <result-type name="plainText" class="org.apache.struts2.result.PlainTextResult"/>
             <result-type name="postback" class="org.apache.struts2.result.PostbackResult"/>
         </result-types>
diff --git a/plugins/pom.xml b/plugins/pom.xml
index e22f4040f..5c6749590 100644
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -58,6 +58,7 @@
         <module>testng</module>
         <module>tiles</module>
         <module>velocity</module>
+        <module>xslt</module>
     </modules>
 
     <dependencies>
diff --git a/plugins/xslt/README.md b/plugins/xslt/README.md
new file mode 100644
index 000000000..f0130e163
--- /dev/null
+++ b/plugins/xslt/README.md
@@ -0,0 +1,3 @@
+# Struts 2 XSLT plugin
+
+The XSLT plugin provides XSLT result.
diff --git a/plugins/pom.xml b/plugins/xslt/pom.xml
similarity index 52%
copy from plugins/pom.xml
copy to plugins/xslt/pom.xml
index e22f4040f..2b3d3bbb6 100644
--- a/plugins/pom.xml
+++ b/plugins/xslt/pom.xml
@@ -23,66 +23,38 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.apache.struts</groupId>
-        <artifactId>struts2-parent</artifactId>
+        <artifactId>struts2-plugins</artifactId>
         <version>6.2.0-SNAPSHOT</version>
     </parent>
 
-    <artifactId>struts2-plugins</artifactId>
-    <packaging>pom</packaging>
-    <name>Struts 2 Plugins</name>
-
-    <modules>
-        <module>async</module>
-        <module>bean-validation</module>
-        <module>cdi</module>
-        <module>config-browser</module>
-        <module>convention</module>
-        <module>dwr</module>
-        <module>embeddedjsp</module>
-        <module>gxp</module>
-        <module>jasperreports</module>
-        <module>javatemplates</module>
-        <module>jfreechart</module>
-        <module>json</module>
-        <module>junit</module>
-        <module>osgi</module>
-        <module>oval</module>
-        <module>pell-multipart</module>
-        <module>plexus</module>
-        <module>portlet</module>
-        <module>portlet-mocks</module>
-        <module>portlet-tiles</module>
-        <module>rest</module>
-        <module>sitemesh</module>
-        <module>spring</module>
-        <module>testng</module>
-        <module>tiles</module>
-        <module>velocity</module>
-    </modules>
+    <artifactId>struts2-xslt-plugin</artifactId>
+    <packaging>jar</packaging>
+    <name>Struts 2 XSLT Plugin</name>
 
     <dependencies>
-
         <dependency>
             <groupId>org.apache.struts</groupId>
-            <artifactId>struts2-core</artifactId>
+            <artifactId>struts2-junit-plugin</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet.jsp</groupId>
+            <artifactId>jsp-api</artifactId>
+            <scope>provided</scope>
         </dependency>
-
-        <!-- Test dependencies -->
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
             <scope>test</scope>
         </dependency>
-
         <dependency>
-            <groupId>javax.servlet</groupId>
-            <artifactId>javax.servlet-api</artifactId>
-            <scope>provided</scope>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-test</artifactId>
+            <scope>test</scope>
         </dependency>
-
     </dependencies>
 
     <properties>
-    	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     </properties>
+
 </project>
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/AbstractAdapterElement.java b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/AbstractAdapterElement.java
similarity index 87%
rename from core/src/main/java/org/apache/struts2/views/xslt/AbstractAdapterElement.java
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/AbstractAdapterElement.java
index e2f136271..346a91675 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/AbstractAdapterElement.java
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/AbstractAdapterElement.java
@@ -16,10 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
-
-import java.util.HashMap;
-import java.util.Map;
+package org.apache.struts2.result.xslt;
 
 import org.w3c.dom.Attr;
 import org.w3c.dom.DOMException;
@@ -27,28 +24,33 @@ import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.TypeInfo;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * AbstractAdapterElement extends the abstract Node type and implements
  * the DOM Element interface.
  */
 public abstract class AbstractAdapterElement extends AbstractAdapterNode implements Element {
 
-    private Map attributeAdapters;
+    private Map<String, Object> attributeAdapters;
 
-    public AbstractAdapterElement() { }
+    public AbstractAdapterElement() {
+    }
 
     public void setAttribute(String string, String string1) throws DOMException {
         throw operationNotSupported();
     }
 
-    protected Map getAttributeAdapters() {
-        if ( attributeAdapters == null )
+    protected Map<String, Object> getAttributeAdapters() {
+        if (attributeAdapters == null) {
             attributeAdapters = buildAttributeAdapters();
+        }
         return attributeAdapters;
     }
 
-    protected Map buildAttributeAdapters() {
-        return new HashMap();
+    protected Map<String, Object> buildAttributeAdapters() {
+        return new HashMap<>();
     }
 
     /**
@@ -63,15 +65,15 @@ public abstract class AbstractAdapterElement extends AbstractAdapterNode impleme
     }
 
     public String getAttributeNS(String string, String string1) {
-        return null;
+        throw operationNotSupported();
     }
 
     public Attr setAttributeNode(Attr attr) throws DOMException {
         throw operationNotSupported();
     }
 
-    public Attr getAttributeNode( String name ) {
-        return (Attr)getAttributes().getNamedItem( name );
+    public Attr getAttributeNode(String name) {
+        return (Attr) getAttributes().getNamedItem(name);
     }
 
     public Attr setAttributeNodeNS(Attr attr) throws DOMException {
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/AbstractAdapterNode.java b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/AbstractAdapterNode.java
similarity index 89%
rename from core/src/main/java/org/apache/struts2/views/xslt/AbstractAdapterNode.java
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/AbstractAdapterNode.java
index a9713fa92..f33180227 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/AbstractAdapterNode.java
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/AbstractAdapterNode.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
+package org.apache.struts2.result.xslt;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -29,7 +29,7 @@ import java.util.List;
 
 /**
  * AbstractAdapterNode is the base for childAdapters that expose a read-only view
- * of a Java object as a DOM Node.  This class implements the core parent-child
+ * of a Java object as a DOM Node. This class implements the core parent-child
  * and sibling node traversal functionality shared by all adapter type nodes
  * and used in proxy node support.
  *
@@ -37,7 +37,9 @@ import java.util.List;
  */
 public abstract class AbstractAdapterNode implements AdapterNode {
 
-    private static final NamedNodeMap EMPTY_NAMEDNODEMAP =
+    private static final Logger LOG = LogManager.getLogger(AbstractAdapterNode.class);
+
+    private static final NamedNodeMap EMPTY_NAMED_NODE_MAP =
             new NamedNodeMap() {
                 public int getLength() {
                     return 0;
@@ -73,7 +75,6 @@ public abstract class AbstractAdapterNode implements AdapterNode {
             };
 
     private List<Node> childAdapters;
-    private Logger log = LogManager.getLogger(this.getClass());
 
     // The domain object that we are adapting
     private Object propertyValue;
@@ -108,11 +109,11 @@ public abstract class AbstractAdapterNode implements AdapterNode {
      * @return List of child adapters.
      */
     protected List<Node> buildChildAdapters() {
-        return new ArrayList<Node>();
+        return new ArrayList<>();
     }
 
     /**
-     * Lazily initialize child childAdapters
+     * Lazily initialize child adapters
      *
      * @return node list
      */
@@ -124,27 +125,26 @@ public abstract class AbstractAdapterNode implements AdapterNode {
     }
 
     public Node getChildBeforeOrAfter(Node child, boolean before) {
-        log.debug("getChildBeforeOrAfter: ");
-        List adapters = getChildAdapters();
-        if (log.isDebugEnabled()) {
-            log.debug("childAdapters = {}", adapters);
-            log.debug("child = {}", child);
+        LOG.debug("getChildBeforeOrAfter: ");
+        List<Node> adapters = getChildAdapters();
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("childAdapters = {}", adapters);
+            LOG.debug("child = {}", child);
         }
         int index = adapters.indexOf(child);
         if (index < 0)
             throw new StrutsException(child + " is no child of " + this);
         int siblingIndex = before ? index - 1 : index + 1;
-        return ((0 < siblingIndex) && (siblingIndex < adapters.size())) ?
-                ((Node) adapters.get(siblingIndex)) : null;
+        return ((0 < siblingIndex) && (siblingIndex < adapters.size())) ? adapters.get(siblingIndex) : null;
     }
 
     public Node getChildAfter(Node child) {
-        log.trace("getChildAfter");
+        LOG.trace("getChildAfter");
         return getChildBeforeOrAfter(child, false/*after*/);
     }
 
     public Node getChildBefore(Node child) {
-        log.trace("getChildBefore");
+        LOG.trace("getChildBefore");
         return getChildBeforeOrAfter(child, true/*after*/);
     }
 
@@ -165,19 +165,16 @@ public abstract class AbstractAdapterNode implements AdapterNode {
     }
 
     public NodeList getElementsByTagNameNS(String string, String string1) {
-        // TODO:
-        return null;
+        throw operationNotSupported();
     }
 
-    // Begin Node methods
-
     public NamedNodeMap getAttributes() {
-        return EMPTY_NAMEDNODEMAP;
+        return EMPTY_NAMED_NODE_MAP;
     }
 
     public NodeList getChildNodes() {
         NodeList nl = new SimpleNodeList(getChildAdapters());
-        log.debug("getChildNodes for tag: {} num children: {}", getNodeName(), nl.getLength());
+        LOG.debug("getChildNodes for tag: {} num children: {}", getNodeName(), nl.getLength());
         return nl;
     }
 
@@ -211,7 +208,7 @@ public abstract class AbstractAdapterNode implements AdapterNode {
     }
 
     public Node getParentNode() {
-        log.trace("getParentNode");
+        LOG.trace("getParentNode");
         return getParent();
     }
 
@@ -241,8 +238,8 @@ public abstract class AbstractAdapterNode implements AdapterNode {
 
     public Node getNextSibling() {
         Node next = getParent().getChildAfter(this);
-        if (log.isTraceEnabled()) {
-            log.trace("getNextSibling on " + getNodeName() + ": "
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("getNextSibling on " + getNodeName() + ": "
                     + ((next == null) ? "null" : next.getNodeName()));
         }
 
@@ -278,7 +275,7 @@ public abstract class AbstractAdapterNode implements AdapterNode {
     }
 
     public Node cloneNode(boolean b) {
-        log.trace("cloneNode");
+        LOG.trace("cloneNode");
         throw operationNotSupported();
     }
 
@@ -295,7 +292,7 @@ public abstract class AbstractAdapterNode implements AdapterNode {
     }
 
     public void normalize() {
-        log.trace("normalize");
+        LOG.trace("normalize");
         throw operationNotSupported();
     }
 
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/AdapterFactory.java b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/AdapterFactory.java
similarity index 91%
rename from core/src/main/java/org/apache/struts2/views/xslt/AdapterFactory.java
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/AdapterFactory.java
index c08d3925c..77ea5a552 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/AdapterFactory.java
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/AdapterFactory.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
+package org.apache.struts2.result.xslt;
 
 import org.apache.struts2.StrutsException;
 import org.w3c.dom.*;
@@ -100,7 +100,7 @@ import java.util.Map;
  */
 public class AdapterFactory {
 
-    private Map<Class, Class> adapterTypes = new HashMap<>();
+    private final Map<Class<?>, Class<?>> adapterTypes = new HashMap<>();
 
     /**
      * Register an adapter type for a Java class type.
@@ -108,7 +108,7 @@ public class AdapterFactory {
      * @param type        the Java class type which is to be handled by the adapter.
      * @param adapterType The adapter class, which implements AdapterNode.
      */
-    public void registerAdapterType(Class type, Class adapterType) {
+    public void registerAdapterType(Class<?> type, Class<?> adapterType) {
         adapterTypes.put(type, adapterType);
     }
 
@@ -121,16 +121,11 @@ public class AdapterFactory {
      * @param propertyValue the property value
      *
      * @return the document object
-     *
-     * @throws IllegalAccessException in case of illegal access
-     * @throws InstantiationException in case of instantiation errors
      */
-    public Document adaptDocument(String propertyName, Object propertyValue)
-            throws IllegalAccessException, InstantiationException {
+    public Document adaptDocument(String propertyName, Object propertyValue) {
         return new SimpleAdapterDocument(this, null, propertyName, propertyValue);
     }
 
-
     /**
      * Create an Node adapter for a child element.
      * Note that the parent of the created node must be an AdapterNode, however
@@ -145,7 +140,7 @@ public class AdapterFactory {
      * @return a node
      */
     public Node adaptNode(AdapterNode parent, String propertyName, Object value) {
-        Class adapterClass = getAdapterForValue(value);
+        Class<?> adapterClass = getAdapterForValue(value);
         if (adapterClass != null) {
             return constructAdapterInstance(adapterClass, parent, propertyName, value);
         }
@@ -161,7 +156,7 @@ public class AdapterFactory {
         }
 
         // Check other supported types or default to generic JavaBean introspecting adapter
-        Class valueType = value.getClass();
+        Class<?> valueType = value.getClass();
 
         if (valueType.isArray()) {
             adapterClass = ArrayAdapter.class;
@@ -238,10 +233,10 @@ public class AdapterFactory {
      *
      * @return the new node
      */
-    private Node constructAdapterInstance(Class adapterClass, AdapterNode parent, String propertyName, Object propertyValue) {
+    private Node constructAdapterInstance(Class<?> adapterClass, AdapterNode parent, String propertyName, Object propertyValue) {
         // Check to see if the class has a no-args constructor
         try {
-            adapterClass.getConstructor(new Class []{});
+            adapterClass.getConstructor();
         } catch (NoSuchMethodException e1) {
             throw new StrutsException("Adapter class: " + adapterClass + " does not have a no-args constructor.");
         }
@@ -272,8 +267,8 @@ public class AdapterFactory {
         return new StringAdapter(this, parent, propertyName, "null");
     }
 
-    //TODO: implement Configuration option to provide additional adapter classes
-    public Class getAdapterForValue(Object value) {
+    public Class<?> getAdapterForValue(Object value) {
         return adapterTypes.get(value.getClass());
     }
+
 }
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/AdapterNode.java b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/AdapterNode.java
similarity index 98%
rename from core/src/main/java/org/apache/struts2/views/xslt/AdapterNode.java
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/AdapterNode.java
index 81b0cd76f..13243e848 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/AdapterNode.java
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/AdapterNode.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
+package org.apache.struts2.result.xslt;
 
 import org.w3c.dom.Node;
 
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/ArrayAdapter.java b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ArrayAdapter.java
similarity index 90%
rename from core/src/main/java/org/apache/struts2/views/xslt/ArrayAdapter.java
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ArrayAdapter.java
index bd000189a..6c77f10c5 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/ArrayAdapter.java
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ArrayAdapter.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
+package org.apache.struts2.result.xslt;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -27,7 +27,7 @@ import java.util.List;
 
 public class ArrayAdapter extends AbstractAdapterElement {
 
-    private Logger log = LogManager.getLogger(this.getClass());
+    private static final Logger LOG = LogManager.getLogger(ArrayAdapter.class);
 
     public ArrayAdapter() {
     }
@@ -45,7 +45,7 @@ public class ArrayAdapter extends AbstractAdapterElement {
             if (childAdapter != null)
                 children.add(childAdapter);
 
-            log.debug("{} adding adapter: {}", this, childAdapter);
+            LOG.debug("{} adding adapter: {}", this, childAdapter);
         }
 
         return children;
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/BeanAdapter.java b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/BeanAdapter.java
similarity index 79%
rename from core/src/main/java/org/apache/struts2/views/xslt/BeanAdapter.java
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/BeanAdapter.java
index c62582312..e7def0713 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/BeanAdapter.java
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/BeanAdapter.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
+package org.apache.struts2.result.xslt;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -46,35 +46,27 @@ import java.util.Map;
  *      public String getLastName();
  * }
  * </pre>
- *
+ * <p>
  * would be rendered as: &lt;myPerson&gt; &lt;firstName&gt;...&lt;/firstName&gt; &lt;lastName&gt;...&lt;/lastName&gt; &lt;/myPerson&gt;
  */
 public class BeanAdapter extends AbstractAdapterElement {
-    //Static fields/initializer
 
-    private static final Object[] NULLPARAMS = new Object[0];
+    private static final Logger LOG = LogManager.getLogger(BeanAdapter.class);
+
+    private static final Object[] NULL_PARAMS = new Object[0];
 
     /**
      * Cache can savely be static because the cached information is the same for all instances of this class.
      */
-    private static Map<Class, PropertyDescriptor[]> propertyDescriptorCache;
-
-    //Instance fields
-
-    private Logger log = LogManager.getLogger(this.getClass());
-
-    //Constructors
+    private static Map<Class<?>, PropertyDescriptor[]> propertyDescriptorCache;
 
     public BeanAdapter() {
     }
 
-    public BeanAdapter(
-            AdapterFactory adapterFactory, AdapterNode parent, String propertyName, Object value) {
+    public BeanAdapter(AdapterFactory adapterFactory, AdapterNode parent, String propertyName, Object value) {
         setContext(adapterFactory, parent, propertyName, value);
     }
 
-    //Methods
-
     public String getTagName() {
         return getPropertyName();
     }
@@ -82,17 +74,17 @@ public class BeanAdapter extends AbstractAdapterElement {
     public NodeList getChildNodes() {
         NodeList nl = super.getChildNodes();
         // Log child nodes for debug:
-        if (log.isDebugEnabled() && nl != null) {
-            log.debug("BeanAdapter getChildNodes for: {}", getTagName());
-            log.debug(nl.toString());
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("BeanAdapter getChildNodes for: {}", getTagName());
+            LOG.debug(nl.toString());
         }
         return nl;
     }
 
     protected List<Node> buildChildAdapters() {
-        log.debug("BeanAdapter building children. Property name: {}", getPropertyName());
+        LOG.debug("BeanAdapter building children. Property name: {}", getPropertyName());
         List<Node> newAdapters = new ArrayList<>();
-        Class type = getPropertyValue().getClass();
+        Class<?> type = getPropertyValue().getClass();
         PropertyDescriptor[] props = getPropertyDescriptors(getPropertyValue());
 
         if (props.length > 0) {
@@ -103,7 +95,7 @@ public class BeanAdapter extends AbstractAdapterElement {
                     //FIXME: write only property or indexed access
                     continue;
                 }
-                log.debug("Bean reading property method: {}", m.getName());
+                LOG.debug("Bean reading property method: {}", m.getName());
 
                 String propertyName = prop.getName();
                 Object propertyValue;
@@ -114,12 +106,13 @@ public class BeanAdapter extends AbstractAdapterElement {
                     Perhaps with annotations in Java5?
                 */
                 try {
-                    propertyValue = m.invoke(getPropertyValue(), NULLPARAMS);
+                    propertyValue = m.invoke(getPropertyValue(), NULL_PARAMS);
                 } catch (Exception e) {
+                    Exception report = e;
                     if (e instanceof InvocationTargetException) {
-                        e = (Exception) ((InvocationTargetException) e).getTargetException();
+                        report = (Exception) ((InvocationTargetException) e).getTargetException();
                     }
-                    log.error("Cannot access bean property: {}", propertyName, e);
+                    LOG.error("Cannot access bean property: {}", propertyName, report);
                     continue;
                 }
 
@@ -134,11 +127,11 @@ public class BeanAdapter extends AbstractAdapterElement {
                 if (childAdapter != null)
                     newAdapters.add(childAdapter);
 
-                log.debug("{} adding adapter: {}", this, childAdapter);
+                LOG.debug("{} adding adapter: {}", this, childAdapter);
             }
         } else {
             // No properties found
-            log.info("Class {} has no readable properties, trying to adapt {} with StringAdapter...", type.getName(), getPropertyName());
+            LOG.info("Class {} has no readable properties, trying to adapt {} with StringAdapter...", type.getName(), getPropertyName());
         }
 
         return newAdapters;
@@ -150,13 +143,13 @@ public class BeanAdapter extends AbstractAdapterElement {
     private synchronized PropertyDescriptor[] getPropertyDescriptors(Object bean) {
         try {
             if (propertyDescriptorCache == null) {
-                propertyDescriptorCache = new HashMap<Class, PropertyDescriptor[]>();
+                propertyDescriptorCache = new HashMap<>();
             }
 
             PropertyDescriptor[] props = propertyDescriptorCache.get(bean.getClass());
 
             if (props == null) {
-                log.debug("Caching property descriptor for {}", bean.getClass().getName());
+                LOG.debug("Caching property descriptor for {}", bean.getClass().getName());
                 props = Introspector.getBeanInfo(bean.getClass(), Object.class).getPropertyDescriptors();
                 propertyDescriptorCache.put(bean.getClass(), props);
             }
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/CollectionAdapter.java b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/CollectionAdapter.java
similarity index 85%
rename from core/src/main/java/org/apache/struts2/views/xslt/CollectionAdapter.java
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/CollectionAdapter.java
index b53118f71..daeb12ebe 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/CollectionAdapter.java
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/CollectionAdapter.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
+package org.apache.struts2.result.xslt;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -28,7 +28,7 @@ import java.util.List;
 
 public class CollectionAdapter extends AbstractAdapterElement {
 
-    private Logger log = LogManager.getLogger(this.getClass());
+    private static final Logger LOG = LogManager.getLogger(CollectionAdapter.class);
 
     public CollectionAdapter() { }
 
@@ -37,7 +37,7 @@ public class CollectionAdapter extends AbstractAdapterElement {
     }
 
     protected List<Node> buildChildAdapters() {
-        Collection values = (Collection) getPropertyValue();
+        Collection<?> values = (Collection<?>) getPropertyValue();
         List<Node> children = new ArrayList<>(values.size());
 
         for (Object value : values) {
@@ -47,10 +47,12 @@ public class CollectionAdapter extends AbstractAdapterElement {
             } else {
                 childAdapter = getAdapterFactory().adaptNode(this, "item", value);
             }
-            if (childAdapter != null)
+
+            if (childAdapter != null) {
                 children.add(childAdapter);
+            }
 
-            log.debug("{} adding adapter: {}", this, childAdapter);
+            LOG.debug("{} adding adapter: {}", this, childAdapter);
         }
 
         return children;
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/MapAdapter.java b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/MapAdapter.java
similarity index 73%
rename from core/src/main/java/org/apache/struts2/views/xslt/MapAdapter.java
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/MapAdapter.java
index 9595f6568..82be5a446 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/MapAdapter.java
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/MapAdapter.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
+package org.apache.struts2.result.xslt;
 
 import org.w3c.dom.Node;
 
@@ -39,21 +39,21 @@ import java.util.Map;
  */
 public class MapAdapter extends AbstractAdapterElement {
 
-    public MapAdapter() { }
+    public MapAdapter() {
+    }
 
-    public MapAdapter(AdapterFactory adapterFactory, AdapterNode parent, String propertyName, Map value) {
-        setContext( adapterFactory, parent, propertyName, value );
+    public MapAdapter(AdapterFactory adapterFactory, AdapterNode parent, String propertyName, Map<?, ?> value) {
+        setContext(adapterFactory, parent, propertyName, value);
     }
 
-    public Map map() {
-        return (Map)getPropertyValue();
+    public Map<?, ?> map() {
+        return (Map<?, ?>) getPropertyValue();
     }
 
     protected List<Node> buildChildAdapters() {
         List<Node> children = new ArrayList<>(map().entrySet().size());
 
-        for (Object o : map().entrySet()) {
-            Map.Entry entry = (Map.Entry) o;
+        for (Map.Entry<?, ?> entry : map().entrySet()) {
             Object key = entry.getKey();
             Object value = entry.getValue();
             EntryElement child = new EntryElement(getAdapterFactory(), this, "entry", key, value);
@@ -66,17 +66,16 @@ public class MapAdapter extends AbstractAdapterElement {
     static class EntryElement extends AbstractAdapterElement {
         Object key, value;
 
-        public EntryElement(  AdapterFactory adapterFactory,
-                              AdapterNode parent, String propertyName, Object key, Object value ) {
-            setContext( adapterFactory, parent, propertyName, null/*we have two values*/ );
+        public EntryElement(AdapterFactory adapterFactory, AdapterNode parent, String propertyName, Object key, Object value) {
+            setContext(adapterFactory, parent, propertyName, null/*we have two values*/);
             this.key = key;
             this.value = value;
         }
 
         protected List<Node> buildChildAdapters() {
             List<Node> children = new ArrayList<>();
-            children.add( getAdapterFactory().adaptNode( this, "key", key ) );
-            children.add( getAdapterFactory().adaptNode( this, "value", value ) );
+            children.add(getAdapterFactory().adaptNode(this, "key", key));
+            children.add(getAdapterFactory().adaptNode(this, "value", value));
             return children;
         }
     }
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/ProxyAttrAdapter.java b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ProxyAttrAdapter.java
similarity index 93%
rename from core/src/main/java/org/apache/struts2/views/xslt/ProxyAttrAdapter.java
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ProxyAttrAdapter.java
index 53ecf049e..84885453a 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/ProxyAttrAdapter.java
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ProxyAttrAdapter.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
+package org.apache.struts2.result.xslt;
 
 import org.w3c.dom.Attr;
 import org.w3c.dom.DOMException;
@@ -35,13 +35,10 @@ public class ProxyAttrAdapter extends ProxyNodeAdapter implements Attr {
         super(factory, parent, value);
     }
 
-    // convenience
     protected Attr attr() {
         return (Attr) getPropertyValue();
     }
 
-    // Proxied Attr methods
-
     public String getName() {
         return attr().getName();
     }
@@ -62,8 +59,6 @@ public class ProxyAttrAdapter extends ProxyNodeAdapter implements Attr {
         return (Element) getParent();
     }
 
-    // DOM level 3
-
     public TypeInfo getSchemaTypeInfo() {
         throw operationNotSupported();
     }
@@ -72,12 +67,9 @@ public class ProxyAttrAdapter extends ProxyNodeAdapter implements Attr {
         throw operationNotSupported();
     }
 
-    // end DOM level 3
-
-    // End Proxied Attr methods
-
     public String toString() {
         return "ProxyAttribute for: " + attr();
     }
+
 }
 
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/ProxyElementAdapter.java b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ProxyElementAdapter.java
similarity index 92%
rename from core/src/main/java/org/apache/struts2/views/xslt/ProxyElementAdapter.java
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ProxyElementAdapter.java
index 8fbc6d45e..ada1b6760 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/ProxyElementAdapter.java
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ProxyElementAdapter.java
@@ -16,11 +16,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
+package org.apache.struts2.result.xslt;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
-import org.w3c.dom.*;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.TypeInfo;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -40,7 +45,7 @@ import java.util.List;
  */
 public class ProxyElementAdapter extends ProxyNodeAdapter implements Element {
 
-    private Logger log = LogManager.getLogger(this.getClass());
+    private static final Logger LOG = LogManager.getLogger(ProxyElementAdapter.class);
 
     public ProxyElementAdapter(AdapterFactory factory, AdapterNode parent, Element value) {
         super(factory, parent, value);
@@ -60,7 +65,7 @@ public class ProxyElementAdapter extends ProxyNodeAdapter implements Element {
             Node child = children.item(i);
             Node adapter = wrap(child);
             if (adapter != null) {
-                log.debug("Wrapped child node: {}", child.getNodeName());
+                LOG.debug("Wrapped child node: {}", child.getNodeName());
                 adapters.add(adapter);
             }
         }
@@ -86,11 +91,10 @@ public class ProxyElementAdapter extends ProxyNodeAdapter implements Element {
     }
 
     public Attr getAttributeNode(String name) {
-        log.debug("Wrapping attribute: {}", name);
+        LOG.debug("Wrapping attribute: {}", name);
         return (Attr) wrap(element().getAttributeNode(name));
     }
 
-    // I'm overriding this just for clarity.  The base impl is correct.
     public NodeList getElementsByTagName(String name) {
         return super.getElementsByTagName(name);
     }
@@ -108,7 +112,6 @@ public class ProxyElementAdapter extends ProxyNodeAdapter implements Element {
     }
 
     // Unsupported mutators of Element
-
     public void removeAttribute(String name) throws DOMException {
         throw new UnsupportedOperationException();
     }
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/ProxyNamedNodeMap.java b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ProxyNamedNodeMap.java
similarity index 93%
rename from core/src/main/java/org/apache/struts2/views/xslt/ProxyNamedNodeMap.java
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ProxyNamedNodeMap.java
index f0a218195..b707c0da8 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/ProxyNamedNodeMap.java
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ProxyNamedNodeMap.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
+package org.apache.struts2.result.xslt;
 
 import org.w3c.dom.DOMException;
 import org.w3c.dom.NamedNodeMap;
@@ -24,16 +24,16 @@ import org.w3c.dom.Node;
 
 /**
  * A NamedNodeMap that wraps the Nodes returned in their proxies.
- *
+ * <p>
  * Note: Since maps have no guaranteed order we don't need to worry about identity
  * here as we do with "child" adapters.  In that case we need to preserve identity
  * in order to support finding the next/previous siblings.
  */
 public class ProxyNamedNodeMap implements NamedNodeMap {
 
-    private NamedNodeMap nodes;
-    private AdapterFactory adapterFactory;
-    private AdapterNode parent;
+    private final NamedNodeMap nodes;
+    private final AdapterFactory adapterFactory;
+    private final AdapterNode parent;
 
     public ProxyNamedNodeMap(AdapterFactory factory, AdapterNode parent, NamedNodeMap nodes) {
         this.nodes = nodes;
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/ProxyNodeAdapter.java b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ProxyNodeAdapter.java
similarity index 77%
rename from core/src/main/java/org/apache/struts2/views/xslt/ProxyNodeAdapter.java
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ProxyNodeAdapter.java
index 52f76d33d..2e046b011 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/ProxyNodeAdapter.java
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ProxyNodeAdapter.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
+package org.apache.struts2.result.xslt;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -32,14 +32,14 @@ import org.w3c.dom.Node;
  */
 public abstract class ProxyNodeAdapter extends AbstractAdapterNode {
 
-    private Logger log = LogManager.getLogger(this.getClass());
+    private static final Logger LOG = LogManager.getLogger(ProxyNodeAdapter.class);
 
     public ProxyNodeAdapter(AdapterFactory factory, AdapterNode parent, Node value) {
-        setContext(factory, parent, "document"/*propname unused*/, value);
-        log.debug("Proxied node is: {}" + value);
-        log.debug("Node class is: {}", value.getClass());
-        log.debug("Node type is: {}", value.getNodeType());
-        log.debug("Node name is: {}", value.getNodeName());
+        setContext(factory, parent, "document", value);
+        LOG.debug("Proxied node is: {}", value);
+        LOG.debug("Node class is: {}", value.getClass());
+        LOG.debug("Node type is: {}", value.getNodeType());
+        LOG.debug("Node name is: {}", value.getNodeName());
     }
 
     /**
@@ -69,58 +69,57 @@ public abstract class ProxyNodeAdapter extends AbstractAdapterNode {
     // Proxied Node methods
 
     public String getNodeName() {
-        log.trace("getNodeName");
+        LOG.trace("getNodeName");
         return node().getNodeName();
     }
 
     public String getNodeValue() throws DOMException {
-        log.trace("getNodeValue");
+        LOG.trace("getNodeValue");
         return node().getNodeValue();
     }
 
     public short getNodeType() {
-        if (log.isTraceEnabled()) {
-            log.trace("getNodeType: " + getNodeName() + ": " + node().getNodeType());
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("getNodeType: " + getNodeName() + ": " + node().getNodeType());
         }
         return node().getNodeType();
     }
 
     public NamedNodeMap getAttributes() {
         NamedNodeMap nnm = wrap(node().getAttributes());
-        if (log.isTraceEnabled()) {
-            log.trace("getAttributes: " + nnm);
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("getAttributes: " + nnm);
         }
         return nnm;
     }
 
     public boolean hasChildNodes() {
-        log.trace("hasChildNodes");
+        LOG.trace("hasChildNodes");
         return node().hasChildNodes();
     }
 
     public boolean isSupported(String s, String s1) {
-        log.trace("isSupported");
-        // Is this ok?  What kind of features are they asking about?
+        LOG.trace("isSupported");
         return node().isSupported(s, s1);
     }
 
     public String getNamespaceURI() {
-        log.trace("getNamespaceURI");
+        LOG.trace("getNamespaceURI");
         return node().getNamespaceURI();
     }
 
     public String getPrefix() {
-        log.trace("getPrefix");
+        LOG.trace("getPrefix");
         return node().getPrefix();
     }
 
     public String getLocalName() {
-        log.trace("getLocalName");
+        LOG.trace("getLocalName");
         return node().getLocalName();
     }
 
     public boolean hasAttributes() {
-        log.trace("hasAttributes");
+        LOG.trace("hasAttributes");
         return node().hasAttributes();
     }
 
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/ProxyTextNodeAdapter.java b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ProxyTextNodeAdapter.java
similarity index 98%
rename from core/src/main/java/org/apache/struts2/views/xslt/ProxyTextNodeAdapter.java
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ProxyTextNodeAdapter.java
index 1f5b45b22..9530de111 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/ProxyTextNodeAdapter.java
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ProxyTextNodeAdapter.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
+package org.apache.struts2.result.xslt;
 
 import org.w3c.dom.DOMException;
 import org.w3c.dom.Text;
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/ServletURIResolver.java b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ServletURIResolver.java
similarity index 71%
rename from core/src/main/java/org/apache/struts2/views/xslt/ServletURIResolver.java
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ServletURIResolver.java
index 23a1c86a8..4aae103c1 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/ServletURIResolver.java
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/ServletURIResolver.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
+package org.apache.struts2.result.xslt;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -31,39 +31,40 @@ import java.io.InputStream;
 /**
  * ServletURIResolver is a URIResolver that can retrieve resources from the servlet context using the scheme "response".
  * e.g.
- *
+ * <p>
  * A URI resolver is called when a stylesheet uses an xsl:include, xsl:import, or document() function to find the
  * resource (file).
  */
 public class ServletURIResolver implements URIResolver {
 
-    private Logger log = LogManager.getLogger(getClass());
-    static final String PROTOCOL = "response:";
+    private static final Logger LOG = LogManager.getLogger(ServletURIResolver.class);
+
+    private static final String PROTOCOL = "response:";
 
-    private ServletContext sc;
+    private final ServletContext servletContext;
 
-    public ServletURIResolver(ServletContext sc) {
-        log.trace("ServletURIResolver: {}", sc);
-        this.sc = sc;
+    public ServletURIResolver(ServletContext servletContext) {
+        LOG.trace("ServletURIResolver: {}", servletContext);
+        this.servletContext = servletContext;
     }
 
     public Source resolve(String href, String base) throws TransformerException {
-        log.debug("ServletURIResolver resolve(): href={}, base={}", href, base);
+        LOG.debug("ServletURIResolver resolve(): href={}, base={}", href, base);
         if (href.startsWith(PROTOCOL)) {
             String res = href.substring(PROTOCOL.length());
-            log.debug("Resolving resource <{}>", res);
+            LOG.debug("Resolving resource <{}>", res);
 
-            InputStream is = sc.getResourceAsStream(res);
+            InputStream is = servletContext.getResourceAsStream(res);
 
             if (is == null) {
                 throw new TransformerException(
-                        "Resource " + res + " not found in resources.");
+                    "Resource " + res + " not found in resources.");
             }
 
             return new StreamSource(is);
         }
 
         throw new TransformerException(
-                "Cannot handle protocol of resource " + href);
+            "Cannot handle protocol of resource " + href);
     }
 }
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/SimpleAdapterDocument.java b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/SimpleAdapterDocument.java
similarity index 92%
rename from core/src/main/java/org/apache/struts2/views/xslt/SimpleAdapterDocument.java
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/SimpleAdapterDocument.java
index 23c315070..b3359af67 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/SimpleAdapterDocument.java
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/SimpleAdapterDocument.java
@@ -16,10 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
-
-import java.util.Arrays;
-import java.util.List;
+package org.apache.struts2.result.xslt;
 
 import org.apache.struts2.StrutsException;
 import org.w3c.dom.Attr;
@@ -38,12 +35,15 @@ import org.w3c.dom.NodeList;
 import org.w3c.dom.ProcessingInstruction;
 import org.w3c.dom.Text;
 
+import java.util.Arrays;
+import java.util.List;
+
 /**
  * SimpleAdapterDocument adapted a Java object and presents it as
  * a Document.  This class represents the Document container and uses
  * the AdapterFactory to produce a child adapter for the wrapped object.
  * The adapter produced must be of an Element type or an exception is thrown.
- *
+ * <p>
  * Note: in theory we could base this on AbstractAdapterElement and then allow
  * the wrapped object to be a more general Node type.  We would just use
  * ourselves as the root element.  However I don't think this is an issue as
@@ -53,10 +53,8 @@ public class SimpleAdapterDocument extends AbstractAdapterNode implements Docume
 
     private Element rootElement;
 
-    public SimpleAdapterDocument(
-            AdapterFactory adapterFactory, AdapterNode parent, String propertyName, Object value) {
+    public SimpleAdapterDocument(AdapterFactory adapterFactory, AdapterNode parent, String propertyName, Object value) {
         setContext(adapterFactory, parent, propertyName, value);
-
     }
 
     public void setPropertyValue(Object prop) {
@@ -68,17 +66,16 @@ public class SimpleAdapterDocument extends AbstractAdapterNode implements Docume
      * Lazily construct the root element adapter from the value object.
      */
     private Element getRootElement() {
-        if (rootElement != null)
+        if (rootElement != null) {
             return rootElement;
+        }
 
-        Node node = getAdapterFactory().adaptNode(
-                this, getPropertyName(), getPropertyValue());
-        if (node instanceof Element)
+        Node node = getAdapterFactory().adaptNode(this, getPropertyName(), getPropertyValue());
+        if (node instanceof Element) {
             rootElement = (Element) node;
-        else
-            throw new StrutsException(
-                    "Document adapter expected to wrap an Element type.  Node is not an element:" + node);
-
+        } else {
+            throw new StrutsException("Document adapter expected to wrap an Element type.  Node is not an element: " + node);
+        }
         return rootElement;
     }
 
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/SimpleNodeList.java b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/SimpleNodeList.java
similarity index 80%
rename from core/src/main/java/org/apache/struts2/views/xslt/SimpleNodeList.java
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/SimpleNodeList.java
index 7affaa919..c15d86326 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/SimpleNodeList.java
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/SimpleNodeList.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
+package org.apache.struts2.result.xslt;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -26,30 +26,32 @@ import org.w3c.dom.NodeList;
 import java.util.List;
 
 public class SimpleNodeList implements NodeList {
-    private Logger log = LogManager.getLogger(SimpleNodeList.class);
 
-    private List<Node> nodes;
+    private static final Logger LOG = LogManager.getLogger(SimpleNodeList.class);
+
+    private final List<Node> nodes;
 
     public SimpleNodeList(List<Node> nodes) {
         this.nodes = nodes;
     }
 
     public int getLength() {
-        if (log.isTraceEnabled()) {
-            log.trace("getLength: {}", nodes.size());
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("getLength: {}", nodes.size());
         }
         return nodes.size();
     }
 
     public Node item(int i) {
-        log.trace("getItem: {}", i);
+        LOG.trace("getItem: {}", i);
         return nodes.get(i);
     }
 
     public String toString() {
         StringBuilder sb = new StringBuilder("SimpleNodeList: [");
-        for (int i = 0; i < getLength(); i++)
+        for (int i = 0; i < getLength(); i++) {
             sb.append(item(i).getNodeName()).append(',');
+        }
         sb.append("]");
         return sb.toString();
     }
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/SimpleTextNode.java b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/SimpleTextNode.java
similarity index 98%
rename from core/src/main/java/org/apache/struts2/views/xslt/SimpleTextNode.java
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/SimpleTextNode.java
index b09b58f99..84ec3a3da 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/SimpleTextNode.java
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/SimpleTextNode.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
+package org.apache.struts2.result.xslt;
 
 import org.apache.struts2.StrutsException;
 import org.w3c.dom.DOMException;
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/StringAdapter.java b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/StringAdapter.java
similarity index 94%
rename from core/src/main/java/org/apache/struts2/views/xslt/StringAdapter.java
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/StringAdapter.java
index 3948d2e49..457ff0c5f 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/StringAdapter.java
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/StringAdapter.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
+package org.apache.struts2.result.xslt;
 
 import com.opensymphony.xwork2.util.DomHelper;
 import org.apache.logging.log4j.LogManager;
@@ -46,7 +46,8 @@ import java.util.List;
  */
 public class StringAdapter extends AbstractAdapterElement {
 
-    private Logger log = LogManager.getLogger(this.getClass());
+    private static final Logger LOG = LogManager.getLogger(StringAdapter.class);
+
     boolean parseStringAsXML;
 
     public StringAdapter() {
@@ -78,12 +79,12 @@ public class StringAdapter extends AbstractAdapterElement {
     protected List<Node> buildChildAdapters() {
         Node node;
         if (getParseStringAsXML()) {
-            log.debug("parsing string as xml: {}", getStringValue());
+            LOG.debug("parsing string as xml: {}", getStringValue());
             // Parse the String to a DOM, then proxy that as our child
             node = DomHelper.parse(new InputSource(new StringReader(getStringValue())));
             node = getAdapterFactory().proxyNode(this, node);
         } else {
-            log.debug("using string as is: {}", getStringValue());
+            LOG.debug("using string as is: {}", getStringValue());
             // Create a Text node as our child
             node = new SimpleTextNode(getAdapterFactory(), this, "text", getStringValue());
         }
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/XSLTResult.java
similarity index 98%
rename from core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/XSLTResult.java
index 1361c628a..6bc7541b1 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/XSLTResult.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
+package org.apache.struts2.result.xslt;
 
 import com.opensymphony.xwork2.ActionInvocation;
 import com.opensymphony.xwork2.Result;
@@ -62,7 +62,7 @@ public class XSLTResult implements Result {
     private static final Logger LOG = LogManager.getLogger(XSLTResult.class);
 
     /**
-     * 'stylesheetLocation' parameter.  Points to the xsl.
+     * 'stylesheetLocation' parameter. Points to the xsl.
      */
     public static final String DEFAULT_PARAM = "stylesheetLocation";
 
@@ -120,7 +120,7 @@ public class XSLTResult implements Result {
         setStylesheetLocation(stylesheetLocation);
     }
 
-    @Inject(StrutsConstants.STRUTS_XSLT_NOCACHE)
+    @Inject(XsltConstants.STRUTS_XSLT_NOCACHE)
     public void setNoCache(String xsltNoCache) {
         this.noCache = BooleanUtils.toBoolean(xsltNoCache);
     }
diff --git a/core/src/test/resources/XSLTResultTest.xsl b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/XsltConstants.java
similarity index 73%
copy from core/src/test/resources/XSLTResultTest.xsl
copy to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/XsltConstants.java
index 0d97e1525..a1749a579 100644
--- a/core/src/test/resources/XSLTResultTest.xsl
+++ b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/XsltConstants.java
@@ -1,7 +1,4 @@
-<!--
 /*
- * $Id$
- *
  * 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
@@ -19,13 +16,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
--->
-<xsl:stylesheet version="1.0"
-                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
-                xmlns="http://www.w3.org/TR/xhtml1/strict">
+package org.apache.struts2.result.xslt;
+
+public final class XsltConstants {
+
+    /**
+     * Avoids creating instance
+     */
+    private XsltConstants() {}
 
-    <xsl:template match="/">
-        <result/>
-    </xsl:template>
+    /** Whether XSLT templates should not be cached */
+    public static final String STRUTS_XSLT_NOCACHE = "struts.xslt.nocache";
 
-</xsl:stylesheet>
\ No newline at end of file
+}
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/package.html b/plugins/xslt/src/main/java/org/apache/struts2/result/xslt/package.html
similarity index 100%
rename from core/src/main/java/org/apache/struts2/views/xslt/package.html
rename to plugins/xslt/src/main/java/org/apache/struts2/result/xslt/package.html
diff --git a/core/src/test/resources/XSLTResultTest.xsl b/plugins/xslt/src/main/resources/struts-plugin.xml
similarity index 65%
copy from core/src/test/resources/XSLTResultTest.xsl
copy to plugins/xslt/src/main/resources/struts-plugin.xml
index 0d97e1525..9bda180f4 100644
--- a/core/src/test/resources/XSLTResultTest.xsl
+++ b/plugins/xslt/src/main/resources/struts-plugin.xml
@@ -1,7 +1,6 @@
+<?xml version="1.0" encoding="UTF-8" ?>
 <!--
 /*
- * $Id$
- *
  * 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
@@ -20,12 +19,16 @@
  * under the License.
  */
 -->
-<xsl:stylesheet version="1.0"
-                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
-                xmlns="http://www.w3.org/TR/xhtml1/strict">
+<!DOCTYPE struts PUBLIC
+        "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN"
+        "https://struts.apache.org/dtds/struts-6.0.dtd">
+
+<struts>
 
-    <xsl:template match="/">
-        <result/>
-    </xsl:template>
+    <package name="xslt-default" extends="struts-default">
+        <result-types>
+            <result-type name="xslt" class="org.apache.struts2.result.xslt.XSLTResult"/>
+        </result-types>
+    </package>
 
-</xsl:stylesheet>
\ No newline at end of file
+</struts>
diff --git a/core/src/test/java/org/apache/struts2/views/xslt/XSLTResultTest.java b/plugins/xslt/src/test/java/org/apache/struts2/result/xslt/XSLTResultTest.java
similarity index 68%
rename from core/src/test/java/org/apache/struts2/views/xslt/XSLTResultTest.java
rename to plugins/xslt/src/test/java/org/apache/struts2/result/xslt/XSLTResultTest.java
index ecc2b8469..861b02551 100644
--- a/core/src/test/java/org/apache/struts2/views/xslt/XSLTResultTest.java
+++ b/plugins/xslt/src/test/java/org/apache/struts2/result/xslt/XSLTResultTest.java
@@ -16,17 +16,17 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.struts2.views.xslt;
+package org.apache.struts2.result.xslt;
 
 import com.opensymphony.xwork2.Action;
-import com.opensymphony.xwork2.ActionChainResult;
 import com.opensymphony.xwork2.ActionContext;
 import com.opensymphony.xwork2.Result;
 import com.opensymphony.xwork2.mock.MockActionInvocation;
 import com.opensymphony.xwork2.util.ClassLoaderUtil;
 import com.opensymphony.xwork2.util.ValueStack;
+import junit.framework.TestCase;
 import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.StrutsInternalTestCase;
+import org.apache.struts2.junit.StrutsTestCase;
 import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.mock.web.MockHttpServletResponse;
 import org.springframework.mock.web.MockServletContext;
@@ -43,7 +43,7 @@ import java.util.List;
  * Unit test for {@link XSLTResult}.
  *
  */
-public class XSLTResultTest extends StrutsInternalTestCase {
+public class XSLTResultTest extends StrutsTestCase {
 
     private XSLTResult result;
     private MockHttpServletResponse response;
@@ -57,7 +57,7 @@ public class XSLTResultTest extends StrutsInternalTestCase {
             result.setParse(false);
             result.setStylesheetLocation(null);
             result.execute(mai);
-            fail("Should have thrown an IllegalArgumentException");
+            TestCase.fail("Should have thrown an IllegalArgumentException");
         } catch (IllegalArgumentException e) {
             // success
         }
@@ -68,7 +68,7 @@ public class XSLTResultTest extends StrutsInternalTestCase {
             result.setParse(false);
             result.setStylesheetLocation("nofile.xsl");
             result.execute(mai);
-            fail("Should have thrown a TransformerException");
+            TestCase.fail("Should have thrown a TransformerException");
         } catch (TransformerException e) {
             // success
         }
@@ -80,8 +80,8 @@ public class XSLTResultTest extends StrutsInternalTestCase {
         result.execute(mai);
 
         String out = response.getContentAsString();
-        assertTrue(out.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
-        assertTrue(out.indexOf("<result xmlns=\"http://www.w3.org/TR/xhtml1/strict\"") > -1);
+        TestCase.assertTrue(out.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
+        TestCase.assertTrue(out.contains("<result xmlns=\"http://www.w3.org/TR/xhtml1/strict\""));
     }
 
     public void testSimpleTransform5() throws Exception {
@@ -90,14 +90,14 @@ public class XSLTResultTest extends StrutsInternalTestCase {
         result.execute(mai);
 
         String out = response.getContentAsString();
-        assertTrue(out.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
-        assertTrue(out.contains("<title>WebWork in Action</title>"));
-        assertTrue(out.contains("<author>Patrick and Jason</author>"));
-        assertTrue(out.contains("<editions><edition value=\"I\">I</edition><edition value=\"IV\">IV</edition></editions>"));
-        assertTrue(out.contains("<book><title/><author/><editions/></book>"));
-        assertTrue(out.contains("<title>XWork not in Action</title>"));
-        assertTrue(out.contains("<author>Superman</author>"));
-        assertTrue(out.contains("<editions><edition value=\"1234\">1234</edition><edition value=\"345\">345</edition><edition value=\"6667\">6667</edition></editions>"));
+        TestCase.assertTrue(out.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
+        TestCase.assertTrue(out.contains("<title>WebWork in Action</title>"));
+        TestCase.assertTrue(out.contains("<author>Patrick and Jason</author>"));
+        TestCase.assertTrue(out.contains("<editions><edition value=\"I\">I</edition><edition value=\"IV\">IV</edition></editions>"));
+        TestCase.assertTrue(out.contains("<book><title/><author/><editions/></book>"));
+        TestCase.assertTrue(out.contains("<title>XWork not in Action</title>"));
+        TestCase.assertTrue(out.contains("<author>Superman</author>"));
+        TestCase.assertTrue(out.contains("<editions><edition value=\"1234\">1234</edition><edition value=\"345\">345</edition><edition value=\"6667\">6667</edition></editions>"));
     }
 
     public void testSimpleTransformParse() throws Exception {
@@ -106,8 +106,8 @@ public class XSLTResultTest extends StrutsInternalTestCase {
         result.execute(mai);
 
         String out = response.getContentAsString();
-        assertTrue(out.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
-        assertTrue(out.indexOf("<result xmlns=\"http://www.w3.org/TR/xhtml1/strict\"") > -1);
+        TestCase.assertTrue(out.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
+        TestCase.assertTrue(out.contains("<result xmlns=\"http://www.w3.org/TR/xhtml1/strict\""));
     }
 
     public void testTransform2() throws Exception {
@@ -116,36 +116,36 @@ public class XSLTResultTest extends StrutsInternalTestCase {
         result.execute(mai);
 
         String out = response.getContentAsString();
-        assertTrue(out.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
-        assertTrue(out.indexOf("<html xmlns=\"http://www.w3.org/TR/xhtml1/strict\"") > -1);
-        assertTrue(out.indexOf("Hello Santa Claus how are you?") > -1);
+        TestCase.assertTrue(out.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
+        TestCase.assertTrue(out.contains("<html xmlns=\"http://www.w3.org/TR/xhtml1/strict\""));
+        TestCase.assertTrue(out.contains("Hello Santa Claus how are you?"));
     }
-    
+
     public void testTransform3() throws Exception {
         result.setParse(false);
         result.setStylesheetLocation("XSLTResultTest3.xsl");
         result.execute(mai);
 
         String out = response.getContentAsString();
-        assertTrue(out.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
-        assertTrue(out.indexOf("<html xmlns=\"http://www.w3.org/TR/xhtml1/strict\"") > -1);
-        assertTrue(out.indexOf("Hello Santa Claus how are you?") > -1);
-        assertTrue(out.indexOf("WebWork in Action by Patrick and Jason") > -1);
-        assertTrue(out.indexOf("XWork not in Action by Superman") > -1);
+        TestCase.assertTrue(out.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
+        TestCase.assertTrue(out.contains("<html xmlns=\"http://www.w3.org/TR/xhtml1/strict\""));
+        TestCase.assertTrue(out.contains("Hello Santa Claus how are you?"));
+        TestCase.assertTrue(out.contains("WebWork in Action by Patrick and Jason"));
+        TestCase.assertTrue(out.contains("XWork not in Action by Superman"));
     }
-    
+
     public void testTransformWithBoolean() throws Exception {
         result.setParse(false);
         result.setStylesheetLocation("XSLTResultTest5.xsl");
         result.execute(mai);
 
         String out = response.getContentAsString();
-        assertTrue(out.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
-        assertTrue(out.indexOf("<html xmlns=\"http://www.w3.org/TR/xhtml1/strict\"") > -1);
-        assertTrue(out.indexOf("Hello Santa Claus how are you?") > -1);
-        assertTrue(out.indexOf("You are active: true") > -1);
+        TestCase.assertTrue(out.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
+        TestCase.assertTrue(out.contains("<html xmlns=\"http://www.w3.org/TR/xhtml1/strict\""));
+        TestCase.assertTrue(out.contains("Hello Santa Claus how are you?"));
+        TestCase.assertTrue(out.contains("You are active: true"));
     }
-    
+
     public void testTransform4WithDocumentInclude() throws Exception {
         result = new XSLTResult(){
             protected URIResolver getURIResolver() {
@@ -153,21 +153,21 @@ public class XSLTResultTest extends StrutsInternalTestCase {
                     public Source resolve(String href, String base) throws TransformerException {
                         return new StreamSource(ClassLoaderUtil.getResourceAsStream(href, this.getClass()));
                     }
-                    
+
                 };
             }
-            
+
         };
         result.setParse(false);
         result.setStylesheetLocation("XSLTResultTest4.xsl");
         result.execute(mai);
 
         String out = response.getContentAsString();
-        assertTrue(out.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
-        assertTrue(out.indexOf("<validators>") > -1);
+        TestCase.assertTrue(out.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
+        TestCase.assertTrue(out.contains("<validators>"));
     }
 
-    public void testTransform4WithBadDocumentInclude() throws Exception {
+    public void testTransform4WithBadDocumentInclude() {
         result = new XSLTResult(){
             protected URIResolver getURIResolver() {
                 return new URIResolver() {
@@ -183,28 +183,26 @@ public class XSLTResultTest extends StrutsInternalTestCase {
         result.setStylesheetLocation("XSLTResultTest4.badinclude.xsl");
         try {
             result.execute(mai);
-            fail("Should have thrown an exception");
+            TestCase.fail("Should have thrown an exception");
         } catch (Exception ex) {
-            assertEquals("Error transforming result", ex.getMessage());
+            TestCase.assertEquals("Error transforming result", ex.getMessage());
         }
     }
-    
-    public void testTransformWithError() throws Exception {
+
+    public void testTransformWithError() {
         result = new XSLTResult(){
             protected URIResolver getURIResolver() {
-                return new URIResolver() {
-                    public Source resolve(String href, String base) throws TransformerException {
-                        throw new TransformerException("Some random error");
-                    }
+                return (href, base) -> {
+                    throw new TransformerException("Some random error");
                 };
             }
         };
         result.setStylesheetLocation("XSLTResultTest4.xsl");
         try {
             result.execute(mai);
-            fail("Should have thrown an exception");
+            TestCase.fail("Should have thrown an exception");
         } catch (Exception ex) {
-            assertEquals("Error transforming result", ex.getMessage());
+            TestCase.assertEquals("Error transforming result", ex.getMessage());
         }
     }
 
@@ -213,9 +211,9 @@ public class XSLTResultTest extends StrutsInternalTestCase {
         result.setStylesheetLocation("XSLTResultTest.bad.character.xsl");
         try {
             result.execute(mai);
-            fail("Should have thrown an exception");
+            TestCase.fail("Should have thrown an exception");
         } catch (Exception ex) {
-            assertEquals("Error transforming result", ex.getMessage());
+            TestCase.assertEquals("Error transforming result", ex.getMessage());
         }
     }
 
@@ -227,9 +225,9 @@ public class XSLTResultTest extends StrutsInternalTestCase {
 
         String out = response.getContentAsString();
 
-        assertEquals(302, response.getStatus());
-        assertTrue(out.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
-        assertTrue(out.indexOf("<result xmlns=\"http://www.w3.org/TR/xhtml1/strict\"") > -1);
+        TestCase.assertEquals(302, response.getStatus());
+        TestCase.assertTrue(out.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
+        TestCase.assertTrue(out.contains("<result xmlns=\"http://www.w3.org/TR/xhtml1/strict\""));
     }
 
     public void testEncoding() throws Exception {
@@ -240,16 +238,16 @@ public class XSLTResultTest extends StrutsInternalTestCase {
 
         String actual = response.getCharacterEncoding();
 
-        assertEquals(actual, "ISO-8859-1");
+        TestCase.assertEquals(actual, "ISO-8859-1");
     }
 
     public void testPassingNullInvocation() throws Exception{
         Result result = new XSLTResult();
         try {
             result.execute(null);
-            fail("Exception should be thrown!");
+            TestCase.fail("Exception should be thrown!");
         } catch (IllegalArgumentException e) {
-            assertEquals("Invocation cannot be null!", e.getMessage());
+            TestCase.assertEquals("Invocation cannot be null!", e.getMessage());
         }
     }
 
@@ -298,13 +296,13 @@ public class XSLTResultTest extends StrutsInternalTestCase {
         public String getUsername() {
             return "Santa Claus";
         }
-        
+
         public boolean isActive() {
             return true;
         }
 
-        public List getBooks() {
-            List list = new ArrayList();
+        public List<Book> getBooks() {
+            List<Book> list = new ArrayList<>();
             list.add(new Book("WebWork in Action", "Patrick and Jason", Arrays.asList("I", "IV")));
             list.add(null);
             list.add(new Book("XWork not in Action", "Superman", Arrays.asList("1234", "345", "6667")));
@@ -313,11 +311,11 @@ public class XSLTResultTest extends StrutsInternalTestCase {
 
     }
 
-    public class Book {
+    public static class Book {
 
-        private String title;
-        private String author;
-        private List<String> editions;
+        private final String title;
+        private final String author;
+        private final List<String> editions;
 
         public Book(String title, String author, List<String> editions) {
             this.title = title;
diff --git a/core/src/test/resources/XSLTResultTest-val.xml b/plugins/xslt/src/test/resources/XSLTResultTest-val.xml
similarity index 100%
rename from core/src/test/resources/XSLTResultTest-val.xml
rename to plugins/xslt/src/test/resources/XSLTResultTest-val.xml
diff --git a/core/src/test/resources/XSLTResultTest.bad.character.xsl b/plugins/xslt/src/test/resources/XSLTResultTest.bad.character.xsl
similarity index 100%
rename from core/src/test/resources/XSLTResultTest.bad.character.xsl
rename to plugins/xslt/src/test/resources/XSLTResultTest.bad.character.xsl
diff --git a/core/src/test/resources/XSLTResultTest.xsl b/plugins/xslt/src/test/resources/XSLTResultTest.xsl
similarity index 100%
rename from core/src/test/resources/XSLTResultTest.xsl
rename to plugins/xslt/src/test/resources/XSLTResultTest.xsl
diff --git a/core/src/test/resources/XSLTResultTest2.xsl b/plugins/xslt/src/test/resources/XSLTResultTest2.xsl
similarity index 100%
rename from core/src/test/resources/XSLTResultTest2.xsl
rename to plugins/xslt/src/test/resources/XSLTResultTest2.xsl
diff --git a/core/src/test/resources/XSLTResultTest3.xsl b/plugins/xslt/src/test/resources/XSLTResultTest3.xsl
similarity index 100%
rename from core/src/test/resources/XSLTResultTest3.xsl
rename to plugins/xslt/src/test/resources/XSLTResultTest3.xsl
diff --git a/core/src/test/resources/XSLTResultTest4.badinclude.xsl b/plugins/xslt/src/test/resources/XSLTResultTest4.badinclude.xsl
similarity index 100%
rename from core/src/test/resources/XSLTResultTest4.badinclude.xsl
rename to plugins/xslt/src/test/resources/XSLTResultTest4.badinclude.xsl
diff --git a/core/src/test/resources/XSLTResultTest4.xsl b/plugins/xslt/src/test/resources/XSLTResultTest4.xsl
similarity index 100%
rename from core/src/test/resources/XSLTResultTest4.xsl
rename to plugins/xslt/src/test/resources/XSLTResultTest4.xsl
diff --git a/core/src/test/resources/XSLTResultTest5.xsl b/plugins/xslt/src/test/resources/XSLTResultTest5.xsl
similarity index 100%
rename from core/src/test/resources/XSLTResultTest5.xsl
rename to plugins/xslt/src/test/resources/XSLTResultTest5.xsl
diff --git a/core/src/test/resources/XSLTResultTest6.xsl b/plugins/xslt/src/test/resources/XSLTResultTest6.xsl
similarity index 100%
rename from core/src/test/resources/XSLTResultTest6.xsl
rename to plugins/xslt/src/test/resources/XSLTResultTest6.xsl
diff --git a/pom.xml b/pom.xml
index c866e545b..dcc4d0ee5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,24 +2,25 @@
 <!--
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
+ * or more contributor license agreements. See the NOTICE file
  * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
+ * 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
+ * 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
+ * KIND, either express or implied. See the License for the
  * specific language governing permissions and limitations
  * under the License.
  */
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
 
     <parent>
         <groupId>org.apache.struts</groupId>
@@ -32,7 +33,7 @@
     <version>6.2.0-SNAPSHOT</version>
     <packaging>pom</packaging>
     <name>Struts 2</name>
-    <url>http://struts.apache.org/</url>
+    <url>https://struts.apache.org/</url>
     <description>Apache Struts 2</description>
 
     <inceptionYear>2000</inceptionYear>
@@ -91,15 +92,15 @@
     <licenses>
         <license>
             <name>The Apache Software License, Version 2.0</name>
-            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+            <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
             <distribution>repo</distribution>
-            <comments />
+            <comments/>
         </license>
     </licenses>
 
     <organization>
         <name>Apache Software Foundation</name>
-        <url>http://www.apache.org</url>
+        <url>https://www.apache.org</url>
     </organization>
 
     <properties>
@@ -271,10 +272,10 @@
                             <exclude>**/TestBean.java</exclude>
                         </excludes>
                         <properties>
-                          <property>
-                            <name>junit</name>
-                            <value>false</value>
-                          </property>
+                            <property>
+                                <name>junit</name>
+                                <value>false</value>
+                            </property>
                         </properties>
                     </configuration>
                 </plugin>
@@ -315,10 +316,10 @@
                         <useDefaultExcludes>true</useDefaultExcludes>
                         <addDefaultLicenseMatchers>false</addDefaultLicenseMatchers>
                         <licenses>
-                            <licens implementation="org.apache.rat.analysis.license.ApacheSoftwareLicense20" />
+                            <licens implementation="org.apache.rat.analysis.license.ApacheSoftwareLicense20"/>
                         </licenses>
                         <licenseFamilies>
-                            <licenseFamily implementation="org.apache.rat.license.Apache20LicenseFamily" />
+                            <licenseFamily implementation="org.apache.rat.license.Apache20LicenseFamily"/>
                         </licenseFamilies>
                         <includes>
                             <include>pom.xml</include>
@@ -367,7 +368,7 @@
                             <id>enforce</id>
                             <configuration>
                                 <rules>
-                                    <dependencyConvergence />
+                                    <dependencyConvergence/>
                                 </rules>
                             </configuration>
                             <goals>
@@ -673,6 +674,12 @@
                 <version>${project.version}</version>
             </dependency>
 
+            <dependency>
+                <groupId>org.apache.struts</groupId>
+                <artifactId>struts2-xslt-plugin</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+
             <dependency>
                 <groupId>org.freemarker</groupId>
                 <artifactId>freemarker</artifactId>
@@ -683,7 +690,8 @@
                 <groupId>org.apache.felix</groupId>
                 <artifactId>org.apache.felix.framework</artifactId>
                 <version>6.0.3</version>
-                <scope>provided</scope>  <!-- felix-main provides everything in felix-framework (and more), override here to provent both JARs from being included in the build. -->
+                <scope>provided
+                </scope>  <!-- felix-main provides everything in felix-framework (and more), override here to provent both JARs from being included in the build. -->
             </dependency>
 
             <dependency>
@@ -1045,7 +1053,8 @@
                 <version>4.3.1</version>
                 <exclusions>
                     <!-- The mockito-core artifact and easymock artifact use different versions of objenesis (2.6 vs 3.1).
-                         Excluding the older version here to pass enforcer.  When next upgrading mockito-core, confirm whether this exclusion is still required. -->
+                         Excluding the older version here to pass enforcer. When next upgrading mockito-core,
+                         confirm whether this exclusion is still required. -->
                     <exclusion>
                         <groupId>org.objenesis</groupId>
                         <artifactId>objenesis</artifactId>