< prev index next >

src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java

Print this page
rev 959 : 8162598: XSLTC transformer swallows empty namespace declaration which is needed to undeclare default namespace
   1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *     http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 /*
  21  * $Id: Parser.java,v 1.2.4.1 2005/09/13 12:14:32 pvedula Exp $
  22  */
  23 
  24 package com.sun.org.apache.xalan.internal.xsltc.compiler;
  25 
  26 import com.sun.java_cup.internal.runtime.Symbol;
  27 import com.sun.org.apache.xalan.internal.XalanConstants;
  28 import com.sun.org.apache.xalan.internal.utils.FactoryImpl;
  29 import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
  30 import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
  31 import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
  32 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
  33 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodType;
  34 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
  35 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
  36 import com.sun.org.apache.xml.internal.serializer.utils.SystemIDResolver;
  37 import java.io.File;
  38 import java.io.IOException;
  39 import java.io.StringReader;

  40 import java.util.HashMap;
  41 import java.util.Iterator;
  42 import java.util.List;
  43 import java.util.Map;
  44 import java.util.Properties;
  45 import java.util.Stack;
  46 import java.util.StringTokenizer;
  47 import java.util.Vector;
  48 import javax.xml.XMLConstants;
  49 import javax.xml.parsers.ParserConfigurationException;
  50 import javax.xml.parsers.SAXParser;
  51 import javax.xml.parsers.SAXParserFactory;
  52 import org.xml.sax.Attributes;
  53 import org.xml.sax.ContentHandler;
  54 import org.xml.sax.InputSource;
  55 import org.xml.sax.Locator;
  56 import org.xml.sax.SAXException;
  57 import org.xml.sax.SAXNotRecognizedException;
  58 import org.xml.sax.SAXParseException;
  59 import org.xml.sax.XMLReader;
  60 import org.xml.sax.helpers.AttributesImpl;
  61 
  62 /**
  63  * @author Jacek Ambroziak
  64  * @author Santiago Pericas-Geertsen
  65  * @author G. Todd Miller
  66  * @author Morten Jorgensen
  67  * @author Erwin Bolwidt <ejb@klomp.org>
  68  */
  69 public class Parser implements Constants, ContentHandler {
  70 
  71     private static final String XSL = "xsl";            // standard prefix
  72     private static final String TRANSLET = "translet"; // extension prefix
  73 
  74     private Locator _locator = null;
  75 
  76     private XSLTC _xsltc;             // Reference to the compiler object.
  77     private XPathParser _xpathParser; // Reference to the XPath parser.
  78     private Vector _errors;           // Contains all compilation errors
  79     private Vector _warnings;         // Contains all compilation errors
  80 
  81     private Map<String, String>   _instructionClasses; // Maps instructions to classes
  82     private Map<String, String[]> _instructionAttrs;  // reqd and opt attrs
  83     private Map<String, QName>   _qNames;
  84     private Map<String, Map>     _namespaces;
  85     private QName       _useAttributeSets;
  86     private QName       _excludeResultPrefixes;
  87     private QName       _extensionElementPrefixes;
  88     private Map<String, Object>   _variableScope;
  89     private Stylesheet  _currentStylesheet;
  90     private SymbolTable _symbolTable; // Maps QNames to syntax-tree nodes
  91     private Output      _output;
  92     private Template    _template;    // Reference to the template being parsed.
  93 
  94     private boolean     _rootNamespaceDef; // Used for validity check
  95 
  96     private SyntaxTreeNode _root;
  97 
  98     private String _target;
  99 
 100     private int _currentImportPrecedence;
 101 
 102     private boolean _useServicesMechanism = true;
 103 
 104     public Parser(XSLTC xsltc, boolean useServicesMechanism) {
 105         _xsltc = xsltc;
 106         _useServicesMechanism = useServicesMechanism;
 107     }
 108 
 109     public void init() {
 110         _qNames              = new HashMap<>(512);
 111         _namespaces          = new HashMap<>();
 112         _instructionClasses  = new HashMap<>();
 113         _instructionAttrs    = new HashMap<>();
 114         _variableScope       = new HashMap<>();
 115         _template            = null;
 116         _errors              = new Vector();
 117         _warnings            = new Vector();
 118         _symbolTable         = new SymbolTable();
 119         _xpathParser         = new XPathParser(this);
 120         _currentStylesheet   = null;
 121         _output              = null;
 122         _root                = null;
 123         _rootNamespaceDef    = false;
 124         _currentImportPrecedence = 1;
 125 
 126         initStdClasses();
 127         initInstructionAttrs();
 128         initExtClasses();
 129         initSymbolTable();
 130 
 131         _useAttributeSets =
 132             getQName(XSLT_URI, XSL, "use-attribute-sets");
 133         _excludeResultPrefixes =
 134             getQName(XSLT_URI, XSL, "exclude-result-prefixes");
 135         _extensionElementPrefixes =
 136             getQName(XSLT_URI, XSL, "extension-element-prefixes");
 137     }
 138 
 139     public void setOutput(Output output) {
 140         if (_output != null) {
 141             if (_output.getImportPrecedence() <= output.getImportPrecedence()) {
 142                 String cdata = _output.getCdata();
 143                 output.mergeOutput(_output);
 144                 _output.disable();
 145                 _output = output;
 146             }
 147             else {
 148                 output.disable();
 149             }
 150         }
 151         else {
 152             _output = output;
 153         }
 154     }
 155 
 156     public Output getOutput() {
 157         return _output;
 158     }
 159 
 160     public Properties getOutputProperties() {
 161         return getTopLevelStylesheet().getOutputProperties();
 162     }
 163 
 164     public void addVariable(Variable var) {
 165         addVariableOrParam(var);
 166     }
 167 
 168     public void addParameter(Param param) {
 169         addVariableOrParam(param);
 170     }
 171 
 172     private void addVariableOrParam(VariableBase var) {
 173         Object existing = _variableScope.get(var.getName().getStringRep());
 174         if (existing != null) {
 175             if (existing instanceof Stack) {
 176                 Stack stack = (Stack)existing;

 177                 stack.push(var);
 178             }
 179             else if (existing instanceof VariableBase) {
 180                 Stack stack = new Stack();
 181                 stack.push(existing);
 182                 stack.push(var);
 183                 _variableScope.put(var.getName().getStringRep(), stack);
 184             }
 185         }
 186         else {
 187             _variableScope.put(var.getName().getStringRep(), var);
 188         }
 189     }
 190 
 191     public void removeVariable(QName name) {
 192         Object existing = _variableScope.get(name.getStringRep());
 193         if (existing instanceof Stack) {
 194             Stack stack = (Stack)existing;
 195             if (!stack.isEmpty()) stack.pop();
 196             if (!stack.isEmpty()) return;
 197         }
 198         _variableScope.remove(name.getStringRep());
 199     }
 200 
 201     public VariableBase lookupVariable(QName name) {
 202         Object existing = _variableScope.get(name.getStringRep());
 203         if (existing instanceof VariableBase) {
 204             return((VariableBase)existing);
 205         }
 206         else if (existing instanceof Stack) {
 207             Stack stack = (Stack)existing;
 208             return((VariableBase)stack.peek());

 209         }
 210         return(null);
 211     }
 212 
 213     public void setXSLTC(XSLTC xsltc) {
 214         _xsltc = xsltc;
 215     }
 216 
 217     public XSLTC getXSLTC() {
 218         return _xsltc;
 219     }
 220 
 221     public int getCurrentImportPrecedence() {
 222         return _currentImportPrecedence;
 223     }
 224 
 225     public int getNextImportPrecedence() {
 226         return ++_currentImportPrecedence;
 227     }
 228 
 229     public void setCurrentStylesheet(Stylesheet stylesheet) {
 230         _currentStylesheet = stylesheet;


 380                 if (element.lookupNamespace(EMPTYSTRING) == null) {
 381                     element.addPrefixMapping(EMPTYSTRING, EMPTYSTRING);
 382                 }
 383             }
 384             stylesheet.setParser(this);
 385             return stylesheet;
 386         }
 387         catch (ClassCastException e) {
 388             ErrorMsg err = new ErrorMsg(ErrorMsg.NOT_STYLESHEET_ERR, element);
 389             throw new CompilerException(err.toString());
 390         }
 391     }
 392 
 393     /**
 394      * Instanciates a SAX2 parser and generate the AST from the input.
 395      */
 396     public void createAST(Stylesheet stylesheet) {
 397         try {
 398             if (stylesheet != null) {
 399                 stylesheet.parseContents(this);
 400                 final int precedence = stylesheet.getImportPrecedence();
 401                 final Iterator<SyntaxTreeNode> elements = stylesheet.elements();
 402                 while (elements.hasNext()) {
 403                     Object child = elements.next();
 404                     if (child instanceof Text) {
 405                         final int l = getLineNumber();
 406                         ErrorMsg err =
 407                             new ErrorMsg(ErrorMsg.ILLEGAL_TEXT_NODE_ERR,l,null);
 408                         reportError(ERROR, err);
 409                     }
 410                 }
 411                 if (!errorsFound()) {
 412                     stylesheet.typeCheck(_symbolTable);
 413                 }
 414             }
 415         }
 416         catch (TypeCheckError e) {
 417             reportError(ERROR, new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR, e));
 418         }
 419     }
 420 
 421     /**
 422      * Parses a stylesheet and builds the internal abstract syntax tree
 423      * @param reader A SAX2 SAXReader (parser)


 687         initAttrTable("value-of",
 688             new String[] {"select", "disable-output-escaping"});
 689         initAttrTable("element",
 690             new String[] {"name", "namespace", "use-attribute-sets"});
 691         initAttrTable("call-template", new String[] {"name"});
 692         initAttrTable("apply-templates", new String[] {"select", "mode"});
 693         initAttrTable("apply-imports", new String[] {});
 694         initAttrTable("decimal-format",
 695             new String[] {"name", "decimal-separator", "grouping-separator",
 696                 "infinity", "minus-sign", "NaN", "percent", "per-mille",
 697                 "zero-digit", "digit", "pattern-separator"});
 698         initAttrTable("import", new String[] {"href"});
 699         initAttrTable("include", new String[] {"href"});
 700         initAttrTable("strip-space", new String[] {"elements"});
 701         initAttrTable("preserve-space", new String[] {"elements"});
 702         initAttrTable("processing-instruction", new String[] {"name"});
 703         initAttrTable("namespace-alias",
 704            new String[] {"stylesheet-prefix", "result-prefix"});
 705     }
 706 
 707 
 708 
 709     /**
 710      * Initialize the _instructionClasses map, which maps XSL element
 711      * names to Java classes in this package.
 712      */
 713     private void initStdClasses() {
 714         initStdClass("template", "Template");
 715         initStdClass("stylesheet", "Stylesheet");
 716         initStdClass("transform", "Stylesheet");
 717         initStdClass("text", "Text");
 718         initStdClass("if", "If");
 719         initStdClass("choose", "Choose");
 720         initStdClass("when", "When");
 721         initStdClass("otherwise", "Otherwise");
 722         initStdClass("for-each", "ForEach");
 723         initStdClass("message", "Message");
 724         initStdClass("number", "Number");
 725         initStdClass("comment", "Comment");
 726         initStdClass("copy", "Copy");
 727         initStdClass("copy-of", "CopyOf");
 728         initStdClass("param", "Param");


 762     }
 763 
 764     private void initExtClasses() {
 765         initExtClass("output", "TransletOutput");
 766         initExtClass(REDIRECT_URI, "write", "TransletOutput");
 767     }
 768 
 769     private void initExtClass(String elementName, String className) {
 770         _instructionClasses.put(getQName(TRANSLET_URI, TRANSLET, elementName).getStringRep(),
 771                                 COMPILER_PACKAGE + '.' + className);
 772     }
 773 
 774     private void initExtClass(String namespace, String elementName, String className) {
 775         _instructionClasses.put(getQName(namespace, TRANSLET, elementName).getStringRep(),
 776                                 COMPILER_PACKAGE + '.' + className);
 777     }
 778 
 779     /**
 780      * Add primops and base functions to the symbol table.
 781      */

 782     private void initSymbolTable() {
 783         MethodType I_V  = new MethodType(Type.Int, Type.Void);
 784         MethodType I_R  = new MethodType(Type.Int, Type.Real);
 785         MethodType I_S  = new MethodType(Type.Int, Type.String);
 786         MethodType I_D  = new MethodType(Type.Int, Type.NodeSet);
 787         MethodType R_I  = new MethodType(Type.Real, Type.Int);
 788         MethodType R_V  = new MethodType(Type.Real, Type.Void);
 789         MethodType R_R  = new MethodType(Type.Real, Type.Real);
 790         MethodType R_D  = new MethodType(Type.Real, Type.NodeSet);
 791         MethodType R_O  = new MethodType(Type.Real, Type.Reference);
 792         MethodType I_I  = new MethodType(Type.Int, Type.Int);
 793         MethodType D_O  = new MethodType(Type.NodeSet, Type.Reference);
 794         MethodType D_V  = new MethodType(Type.NodeSet, Type.Void);
 795         MethodType D_S  = new MethodType(Type.NodeSet, Type.String);
 796         MethodType D_D  = new MethodType(Type.NodeSet, Type.NodeSet);
 797         MethodType A_V  = new MethodType(Type.Node, Type.Void);
 798         MethodType S_V  = new MethodType(Type.String, Type.Void);
 799         MethodType S_S  = new MethodType(Type.String, Type.String);
 800         MethodType S_A  = new MethodType(Type.String, Type.Node);
 801         MethodType S_D  = new MethodType(Type.String, Type.NodeSet);


 954     }
 955 
 956     /**
 957      * Creates a new node in the abstract syntax tree. This node can be
 958      *  o) a supported XSLT 1.0 element
 959      *  o) an unsupported XSLT element (post 1.0)
 960      *  o) a supported XSLT extension
 961      *  o) an unsupported XSLT extension
 962      *  o) a literal result element (not an XSLT element and not an extension)
 963      * Unsupported elements do not directly generate an error. We have to wait
 964      * until we have received all child elements of an unsupported element to
 965      * see if any <xsl:fallback> elements exist.
 966      */
 967 
 968     private boolean versionIsOne = true;
 969 
 970     public SyntaxTreeNode makeInstance(String uri, String prefix,
 971         String local, Attributes attributes)
 972     {
 973         SyntaxTreeNode node = null;
 974         QName  qname = getQName(uri, prefix, local);
 975         String className = _instructionClasses.get(qname.getStringRep());
 976 
 977         if (className != null) {
 978             try {
 979                 final Class clazz = ObjectFactory.findProviderClass(className, true);
 980                 node = (SyntaxTreeNode)clazz.newInstance();
 981                 node.setQName(qname);
 982                 node.setParser(this);
 983                 if (_locator != null) {
 984                     node.setLineNumber(getLineNumber());
 985                 }
 986                 if (node instanceof Stylesheet) {
 987                     _xsltc.setStylesheet((Stylesheet)node);
 988                 }
 989                 checkForSuperfluousAttributes(node, attributes);
 990             }
 991             catch (ClassNotFoundException e) {
 992                 ErrorMsg err = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, node);
 993                 reportError(ERROR, err);
 994             }
 995             catch (Exception e) {
 996                 ErrorMsg err = new ErrorMsg(ErrorMsg.INTERNAL_ERR,
 997                                             e.getMessage(), node);
 998                 reportError(FATAL, err);
 999             }


1006                     UnsupportedElement element = (UnsupportedElement)node;
1007                     ErrorMsg msg = new ErrorMsg(ErrorMsg.UNSUPPORTED_XSL_ERR,
1008                                                 getLineNumber(),local);
1009                     element.setErrorMessage(msg);
1010                     if (versionIsOne) {
1011                         reportError(UNSUPPORTED,msg);
1012                     }
1013                 }
1014                 // Check if this is an XSLTC extension element
1015                 else if (uri.equals(TRANSLET_URI)) {
1016                     node = new UnsupportedElement(uri, prefix, local, true);
1017                     UnsupportedElement element = (UnsupportedElement)node;
1018                     ErrorMsg msg = new ErrorMsg(ErrorMsg.UNSUPPORTED_EXT_ERR,
1019                                                 getLineNumber(),local);
1020                     element.setErrorMessage(msg);
1021                 }
1022                 // Check if this is an extension of some other XSLT processor
1023                 else {
1024                     Stylesheet sheet = _xsltc.getStylesheet();
1025                     if ((sheet != null) && (sheet.isExtension(uri))) {
1026                         if (sheet != (SyntaxTreeNode)_parentStack.peek()) {
1027                             node = new UnsupportedElement(uri, prefix, local, true);
1028                             UnsupportedElement elem = (UnsupportedElement)node;
1029                             ErrorMsg msg =
1030                                 new ErrorMsg(ErrorMsg.UNSUPPORTED_EXT_ERR,
1031                                              getLineNumber(),
1032                                              prefix+":"+local);
1033                             elem.setErrorMessage(msg);
1034                         }
1035                     }
1036                 }
1037             }
1038             if (node == null) {
1039                 node = new LiteralElement();
1040                 node.setLineNumber(getLineNumber());
1041             }
1042         }
1043         if ((node != null) && (node instanceof LiteralElement)) {
1044             ((LiteralElement)node).setQName(qname);
1045         }
1046         return(node);


