< prev index next >

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

Print this page
rev 964 : 8162598: XSLTC transformer swallows empty namespace declaration which is needed to undeclare default namespace
   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  * $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.ArrayList;
  41 import java.util.HashMap;
  42 import java.util.Iterator;


  55 import org.xml.sax.Attributes;
  56 import org.xml.sax.ContentHandler;
  57 import org.xml.sax.InputSource;
  58 import org.xml.sax.Locator;
  59 import org.xml.sax.SAXException;
  60 import org.xml.sax.SAXNotRecognizedException;
  61 import org.xml.sax.SAXNotSupportedException;
  62 import org.xml.sax.SAXParseException;
  63 import org.xml.sax.XMLReader;
  64 import org.xml.sax.helpers.AttributesImpl;
  65 
  66 /**
  67  * @author Jacek Ambroziak
  68  * @author Santiago Pericas-Geertsen
  69  * @author G. Todd Miller
  70  * @author Morten Jorgensen
  71  * @author Erwin Bolwidt <ejb@klomp.org>
  72  */
  73 public class Parser implements Constants, ContentHandler {
  74 
  75     private static final String XSL = "xsl";            // standard prefix
  76     private static final String TRANSLET = "translet"; // extension prefix
  77 
  78     private Locator _locator = null;
  79 
  80     private XSLTC _xsltc;             // Reference to the compiler object.
  81     private XPathParser _xpathParser; // Reference to the XPath parser.
  82     private ArrayList<ErrorMsg> _errors;           // Contains all compilation errors
  83     private ArrayList<ErrorMsg> _warnings;         // Contains all compilation errors
  84 
  85     private Map<String, String>   _instructionClasses; // Maps instructions to classes
  86     private Map<String, String[]> _instructionAttrs;  // reqd and opt attrs
  87     private Map<String, QName>   _qNames;
  88     private Map<String, Map>     _namespaces;
  89     private QName       _useAttributeSets;
  90     private QName       _excludeResultPrefixes;
  91     private QName       _extensionElementPrefixes;
  92     private Map<String, Object>   _variableScope;
  93     private Stylesheet  _currentStylesheet;
  94     private SymbolTable _symbolTable; // Maps QNames to syntax-tree nodes
  95     private Output      _output;
  96     private Template    _template;    // Reference to the template being parsed.
  97 
  98     private boolean     _rootNamespaceDef; // Used for validity check
  99 
 100     private SyntaxTreeNode _root;
 101 
 102     private String _target;
 103 
 104     private int _currentImportPrecedence;
 105 
 106     private boolean _useServicesMechanism = true;
 107 
 108     public Parser(XSLTC xsltc, boolean useServicesMechanism) {


 126         _root                = null;
 127         _rootNamespaceDef    = false;
 128         _currentImportPrecedence = 1;
 129 
 130         initStdClasses();
 131         initInstructionAttrs();
 132         initExtClasses();
 133         initSymbolTable();
 134 
 135         _useAttributeSets =
 136             getQName(XSLT_URI, XSL, "use-attribute-sets");
 137         _excludeResultPrefixes =
 138             getQName(XSLT_URI, XSL, "exclude-result-prefixes");
 139         _extensionElementPrefixes =
 140             getQName(XSLT_URI, XSL, "extension-element-prefixes");
 141     }
 142 
 143     public void setOutput(Output output) {
 144         if (_output != null) {
 145             if (_output.getImportPrecedence() <= output.getImportPrecedence()) {
 146                 String cdata = _output.getCdata();
 147                 output.mergeOutput(_output);
 148                 _output.disable();
 149                 _output = output;
 150             }
 151             else {
 152                 output.disable();
 153             }
 154         }
 155         else {
 156             _output = output;
 157         }
 158     }
 159 
 160     public Output getOutput() {
 161         return _output;
 162     }
 163 
 164     public Properties getOutputProperties() {
 165         return getTopLevelStylesheet().getOutputProperties();
 166     }
 167 
 168     public void addVariable(Variable var) {
 169         addVariableOrParam(var);
 170     }
 171 
 172     public void addParameter(Param param) {
 173         addVariableOrParam(param);
 174     }
 175 
 176     private void addVariableOrParam(VariableBase var) {
 177         Object existing = _variableScope.get(var.getName().getStringRep());
 178         if (existing != null) {
 179             if (existing instanceof Stack) {
 180                 Stack stack = (Stack)existing;

 181                 stack.push(var);
 182             }
 183             else if (existing instanceof VariableBase) {
 184                 Stack stack = new Stack();
 185                 stack.push(existing);
 186                 stack.push(var);
 187                 _variableScope.put(var.getName().getStringRep(), stack);
 188             }
 189         }
 190         else {
 191             _variableScope.put(var.getName().getStringRep(), var);
 192         }
 193     }
 194 
 195     public void removeVariable(QName name) {
 196         Object existing = _variableScope.get(name.getStringRep());
 197         if (existing instanceof Stack) {
 198             Stack stack = (Stack)existing;

 199             if (!stack.isEmpty()) stack.pop();
 200             if (!stack.isEmpty()) return;
 201         }
 202         _variableScope.remove(name.getStringRep());
 203     }
 204 
 205     public VariableBase lookupVariable(QName name) {
 206         Object existing = _variableScope.get(name.getStringRep());
 207         if (existing instanceof VariableBase) {
 208             return((VariableBase)existing);
 209         }
 210         else if (existing instanceof Stack) {
 211             Stack stack = (Stack)existing;
 212             return((VariableBase)stack.peek());

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


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


 714         initAttrTable("value-of",
 715             new String[] {"select", "disable-output-escaping"});
 716         initAttrTable("element",
 717             new String[] {"name", "namespace", "use-attribute-sets"});
 718         initAttrTable("call-template", new String[] {"name"});
 719         initAttrTable("apply-templates", new String[] {"select", "mode"});
 720         initAttrTable("apply-imports", new String[] {});
 721         initAttrTable("decimal-format",
 722             new String[] {"name", "decimal-separator", "grouping-separator",
 723                 "infinity", "minus-sign", "NaN", "percent", "per-mille",
 724                 "zero-digit", "digit", "pattern-separator"});
 725         initAttrTable("import", new String[] {"href"});
 726         initAttrTable("include", new String[] {"href"});
 727         initAttrTable("strip-space", new String[] {"elements"});
 728         initAttrTable("preserve-space", new String[] {"elements"});
 729         initAttrTable("processing-instruction", new String[] {"name"});
 730         initAttrTable("namespace-alias",
 731            new String[] {"stylesheet-prefix", "result-prefix"});
 732     }
 733 
 734 
 735 
 736     /**
 737      * Initialize the _instructionClasses map, which maps XSL element
 738      * names to Java classes in this package.
 739      */
 740     private void initStdClasses() {
 741         initStdClass("template", "Template");
 742         initStdClass("stylesheet", "Stylesheet");
 743         initStdClass("transform", "Stylesheet");
 744         initStdClass("text", "Text");
 745         initStdClass("if", "If");
 746         initStdClass("choose", "Choose");
 747         initStdClass("when", "When");
 748         initStdClass("otherwise", "Otherwise");
 749         initStdClass("for-each", "ForEach");
 750         initStdClass("message", "Message");
 751         initStdClass("number", "Number");
 752         initStdClass("comment", "Comment");
 753         initStdClass("copy", "Copy");
 754         initStdClass("copy-of", "CopyOf");
 755         initStdClass("param", "Param");


 789     }
 790 
 791     private void initExtClasses() {
 792         initExtClass("output", "TransletOutput");
 793         initExtClass(REDIRECT_URI, "write", "TransletOutput");
 794     }
 795 
 796     private void initExtClass(String elementName, String className) {
 797         _instructionClasses.put(getQName(TRANSLET_URI, TRANSLET, elementName).getStringRep(),
 798                                 COMPILER_PACKAGE + '.' + className);
 799     }
 800 
 801     private void initExtClass(String namespace, String elementName, String className) {
 802         _instructionClasses.put(getQName(namespace, TRANSLET, elementName).getStringRep(),
 803                                 COMPILER_PACKAGE + '.' + className);
 804     }
 805 
 806     /**
 807      * Add primops and base functions to the symbol table.
 808      */

 809     private void initSymbolTable() {
 810         MethodType I_V  = new MethodType(Type.Int, Type.Void);
 811         MethodType I_R  = new MethodType(Type.Int, Type.Real);
 812         MethodType I_S  = new MethodType(Type.Int, Type.String);
 813         MethodType I_D  = new MethodType(Type.Int, Type.NodeSet);
 814         MethodType R_I  = new MethodType(Type.Real, Type.Int);
 815         MethodType R_V  = new MethodType(Type.Real, Type.Void);
 816         MethodType R_R  = new MethodType(Type.Real, Type.Real);
 817         MethodType R_D  = new MethodType(Type.Real, Type.NodeSet);
 818         MethodType R_O  = new MethodType(Type.Real, Type.Reference);
 819         MethodType I_I  = new MethodType(Type.Int, Type.Int);
 820         MethodType D_O  = new MethodType(Type.NodeSet, Type.Reference);
 821         MethodType D_V  = new MethodType(Type.NodeSet, Type.Void);
 822         MethodType D_S  = new MethodType(Type.NodeSet, Type.String);
 823         MethodType D_D  = new MethodType(Type.NodeSet, Type.NodeSet);
 824         MethodType A_V  = new MethodType(Type.Node, Type.Void);
 825         MethodType S_V  = new MethodType(Type.String, Type.Void);
 826         MethodType S_S  = new MethodType(Type.String, Type.String);
 827         MethodType S_A  = new MethodType(Type.String, Type.Node);
 828         MethodType S_D  = new MethodType(Type.String, Type.NodeSet);


 981     }
 982 
 983     /**
 984      * Creates a new node in the abstract syntax tree. This node can be
 985      *  o) a supported XSLT 1.0 element
 986      *  o) an unsupported XSLT element (post 1.0)
 987      *  o) a supported XSLT extension
 988      *  o) an unsupported XSLT extension
 989      *  o) a literal result element (not an XSLT element and not an extension)
 990      * Unsupported elements do not directly generate an error. We have to wait
 991      * until we have received all child elements of an unsupported element to
 992      * see if any <xsl:fallback> elements exist.
 993      */
 994 
 995     private boolean versionIsOne = true;
 996 
 997     public SyntaxTreeNode makeInstance(String uri, String prefix,
 998         String local, Attributes attributes)
 999     {
1000         SyntaxTreeNode node = null;
1001         QName  qname = getQName(uri, prefix, local);
1002         String className = _instructionClasses.get(qname.getStringRep());
1003 
1004         if (className != null) {
1005             try {
1006                 final Class clazz = ObjectFactory.findProviderClass(className, true);
1007                 node = (SyntaxTreeNode)clazz.newInstance();
1008                 node.setQName(qname);
1009                 node.setParser(this);
1010                 if (_locator != null) {
1011                     node.setLineNumber(getLineNumber());
1012                 }
1013                 if (node instanceof Stylesheet) {
1014                     _xsltc.setStylesheet((Stylesheet)node);
1015                 }
1016                 checkForSuperfluousAttributes(node, attributes);
1017             }
1018             catch (ClassNotFoundException e) {
1019                 ErrorMsg err = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, node);
1020                 reportError(ERROR, err);
1021             }
1022             catch (Exception e) {
1023                 ErrorMsg err = new ErrorMsg(ErrorMsg.INTERNAL_ERR,
1024                                             e.getMessage(), node);
1025                 reportError(FATAL, err);
1026             }


1033                     UnsupportedElement element = (UnsupportedElement)node;
1034                     ErrorMsg msg = new ErrorMsg(ErrorMsg.UNSUPPORTED_XSL_ERR,
1035                                                 getLineNumber(),local);
1036                     element.setErrorMessage(msg);
1037                     if (versionIsOne) {
1038                         reportError(UNSUPPORTED,msg);
1039                     }
1040                 }
1041                 // Check if this is an XSLTC extension element
1042                 else if (uri.equals(TRANSLET_URI)) {
1043                     node = new UnsupportedElement(uri, prefix, local, true);
1044                     UnsupportedElement element = (UnsupportedElement)node;
1045                     ErrorMsg msg = new ErrorMsg(ErrorMsg.UNSUPPORTED_EXT_ERR,
1046                                                 getLineNumber(),local);
1047                     element.setErrorMessage(msg);
1048                 }
1049                 // Check if this is an extension of some other XSLT processor
1050                 else {
1051                     Stylesheet sheet = _xsltc.getStylesheet();
1052                     if ((sheet != null) && (sheet.isExtension(uri))) {
1053                         if (sheet != (SyntaxTreeNode)_parentStack.peek()) {
1054                             node = new UnsupportedElement(uri, prefix, local, true);
1055                             UnsupportedElement elem = (UnsupportedElement)node;
1056                             ErrorMsg msg =
1057                                 new ErrorMsg(ErrorMsg.UNSUPPORTED_EXT_ERR,
1058                                              getLineNumber(),
1059                                              prefix+":"+local);
1060                             elem.setErrorMessage(msg);
1061                         }
1062                     }
1063                 }
1064             }
1065             if (node == null) {
1066                 node = new LiteralElement();
1067                 node.setLineNumber(getLineNumber());
1068             }
1069         }
1070         if ((node != null) && (node instanceof LiteralElement)) {
1071             ((LiteralElement)node).setQName(qname);
1072         }
1073         return(node);


