diff --git a/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java b/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java index fb5068ca1..c264a59a2 100644 --- a/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java +++ b/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java @@ -43,162 +43,8 @@ import java.net.URL; import java.util.HashMap; import java.util.Map; - /** - * - * - * XSLTResult uses XSLT to transform an action object to XML. The recent version - * has been specifically modified to deal with Xalan flaws. When using Xalan you - * may notice that even though you have a very minimal stylesheet like this one - *
- * <xsl:template match="/result">
- *   <result/>
- * </xsl:template>
- * - *

- * Xalan would still iterate through every property of your action and all - * its descendants. - *

- * - *

- * If you had double-linked objects, Xalan would work forever analysing an - * infinite object tree. Even if your stylesheet was not constructed to process - * them all. It's because the current Xalan eagerly and extensively converts - * everything to its internal DTM model before further processing. - *

- * - *

- * That's why there's a loop eliminator added that works by indexing every - * object-property combination during processing. If it notices that some - * object's property was already walked through, it doesn't go any deeper. - * Say you have two objects, x and y, with the following properties set - * (pseudocode): - *

- *
- * x.y = y;
- * and
- * y.x = x;
- * action.x=x;
- * - *

- * Due to that modification, the resulting XML document based on x would be: - *

- * - *
- * <result>
- *   <x>
- *     <y/>
- *   </x>
- * </result>
- * - *

- * Without it there would be endless x/y/x/y/x/y/... elements. - *

- * - *

- * The XSLTResult code tries also to deal with the fact that DTM model is built - * in a manner that children are processed before siblings. The result is that if - * there is object x that is both set in action's x property, and very deeply - * under action's a property then it would only appear under a, not under x. - * That's not what we expect, and that's why XSLTResult allows objects to repeat - * in various places to some extent. - *

- * - *

- * Sometimes the object mesh is still very dense and you may notice that even - * though you have a relatively simple stylesheet, execution takes a tremendous - * amount of time. To help you to deal with that obstacle of Xalan, you may - * attach regexp filters to elements paths (xpath). - *

- * - *

- * Note: In your .xsl file the root match must be named result. - *
This example will output the username by using getUsername on your - * action class: - *

- * <xsl:template match="result">
- *   <html>
- *   <body>
- *   Hello <xsl:value-of select="username"/> how are you?
- *   </body>
- *   </html>
- * </xsl:template>
- * 
- * - *

- * In the following example the XSLT result would only walk through action's - * properties without their childs. It would also skip every property that has - * "hugeCollection" in their name. Element's path is first compared to - * excludingPattern - if it matches it's no longer processed. Then it is - * compared to matchingPattern and processed only if there's a match. - *

- * - * - * - *

- * <result name="success" type="xslt">
- *   <param name="location">foo.xslt</param>
- *   <param name="matchingPattern">^/result/[^/*]$</param>
- *   <param name="excludingPattern">.*(hugeCollection).*</param>
- * </result>
- * 
- * - *

- * In the following example the XSLT result would use the action's user property - * instead of the action as it's base document and walk through it's properties. - * The exposedValue uses an ognl expression to derive it's value. - *

- * - *
- * <result name="success" type="xslt">
- *   <param name="location">foo.xslt</param>
- *   <param name="exposedValue">user$</param>
- * </result>
- * 
- * * - * This result type takes the following parameters: - * - * - * - * - * - *

- * struts.properties related configuration: - *

- * - * - * - *

- * Example: - *

- * - *
- * 
- * <result name="success" type="xslt">foo.xslt</result>
- * 
- * 
- * + * XSLTResult uses XSLT to transform an action object to XML. */ public class XSLTResult implements Result { @@ -233,7 +79,7 @@ public class XSLTResult implements Result { /** Indicates the property name patterns which should be excluded from the xml. */ private String excludingPattern; - /** Indicates the ognl expression respresenting the bean which is to be exposed as xml. */ + /** Indicates the ognl expression representing the bean which is to be exposed as xml. */ private String exposedValue; /** Indicates the status to return in the response */ @@ -258,8 +104,6 @@ public class XSLTResult implements Result { } public void setStylesheetLocation(String location) { - if (location == null) - throw new IllegalArgumentException("Null location"); this.stylesheetLocation = location; } @@ -306,12 +150,15 @@ public class XSLTResult implements Result { long startTime = System.currentTimeMillis(); String location = getStylesheetLocation(); + if (location == null) { + throw new IllegalArgumentException("Parameter 'stylesheetLocation' cannot be null!"); + } + if (parse) { ValueStack stack = ActionContext.getContext().getValueStack(); location = TextParseUtil.translateVariables(location, stack); } - try { HttpServletResponse response = ServletActionContext.getResponse(); response.setStatus(status); @@ -331,10 +178,12 @@ public class XSLTResult implements Result { transformer.setErrorListener(buildErrorListener()); String mimeType; - if (templates == null) + if (templates == null) { mimeType = "text/xml"; // no stylesheet, raw xml - else + } else { mimeType = templates.getOutputProperties().getProperty(OutputKeys.MEDIA_TYPE); + } + if (mimeType == null) { // guess (this is a servlet, so text/html might be the best guess) mimeType = "text/html"; @@ -383,8 +232,9 @@ public class XSLTResult implements Result { } protected AdapterFactory getAdapterFactory() { - if (adapterFactory == null) + if (adapterFactory == null) { adapterFactory = new AdapterFactory(); + } return adapterFactory; } @@ -428,8 +278,7 @@ public class XSLTResult implements Result { return templates; } - protected Source getDOMSourceForStack(Object value) - throws IllegalAccessException, InstantiationException { + protected Source getDOMSourceForStack(Object value) throws IllegalAccessException, InstantiationException { return new DOMSource(getAdapterFactory().adaptDocument("result", value) ); } }