# HG changeset patch # User clanger # Date 1469799280 -7200 # Fri Jul 29 15:34:40 2016 +0200 # Node ID 6be34b4fcc58dbc3c1602f2a8d1d213fa039035f # Parent 0ea62da60f01a27a937c398426b6749f9e723d27 8162598: XSLTC transformer swallows empty namespace declaration which is needed to undeclare default namespace diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/LiteralElement.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/LiteralElement.java --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/LiteralElement.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/LiteralElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -9,7 +9,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: LiteralElement.java,v 1.2.4.1 2005/09/13 12:38:33 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; @@ -58,8 +55,6 @@ // names are not known at compile time. private boolean _allAttributesUnique = false; - private final static String XMLNS_STRING = "xmlns"; - /** * Returns the QName for this literal element */ @@ -140,8 +135,8 @@ // Treat default namespace as "" and not null if (prefix == null) prefix = Constants.EMPTYSTRING; - else if (prefix.equals(XMLNS_STRING)) - return(XMLNS_STRING); + else if (prefix.equals(XMLNS_PREFIX)) + return(XMLNS_PREFIX); // Check if we must translate the prefix final String alternative = stable.lookupPrefixAlias(prefix); @@ -264,7 +259,7 @@ // Ignore special attributes (e.g. xmlns:prefix and xmlns) final String prefix = qname.getPrefix(); if (prefix != null && prefix.equals(XMLNS_PREFIX) || - prefix == null && qname.getLocalPart().equals("xmlns") || + prefix == null && qname.getLocalPart().equals(XMLNS_PREFIX) || uri != null && uri.equals(XSLT_URI)) { continue; @@ -337,9 +332,9 @@ il.append(methodGen.startElement()); // The value of an attribute may depend on a (sibling) variable - int j=0; + int j = 0; while (j < elementCount()) { - final SyntaxTreeNode item = (SyntaxTreeNode) elementAt(j); + final SyntaxTreeNode item = elementAt(j); if (item instanceof Variable) { item.translate(classGen, methodGen); } @@ -348,35 +343,12 @@ // Compile code to emit namespace attributes if (_accessedPrefixes != null) { - boolean declaresDefaultNS = false; - for (Map.Entry entry : _accessedPrefixes.entrySet()) { final String prefix = entry.getKey(); final String uri = entry.getValue(); - - if (uri != Constants.EMPTYSTRING || - prefix != Constants.EMPTYSTRING) - { - if (prefix == Constants.EMPTYSTRING) { - declaresDefaultNS = true; - } - il.append(methodGen.loadHandler()); - il.append(new PUSH(cpg,prefix)); - il.append(new PUSH(cpg,uri)); - il.append(methodGen.namespace()); - } - } - - /* - * If our XslElement parent redeclares the default NS, and this - * element doesn't, it must be redeclared one more time. - */ - if (!declaresDefaultNS && (_parent instanceof XslElement) - && ((XslElement) _parent).declaresDefaultNS()) - { il.append(methodGen.loadHandler()); - il.append(new PUSH(cpg, Constants.EMPTYSTRING)); - il.append(new PUSH(cpg, Constants.EMPTYSTRING)); + il.append(new PUSH(cpg, prefix)); + il.append(new PUSH(cpg, uri)); il.append(methodGen.namespace()); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: Parser.java,v 1.2.4.1 2005/09/13 12:14:32 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; @@ -72,20 +69,20 @@ */ public class Parser implements Constants, ContentHandler { - private static final String XSL = "xsl"; // standard prefix + private static final String XSL = "xsl"; // standard prefix private static final String TRANSLET = "translet"; // extension prefix private Locator _locator = null; - private XSLTC _xsltc; // Reference to the compiler object. - private XPathParser _xpathParser; // Reference to the XPath parser. - private ArrayList _errors; // Contains all compilation errors - private ArrayList _warnings; // Contains all compilation errors + private XSLTC _xsltc; // Reference to the compiler object. + private XPathParser _xpathParser; // Reference to the XPath parser. + private ArrayList _errors; // Contains all compilation errors + private ArrayList _warnings; // Contains all compilation warnings private Map _instructionClasses; // Maps instructions to classes private Map _instructionAttrs; // reqd and opt attrs - private Map _qNames; - private Map _namespaces; + private Map _qNames; + private Map> _namespaces; private QName _useAttributeSets; private QName _excludeResultPrefixes; private QName _extensionElementPrefixes; @@ -143,7 +140,6 @@ public void setOutput(Output output) { if (_output != null) { if (_output.getImportPrecedence() <= output.getImportPrecedence()) { - String cdata = _output.getCdata(); output.mergeOutput(_output); _output.disable(); _output = output; @@ -177,12 +173,13 @@ Object existing = _variableScope.get(var.getName().getStringRep()); if (existing != null) { if (existing instanceof Stack) { - Stack stack = (Stack)existing; + @SuppressWarnings("unchecked") + Stack stack = (Stack)existing; stack.push(var); } else if (existing instanceof VariableBase) { - Stack stack = new Stack(); - stack.push(existing); + Stack stack = new Stack<>(); + stack.push((VariableBase)existing); stack.push(var); _variableScope.put(var.getName().getStringRep(), stack); } @@ -195,7 +192,8 @@ public void removeVariable(QName name) { Object existing = _variableScope.get(name.getStringRep()); if (existing instanceof Stack) { - Stack stack = (Stack)existing; + @SuppressWarnings("unchecked") + Stack stack = (Stack)existing; if (!stack.isEmpty()) stack.pop(); if (!stack.isEmpty()) return; } @@ -205,13 +203,14 @@ public VariableBase lookupVariable(QName name) { Object existing = _variableScope.get(name.getStringRep()); if (existing instanceof VariableBase) { - return((VariableBase)existing); + return (VariableBase)existing; } else if (existing instanceof Stack) { - Stack stack = (Stack)existing; - return((VariableBase)stack.peek()); + @SuppressWarnings("unchecked") + Stack stack = (Stack)existing; + return stack.peek(); } - return(null); + return null; } public void setXSLTC(XSLTC xsltc) { @@ -401,10 +400,9 @@ try { if (stylesheet != null) { stylesheet.parseContents(this); - final int precedence = stylesheet.getImportPrecedence(); final Iterator elements = stylesheet.elements(); while (elements.hasNext()) { - Object child = elements.next(); + SyntaxTreeNode child = elements.next(); if (child instanceof Text) { final int l = getLineNumber(); ErrorMsg err = @@ -731,8 +729,6 @@ new String[] {"stylesheet-prefix", "result-prefix"}); } - - /** * Initialize the _instructionClasses map, which maps XSL element * names to Java classes in this package. @@ -806,6 +802,7 @@ /** * Add primops and base functions to the symbol table. */ + @SuppressWarnings("unused") private void initSymbolTable() { MethodType I_V = new MethodType(Type.Int, Type.Void); MethodType I_R = new MethodType(Type.Int, Type.Real); @@ -998,12 +995,12 @@ String local, Attributes attributes) { SyntaxTreeNode node = null; - QName qname = getQName(uri, prefix, local); + QName qname = getQName(uri, prefix, local); String className = _instructionClasses.get(qname.getStringRep()); if (className != null) { try { - final Class clazz = ObjectFactory.findProviderClass(className, true); + final Class clazz = ObjectFactory.findProviderClass(className, true); node = (SyntaxTreeNode)clazz.newInstance(); node.setQName(qname); node.setParser(this); @@ -1050,7 +1047,7 @@ else { Stylesheet sheet = _xsltc.getStylesheet(); if ((sheet != null) && (sheet.isExtension(uri))) { - if (sheet != (SyntaxTreeNode)_parentStack.peek()) { + if (sheet != _parentStack.peek()) { node = new UnsupportedElement(uri, prefix, local, true); UnsupportedElement elem = (UnsupportedElement)node; ErrorMsg msg = @@ -1183,7 +1180,6 @@ node.setParser(this); node.setParent(parent); node.setLineNumber(line); -// System.out.println("e = " + text + " " + node); return node; } } @@ -1279,7 +1275,7 @@ /************************ SAX2 ContentHandler INTERFACE *****************/ - private Stack _parentStack = null; + private Stack _parentStack = null; private Map _prefixMapping = null; /** @@ -1289,7 +1285,7 @@ _root = null; _target = null; _prefixMapping = null; - _parentStack = new Stack(); + _parentStack = new Stack<>(); } /** @@ -1345,7 +1341,7 @@ _root = element; } else { - SyntaxTreeNode parent = (SyntaxTreeNode)_parentStack.peek(); + SyntaxTreeNode parent = _parentStack.peek(); parent.addElement(element); element.setParent(parent); } @@ -1376,7 +1372,7 @@ */ public void characters(char[] ch, int start, int length) { String string = new String(ch, start, length); - SyntaxTreeNode parent = (SyntaxTreeNode)_parentStack.peek(); + SyntaxTreeNode parent = _parentStack.peek(); if (string.length() == 0) return; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java @@ -73,7 +73,7 @@ protected QName _qname; // The element QName private int _line; // Source file line number protected AttributesImpl _attributes = null; // Attributes of this element - private Map _prefixMapping = null; // Namespace declarations + private Map _prefixMapping = null; // Namespace declarations // Sentinel - used to denote unrecognised syntaxt tree nodes. protected static final SyntaxTreeNode Dummy = new AbsolutePathPattern(null); @@ -828,7 +828,7 @@ * @param pos The child node's position. * @return The child node. */ - protected final Object elementAt(int pos) { + protected final SyntaxTreeNode elementAt(int pos) { return _contents.get(pos); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java @@ -154,11 +154,11 @@ * Extension function class loader variables */ - /* Class loader reference that will be used to external extension functions loading */ + /* Class loader reference that will be used for external extension functions loading */ private ClassLoader _extensionClassLoader; /** - * HashSet with the loaded classes + * HashMap with the loaded classes */ private final Map _externalExtensionFunctions; @@ -295,7 +295,7 @@ } /* - * Function loads an external external extension functions. + * Function loads an external extension function. * The filtering of function types (external,internal) takes place in FunctionCall class * */ diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XslElement.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XslElement.java --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XslElement.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XslElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,16 +17,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: XslElement.java,v 1.2.4.1 2005/09/12 11:39:55 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; import com.sun.org.apache.bcel.internal.generic.ALOAD; import com.sun.org.apache.bcel.internal.generic.ASTORE; import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; -import com.sun.org.apache.bcel.internal.generic.ICONST; import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; import com.sun.org.apache.bcel.internal.generic.InstructionList; import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; @@ -61,14 +57,6 @@ displayContents(indent + IndentIncrement); } - /** - * This method is now deprecated. The new implemation of this class - * never declares the default NS. - */ - public boolean declaresDefaultNS() { - return false; - } - public void parseContents(Parser parser) { final SymbolTable stable = parser.getSymbolTable(); @@ -211,7 +199,6 @@ * on the handler (vii) evaluates the contents (viii) calls endElement(). */ public void translate(ClassGenerator classGen, MethodGenerator methodGen) { - LocalVariableGen local = null; final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java @@ -634,7 +634,7 @@ } // Inefficient, but array is small - for (int i =0; i < features.length; i++) { + for (int i = 0; i < features.length; i++) { if (name.equals(features[i])) { return true; } @@ -923,7 +923,7 @@ String transletClassName = getTransletBaseName(source); if (_packageName != null) - transletClassName = _packageName + "." + transletClassName; + transletClassName = _packageName + "." + transletClassName; if (_jarFileName != null) bytecodes = getBytecodesFromJar(source, transletClassName); diff --git a/test/javax/xml/jaxp/unittest/transform/TransformerTest.java b/test/javax/xml/jaxp/unittest/transform/TransformerTest.java --- a/test/javax/xml/jaxp/unittest/transform/TransformerTest.java +++ b/test/javax/xml/jaxp/unittest/transform/TransformerTest.java @@ -62,7 +62,7 @@ /* * @summary Transformer Tests - * @bug 6272879 6305029 6505031 8150704 + * @bug 6272879 6305029 6505031 8150704 8162598 */ public class TransformerTest { private Transformer createTransformer() throws TransformerException { @@ -111,6 +111,27 @@ } } + private void checkNodeNS8162598(Node test, String nstest, String nsb, String nsc) { + String testNodeName = test.getNodeName(); + if (nstest == null) { + Assert.assertNull(test.getNamespaceURI(), "unexpected namespace for " + testNodeName); + } else { + Assert.assertEquals(test.getNamespaceURI(), nstest, "unexpected namespace for " + testNodeName); + } + Node b = test.getChildNodes().item(0); + if (nsb == null) { + Assert.assertNull(b.getNamespaceURI(), "unexpected namespace for " + testNodeName + "->b"); + } else { + Assert.assertEquals(b.getNamespaceURI(), nsb, "unexpected namespace for " + testNodeName + "->b"); + } + Node c = b.getChildNodes().item(0); + if (nsc == null) { + Assert.assertNull(c.getNamespaceURI(), "unexpected namespace for " + testNodeName + "->b->c"); + } else { + Assert.assertEquals(c.getNamespaceURI(), nsc, "unexpected namespace for " + testNodeName + "->b->c"); + } + } + private class XMLReaderFor6305029 implements XMLReader { private static final String NAMESPACES = "http://xml.org/sax/features/namespaces"; private static final String NAMESPACE_PREFIXES = "http://xml.org/sax/features/namespace-prefixes"; @@ -249,22 +270,19 @@ " " + LINE_SEPARATOR + ""; - Document document; - Node node; - System.out.println("Stylesheet:"); - System.out.println("=================================="); + System.out.println("============================="); System.out.println(xsl); System.out.println(); - System.out.println("Source file before transformation:"); - System.out.println("=================================="); + System.out.println("Source before transformation:"); + System.out.println("============================="); System.out.println(sourceXml); System.out.println(); - System.out.println("Source file after transformation:"); - System.out.println("================================="); - document = transformInputStreamToDocument(createTransformerFromInputstream(new ByteArrayInputStream(xsl.getBytes())), + System.out.println("Result after transformation:"); + System.out.println("============================"); + Document document = transformInputStreamToDocument(createTransformerFromInputstream(new ByteArrayInputStream(xsl.getBytes())), new ByteArrayInputStream(sourceXml.getBytes())); OutputFormat format = new OutputFormat(); format.setIndenting(true); @@ -274,9 +292,8 @@ System.out.println("Node content for element valeur2:"); System.out.println("================================="); NodeList nodes = document.getElementsByTagName("valeur2"); - nodes = document.getElementsByTagName("valeur2"); for (int i = 0; i < nodes.getLength(); i++) { - node = nodes.item(i); + Node node = nodes.item(i); System.out.println(" Node value: " + node.getFirstChild().getNodeValue()); System.out.println(" Node attribute: " + node.getAttributes().item(0).getNodeValue()); @@ -341,4 +358,62 @@ Assert.assertEquals(resultstring, reference, "Output of transformation of Bug8150704-2.xml does not match reference"); System.out.println("Passed."); } + + /* + * @bug 8162598 + * @summary Test XSLTC handling of namespaces, especially empty namespace definitions to reset the + * default namespace + */ + @Test + public final void testBug8162598() throws IOException, TransformerException { + final String LINE_SEPARATOR = System.getProperty("line.separator"); + + final String xsl = + "" + LINE_SEPARATOR + + "" + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + ""; + + + final String sourceXml = + "" + LINE_SEPARATOR; + + System.out.println("Stylesheet:"); + System.out.println("============================="); + System.out.println(xsl); + System.out.println(); + + System.out.println("Source before transformation:"); + System.out.println("============================="); + System.out.println(sourceXml); + System.out.println(); + + System.out.println("Result after transformation:"); + System.out.println("============================"); + Document document = transformInputStreamToDocument( + createTransformerFromInputstream(new ByteArrayInputStream(xsl.getBytes())), + new ByteArrayInputStream(sourceXml.getBytes())); + OutputFormat format = new OutputFormat(); + format.setIndenting(true); + new XMLSerializer(System.out, format).serialize(document); + System.out.println(); + checkNodeNS8162598(document.getElementsByTagName("test1").item(0), "ns2", "ns2", null); + checkNodeNS8162598(document.getElementsByTagName("test2").item(0), "ns1", "ns2", null); + checkNodeNS8162598(document.getElementsByTagName("test3").item(0), null, null, null); + checkNodeNS8162598(document.getElementsByTagName("test4").item(0), null, null, null); + checkNodeNS8162598(document.getElementsByTagName("test5").item(0), "ns1", "ns1", null); + Assert.assertNull(document.getElementsByTagName("test6").item(0).getNamespaceURI(), "unexpected namespace for test6"); + } }