1166         return (Pattern)parseTopLevel(parent, "<PATTERN>"+pattern, pattern);
1167     }
1168 
1169     /**
1170      * Parse an XPath expression or pattern using the generated XPathParser
1171      * The method will return a Dummy node if the XPath parser fails.
1172      */
1173     private SyntaxTreeNode parseTopLevel(SyntaxTreeNode parent, String text,
1174                                          String expression) {
1175         int line = getLineNumber();
1176 
1177         try {
1178             _xpathParser.setScanner(new XPathLexer(new StringReader(text)));
1179             Symbol result = _xpathParser.parse(expression, line);
1180             if (result != null) {
1181                 final SyntaxTreeNode node = (SyntaxTreeNode)result.value;
1182                 if (node != null) {
1183                     node.setParser(this);
1184                     node.setParent(parent);
1185                     node.setLineNumber(line);
1186 // System.out.println("e = " + text + " " + node);
1187                     return node;
1188                 }
1189             }
1190             reportError(ERROR, new ErrorMsg(ErrorMsg.XPATH_PARSER_ERR,
1191                                             expression, parent));
1192         }
1193         catch (Exception e) {
1194             if (_xsltc.debug()) e.printStackTrace();
1195             reportError(ERROR, new ErrorMsg(ErrorMsg.XPATH_PARSER_ERR,
1196                                             expression, parent));
1197         }
1198 
1199         // Return a dummy pattern (which is an expression)
1200         SyntaxTreeNode.Dummy.setParser(this);
1201         return SyntaxTreeNode.Dummy;
1202     }
1203 
1204     /************************ ERROR HANDLING SECTION ************************/
1205 
1206     /**


1262             _errors.add(error);
1263             break;
1264         case Constants.WARNING:
1265             // Other error in the stylesheet input (content errors only)
1266             // Does not terminate compilation, a translet is produced
1267             _warnings.add(error);
1268             break;
1269         }
1270     }
1271 
1272     public ArrayList<ErrorMsg> getErrors() {
1273         return _errors;
1274     }
1275 
1276     public ArrayList<ErrorMsg> getWarnings() {
1277         return _warnings;
1278     }
1279 
1280     /************************ SAX2 ContentHandler INTERFACE *****************/
1281 
1282     private Stack _parentStack = null;
1283     private Map<String, String> _prefixMapping = null;
1284 
1285     /**
1286      * SAX2: Receive notification of the beginning of a document.
1287      */
1288     public void startDocument() {
1289         _root = null;
1290         _target = null;
1291         _prefixMapping = null;
1292         _parentStack = new Stack();
1293     }
1294 
1295     /**
1296      * SAX2: Receive notification of the end of a document.
1297      */
1298     public void endDocument() { }
1299 
1300 
1301     /**
1302      * SAX2: Begin the scope of a prefix-URI Namespace mapping.
1303      *       This has to be passed on to the symbol table!
1304      */
1305     public void startPrefixMapping(String prefix, String uri) {
1306         if (_prefixMapping == null) {
1307             _prefixMapping = new HashMap<>();
1308         }
1309         _prefixMapping.put(prefix, uri);
1310     }
1311 
1312     /**


1328 
1329         SyntaxTreeNode element = makeInstance(uri, prefix,
1330                                         localname, attributes);
1331         if (element == null) {
1332             ErrorMsg err = new ErrorMsg(ErrorMsg.ELEMENT_PARSE_ERR,
1333                                         prefix+':'+localname);
1334             throw new SAXException(err.toString());
1335         }
1336 
1337         // If this is the root element of the XML document we need to make sure
1338         // that it contains a definition of the XSL namespace URI
1339         if (_root == null) {
1340             if ((_prefixMapping == null) ||
1341                 (_prefixMapping.containsValue(Constants.XSLT_URI) == false))
1342                 _rootNamespaceDef = false;
1343             else
1344                 _rootNamespaceDef = true;
1345             _root = element;
1346         }
1347         else {
1348             SyntaxTreeNode parent = (SyntaxTreeNode)_parentStack.peek();
1349             parent.addElement(element);
1350             element.setParent(parent);
1351         }
1352         element.setAttributes(new AttributesImpl(attributes));
1353         element.setPrefixMapping(_prefixMapping);
1354 
1355         if (element instanceof Stylesheet) {
1356             // Extension elements and excluded elements have to be
1357             // handled at this point in order to correctly generate
1358             // Fallback elements from <xsl:fallback>s.
1359             getSymbolTable().setCurrentNode(element);
1360             ((Stylesheet)element).declareExtensionPrefixes(this);
1361         }
1362 
1363         _prefixMapping = null;
1364         _parentStack.push(element);
1365     }
1366 
1367     /**
1368      * SAX2: Receive notification of the end of an element.
1369      */
1370     public void endElement(String uri, String localname, String qname) {
1371         _parentStack.pop();
1372     }
1373 
1374     /**
1375      * SAX2: Receive notification of character data.
1376      */
1377     public void characters(char[] ch, int start, int length) {
1378         String string = new String(ch, start, length);
1379         SyntaxTreeNode parent = (SyntaxTreeNode)_parentStack.peek();
1380 
1381         if (string.length() == 0) return;
1382 
1383         // If this text occurs within an <xsl:text> element we append it
1384         // as-is to the existing text element
1385         if (parent instanceof Text) {
1386             ((Text)parent).setText(string);
1387             return;
1388         }
1389 
1390         // Ignore text nodes that occur directly under <xsl:stylesheet>
1391         if (parent instanceof Stylesheet) return;
1392 
1393         SyntaxTreeNode bro = parent.lastChild();
1394         if ((bro != null) && (bro instanceof Text)) {
1395             Text text = (Text)bro;
1396             if (!text.isTextElement()) {
1397                 if ((length > 1) || ( ((int)ch[0]) < 0x100)) {
1398                     text.setText(string);
1399                     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;


  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.SAXNotSupportedException;
  59 import org.xml.sax.SAXParseException;
  60 import org.xml.sax.XMLReader;
  61 import org.xml.sax.helpers.AttributesImpl;
  62 
  63 /**
  64  * @author Jacek Ambroziak
  65  * @author Santiago Pericas-Geertsen
  66  * @author G. Todd Miller
  67  * @author Morten Jorgensen
  68  * @author Erwin Bolwidt <ejb@klomp.org>
  69  */
  70 public class Parser implements Constants, ContentHandler {
  71 
  72     private static final String XSL = "xsl";           // standard prefix
  73     private static final String TRANSLET = "translet"; // extension prefix
  74 
  75     private Locator _locator = null;
  76 
  77     private XSLTC _xsltc;                  // Reference to the compiler object.
  78     private XPathParser _xpathParser;      // Reference to the XPath parser.
  79     private ArrayList<ErrorMsg> _errors;   // Contains all compilation errors
  80     private ArrayList<ErrorMsg> _warnings; // Contains all compilation warnings
  81 
  82     private Map<String, String>   _instructionClasses; // Maps instructions to classes
  83     private Map<String, String[]> _instructionAttrs;  // reqd and opt attrs
  84     private Map<String, QName>    _qNames;
  85     private Map<String, Map<String, QName>> _namespaces;
  86     private QName       _useAttributeSets;
  87     private QName       _excludeResultPrefixes;
  88     private QName       _extensionElementPrefixes;
  89     private Map<String, Object>   _variableScope;
  90     private Stylesheet  _currentStylesheet;
  91     private SymbolTable _symbolTable; // Maps QNames to syntax-tree nodes
  92     private Output      _output;
  93     private Template    _template;    // Reference to the template being parsed.
  94 
  95     private boolean     _rootNamespaceDef; // Used for validity check
  96 
  97     private SyntaxTreeNode _root;
  98 
  99     private String _target;
 100 
 101     private int _currentImportPrecedence;
 102 
 103     private boolean _useServicesMechanism = true;
 104 
 105     public Parser(XSLTC xsltc, boolean useServicesMechanism) {


 123         _root                = null;
 124         _rootNamespaceDef    = false;
 125         _currentImportPrecedence = 1;
 126 
 127         initStdClasses();
 128         initInstructionAttrs();
 129         initExtClasses();
 130         initSymbolTable();
 131 
 132         _useAttributeSets =
 133             getQName(XSLT_URI, XSL, "use-attribute-sets");
 134         _excludeResultPrefixes =
 135             getQName(XSLT_URI, XSL, "exclude-result-prefixes");
 136         _extensionElementPrefixes =
 137             getQName(XSLT_URI, XSL, "extension-element-prefixes");
 138     }
 139 
 140     public void setOutput(Output output) {
 141         if (_output != null) {
 142             if (_output.getImportPrecedence() <= output.getImportPrecedence()) {

 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                 @SuppressWarnings("unchecked")
 177                 Stack<VariableBase> stack = (Stack<VariableBase>)existing;
 178                 stack.push(var);
 179             }
 180             else if (existing instanceof VariableBase) {
 181                 Stack<VariableBase> stack = new Stack<>();
 182                 stack.push((VariableBase)existing);
 183                 stack.push(var);
 184                 _variableScope.put(var.getName().getStringRep(), stack);
 185             }
 186         }
 187         else {
 188             _variableScope.put(var.getName().getStringRep(), var);
 189         }
 190     }
 191 
 192     public void removeVariable(QName name) {
 193         Object existing = _variableScope.get(name.getStringRep());
 194         if (existing instanceof Stack) {
 195             @SuppressWarnings("unchecked")
 196             Stack<VariableBase> stack = (Stack<VariableBase>)existing;
 197             if (!stack.isEmpty()) stack.pop();
 198             if (!stack.isEmpty()) return;
 199         }
 200         _variableScope.remove(name.getStringRep());
 201     }
 202 
 203     public VariableBase lookupVariable(QName name) {
 204         Object existing = _variableScope.get(name.getStringRep());
 205         if (existing instanceof VariableBase) {
 206             return (VariableBase)existing;
 207         }
 208         else if (existing instanceof Stack) {
 209             @SuppressWarnings("unchecked")
 210             Stack<VariableBase> stack = (Stack<VariableBase>)existing;
 211             return stack.peek();
 212         }
 213         return null;
 214     }
 215 
 216     public void setXSLTC(XSLTC xsltc) {
 217         _xsltc = xsltc;
 218     }
 219 
 220     public XSLTC getXSLTC() {
 221         return _xsltc;
 222     }
 223 
 224     public int getCurrentImportPrecedence() {
 225         return _currentImportPrecedence;
 226     }
 227 
 228     public int getNextImportPrecedence() {
 229         return ++_currentImportPrecedence;
 230     }
 231 
 232     public void setCurrentStylesheet(Stylesheet stylesheet) {
 233         _currentStylesheet = stylesheet;


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

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


 712         initAttrTable("value-of",
 713             new String[] {"select", "disable-output-escaping"});
 714         initAttrTable("element",
 715             new String[] {"name", "namespace", "use-attribute-sets"});
 716         initAttrTable("call-template", new String[] {"name"});
 717         initAttrTable("apply-templates", new String[] {"select", "mode"});
 718         initAttrTable("apply-imports", new String[] {});
 719         initAttrTable("decimal-format",
 720             new String[] {"name", "decimal-separator", "grouping-separator",
 721                 "infinity", "minus-sign", "NaN", "percent", "per-mille",
 722                 "zero-digit", "digit", "pattern-separator"});
 723         initAttrTable("import", new String[] {"href"});
 724         initAttrTable("include", new String[] {"href"});
 725         initAttrTable("strip-space", new String[] {"elements"});
 726         initAttrTable("preserve-space", new String[] {"elements"});
 727         initAttrTable("processing-instruction", new String[] {"name"});
 728         initAttrTable("namespace-alias",
 729            new String[] {"stylesheet-prefix", "result-prefix"});
 730     }
 731 


 732     /**
 733      * Initialize the _instructionClasses map, which maps XSL element
 734      * names to Java classes in this package.
 735      */
 736     private void initStdClasses() {
 737         initStdClass("template", "Template");
 738         initStdClass("stylesheet", "Stylesheet");
 739         initStdClass("transform", "Stylesheet");
 740         initStdClass("text", "Text");
 741         initStdClass("if", "If");
 742         initStdClass("choose", "Choose");
 743         initStdClass("when", "When");
 744         initStdClass("otherwise", "Otherwise");
 745         initStdClass("for-each", "ForEach");
 746         initStdClass("message", "Message");
 747         initStdClass("number", "Number");
 748         initStdClass("comment", "Comment");
 749         initStdClass("copy", "Copy");
 750         initStdClass("copy-of", "CopyOf");
 751         initStdClass("param", "Param");


 785     }
 786 
 787     private void initExtClasses() {
 788         initExtClass("output", "TransletOutput");
 789         initExtClass(REDIRECT_URI, "write", "TransletOutput");
 790     }
 791 
 792     private void initExtClass(String elementName, String className) {
 793         _instructionClasses.put(getQName(TRANSLET_URI, TRANSLET, elementName).getStringRep(),
 794                                 COMPILER_PACKAGE + '.' + className);
 795     }
 796 
 797     private void initExtClass(String namespace, String elementName, String className) {
 798         _instructionClasses.put(getQName(namespace, TRANSLET, elementName).getStringRep(),
 799                                 COMPILER_PACKAGE + '.' + className);
 800     }
 801 
 802     /**
 803      * Add primops and base functions to the symbol table.
 804      */
 805     @SuppressWarnings("unused")
 806     private void initSymbolTable() {
 807         MethodType I_V  = new MethodType(Type.Int, Type.Void);
 808         MethodType I_R  = new MethodType(Type.Int, Type.Real);
 809         MethodType I_S  = new MethodType(Type.Int, Type.String);
 810         MethodType I_D  = new MethodType(Type.Int, Type.NodeSet);
 811         MethodType R_I  = new MethodType(Type.Real, Type.Int);
 812         MethodType R_V  = new MethodType(Type.Real, Type.Void);
 813         MethodType R_R  = new MethodType(Type.Real, Type.Real);
 814         MethodType R_D  = new MethodType(Type.Real, Type.NodeSet);
 815         MethodType R_O  = new MethodType(Type.Real, Type.Reference);
 816         MethodType I_I  = new MethodType(Type.Int, Type.Int);
 817         MethodType D_O  = new MethodType(Type.NodeSet, Type.Reference);
 818         MethodType D_V  = new MethodType(Type.NodeSet, Type.Void);
 819         MethodType D_S  = new MethodType(Type.NodeSet, Type.String);
 820         MethodType D_D  = new MethodType(Type.NodeSet, Type.NodeSet);
 821         MethodType A_V  = new MethodType(Type.Node, Type.Void);
 822         MethodType S_V  = new MethodType(Type.String, Type.Void);
 823         MethodType S_S  = new MethodType(Type.String, Type.String);
 824         MethodType S_A  = new MethodType(Type.String, Type.Node);
 825         MethodType S_D  = new MethodType(Type.String, Type.NodeSet);


 978     }
 979 
 980     /**
 981      * Creates a new node in the abstract syntax tree. This node can be
 982      *  o) a supported XSLT 1.0 element
 983      *  o) an unsupported XSLT element (post 1.0)
 984      *  o) a supported XSLT extension
 985      *  o) an unsupported XSLT extension
 986      *  o) a literal result element (not an XSLT element and not an extension)
 987      * Unsupported elements do not directly generate an error. We have to wait
 988      * until we have received all child elements of an unsupported element to
 989      * see if any <xsl:fallback> elements exist.
 990      */
 991 
 992     private boolean versionIsOne = true;
 993 
 994     public SyntaxTreeNode makeInstance(String uri, String prefix,
 995         String local, Attributes attributes)
 996     {
 997         SyntaxTreeNode node = null;
 998         QName qname = getQName(uri, prefix, local);
 999         String className = _instructionClasses.get(qname.getStringRep());
1000 
1001         if (className != null) {
1002             try {
1003                 final Class<?> clazz = ObjectFactory.findProviderClass(className, true);
1004                 node = (SyntaxTreeNode)clazz.newInstance();
1005                 node.setQName(qname);
1006                 node.setParser(this);
1007                 if (_locator != null) {
1008                     node.setLineNumber(getLineNumber());
1009                 }
1010                 if (node instanceof Stylesheet) {
1011                     _xsltc.setStylesheet((Stylesheet)node);
1012                 }
1013                 checkForSuperfluousAttributes(node, attributes);
1014             }
1015             catch (ClassNotFoundException e) {
1016                 ErrorMsg err = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, node);
1017                 reportError(ERROR, err);
1018             }
1019             catch (Exception e) {
1020                 ErrorMsg err = new ErrorMsg(ErrorMsg.INTERNAL_ERR,
1021                                             e.getMessage(), node);
1022                 reportError(FATAL, err);
1023             }


1030                     UnsupportedElement element = (UnsupportedElement)node;
1031                     ErrorMsg msg = new ErrorMsg(ErrorMsg.UNSUPPORTED_XSL_ERR,
1032                                                 getLineNumber(),local);
1033                     element.setErrorMessage(msg);
1034                     if (versionIsOne) {
1035                         reportError(UNSUPPORTED,msg);
1036                     }
1037                 }
1038                 // Check if this is an XSLTC extension element
1039                 else if (uri.equals(TRANSLET_URI)) {
1040                     node = new UnsupportedElement(uri, prefix, local, true);
1041                     UnsupportedElement element = (UnsupportedElement)node;
1042                     ErrorMsg msg = new ErrorMsg(ErrorMsg.UNSUPPORTED_EXT_ERR,
1043                                                 getLineNumber(),local);
1044                     element.setErrorMessage(msg);
1045                 }
1046                 // Check if this is an extension of some other XSLT processor
1047                 else {
1048                     Stylesheet sheet = _xsltc.getStylesheet();
1049                     if ((sheet != null) && (sheet.isExtension(uri))) {
1050                         if (sheet != _parentStack.peek()) {
1051                             node = new UnsupportedElement(uri, prefix, local, true);
1052                             UnsupportedElement elem = (UnsupportedElement)node;
1053                             ErrorMsg msg =
1054                                 new ErrorMsg(ErrorMsg.UNSUPPORTED_EXT_ERR,
1055                                              getLineNumber(),
1056                                              prefix+":"+local);
1057                             elem.setErrorMessage(msg);
1058                         }
1059                     }
1060                 }
1061             }
1062             if (node == null) {
1063                 node = new LiteralElement();
1064                 node.setLineNumber(getLineNumber());
1065             }
1066         }
1067         if ((node != null) && (node instanceof LiteralElement)) {
1068             ((LiteralElement)node).setQName(qname);
1069         }
1070         return(node);


1163         return (Pattern)parseTopLevel(parent, "<PATTERN>"+pattern, pattern);
1164     }
1165 
1166     /**
1167      * Parse an XPath expression or pattern using the generated XPathParser
1168      * The method will return a Dummy node if the XPath parser fails.
1169      */
1170     private SyntaxTreeNode parseTopLevel(SyntaxTreeNode parent, String text,
1171                                          String expression) {
1172         int line = getLineNumber();
1173 
1174         try {
1175             _xpathParser.setScanner(new XPathLexer(new StringReader(text)));
1176             Symbol result = _xpathParser.parse(expression, line);
1177             if (result != null) {
1178                 final SyntaxTreeNode node = (SyntaxTreeNode)result.value;
1179                 if (node != null) {
1180                     node.setParser(this);
1181                     node.setParent(parent);
1182                     node.setLineNumber(line);

1183                     return node;
1184                 }
1185             }
1186             reportError(ERROR, new ErrorMsg(ErrorMsg.XPATH_PARSER_ERR,
1187                                             expression, parent));
1188         }
1189         catch (Exception e) {
1190             if (_xsltc.debug()) e.printStackTrace();
1191             reportError(ERROR, new ErrorMsg(ErrorMsg.XPATH_PARSER_ERR,
1192                                             expression, parent));
1193         }
1194 
1195         // Return a dummy pattern (which is an expression)
1196         SyntaxTreeNode.Dummy.setParser(this);
1197         return SyntaxTreeNode.Dummy;
1198     }
1199 
1200     /************************ ERROR HANDLING SECTION ************************/
1201 
1202     /**


1258             _errors.add(error);
1259             break;
1260         case Constants.WARNING:
1261             // Other error in the stylesheet input (content errors only)
1262             // Does not terminate compilation, a translet is produced
1263             _warnings.add(error);
1264             break;
1265         }
1266     }
1267 
1268     public ArrayList<ErrorMsg> getErrors() {
1269         return _errors;
1270     }
1271 
1272     public ArrayList<ErrorMsg> getWarnings() {
1273         return _warnings;
1274     }
1275 
1276     /************************ SAX2 ContentHandler INTERFACE *****************/
1277 
1278     private Stack<SyntaxTreeNode> _parentStack = null;
1279     private Map<String, String> _prefixMapping = null;
1280 
1281     /**
1282      * SAX2: Receive notification of the beginning of a document.
1283      */
1284     public void startDocument() {
1285         _root = null;
1286         _target = null;
1287         _prefixMapping = null;
1288         _parentStack = new Stack<>();
1289     }
1290 
1291     /**
1292      * SAX2: Receive notification of the end of a document.
1293      */
1294     public void endDocument() { }
1295 
1296 
1297     /**
1298      * SAX2: Begin the scope of a prefix-URI Namespace mapping.
1299      *       This has to be passed on to the symbol table!
1300      */
1301     public void startPrefixMapping(String prefix, String uri) {
1302         if (_prefixMapping == null) {
1303             _prefixMapping = new HashMap<>();
1304         }
1305         _prefixMapping.put(prefix, uri);
1306     }
1307 
1308     /**


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


< prev index next >