Search code examples
javasecurityxsltjava-7xslt-extension

SecurityManager and XSLT extensions in Java7 Update4 broken?


the Java application FreeMind uses XSLT to update from old files. The XSLT uses a static java function to simplify string operations. This works fine up to Java 7 update 2 and gives the following exception in java7 update 4 under windows:

STDERR: ERROR:  'The first argument to the non-static Java function 'replaceSpacesToNonbreakableSpaces' is not a valid object reference.'
STDERR: FATAL ERROR:  'Could not compile stylesheet'May 26, 2012 10:50:06 PM freemind.main.Resources logException
SEVERE: An exception occured: 
javax.xml.transform.TransformerConfigurationException: Could not compile stylesheet
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTemplates(Unknown Source)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTransformer(Unknown Source)
    at freemind.main.Tools$1TransformerRunnable.run(Tools.java:1023)
    at java.lang.Thread.run(Unknown Source)

Bringing it down to a minimal example, it comes up, that the custom SecurityManager is the culpable. If set, the code fails. If commented out, the code works. Does anybody know, what has changed in the Security system of java7 between update 2 and update 4 or what else can cause this?

Here is an even more minimal example:

package freemind.main;

import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

public final class FreeMindSecurityTest  {

    public static void main(String[] args) throws Exception {
        // if commented out, this program works as expected.
        System.setSecurityManager(new SecurityManager());
        String input = "<map version=\"0.9.0\">"
                + "</map>";
        String xslt = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
                + "     <xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" xmlns:FreeMindSecurityTest=\"xalan://freemind.main.FreeMindSecurityTest\" exclude-result-prefixes=\"FreeMindSecurityTest\">"
                + "         <xsl:template               match=\"/ | node() | @* | comment() | processing-instruction()\">"
                + "             <xsl:value-of select=\"FreeMindSecurityTest:replaceSpacesToNonbreakableSpaces('test')\"/>"
                + "         </xsl:template>" + "        </xsl:stylesheet>";
        StringWriter writer = new StringWriter();
        final Result result = new StreamResult(writer);

        final StreamSource sr = new StreamSource(new StringReader(input));
        // create an instance of TransformerFactory
        TransformerFactory transFact = TransformerFactory.newInstance();
        Transformer trans = transFact.newTransformer(new StreamSource(
                new StringReader(xslt)));

        trans.transform(sr, result);

        System.out.println("Transformed: " + writer.getBuffer());
        writer.close();
    }

    public static String replaceSpacesToNonbreakableSpaces(String input) {
        return input;
    }



}

In brief, java believes, that the method is not static (but it is) and misses the object reference.

TIA, Chris from FreeMind

EDIT: Shortest example (it suffices to set just a copy of the normal security manager) added.


Solution

  • There might be a bug in the JAXP 1.4.6 (in Java 7 Update 4). A change in Java 7u4 is that there was an upgrade to JAXP 1.4.6, see Java Release Notes.

    A workaround/solution (perhaps not the best choice) is to use Xalan 2.7.1 without extra patches via Java endorsed folder. (copy xalan 2.7.1 jars into jre/libs/endorsed) OR to use Xalan as third party lib.

    It worked for me on Linux64 with J7U4 and Xalan 2.7.1

    Transformed: <?xml version="1.0" encoding="UTF-8"?>test