1 16 19 20 package org.apache.xalan.xsltc.compiler; 21 22 import java.net.URL ; 23 import java.net.MalformedURLException ; 24 25 import java.util.Vector ; 26 import java.util.Enumeration ; 27 import java.util.Hashtable ; 28 import java.util.Iterator ; 29 import java.util.Properties ; 30 import java.util.StringTokenizer ; 31 32 import org.apache.xml.utils.SystemIDResolver; 33 import org.apache.bcel.generic.ANEWARRAY; 34 import org.apache.bcel.generic.BasicType; 35 import org.apache.bcel.generic.ConstantPoolGen; 36 import org.apache.bcel.generic.FieldGen; 37 import org.apache.bcel.generic.GETFIELD; 38 import org.apache.bcel.generic.GETSTATIC; 39 import org.apache.bcel.generic.INVOKEINTERFACE; 40 import org.apache.bcel.generic.INVOKESPECIAL; 41 import org.apache.bcel.generic.INVOKEVIRTUAL; 42 import org.apache.bcel.generic.ISTORE; 43 import org.apache.bcel.generic.InstructionHandle; 44 import org.apache.bcel.generic.InstructionList; 45 import org.apache.bcel.generic.LocalVariableGen; 46 import org.apache.bcel.generic.NEW; 47 import org.apache.bcel.generic.NEWARRAY; 48 import org.apache.bcel.generic.PUSH; 49 import org.apache.bcel.generic.PUTFIELD; 50 import org.apache.bcel.generic.PUTSTATIC; 51 import org.apache.bcel.generic.TargetLostException; 52 import org.apache.bcel.util.InstructionFinder; 53 import org.apache.xalan.xsltc.compiler.util.ClassGenerator; 54 import org.apache.xalan.xsltc.compiler.util.ErrorMsg; 55 import org.apache.xalan.xsltc.compiler.util.MethodGenerator; 56 import org.apache.xalan.xsltc.compiler.util.Type; 57 import org.apache.xalan.xsltc.compiler.util.TypeCheckError; 58 import org.apache.xalan.xsltc.compiler.util.Util; 59 import org.apache.xalan.xsltc.runtime.AbstractTranslet; 60 import org.apache.xml.dtm.DTM; 61 62 67 public final class Stylesheet extends SyntaxTreeNode { 68 69 72 private String _version; 73 74 77 private QName _name; 78 79 82 private String _systemId; 83 84 87 private Stylesheet _parentStylesheet; 88 89 92 private Vector _globals = new Vector (); 93 94 97 private Boolean _hasLocalParams = null; 98 99 102 private String _className; 103 104 107 private final Vector _templates = new Vector (); 108 109 113 private Vector _allValidTemplates = null; 114 115 118 private int _nextModeSerial = 1; 119 120 123 private final Hashtable _modes = new Hashtable (); 124 125 128 private Mode _defaultMode; 129 130 133 private final Hashtable _extensions = new Hashtable (); 134 135 139 public Stylesheet _importedFrom = null; 140 141 145 public Stylesheet _includedFrom = null; 146 147 150 private Vector _includedStylesheets = null; 151 152 155 private int _importPrecedence = 1; 156 157 160 private Hashtable _keys = new Hashtable (); 161 162 166 private SourceLoader _loader = null; 167 168 171 private boolean _numberFormattingUsed = false; 172 173 177 private boolean _simplified = false; 178 179 182 private boolean _multiDocument = false; 183 184 187 private boolean _callsNodeset = false; 188 189 192 private boolean _hasIdCall = false; 193 194 197 private boolean _templateInlining = true; 198 199 202 private Output _lastOutputElement = null; 203 204 207 private Properties _outputProperties = null; 208 209 213 private int _outputMethod = UNKNOWN_OUTPUT; 214 215 public static final int UNKNOWN_OUTPUT = 0; 217 public static final int XML_OUTPUT = 1; 218 public static final int HTML_OUTPUT = 2; 219 public static final int TEXT_OUTPUT = 3; 220 221 224 public int getOutputMethod() { 225 return _outputMethod; 226 } 227 228 231 private void checkOutputMethod() { 232 if (_lastOutputElement != null) { 233 String method = _lastOutputElement.getOutputMethod(); 234 if (method != null) { 235 if (method.equals("xml")) 236 _outputMethod = XML_OUTPUT; 237 else if (method.equals("html")) 238 _outputMethod = HTML_OUTPUT; 239 else if (method.equals("text")) 240 _outputMethod = TEXT_OUTPUT; 241 } 242 } 243 } 244 245 public boolean getTemplateInlining() { 246 return _templateInlining; 247 } 248 249 public void setTemplateInlining(boolean flag) { 250 _templateInlining = flag; 251 } 252 253 public boolean isSimplified() { 254 return(_simplified); 255 } 256 257 public void setSimplified() { 258 _simplified = true; 259 } 260 261 public void setHasIdCall(boolean flag) { 262 _hasIdCall = flag; 263 } 264 265 public void setOutputProperty(String key, String value) { 266 if (_outputProperties == null) { 267 _outputProperties = new Properties (); 268 } 269 _outputProperties.setProperty(key, value); 270 } 271 272 public void setOutputProperties(Properties props) { 273 _outputProperties = props; 274 } 275 276 public Properties getOutputProperties() { 277 return _outputProperties; 278 } 279 280 public Output getLastOutputElement() { 281 return _lastOutputElement; 282 } 283 284 public void setMultiDocument(boolean flag) { 285 _multiDocument = flag; 286 } 287 288 public boolean isMultiDocument() { 289 return _multiDocument; 290 } 291 292 public void setCallsNodeset(boolean flag) { 293 if (flag) setMultiDocument(flag); 294 _callsNodeset = flag; 295 } 296 297 public boolean callsNodeset() { 298 return _callsNodeset; 299 } 300 301 public void numberFormattingUsed() { 302 _numberFormattingUsed = true; 303 309 Stylesheet parent = getParentStylesheet(); 310 if (null != parent) parent.numberFormattingUsed(); 311 } 312 313 public void setImportPrecedence(final int precedence) { 314 _importPrecedence = precedence; 316 317 final Enumeration elements = elements(); 319 while (elements.hasMoreElements()) { 320 SyntaxTreeNode child = (SyntaxTreeNode)elements.nextElement(); 321 if (child instanceof Include) { 322 Stylesheet included = ((Include)child).getIncludedStylesheet(); 323 if (included != null && included._includedFrom == this) { 324 included.setImportPrecedence(precedence); 325 } 326 } 327 } 328 329 if (_importedFrom != null) { 331 if (_importedFrom.getImportPrecedence() < precedence) { 332 final Parser parser = getParser(); 333 final int nextPrecedence = parser.getNextImportPrecedence(); 334 _importedFrom.setImportPrecedence(nextPrecedence); 335 } 336 } 337 else if (_includedFrom != null) { 339 if (_includedFrom.getImportPrecedence() != precedence) 340 _includedFrom.setImportPrecedence(precedence); 341 } 342 } 343 344 public int getImportPrecedence() { 345 return _importPrecedence; 346 } 347 348 public boolean checkForLoop(String systemId) { 349 if (_systemId != null && _systemId.equals(systemId)) { 351 return true; 352 } 353 if (_parentStylesheet != null) 355 return _parentStylesheet.checkForLoop(systemId); 356 return false; 358 } 359 360 public void setParser(Parser parser) { 361 super.setParser(parser); 362 _name = makeStylesheetName("__stylesheet_"); 363 } 364 365 public void setParentStylesheet(Stylesheet parent) { 366 _parentStylesheet = parent; 367 } 368 369 public Stylesheet getParentStylesheet() { 370 return _parentStylesheet; 371 } 372 373 public void setImportingStylesheet(Stylesheet parent) { 374 _importedFrom = parent; 375 parent.addIncludedStylesheet(this); 376 } 377 378 public void setIncludingStylesheet(Stylesheet parent) { 379 _includedFrom = parent; 380 parent.addIncludedStylesheet(this); 381 } 382 383 public void addIncludedStylesheet(Stylesheet child) { 384 if (_includedStylesheets == null) { 385 _includedStylesheets = new Vector (); 386 } 387 _includedStylesheets.addElement(child); 388 } 389 390 public void setSystemId(String systemId) { 391 if (systemId != null) { 392 _systemId = SystemIDResolver.getAbsoluteURI(systemId); 393 } 394 } 395 396 public String getSystemId() { 397 return _systemId; 398 } 399 400 public void setSourceLoader(SourceLoader loader) { 401 _loader = loader; 402 } 403 404 public SourceLoader getSourceLoader() { 405 return _loader; 406 } 407 408 private QName makeStylesheetName(String prefix) { 409 return getParser().getQName(prefix+getXSLTC().nextStylesheetSerial()); 410 } 411 412 415 public boolean hasGlobals() { 416 return _globals.size() > 0; 417 } 418 419 424 public boolean hasLocalParams() { 425 if (_hasLocalParams == null) { 426 Vector templates = getAllValidTemplates(); 427 final int n = templates.size(); 428 for (int i = 0; i < n; i++) { 429 final Template template = (Template)templates.elementAt(i); 430 if (template.hasParams()) { 431 _hasLocalParams = new Boolean (true); 432 return true; 433 } 434 } 435 _hasLocalParams = new Boolean (false); 436 return false; 437 } 438 else { 439 return _hasLocalParams.booleanValue(); 440 } 441 } 442 443 448 protected void addPrefixMapping(String prefix, String uri) { 449 if (prefix.equals(EMPTYSTRING) && uri.equals(XHTML_URI)) return; 450 super.addPrefixMapping(prefix, uri); 451 } 452 453 456 private void extensionURI(String prefixes, SymbolTable stable) { 457 if (prefixes != null) { 458 StringTokenizer tokens = new StringTokenizer (prefixes); 459 while (tokens.hasMoreTokens()) { 460 final String prefix = tokens.nextToken(); 461 final String uri = lookupNamespace(prefix); 462 if (uri != null) { 463 _extensions.put(uri, prefix); 464 } 465 } 466 } 467 } 468 469 public boolean isExtension(String uri) { 470 return (_extensions.get(uri) != null); 471 } 472 473 public void excludeExtensionPrefixes(Parser parser) { 474 final SymbolTable stable = parser.getSymbolTable(); 475 final String excludePrefixes = getAttribute("exclude-result-prefixes"); 476 final String extensionPrefixes = getAttribute("extension-element-prefixes"); 477 478 stable.excludeURI(Constants.XSLT_URI); 480 stable.excludeNamespaces(excludePrefixes); 481 stable.excludeNamespaces(extensionPrefixes); 482 extensionURI(extensionPrefixes, stable); 483 } 484 485 490 public void parseContents(Parser parser) { 491 final SymbolTable stable = parser.getSymbolTable(); 492 493 503 504 addPrefixMapping("xml", "http://www.w3.org/XML/1998/namespace"); 506 507 final Stylesheet sheet = stable.addStylesheet(_name, this); 509 if (sheet != null) { 510 ErrorMsg err = new ErrorMsg(ErrorMsg.MULTIPLE_STYLESHEET_ERR,this); 512 parser.reportError(Constants.ERROR, err); 513 } 514 515 if (_simplified) { 521 stable.excludeURI(XSLT_URI); 522 Template template = new Template(); 523 template.parseSimplified(this, parser); 524 } 525 else { 527 parseOwnChildren(parser); 528 } 529 } 530 531 534 public final void parseOwnChildren(Parser parser) { 535 final Vector contents = getContents(); 536 final int count = contents.size(); 537 538 for (int i = 0; i < count; i++) { 541 SyntaxTreeNode child = (SyntaxTreeNode)contents.elementAt(i); 542 if ((child instanceof VariableBase) || 543 (child instanceof NamespaceAlias)) { 544 parser.getSymbolTable().setCurrentNode(child); 545 child.parseContents(parser); 546 } 547 } 548 549 for (int i = 0; i < count; i++) { 551 SyntaxTreeNode child = (SyntaxTreeNode)contents.elementAt(i); 552 if (!(child instanceof VariableBase) && 553 !(child instanceof NamespaceAlias)) { 554 parser.getSymbolTable().setCurrentNode(child); 555 child.parseContents(parser); 556 } 557 558 if (!_templateInlining && (child instanceof Template)) { 561 Template template = (Template)child; 562 String name = "template$dot$" + template.getPosition(); 563 template.setName(parser.getQName(name)); 564 } 565 } 566 } 567 568 public void processModes() { 569 if (_defaultMode == null) 570 _defaultMode = new Mode(null, this, Constants.EMPTYSTRING); 571 _defaultMode.processPatterns(_keys); 572 final Enumeration modes = _modes.elements(); 573 while (modes.hasMoreElements()) { 574 final Mode mode = (Mode)modes.nextElement(); 575 mode.processPatterns(_keys); 576 } 577 } 578 579 private void compileModes(ClassGenerator classGen) { 580 _defaultMode.compileApplyTemplates(classGen); 581 final Enumeration modes = _modes.elements(); 582 while (modes.hasMoreElements()) { 583 final Mode mode = (Mode)modes.nextElement(); 584 mode.compileApplyTemplates(classGen); 585 } 586 } 587 588 public Mode getMode(QName modeName) { 589 if (modeName == null) { 590 if (_defaultMode == null) { 591 _defaultMode = new Mode(null, this, Constants.EMPTYSTRING); 592 } 593 return _defaultMode; 594 } 595 else { 596 Mode mode = (Mode)_modes.get(modeName); 597 if (mode == null) { 598 final String suffix = Integer.toString(_nextModeSerial++); 599 _modes.put(modeName, mode = new Mode(modeName, this, suffix)); 600 } 601 return mode; 602 } 603 } 604 605 608 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 609 final int count = _globals.size(); 610 for (int i = 0; i < count; i++) { 611 final VariableBase var = (VariableBase)_globals.elementAt(i); 612 var.typeCheck(stable); 613 } 614 return typeCheckContents(stable); 615 } 616 617 620 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 621 translate(); 622 } 623 624 private void addDOMField(ClassGenerator classGen) { 625 final FieldGen fgen = new FieldGen(ACC_PUBLIC, 626 Util.getJCRefType(DOM_INTF_SIG), 627 DOM_FIELD, 628 classGen.getConstantPool()); 629 classGen.addField(fgen.getField()); 630 } 631 632 635 private void addStaticField(ClassGenerator classGen, String type, 636 String name) 637 { 638 final FieldGen fgen = new FieldGen(ACC_PROTECTED|ACC_STATIC, 639 Util.getJCRefType(type), 640 name, 641 classGen.getConstantPool()); 642 classGen.addField(fgen.getField()); 643 644 } 645 646 649 public void translate() { 650 _className = getXSLTC().getClassName(); 651 652 final ClassGenerator classGen = 654 new ClassGenerator(_className, 655 TRANSLET_CLASS, 656 Constants.EMPTYSTRING, 657 ACC_PUBLIC | ACC_SUPER, 658 null, this); 659 660 addDOMField(classGen); 661 662 compileTransform(classGen); 665 666 final Enumeration elements = elements(); 668 while (elements.hasMoreElements()) { 669 Object element = elements.nextElement(); 670 if (element instanceof Template) { 672 final Template template = (Template)element; 674 getMode(template.getModeName()).addTemplate(template); 676 } 677 else if (element instanceof AttributeSet) { 679 ((AttributeSet)element).translate(classGen, null); 680 } 681 else if (element instanceof Output) { 682 Output output = (Output)element; 684 if (output.enabled()) _lastOutputElement = output; 685 } 686 else { 687 } 691 } 692 693 checkOutputMethod(); 694 processModes(); 695 compileModes(classGen); 696 compileStaticInitializer(classGen); 697 compileConstructor(classGen, _lastOutputElement); 698 699 if (!getParser().errorsFound()) { 700 getXSLTC().dumpClass(classGen.getJavaClass()); 701 } 702 } 703 704 710 private void compileStaticInitializer(ClassGenerator classGen) { 711 final ConstantPoolGen cpg = classGen.getConstantPool(); 712 final InstructionList il = new InstructionList(); 713 714 final MethodGenerator staticConst = 715 new MethodGenerator(ACC_PUBLIC|ACC_STATIC, 716 org.apache.bcel.generic.Type.VOID, 717 null, null, "<clinit>", 718 _className, il, cpg); 719 720 addStaticField(classGen, "[" + STRING_SIG, STATIC_NAMES_ARRAY_FIELD); 721 addStaticField(classGen, "[" + STRING_SIG, STATIC_URIS_ARRAY_FIELD); 722 addStaticField(classGen, "[I", STATIC_TYPES_ARRAY_FIELD); 723 addStaticField(classGen, "[" + STRING_SIG, STATIC_NAMESPACE_ARRAY_FIELD); 724 final int charDataFieldCount = getXSLTC().getCharacterDataCount(); 727 for (int i = 0; i < charDataFieldCount; i++) { 728 addStaticField(classGen, STATIC_CHAR_DATA_FIELD_SIG, 729 STATIC_CHAR_DATA_FIELD+i); 730 } 731 732 final Vector namesIndex = getXSLTC().getNamesIndex(); 734 int size = namesIndex.size(); 735 String [] namesArray = new String [size]; 736 String [] urisArray = new String [size]; 737 int[] typesArray = new int[size]; 738 739 int index; 740 for (int i = 0; i < size; i++) { 741 String encodedName = (String )namesIndex.elementAt(i); 742 if ((index = encodedName.lastIndexOf(':')) > -1) { 743 urisArray[i] = encodedName.substring(0, index); 744 } 745 746 index = index + 1; 747 if (encodedName.charAt(index) == '@') { 748 typesArray[i] = DTM.ATTRIBUTE_NODE; 749 index++; 750 } else if (encodedName.charAt(index) == '?') { 751 typesArray[i] = DTM.NAMESPACE_NODE; 752 index++; 753 } else { 754 typesArray[i] = DTM.ELEMENT_NODE; 755 } 756 757 if (index == 0) { 758 namesArray[i] = encodedName; 759 } 760 else { 761 namesArray[i] = encodedName.substring(index); 762 } 763 } 764 765 il.append(new PUSH(cpg, size)); 766 il.append(new ANEWARRAY(cpg.addClass(STRING))); 767 768 for (int i = 0; i < size; i++) { 769 final String name = namesArray[i]; 770 il.append(DUP); 771 il.append(new PUSH(cpg, i)); 772 il.append(new PUSH(cpg, name)); 773 il.append(AASTORE); 774 } 775 il.append(new PUTSTATIC(cpg.addFieldref(_className, 776 STATIC_NAMES_ARRAY_FIELD, 777 NAMES_INDEX_SIG))); 778 779 il.append(new PUSH(cpg, size)); 780 il.append(new ANEWARRAY(cpg.addClass(STRING))); 781 782 for (int i = 0; i < size; i++) { 783 final String uri = urisArray[i]; 784 il.append(DUP); 785 il.append(new PUSH(cpg, i)); 786 il.append(new PUSH(cpg, uri)); 787 il.append(AASTORE); 788 } 789 il.append(new PUTSTATIC(cpg.addFieldref(_className, 790 STATIC_URIS_ARRAY_FIELD, 791 URIS_INDEX_SIG))); 792 793 il.append(new PUSH(cpg, size)); 794 il.append(new NEWARRAY(BasicType.INT)); 795 796 for (int i = 0; i < size; i++) { 797 final int nodeType = typesArray[i]; 798 il.append(DUP); 799 il.append(new PUSH(cpg, i)); 800 il.append(new PUSH(cpg, nodeType)); 801 il.append(IASTORE); 802 } 803 il.append(new PUTSTATIC(cpg.addFieldref(_className, 804 STATIC_TYPES_ARRAY_FIELD, 805 TYPES_INDEX_SIG))); 806 807 final Vector namespaces = getXSLTC().getNamespaceIndex(); 809 il.append(new PUSH(cpg, namespaces.size())); 810 il.append(new ANEWARRAY(cpg.addClass(STRING))); 811 812 for (int i = 0; i < namespaces.size(); i++) { 813 final String ns = (String )namespaces.elementAt(i); 814 il.append(DUP); 815 il.append(new PUSH(cpg, i)); 816 il.append(new PUSH(cpg, ns)); 817 il.append(AASTORE); 818 } 819 il.append(new PUTSTATIC(cpg.addFieldref(_className, 820 STATIC_NAMESPACE_ARRAY_FIELD, 821 NAMESPACE_INDEX_SIG))); 822 823 final int charDataCount = getXSLTC().getCharacterDataCount(); 825 final int toCharArray = cpg.addMethodref(STRING, "toCharArray", "()[C"); 826 for (int i = 0; i < charDataCount; i++) { 827 il.append(new PUSH(cpg, getXSLTC().getCharacterData(i))); 828 il.append(new INVOKEVIRTUAL(toCharArray)); 829 il.append(new PUTSTATIC(cpg.addFieldref(_className, 830 STATIC_CHAR_DATA_FIELD+i, 831 STATIC_CHAR_DATA_FIELD_SIG))); 832 } 833 834 il.append(RETURN); 835 836 staticConst.stripAttributes(true); 837 staticConst.setMaxLocals(); 838 staticConst.setMaxStack(); 839 classGen.addMethod(staticConst.getMethod()); 840 841 } 842 843 846 private void compileConstructor(ClassGenerator classGen, Output output) { 847 848 final ConstantPoolGen cpg = classGen.getConstantPool(); 849 final InstructionList il = new InstructionList(); 850 851 final MethodGenerator constructor = 852 new MethodGenerator(ACC_PUBLIC, 853 org.apache.bcel.generic.Type.VOID, 854 null, null, "<init>", 855 _className, il, cpg); 856 857 il.append(classGen.loadTranslet()); 859 il.append(new INVOKESPECIAL(cpg.addMethodref(TRANSLET_CLASS, 860 "<init>", "()V"))); 861 862 il.append(classGen.loadTranslet()); 863 il.append(new GETSTATIC(cpg.addFieldref(_className, 864 STATIC_NAMES_ARRAY_FIELD, 865 NAMES_INDEX_SIG))); 866 il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, 867 NAMES_INDEX, 868 NAMES_INDEX_SIG))); 869 870 il.append(classGen.loadTranslet()); 871 il.append(new GETSTATIC(cpg.addFieldref(_className, 872 STATIC_URIS_ARRAY_FIELD, 873 URIS_INDEX_SIG))); 874 il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, 875 URIS_INDEX, 876 URIS_INDEX_SIG))); 877 878 il.append(classGen.loadTranslet()); 879 il.append(new GETSTATIC(cpg.addFieldref(_className, 880 STATIC_TYPES_ARRAY_FIELD, 881 TYPES_INDEX_SIG))); 882 il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, 883 TYPES_INDEX, 884 TYPES_INDEX_SIG))); 885 886 il.append(classGen.loadTranslet()); 887 il.append(new GETSTATIC(cpg.addFieldref(_className, 888 STATIC_NAMESPACE_ARRAY_FIELD, 889 NAMESPACE_INDEX_SIG))); 890 il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, 891 NAMESPACE_INDEX, 892 NAMESPACE_INDEX_SIG))); 893 894 il.append(classGen.loadTranslet()); 895 il.append(new PUSH(cpg, AbstractTranslet.CURRENT_TRANSLET_VERSION)); 896 il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, 897 TRANSLET_VERSION_INDEX, 898 TRANSLET_VERSION_INDEX_SIG))); 899 900 if (_hasIdCall) { 901 il.append(classGen.loadTranslet()); 902 il.append(new PUSH(cpg, Boolean.TRUE)); 903 il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, 904 HASIDCALL_INDEX, 905 HASIDCALL_INDEX_SIG))); 906 } 907 908 if (output != null) { 910 output.translate(classGen, constructor); 912 } 913 914 if (_numberFormattingUsed) 917 DecimalFormatting.translateDefaultDFS(classGen, constructor); 918 919 il.append(RETURN); 920 921 constructor.stripAttributes(true); 922 constructor.setMaxLocals(); 923 constructor.setMaxStack(); 924 classGen.addMethod(constructor.getMethod()); 925 } 926 927 932 private String compileTopLevel(ClassGenerator classGen, 933 Enumeration elements) { 934 935 final ConstantPoolGen cpg = classGen.getConstantPool(); 936 937 final org.apache.bcel.generic.Type[] argTypes = { 938 Util.getJCRefType(DOM_INTF_SIG), 939 Util.getJCRefType(NODE_ITERATOR_SIG), 940 Util.getJCRefType(TRANSLET_OUTPUT_SIG) 941 }; 942 943 final String [] argNames = { 944 DOCUMENT_PNAME, ITERATOR_PNAME, TRANSLET_OUTPUT_PNAME 945 }; 946 947 final InstructionList il = new InstructionList(); 948 949 final MethodGenerator toplevel = 950 new MethodGenerator(ACC_PUBLIC, 951 org.apache.bcel.generic.Type.VOID, 952 argTypes, argNames, 953 "topLevel", _className, il, 954 classGen.getConstantPool()); 955 956 toplevel.addException("org.apache.xalan.xsltc.TransletException"); 957 958 final LocalVariableGen current = 960 toplevel.addLocalVariable("current", 961 org.apache.bcel.generic.Type.INT, 962 il.getEnd(), null); 963 964 final int setFilter = cpg.addInterfaceMethodref(DOM_INTF, 965 "setFilter", 966 "(Lorg/apache/xalan/xsltc/StripFilter;)V"); 967 968 il.append(new PUSH(cpg, DTM.ROOT_NODE)); 969 il.append(new ISTORE(current.getIndex())); 970 971 _globals = resolveReferences(_globals); 973 final int count = _globals.size(); 974 for (int i = 0; i < count; i++) { 975 final VariableBase var = (VariableBase)_globals.elementAt(i); 976 var.translate(classGen,toplevel); 977 } 978 979 Vector whitespaceRules = new Vector (); 981 while (elements.hasMoreElements()) { 982 final Object element = elements.nextElement(); 983 if (element instanceof DecimalFormatting) { 985 ((DecimalFormatting)element).translate(classGen,toplevel); 986 } 987 else if (element instanceof Whitespace) { 989 whitespaceRules.addAll(((Whitespace)element).getRules()); 990 } 991 } 992 993 if (whitespaceRules.size() > 0) { 995 Whitespace.translateRules(whitespaceRules,classGen); 996 } 997 998 if (classGen.containsMethod(STRIP_SPACE, STRIP_SPACE_PARAMS) != null) { 999 il.append(toplevel.loadDOM()); 1000 il.append(classGen.loadTranslet()); 1001 il.append(new INVOKEINTERFACE(setFilter, 2)); 1002 } 1003 1004 il.append(RETURN); 1005 1006 toplevel.stripAttributes(true); 1008 toplevel.setMaxLocals(); 1009 toplevel.setMaxStack(); 1010 toplevel.removeNOPs(); 1011 1012 classGen.addMethod(toplevel.getMethod()); 1013 1014 return("("+DOM_INTF_SIG+NODE_ITERATOR_SIG+TRANSLET_OUTPUT_SIG+")V"); 1015 } 1016 1017 1025 private Vector resolveReferences(Vector input) { 1026 1027 for (int i = 0; i < input.size(); i++) { 1029 final VariableBase var = (VariableBase) input.elementAt(i); 1030 final Vector dep = var.getDependencies(); 1031 final int depSize = (dep != null) ? dep.size() : 0; 1032 1033 for (int j = 0; j < depSize; j++) { 1034 final VariableBase depVar = (VariableBase) dep.elementAt(j); 1035 if (!input.contains(depVar)) { 1036 input.addElement(depVar); 1037 } 1038 } 1039 } 1040 1041 1048 1049 Vector result = new Vector (); 1050 while (input.size() > 0) { 1051 boolean changed = false; 1052 for (int i = 0; i < input.size(); ) { 1053 final VariableBase var = (VariableBase)input.elementAt(i); 1054 final Vector dep = var.getDependencies(); 1055 if (dep == null || result.containsAll(dep)) { 1056 result.addElement(var); 1057 input.remove(i); 1058 changed = true; 1059 } 1060 else { 1061 i++; 1062 } 1063 } 1064 1065 if (!changed) { 1067 ErrorMsg err = new ErrorMsg(ErrorMsg.CIRCULAR_VARIABLE_ERR, 1068 input.toString(), this); 1069 getParser().reportError(Constants.ERROR, err); 1070 return(result); 1071 } 1072 } 1073 1074 1081 1082 return result; 1083 } 1084 1085 1089 private String compileBuildKeys(ClassGenerator classGen) { 1090 1091 final ConstantPoolGen cpg = classGen.getConstantPool(); 1092 1093 final org.apache.bcel.generic.Type[] argTypes = { 1094 Util.getJCRefType(DOM_INTF_SIG), 1095 Util.getJCRefType(NODE_ITERATOR_SIG), 1096 Util.getJCRefType(TRANSLET_OUTPUT_SIG), 1097 org.apache.bcel.generic.Type.INT 1098 }; 1099 1100 final String [] argNames = { 1101 DOCUMENT_PNAME, ITERATOR_PNAME, TRANSLET_OUTPUT_PNAME, "current" 1102 }; 1103 1104 final InstructionList il = new InstructionList(); 1105 1106 final MethodGenerator buildKeys = 1107 new MethodGenerator(ACC_PUBLIC, 1108 org.apache.bcel.generic.Type.VOID, 1109 argTypes, argNames, 1110 "buildKeys", _className, il, 1111 classGen.getConstantPool()); 1112 1113 buildKeys.addException("org.apache.xalan.xsltc.TransletException"); 1114 1115 final Enumeration elements = elements(); 1116 while (elements.hasMoreElements()) { 1118 final Object element = elements.nextElement(); 1120 if (element instanceof Key) { 1121 final Key key = (Key)element; 1122 key.translate(classGen, buildKeys); 1123 _keys.put(key.getName(),key); 1124 } 1125 } 1126 1127 il.append(RETURN); 1128 1129 buildKeys.stripAttributes(true); 1131 buildKeys.setMaxLocals(); 1132 buildKeys.setMaxStack(); 1133 buildKeys.removeNOPs(); 1134 1135 classGen.addMethod(buildKeys.getMethod()); 1136 1137 return("("+DOM_INTF_SIG+NODE_ITERATOR_SIG+TRANSLET_OUTPUT_SIG+"I)V"); 1138 } 1139 1140 1145 private void compileTransform(ClassGenerator classGen) { 1146 final ConstantPoolGen cpg = classGen.getConstantPool(); 1147 1148 1152 final org.apache.bcel.generic.Type[] argTypes = 1153 new org.apache.bcel.generic.Type[3]; 1154 argTypes[0] = Util.getJCRefType(DOM_INTF_SIG); 1155 argTypes[1] = Util.getJCRefType(NODE_ITERATOR_SIG); 1156 argTypes[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG); 1157 1158 final String [] argNames = new String [3]; 1159 argNames[0] = DOCUMENT_PNAME; 1160 argNames[1] = ITERATOR_PNAME; 1161 argNames[2] = TRANSLET_OUTPUT_PNAME; 1162 1163 final InstructionList il = new InstructionList(); 1164 final MethodGenerator transf = 1165 new MethodGenerator(ACC_PUBLIC, 1166 org.apache.bcel.generic.Type.VOID, 1167 argTypes, argNames, 1168 "transform", 1169 _className, 1170 il, 1171 classGen.getConstantPool()); 1172 transf.addException("org.apache.xalan.xsltc.TransletException"); 1173 1174 final LocalVariableGen current = 1176 transf.addLocalVariable("current", 1177 org.apache.bcel.generic.Type.INT, 1178 il.getEnd(), null); 1179 final String applyTemplatesSig = classGen.getApplyTemplatesSig(); 1180 final int applyTemplates = cpg.addMethodref(getClassName(), 1181 "applyTemplates", 1182 applyTemplatesSig); 1183 final int domField = cpg.addFieldref(getClassName(), 1184 DOM_FIELD, 1185 DOM_INTF_SIG); 1186 1187 il.append(classGen.loadTranslet()); 1189 1191 if (isMultiDocument()) { 1192 il.append(new NEW(cpg.addClass(MULTI_DOM_CLASS))); 1193 il.append(DUP); 1194 } 1195 1196 il.append(classGen.loadTranslet()); 1197 il.append(transf.loadDOM()); 1198 il.append(new INVOKEVIRTUAL(cpg.addMethodref(TRANSLET_CLASS, 1199 "makeDOMAdapter", 1200 "("+DOM_INTF_SIG+")"+ 1201 DOM_ADAPTER_SIG))); 1202 1204 if (isMultiDocument()) { 1205 final int init = cpg.addMethodref(MULTI_DOM_CLASS, 1206 "<init>", 1207 "("+DOM_INTF_SIG+")V"); 1208 il.append(new INVOKESPECIAL(init)); 1209 } 1211 1212 il.append(new PUTFIELD(domField)); 1214 1215 il.append(new PUSH(cpg, DTM.ROOT_NODE)); 1217 il.append(new ISTORE(current.getIndex())); 1218 1219 il.append(classGen.loadTranslet()); 1221 il.append(transf.loadHandler()); 1222 final int index = cpg.addMethodref(TRANSLET_CLASS, 1223 "transferOutputSettings", 1224 "("+OUTPUT_HANDLER_SIG+")V"); 1225 il.append(new INVOKEVIRTUAL(index)); 1226 1227 1229 final String keySig = compileBuildKeys(classGen); 1230 final int keyIdx = cpg.addMethodref(getClassName(), 1231 "buildKeys", keySig); 1232 il.append(classGen.loadTranslet()); il.append(classGen.loadTranslet()); 1234 il.append(new GETFIELD(domField)); il.append(transf.loadIterator()); il.append(transf.loadHandler()); il.append(new PUSH(cpg, DTM.ROOT_NODE)); il.append(new INVOKEVIRTUAL(keyIdx)); 1239 1240 1241 final Enumeration toplevel = elements(); 1243 if ((_globals.size() > 0) || (toplevel.hasMoreElements())) { 1244 final String topLevelSig = compileTopLevel(classGen, toplevel); 1246 final int topLevelIdx = cpg.addMethodref(getClassName(), 1248 "topLevel", 1249 topLevelSig); 1250 il.append(classGen.loadTranslet()); il.append(classGen.loadTranslet()); 1253 il.append(new GETFIELD(domField)); il.append(transf.loadIterator()); 1255 il.append(transf.loadHandler()); il.append(new INVOKEVIRTUAL(topLevelIdx)); 1257 } 1258 1259 1260 1261 1262 il.append(transf.loadHandler()); 1264 il.append(transf.startDocument()); 1265 1266 il.append(classGen.loadTranslet()); 1268 il.append(classGen.loadTranslet()); 1270 il.append(new GETFIELD(domField)); 1271 il.append(transf.loadIterator()); 1273 il.append(transf.loadHandler()); 1274 il.append(new INVOKEVIRTUAL(applyTemplates)); 1275 il.append(transf.loadHandler()); 1277 il.append(transf.endDocument()); 1278 1279 il.append(RETURN); 1280 1281 transf.stripAttributes(true); 1283 transf.setMaxLocals(); 1284 transf.setMaxStack(); 1285 transf.removeNOPs(); 1286 1287 classGen.addMethod(transf.getMethod()); 1288 } 1289 1290 1293 private void peepHoleOptimization(MethodGenerator methodGen) { 1294 final String pattern = "`ALOAD'`POP'`Instruction'"; 1295 final InstructionList il = methodGen.getInstructionList(); 1296 final InstructionFinder find = new InstructionFinder(il); 1297 for(Iterator iter=find.search(pattern); iter.hasNext(); ) { 1298 InstructionHandle[] match = (InstructionHandle[])iter.next(); 1299 try { 1300 il.delete(match[0], match[1]); 1301 } 1302 catch (TargetLostException e) { 1303 } 1305 } 1306 } 1307 1308 public int addParam(Param param) { 1309 _globals.addElement(param); 1310 return _globals.size() - 1; 1311 } 1312 1313 public int addVariable(Variable global) { 1314 _globals.addElement(global); 1315 return _globals.size() - 1; 1316 } 1317 1318 public void display(int indent) { 1319 indent(indent); 1320 Util.println("Stylesheet"); 1321 displayContents(indent + IndentIncrement); 1322 } 1323 1324 public String getNamespace(String prefix) { 1326 return lookupNamespace(prefix); 1327 } 1328 1329 public String getClassName() { 1330 return _className; 1331 } 1332 1333 public Vector getTemplates() { 1334 return _templates; 1335 } 1336 1337 public Vector getAllValidTemplates() { 1338 if (_includedStylesheets == null) { 1340 return _templates; 1341 } 1342 1343 if (_allValidTemplates == null) { 1345 Vector templates = new Vector (); 1346 int size = _includedStylesheets.size(); 1347 for (int i = 0; i < size; i++) { 1348 Stylesheet included =(Stylesheet)_includedStylesheets.elementAt(i); 1349 templates.addAll(included.getAllValidTemplates()); 1350 } 1351 templates.addAll(_templates); 1352 1353 if (_parentStylesheet != null) { 1355 return templates; 1356 } 1357 _allValidTemplates = templates; 1358 } 1359 1360 return _allValidTemplates; 1361 } 1362 1363 protected void addTemplate(Template template) { 1364 _templates.addElement(template); 1365 } 1366} 1367 | Popular Tags |