1174         return SyntaxTreeNode.Dummy;
1175     }
1176 
1177     /************************ ERROR HANDLING SECTION ************************/
1178 
1179     /**
1180      * Returns true if there were any errors during compilation
1181      */
1182     public boolean errorsFound() {
1183         return _errors.size() > 0;
1184     }
1185 
1186     /**
1187      * Prints all compile-time errors
1188      */
1189     public void printErrors() {
1190         final int size = _errors.size();
1191         if (size > 0) {
1192             System.err.println(new ErrorMsg(ErrorMsg.COMPILER_ERROR_KEY));
1193             for (int i = 0; i < size; i++) {
1194                 System.err.println("  " + _errors.elementAt(i));
1195             }
1196         }
1197     }
1198 
1199     /**
1200      * Prints all compile-time warnings
1201      */
1202     public void printWarnings() {
1203         final int size = _warnings.size();
1204         if (size > 0) {
1205             System.err.println(new ErrorMsg(ErrorMsg.COMPILER_WARNING_KEY));
1206             for (int i = 0; i < size; i++) {
1207                 System.err.println("  " + _warnings.elementAt(i));
1208             }
1209         }
1210     }
1211 
1212     /**
1213      * Common error/warning message handler
1214      */
1215     public void reportError(final int category, final ErrorMsg error) {
1216         switch (category) {
1217         case Constants.INTERNAL:
1218             // Unexpected internal errors, such as null-ptr exceptions, etc.
1219             // Immediately terminates compilation, no translet produced
1220             _errors.addElement(error);
1221             break;
1222         case Constants.UNSUPPORTED:
1223             // XSLT elements that are not implemented and unsupported ext.
1224             // Immediately terminates compilation, no translet produced
1225             _errors.addElement(error);
1226             break;
1227         case Constants.FATAL:
1228             // Fatal error in the stylesheet input (parsing or content)
1229             // Immediately terminates compilation, no translet produced
1230             _errors.addElement(error);
1231             break;
1232         case Constants.ERROR:
1233             // Other error in the stylesheet input (parsing or content)
1234             // Does not terminate compilation, no translet produced
1235             _errors.addElement(error);
1236             break;
1237         case Constants.WARNING:
1238             // Other error in the stylesheet input (content errors only)
1239             // Does not terminate compilation, a translet is produced
1240             _warnings.addElement(error);
1241             break;
1242         }
1243     }
1244 
1245     public Vector getErrors() {
1246         return _errors;
1247     }
1248 
1249     public Vector getWarnings() {
1250         return _warnings;
1251     }
1252 
1253     /************************ SAX2 ContentHandler INTERFACE *****************/
1254 
1255     private Stack _parentStack = null;
1256     private Map<String, String> _prefixMapping = null;
1257 
1258     /**
1259      * SAX2: Receive notification of the beginning of a document.
1260      */
1261     public void startDocument() {
1262         _root = null;
1263         _target = null;
1264         _prefixMapping = null;
1265         _parentStack = new Stack();
1266     }
1267 
1268     /**
1269      * SAX2: Receive notification of the end of a document.
1270      */
1271     public void endDocument() { }
1272 
1273 
1274     /**
1275      * SAX2: Begin the scope of a prefix-URI Namespace mapping.
1276      *       This has to be passed on to the symbol table!
1277      */
1278     public void startPrefixMapping(String prefix, String uri) {
1279         if (_prefixMapping == null) {
1280             _prefixMapping = new HashMap<>();
1281         }
1282         _prefixMapping.put(prefix, uri);
1283     }
1284 
1285     /**


1301 
1302         SyntaxTreeNode element = makeInstance(uri, prefix,
1303                                         localname, attributes);
1304         if (element == null) {
1305             ErrorMsg err = new ErrorMsg(ErrorMsg.ELEMENT_PARSE_ERR,
1306                                         prefix+':'+localname);
1307             throw new SAXException(err.toString());
1308         }
1309 
1310         // If this is the root element of the XML document we need to make sure
1311         // that it contains a definition of the XSL namespace URI
1312         if (_root == null) {
1313             if ((_prefixMapping == null) ||
1314                 (_prefixMapping.containsValue(Constants.XSLT_URI) == false))
1315                 _rootNamespaceDef = false;
1316             else
1317                 _rootNamespaceDef = true;
1318             _root = element;
1319         }
1320         else {
1321             SyntaxTreeNode parent = (SyntaxTreeNode)_parentStack.peek();
1322             parent.addElement(element);
1323             element.setParent(parent);
1324         }
1325         element.setAttributes(new AttributesImpl(attributes));
1326         element.setPrefixMapping(_prefixMapping);
1327 
1328         if (element instanceof Stylesheet) {
1329             // Extension elements and excluded elements have to be
1330             // handled at this point in order to correctly generate
1331             // Fallback elements from <xsl:fallback>s.
1332             getSymbolTable().setCurrentNode(element);
1333             ((Stylesheet)element).declareExtensionPrefixes(this);
1334         }
1335 
1336         _prefixMapping = null;
1337         _parentStack.push(element);
1338     }
1339 
1340     /**
1341      * SAX2: Receive notification of the end of an element.
1342      */
1343     public void endElement(String uri, String localname, String qname) {
1344         _parentStack.pop();
1345     }
1346 
1347     /**
1348      * SAX2: Receive notification of character data.
1349      */
1350     public void characters(char[] ch, int start, int length) {
1351         String string = new String(ch, start, length);
1352         SyntaxTreeNode parent = (SyntaxTreeNode)_parentStack.peek();
1353 
1354         if (string.length() == 0) return;
1355 
1356         // If this text occurs within an <xsl:text> element we append it
1357         // as-is to the existing text element
1358         if (parent instanceof Text) {
1359             ((Text)parent).setText(string);
1360             return;
1361         }
1362 
1363         // Ignore text nodes that occur directly under <xsl:stylesheet>
1364         if (parent instanceof Stylesheet) return;
1365 
1366         SyntaxTreeNode bro = parent.lastChild();
1367         if ((bro != null) && (bro instanceof Text)) {
1368             Text text = (Text)bro;
1369             if (!text.isTextElement()) {
1370                 if ((length > 1) || ( ((int)ch[0]) < 0x100)) {
1371                     text.setText(string);
1372                     return;


   1 /*
   2  * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *     http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */



  20 
  21 package com.sun.org.apache.xalan.internal.xsltc.compiler;
  22 
  23 import com.sun.java_cup.internal.runtime.Symbol;
  24 import com.sun.org.apache.xalan.internal.XalanConstants;
  25 import com.sun.org.apache.xalan.internal.utils.FactoryImpl;
  26 import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
  27 import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
  28 import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
  29 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
  30 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodType;
  31 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
  32 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
  33 import com.sun.org.apache.xml.internal.serializer.utils.SystemIDResolver;
  34 import java.io.File;
  35 import java.io.IOException;
  36 import java.io.StringReader;
  37 import java.util.ArrayList;
  38 import java.util.HashMap;
  39 import java.util.Iterator;
  40 import java.util.List;
  41 import java.util.Map;
  42 import java.util.Properties;
  43 import java.util.Stack;
  44 import java.util.StringTokenizer;

  45 import javax.xml.XMLConstants;
  46 import javax.xml.parsers.ParserConfigurationException;
  47 import javax.xml.parsers.SAXParser;
  48 import javax.xml.parsers.SAXParserFactory;
  49 import org.xml.sax.Attributes;
  50 import org.xml.sax.ContentHandler;
  51 import org.xml.sax.InputSource;
  52 import org.xml.sax.Locator;
  53 import org.xml.sax.SAXException;
  54 import org.xml.sax.SAXNotRecognizedException;
  55 import org.xml.sax.SAXParseException;
  56 import org.xml.sax.XMLReader;
  57 import org.xml.sax.helpers.AttributesImpl;
  58 
  59 /**
  60  * @author Jacek Ambroziak
  61  * @author Santiago Pericas-Geertsen
  62  * @author G. Todd Miller
  63  * @author Morten Jorgensen
  64  * @author Erwin Bolwidt <ejb@klomp.org>
  65  */
  66 public class Parser implements Constants, ContentHandler {
  67 
  68     private static final String XSL = "xsl";            // standard prefix
  69     private static final String TRANSLET = "translet"; // extension prefix
  70 
  71     private Locator _locator = null;
  72 
  73     private XSLTC _xsltc;                  // Reference to the compiler object.
  74     private XPathParser _xpathParser;      // Reference to the XPath parser.
  75     private ArrayList<ErrorMsg> _errors;   // Contains all compilation errors
  76     private ArrayList<ErrorMsg> _warnings; // Contains all compilation warnings
  77 
  78     private Map<String, String>   _instructionClasses; // Maps instructions to classes
  79     private Map<String, String[]> _instructionAttrs;  // reqd and opt attrs
  80     private Map<String, QName>    _qNames;
  81     private Map<String, Map<String, QName>> _namespaces;
  82     private QName       _useAttributeSets;
  83     private QName       _excludeResultPrefixes;
  84     private QName       _extensionElementPrefixes;
  85     private Map<String, Object>   _variableScope;
  86     private Stylesheet  _currentStylesheet;
  87     private SymbolTable _symbolTable; // Maps QNames to syntax-tree nodes
  88     private Output      _output;
  89     private Template    _template;    // Reference to the template being parsed.
  90 
  91     private boolean     _rootNamespaceDef; // Used for validity check
  92 
  93     private SyntaxTreeNode _root;
  94 
  95     private String _target;
  96 
  97     private int _currentImportPrecedence;
  98 
  99     private boolean _useServicesMechanism = true;
 100 
 101     public Parser(XSLTC xsltc, boolean useServicesMechanism) {
 102         _xsltc = xsltc;
 103         _useServicesMechanism = useServicesMechanism;
 104     }
 105 
 106     public void init() {
 107         _qNames              = new HashMap<>(512);
 108         _namespaces          = new HashMap<>();
 109         _instructionClasses  = new HashMap<>();
 110         _instructionAttrs    = new HashMap<>();
 111         _variableScope       = new HashMap<>();
 112         _template            = null;
 113         _errors              = new ArrayList<>();
 114         _warnings            = new ArrayList<>();
 115         _symbolTable         = new SymbolTable();
 116         _xpathParser         = new XPathParser(this);
 117         _currentStylesheet   = null;
 118         _output              = null;
 119         _root                = null;
 120         _rootNamespaceDef    = false;
 121         _currentImportPrecedence = 1;
 122 
 123         initStdClasses();
 124         initInstructionAttrs();
 125         initExtClasses();
 126         initSymbolTable();
 127 
 128         _useAttributeSets =
 129             getQName(XSLT_URI, XSL, "use-attribute-sets");
 130         _excludeResultPrefixes =
 131             getQName(XSLT_URI, XSL, "exclude-result-prefixes");
 132         _extensionElementPrefixes =
 133             getQName(XSLT_URI, XSL, "extension-element-prefixes");
 134     }
 135 
 136     public void setOutput(Output output) {
 137         if (_output != null) {
 138             if (_output.getImportPrecedence() <= output.getImportPrecedence()) {

 139                 output.mergeOutput(_output);
 140                 _output.disable();
 141                 _output = output;
 142             }
 143             else {
 144                 output.disable();
 145             }
 146         }
 147         else {
 148             _output = output;
 149         }
 150     }
 151 
 152     public Output getOutput() {
 153         return _output;
 154     }
 155 
 156     public Properties getOutputProperties() {
 157         return getTopLevelStylesheet().getOutputProperties();
 158     }
 159 
 160     public void addVariable(Variable var) {
 161         addVariableOrParam(var);
 162     }
 163 
 164     public void addParameter(Param param) {
 165         addVariableOrParam(param);
 166     }
 167 
 168     private void addVariableOrParam(VariableBase var) {
 169         Object existing = _variableScope.get(var.getName().getStringRep());
 170         if (existing != null) {
 171             if (existing instanceof Stack<?>) {
 172                 @SuppressWarnings("unchecked")
 173                 Stack<VariableBase> stack = (Stack<VariableBase>)existing;
 174                 stack.push(var);
 175             }
 176             else if (existing instanceof VariableBase) {
 177                 Stack<VariableBase> stack = new Stack<>();
 178                 stack.push((VariableBase)existing);
 179                 stack.push(var);
 180                 _variableScope.put(var.getName().getStringRep(), stack);
 181             }
 182         }
 183         else {
 184             _variableScope.put(var.getName().getStringRep(), var);
 185         }
 186     }
 187 
 188     public void removeVariable(QName name) {
 189         Object existing = _variableScope.get(name.getStringRep());
 190         if (existing instanceof Stack<?>) {
 191             Stack<?> stack = (Stack<?>)existing;
 192             if (!stack.isEmpty()) stack.pop();
 193             if (!stack.isEmpty()) return;
 194         }
 195         _variableScope.remove(name.getStringRep());
 196     }
 197 
 198     public VariableBase lookupVariable(QName name) {
 199         Object existing = _variableScope.get(name.getStringRep());
 200         if (existing instanceof VariableBase) {
 201             return (VariableBase)existing;
 202         }
 203         else if (existing instanceof Stack<?>) {
 204             @SuppressWarnings("unchecked")
 205             Stack<VariableBase> stack = (Stack<VariableBase>)existing;
 206             return stack.peek();
 207         }
 208         return null;
 209     }
 210 
 211     public void setXSLTC(XSLTC xsltc) {
 212         _xsltc = xsltc;
 213     }
 214 
 215     public XSLTC getXSLTC() {
 216         return _xsltc;
 217     }
 218 
 219     public int getCurrentImportPrecedence() {
 220         return _currentImportPrecedence;
 221     }
 222 
 223     public int getNextImportPrecedence() {
 224         return ++_currentImportPrecedence;
 225     }
 226 
 227     public void setCurrentStylesheet(Stylesheet stylesheet) {
 228         _currentStylesheet = stylesheet;


 378                 if (element.lookupNamespace(EMPTYSTRING) == null) {
 379                     element.addPrefixMapping(EMPTYSTRING, EMPTYSTRING);
 380                 }
 381             }
 382             stylesheet.setParser(this);
 383             return stylesheet;
 384         }
 385         catch (ClassCastException e) {
 386             ErrorMsg err = new ErrorMsg(ErrorMsg.NOT_STYLESHEET_ERR, element);
 387             throw new CompilerException(err.toString());
 388         }
 389     }
 390 
 391     /**
 392      * Instanciates a SAX2 parser and generate the AST from the input.
 393      */
 394     public void createAST(Stylesheet stylesheet) {
 395         try {
 396             if (stylesheet != null) {
 397                 stylesheet.parseContents(this);

 398                 final Iterator<SyntaxTreeNode> elements = stylesheet.elements();
 399                 while (elements.hasNext()) {
 400                     SyntaxTreeNode child = elements.next();
 401                     if (child instanceof Text) {
 402                         final int l = getLineNumber();
 403                         ErrorMsg err =
 404                             new ErrorMsg(ErrorMsg.ILLEGAL_TEXT_NODE_ERR,l,null);
 405                         reportError(ERROR, err);
 406                     }
 407                 }
 408                 if (!errorsFound()) {
 409                     stylesheet.typeCheck(_symbolTable);
 410                 }
 411             }
 412         }
 413         catch (TypeCheckError e) {
 414             reportError(ERROR, new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR, e));
 415         }
 416     }
 417 
 418     /**
 419      * Parses a stylesheet and builds the internal abstract syntax tree
 420      * @param reader A SAX2 SAXReader (parser)


 684         initAttrTable("value-of",
 685             new String[] {"select", "disable-output-escaping"});
 686         initAttrTable("element",
 687             new String[] {"name", "namespace", "use-attribute-sets"});
 688         initAttrTable("call-template", new String[] {"name"});
 689         initAttrTable("apply-templates", new String[] {"select", "mode"});
 690         initAttrTable("apply-imports", new String[] {});
 691         initAttrTable("decimal-format",
 692             new String[] {"name", "decimal-separator", "grouping-separator",
 693                 "infinity", "minus-sign", "NaN", "percent", "per-mille",
 694                 "zero-digit", "digit", "pattern-separator"});
 695         initAttrTable("import", new String[] {"href"});
 696         initAttrTable("include", new String[] {"href"});
 697         initAttrTable("strip-space", new String[] {"elements"});
 698         initAttrTable("preserve-space", new String[] {"elements"});
 699         initAttrTable("processing-instruction", new String[] {"name"});
 700         initAttrTable("namespace-alias",
 701            new String[] {"stylesheet-prefix", "result-prefix"});
 702     }
 703 


 704     /**
 705      * Initialize the _instructionClasses map, which maps XSL element
 706      * names to Java classes in this package.
 707      */
 708     private void initStdClasses() {
 709         initStdClass("template", "Template");
 710         initStdClass("stylesheet", "Stylesheet");
 711         initStdClass("transform", "Stylesheet");
 712         initStdClass("text", "Text");
 713         initStdClass("if", "If");
 714         initStdClass("choose", "Choose");
 715         initStdClass("when", "When");
 716         initStdClass("otherwise", "Otherwise");
 717         initStdClass("for-each", "ForEach");
 718         initStdClass("message", "Message");
 719         initStdClass("number", "Number");
 720         initStdClass("comment", "Comment");
 721         initStdClass("copy", "Copy");
 722         initStdClass("copy-of", "CopyOf");
 723         initStdClass("param", "Param");


 757     }
 758 
 759     private void initExtClasses() {
 760         initExtClass("output", "TransletOutput");
 761         initExtClass(REDIRECT_URI, "write", "TransletOutput");
 762     }
 763 
 764     private void initExtClass(String elementName, String className) {
 765         _instructionClasses.put(getQName(TRANSLET_URI, TRANSLET, elementName).getStringRep(),
 766                                 COMPILER_PACKAGE + '.' + className);
 767     }
 768 
 769     private void initExtClass(String namespace, String elementName, String className) {
 770         _instructionClasses.put(getQName(namespace, TRANSLET, elementName).getStringRep(),
 771                                 COMPILER_PACKAGE + '.' + className);
 772     }
 773 
 774     /**
 775      * Add primops and base functions to the symbol table.
 776      */
 777     @SuppressWarnings("unused")
 778     private void initSymbolTable() {
 779         MethodType I_V  = new MethodType(Type.Int, Type.Void);
 780         MethodType I_R  = new MethodType(Type.Int, Type.Real);
 781         MethodType I_S  = new MethodType(Type.Int, Type.String);
 782         MethodType I_D  = new MethodType(Type.Int, Type.NodeSet);
 783         MethodType R_I  = new MethodType(Type.Real, Type.Int);
 784         MethodType R_V  = new MethodType(Type.Real, Type.Void);
 785         MethodType R_R  = new MethodType(Type.Real, Type.Real);
 786         MethodType R_D  = new MethodType(Type.Real, Type.NodeSet);
 787         MethodType R_O  = new MethodType(Type.Real, Type.Reference);
 788         MethodType I_I  = new MethodType(Type.Int, Type.Int);
 789         MethodType D_O  = new MethodType(Type.NodeSet, Type.Reference);
 790         MethodType D_V  = new MethodType(Type.NodeSet, Type.Void);
 791         MethodType D_S  = new MethodType(Type.NodeSet, Type.String);
 792         MethodType D_D  = new MethodType(Type.NodeSet, Type.NodeSet);
 793         MethodType A_V  = new MethodType(Type.Node, Type.Void);
 794         MethodType S_V  = new MethodType(Type.String, Type.Void);
 795         MethodType S_S  = new MethodType(Type.String, Type.String);
 796         MethodType S_A  = new MethodType(Type.String, Type.Node);
 797         MethodType S_D  = new MethodType(Type.String, Type.NodeSet);


 950     }
 951 
 952     /**
 953      * Creates a new node in the abstract syntax tree. This node can be
 954      *  o) a supported XSLT 1.0 element
 955      *  o) an unsupported XSLT element (post 1.0)
 956      *  o) a supported XSLT extension
 957      *  o) an unsupported XSLT extension
 958      *  o) a literal result element (not an XSLT element and not an extension)
 959      * Unsupported elements do not directly generate an error. We have to wait
 960      * until we have received all child elements of an unsupported element to
 961      * see if any <xsl:fallback> elements exist.
 962      */
 963 
 964     private boolean versionIsOne = true;
 965 
 966     public SyntaxTreeNode makeInstance(String uri, String prefix,
 967         String local, Attributes attributes)
 968     {
 969         SyntaxTreeNode node = null;
 970         QName qname = getQName(uri, prefix, local);
 971         String className = _instructionClasses.get(qname.getStringRep());
 972 
 973         if (className != null) {
 974             try {
 975                 final Class<?> clazz = ObjectFactory.findProviderClass(className, true);
 976                 node = (SyntaxTreeNode)clazz.newInstance();
 977                 node.setQName(qname);
 978                 node.setParser(this);
 979                 if (_locator != null) {
 980                     node.setLineNumber(getLineNumber());
 981                 }
 982                 if (node instanceof Stylesheet) {
 983                     _xsltc.setStylesheet((Stylesheet)node);
 984                 }
 985                 checkForSuperfluousAttributes(node, attributes);
 986             }
 987             catch (ClassNotFoundException e) {
 988                 ErrorMsg err = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, node);
 989                 reportError(ERROR, err);
 990             }
 991             catch (Exception e) {
 992                 ErrorMsg err = new ErrorMsg(ErrorMsg.INTERNAL_ERR,
 993                                             e.getMessage(), node);
 994                 reportError(FATAL, err);
 995             }


1002                     UnsupportedElement element = (UnsupportedElement)node;
1003                     ErrorMsg msg = new ErrorMsg(ErrorMsg.UNSUPPORTED_XSL_ERR,
1004                                                 getLineNumber(),local);
1005                     element.setErrorMessage(msg);
1006                     if (versionIsOne) {
1007                         reportError(UNSUPPORTED,msg);
1008                     }
1009                 }
1010                 // Check if this is an XSLTC extension element
1011                 else if (uri.equals(TRANSLET_URI)) {
1012                     node = new UnsupportedElement(uri, prefix, local, true);
1013                     UnsupportedElement element = (UnsupportedElement)node;
1014                     ErrorMsg msg = new ErrorMsg(ErrorMsg.UNSUPPORTED_EXT_ERR,
1015                                                 getLineNumber(),local);
1016                     element.setErrorMessage(msg);
1017                 }
1018                 // Check if this is an extension of some other XSLT processor
1019                 else {
1020                     Stylesheet sheet = _xsltc.getStylesheet();
1021                     if ((sheet != null) && (sheet.isExtension(uri))) {
1022                         if (sheet != _parentStack.peek()) {
1023                             node = new UnsupportedElement(uri, prefix, local, true);
1024                             UnsupportedElement elem = (UnsupportedElement)node;
1025                             ErrorMsg msg =
1026                                 new ErrorMsg(ErrorMsg.UNSUPPORTED_EXT_ERR,
1027                                              getLineNumber(),
1028                                              prefix+":"+local);
1029                             elem.setErrorMessage(msg);
1030                         }
1031                     }
1032                 }
1033             }
1034             if (node == null) {
1035                 node = new LiteralElement();
1036                 node.setLineNumber(getLineNumber());
1037             }
1038         }
1039         if ((node != null) && (node instanceof LiteralElement)) {
1040             ((LiteralElement)node).setQName(qname);
1041         }
1042         return(node);


1170         return SyntaxTreeNode.Dummy;
1171     }
1172 
1173     /************************ ERROR HANDLING SECTION ************************/
1174 
1175     /**
1176      * Returns true if there were any errors during compilation
1177      */
1178     public boolean errorsFound() {
1179         return _errors.size() > 0;
1180     }
1181 
1182     /**
1183      * Prints all compile-time errors
1184      */
1185     public void printErrors() {
1186         final int size = _errors.size();
1187         if (size > 0) {
1188             System.err.println(new ErrorMsg(ErrorMsg.COMPILER_ERROR_KEY));
1189             for (int i = 0; i < size; i++) {
1190                 System.err.println("  " + _errors.get(i));
1191             }
1192         }
1193     }
1194 
1195     /**
1196      * Prints all compile-time warnings
1197      */
1198     public void printWarnings() {
1199         final int size = _warnings.size();
1200         if (size > 0) {
1201             System.err.println(new ErrorMsg(ErrorMsg.COMPILER_WARNING_KEY));
1202             for (int i = 0; i < size; i++) {
1203                 System.err.println("  " + _warnings.get(i));
1204             }
1205         }
1206     }
1207 
1208     /**
1209      * Common error/warning message handler
1210      */
1211     public void reportError(final int category, final ErrorMsg error) {
1212         switch (category) {
1213         case Constants.INTERNAL:
1214             // Unexpected internal errors, such as null-ptr exceptions, etc.
1215             // Immediately terminates compilation, no translet produced
1216             _errors.add(error);
1217             break;
1218         case Constants.UNSUPPORTED:
1219             // XSLT elements that are not implemented and unsupported ext.
1220             // Immediately terminates compilation, no translet produced
1221             _errors.add(error);
1222             break;
1223         case Constants.FATAL:
1224             // Fatal error in the stylesheet input (parsing or content)
1225             // Immediately terminates compilation, no translet produced
1226             _errors.add(error);
1227             break;
1228         case Constants.ERROR:
1229             // Other error in the stylesheet input (parsing or content)
1230             // Does not terminate compilation, no translet produced
1231             _errors.add(error);
1232             break;
1233         case Constants.WARNING:
1234             // Other error in the stylesheet input (content errors only)
1235             // Does not terminate compilation, a translet is produced
1236             _warnings.add(error);
1237             break;
1238         }
1239     }
1240 
1241     public ArrayList<ErrorMsg> getErrors() {
1242         return _errors;
1243     }
1244 
1245     public ArrayList<ErrorMsg> getWarnings() {
1246         return _warnings;
1247     }
1248 
1249     /************************ SAX2 ContentHandler INTERFACE *****************/
1250 
1251     private Stack<SyntaxTreeNode> _parentStack = null;
1252     private Map<String, String> _prefixMapping = null;
1253 
1254     /**
1255      * SAX2: Receive notification of the beginning of a document.
1256      */
1257     public void startDocument() {
1258         _root = null;
1259         _target = null;
1260         _prefixMapping = null;
1261         _parentStack = new Stack<>();
1262     }
1263 
1264     /**
1265      * SAX2: Receive notification of the end of a document.
1266      */
1267     public void endDocument() { }
1268 
1269 
1270     /**
1271      * SAX2: Begin the scope of a prefix-URI Namespace mapping.
1272      *       This has to be passed on to the symbol table!
1273      */
1274     public void startPrefixMapping(String prefix, String uri) {
1275         if (_prefixMapping == null) {
1276             _prefixMapping = new HashMap<>();
1277         }
1278         _prefixMapping.put(prefix, uri);
1279     }
1280 
1281     /**


1297 
1298         SyntaxTreeNode element = makeInstance(uri, prefix,
1299                                         localname, attributes);
1300         if (element == null) {
1301             ErrorMsg err = new ErrorMsg(ErrorMsg.ELEMENT_PARSE_ERR,
1302                                         prefix+':'+localname);
1303             throw new SAXException(err.toString());
1304         }
1305 
1306         // If this is the root element of the XML document we need to make sure
1307         // that it contains a definition of the XSL namespace URI
1308         if (_root == null) {
1309             if ((_prefixMapping == null) ||
1310                 (_prefixMapping.containsValue(Constants.XSLT_URI) == false))
1311                 _rootNamespaceDef = false;
1312             else
1313                 _rootNamespaceDef = true;
1314             _root = element;
1315         }
1316         else {
1317             SyntaxTreeNode parent = _parentStack.peek();
1318             parent.addElement(element);
1319             element.setParent(parent);
1320         }
1321         element.setAttributes(new AttributesImpl(attributes));
1322         element.setPrefixMapping(_prefixMapping);
1323 
1324         if (element instanceof Stylesheet) {
1325             // Extension elements and excluded elements have to be
1326             // handled at this point in order to correctly generate
1327             // Fallback elements from <xsl:fallback>s.
1328             getSymbolTable().setCurrentNode(element);
1329             ((Stylesheet)element).declareExtensionPrefixes(this);
1330         }
1331 
1332         _prefixMapping = null;
1333         _parentStack.push(element);
1334     }
1335 
1336     /**
1337      * SAX2: Receive notification of the end of an element.
1338      */
1339     public void endElement(String uri, String localname, String qname) {
1340         _parentStack.pop();
1341     }
1342 
1343     /**
1344      * SAX2: Receive notification of character data.
1345      */
1346     public void characters(char[] ch, int start, int length) {
1347         String string = new String(ch, start, length);
1348         SyntaxTreeNode parent = _parentStack.peek();
1349 
1350         if (string.length() == 0) return;
1351 
1352         // If this text occurs within an <xsl:text> element we append it
1353         // as-is to the existing text element
1354         if (parent instanceof Text) {
1355             ((Text)parent).setText(string);
1356             return;
1357         }
1358 
1359         // Ignore text nodes that occur directly under <xsl:stylesheet>
1360         if (parent instanceof Stylesheet) return;
1361 
1362         SyntaxTreeNode bro = parent.lastChild();
1363         if ((bro != null) && (bro instanceof Text)) {
1364             Text text = (Text)bro;
1365             if (!text.isTextElement()) {
1366                 if ((length > 1) || ( ((int)ch[0]) < 0x100)) {
1367                     text.setText(string);
1368                     return;


< prev index next >