Source Home >> Java Source 1.6.0 >> com.sun.org.apache.xalan.internal.xsltc.compiler.Stylesheet V 0.09
  • 0001/*
  • 0002 * Copyright 2001-2004 The Apache Software Foundation.
  • 0003 *
  • 0004 * Licensed under the Apache License, Version 2.0 (the "License");
  • 0005 * you may not use this file except in compliance with the License.
  • 0006 * You may obtain a copy of the License at
  • 0007 *
  • 0008 * http://www.apache.org/licenses/LICENSE-2.0
  • 0009 *
  • 0010 * Unless required by applicable law or agreed to in writing, software
  • 0011 * distributed under the License is distributed on an "AS IS" BASIS,
  • 0012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  • 0013 * See the License for the specific language governing permissions and
  • 0014 * limitations under the License.
  • 0015 */
  • 0016/*
  • 0017 * $Id: Stylesheet.java,v 1.5 2005/09/28 13:48:16 pvedula Exp $
  • 0018 */
  • 0019
  • 0020package com.sun.org.apache.xalan.internal.xsltc.compiler;
  • 0021
  • 0022import java.net.URL;
  • 0023import java.net.MalformedURLException;
  • 0024
  • 0025import java.util.Vector;
  • 0026import java.util.Enumeration;
  • 0027import java.util.Hashtable;
  • 0028import java.util.Iterator;
  • 0029import java.util.Properties;
  • 0030import java.util.StringTokenizer;
  • 0031
  • 0032import com.sun.org.apache.xml.internal.utils.SystemIDResolver;
  • 0033import com.sun.org.apache.bcel.internal.generic.ANEWARRAY;
  • 0034import com.sun.org.apache.bcel.internal.generic.BasicType;
  • 0035import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
  • 0036import com.sun.org.apache.bcel.internal.generic.FieldGen;
  • 0037import com.sun.org.apache.bcel.internal.generic.GETFIELD;
  • 0038import com.sun.org.apache.bcel.internal.generic.GETSTATIC;
  • 0039import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
  • 0040import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL;
  • 0041import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
  • 0042import com.sun.org.apache.bcel.internal.generic.ISTORE;
  • 0043import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
  • 0044import com.sun.org.apache.bcel.internal.generic.InstructionList;
  • 0045import com.sun.org.apache.bcel.internal.generic.LocalVariableGen;
  • 0046import com.sun.org.apache.bcel.internal.generic.NEW;
  • 0047import com.sun.org.apache.bcel.internal.generic.NEWARRAY;
  • 0048import com.sun.org.apache.bcel.internal.generic.PUSH;
  • 0049import com.sun.org.apache.bcel.internal.generic.PUTFIELD;
  • 0050import com.sun.org.apache.bcel.internal.generic.PUTSTATIC;
  • 0051import com.sun.org.apache.bcel.internal.generic.TargetLostException;
  • 0052import com.sun.org.apache.bcel.internal.util.InstructionFinder;
  • 0053import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
  • 0054import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
  • 0055import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
  • 0056import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
  • 0057import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
  • 0058import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
  • 0059import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
  • 0060import com.sun.org.apache.xml.internal.dtm.DTM;
  • 0061
  • 0062/**
  • 0063 * @author Jacek Ambroziak
  • 0064 * @author Santiago Pericas-Geertsen
  • 0065 * @author Morten Jorgensen
  • 0066 */
  • 0067public final class Stylesheet extends SyntaxTreeNode {
  • 0068
  • 0069 /**
  • 0070 * XSLT version defined in the stylesheet.
  • 0071 */
  • 0072 private String _version;
  • 0073
  • 0074 /**
  • 0075 * Internal name of this stylesheet used as a key into the symbol table.
  • 0076 */
  • 0077 private QName _name;
  • 0078
  • 0079 /**
  • 0080 * A URI that represents the system ID for this stylesheet.
  • 0081 */
  • 0082 private String _systemId;
  • 0083
  • 0084 /**
  • 0085 * A reference to the parent stylesheet or null if topmost.
  • 0086 */
  • 0087 private Stylesheet _parentStylesheet;
  • 0088
  • 0089 /**
  • 0090 * Contains global variables and parameters defined in the stylesheet.
  • 0091 */
  • 0092 private Vector _globals = new Vector();
  • 0093
  • 0094 /**
  • 0095 * Used to cache the result returned by <code>hasLocalParams()</code>.
  • 0096 */
  • 0097 private Boolean _hasLocalParams = null;
  • 0098
  • 0099 /**
  • 0100 * The name of the class being generated.
  • 0101 */
  • 0102 private String _className;
  • 0103
  • 0104 /**
  • 0105 * Contains all templates defined in this stylesheet
  • 0106 */
  • 0107 private final Vector _templates = new Vector();
  • 0108
  • 0109 /**
  • 0110 * Used to cache result of <code>getAllValidTemplates()</code>. Only
  • 0111 * set in top-level stylesheets that include/import other stylesheets.
  • 0112 */
  • 0113 private Vector _allValidTemplates = null;
  • 0114
  • 0115 /**
  • 0116 * Counter to generate unique mode suffixes.
  • 0117 */
  • 0118 private int _nextModeSerial = 1;
  • 0119
  • 0120 /**
  • 0121 * Mapping between mode names and Mode instances.
  • 0122 */
  • 0123 private final Hashtable _modes = new Hashtable();
  • 0124
  • 0125 /**
  • 0126 * A reference to the default Mode object.
  • 0127 */
  • 0128 private Mode _defaultMode;
  • 0129
  • 0130 /**
  • 0131 * Mapping between extension URIs and their prefixes.
  • 0132 */
  • 0133 private final Hashtable _extensions = new Hashtable();
  • 0134
  • 0135 /**
  • 0136 * Reference to the stylesheet from which this stylesheet was
  • 0137 * imported (if any).
  • 0138 */
  • 0139 public Stylesheet _importedFrom = null;
  • 0140
  • 0141 /**
  • 0142 * Reference to the stylesheet from which this stylesheet was
  • 0143 * included (if any).
  • 0144 */
  • 0145 public Stylesheet _includedFrom = null;
  • 0146
  • 0147 /**
  • 0148 * Array of all the stylesheets imported or included from this one.
  • 0149 */
  • 0150 private Vector _includedStylesheets = null;
  • 0151
  • 0152 /**
  • 0153 * Import precendence for this stylesheet.
  • 0154 */
  • 0155 private int _importPrecedence = 1;
  • 0156
  • 0157 /**
  • 0158 * Minimum precendence of any descendant stylesheet by inclusion or
  • 0159 * importation.
  • 0160 */
  • 0161 private int _minimumDescendantPrecedence = -1;
  • 0162
  • 0163 /**
  • 0164 * Mapping between key names and Key objects (needed by Key/IdPattern).
  • 0165 */
  • 0166 private Hashtable _keys = new Hashtable();
  • 0167
  • 0168 /**
  • 0169 * A reference to the SourceLoader set by the user (a URIResolver
  • 0170 * if the JAXP API is being used).
  • 0171 */
  • 0172 private SourceLoader _loader = null;
  • 0173
  • 0174 /**
  • 0175 * Flag indicating if format-number() is called.
  • 0176 */
  • 0177 private boolean _numberFormattingUsed = false;
  • 0178
  • 0179 /**
  • 0180 * Flag indicating if this is a simplified stylesheets. A template
  • 0181 * matching on "/" must be added in this case.
  • 0182 */
  • 0183 private boolean _simplified = false;
  • 0184
  • 0185 /**
  • 0186 * Flag indicating if multi-document support is needed.
  • 0187 */
  • 0188 private boolean _multiDocument = false;
  • 0189
  • 0190 /**
  • 0191 * Flag indicating if nodset() is called.
  • 0192 */
  • 0193 private boolean _callsNodeset = false;
  • 0194
  • 0195 /**
  • 0196 * Flag indicating if id() is called.
  • 0197 */
  • 0198 private boolean _hasIdCall = false;
  • 0199
  • 0200 /**
  • 0201 * Set to true to enable template inlining optimization.
  • 0202 */
  • 0203 private boolean _templateInlining = true;
  • 0204
  • 0205 /**
  • 0206 * A reference to the last xsl:output object found in the styleshet.
  • 0207 */
  • 0208 private Output _lastOutputElement = null;
  • 0209
  • 0210 /**
  • 0211 * Output properties for this stylesheet.
  • 0212 */
  • 0213 private Properties _outputProperties = null;
  • 0214
  • 0215 /**
  • 0216 * Output method for this stylesheet (must be set to one of
  • 0217 * the constants defined below).
  • 0218 */
  • 0219 private int _outputMethod = UNKNOWN_OUTPUT;
  • 0220
  • 0221 // Output method constants
  • 0222 public static final int UNKNOWN_OUTPUT = 0;
  • 0223 public static final int XML_OUTPUT = 1;
  • 0224 public static final int HTML_OUTPUT = 2;
  • 0225 public static final int TEXT_OUTPUT = 3;
  • 0226
  • 0227 /**
  • 0228 * Return the output method
  • 0229 */
  • 0230 public int getOutputMethod() {
  • 0231 return _outputMethod;
  • 0232 }
  • 0233
  • 0234 /**
  • 0235 * Check and set the output method
  • 0236 */
  • 0237 private void checkOutputMethod() {
  • 0238 if (_lastOutputElement != null) {
  • 0239 String method = _lastOutputElement.getOutputMethod();
  • 0240 if (method != null) {
  • 0241 if (method.equals("xml"))
  • 0242 _outputMethod = XML_OUTPUT;
  • 0243 else if (method.equals("html"))
  • 0244 _outputMethod = HTML_OUTPUT;
  • 0245 else if (method.equals("text"))
  • 0246 _outputMethod = TEXT_OUTPUT;
  • 0247 }
  • 0248 }
  • 0249 }
  • 0250
  • 0251 public boolean getTemplateInlining() {
  • 0252 return _templateInlining;
  • 0253 }
  • 0254
  • 0255 public void setTemplateInlining(boolean flag) {
  • 0256 _templateInlining = flag;
  • 0257 }
  • 0258
  • 0259 public boolean isSimplified() {
  • 0260 return(_simplified);
  • 0261 }
  • 0262
  • 0263 public void setSimplified() {
  • 0264 _simplified = true;
  • 0265 }
  • 0266
  • 0267 public void setHasIdCall(boolean flag) {
  • 0268 _hasIdCall = flag;
  • 0269 }
  • 0270
  • 0271 public void setOutputProperty(String key, String value) {
  • 0272 if (_outputProperties == null) {
  • 0273 _outputProperties = new Properties();
  • 0274 }
  • 0275 _outputProperties.setProperty(key, value);
  • 0276 }
  • 0277
  • 0278 public void setOutputProperties(Properties props) {
  • 0279 _outputProperties = props;
  • 0280 }
  • 0281
  • 0282 public Properties getOutputProperties() {
  • 0283 return _outputProperties;
  • 0284 }
  • 0285
  • 0286 public Output getLastOutputElement() {
  • 0287 return _lastOutputElement;
  • 0288 }
  • 0289
  • 0290 public void setMultiDocument(boolean flag) {
  • 0291 _multiDocument = flag;
  • 0292 }
  • 0293
  • 0294 public boolean isMultiDocument() {
  • 0295 return _multiDocument;
  • 0296 }
  • 0297
  • 0298 public void setCallsNodeset(boolean flag) {
  • 0299 if (flag) setMultiDocument(flag);
  • 0300 _callsNodeset = flag;
  • 0301 }
  • 0302
  • 0303 public boolean callsNodeset() {
  • 0304 return _callsNodeset;
  • 0305 }
  • 0306
  • 0307 public void numberFormattingUsed() {
  • 0308 _numberFormattingUsed = true;
  • 0309 /*
  • 0310 * Fix for bug 23046, if the stylesheet is included, set the
  • 0311 * numberFormattingUsed flag to the parent stylesheet too.
  • 0312 * AbstractTranslet.addDecimalFormat() will be inlined once for the
  • 0313 * outer most stylesheet.
  • 0314 */
  • 0315 Stylesheet parent = getParentStylesheet();
  • 0316 if (null != parent) parent.numberFormattingUsed();
  • 0317 }
  • 0318
  • 0319 public void setImportPrecedence(final int precedence) {
  • 0320 // Set import precedence for this stylesheet
  • 0321 _importPrecedence = precedence;
  • 0322
  • 0323 // Set import precedence for all included stylesheets
  • 0324 final Enumeration elements = elements();
  • 0325 while (elements.hasMoreElements()) {
  • 0326 SyntaxTreeNode child = (SyntaxTreeNode)elements.nextElement();
  • 0327 if (child instanceof Include) {
  • 0328 Stylesheet included = ((Include)child).getIncludedStylesheet();
  • 0329 if (included != null && included._includedFrom == this) {
  • 0330 included.setImportPrecedence(precedence);
  • 0331 }
  • 0332 }
  • 0333 }
  • 0334
  • 0335 // Set import precedence for the stylesheet that imported this one
  • 0336 if (_importedFrom != null) {
  • 0337 if (_importedFrom.getImportPrecedence() < precedence) {
  • 0338 final Parser parser = getParser();
  • 0339 final int nextPrecedence = parser.getNextImportPrecedence();
  • 0340 _importedFrom.setImportPrecedence(nextPrecedence);
  • 0341 }
  • 0342 }
  • 0343 // Set import precedence for the stylesheet that included this one
  • 0344 else if (_includedFrom != null) {
  • 0345 if (_includedFrom.getImportPrecedence() != precedence)
  • 0346 _includedFrom.setImportPrecedence(precedence);
  • 0347 }
  • 0348 }
  • 0349
  • 0350 public int getImportPrecedence() {
  • 0351 return _importPrecedence;
  • 0352 }
  • 0353
  • 0354 /**
  • 0355 * Get the minimum of the precedence of this stylesheet, any stylesheet
  • 0356 * imported by this stylesheet and any include/import descendant of this
  • 0357 * stylesheet.
  • 0358 */
  • 0359 public int getMinimumDescendantPrecedence() {
  • 0360 if (_minimumDescendantPrecedence == -1) {
  • 0361 // Start with precedence of current stylesheet as a basis.
  • 0362 int min = getImportPrecedence();
  • 0363
  • 0364 // Recursively examine all imported/included stylesheets.
  • 0365 final int inclImpCount = (_includedStylesheets != null)
  • 0366 ? _includedStylesheets.size()
  • 0367 : 0;
  • 0368
  • 0369 for (int i = 0; i < inclImpCount; i++) {
  • 0370 int prec = ((Stylesheet)_includedStylesheets.elementAt(i))
  • 0371 .getMinimumDescendantPrecedence();
  • 0372
  • 0373 if (prec < min) {
  • 0374 min = prec;
  • 0375 }
  • 0376 }
  • 0377
  • 0378 _minimumDescendantPrecedence = min;
  • 0379 }
  • 0380 return _minimumDescendantPrecedence;
  • 0381 }
  • 0382
  • 0383 public boolean checkForLoop(String systemId) {
  • 0384 // Return true if this stylesheet includes/imports itself
  • 0385 if (_systemId != null && _systemId.equals(systemId)) {
  • 0386 return true;
  • 0387 }
  • 0388 // Then check with any stylesheets that included/imported this one
  • 0389 if (_parentStylesheet != null)
  • 0390 return _parentStylesheet.checkForLoop(systemId);
  • 0391 // Otherwise OK
  • 0392 return false;
  • 0393 }
  • 0394
  • 0395 public void setParser(Parser parser) {
  • 0396 super.setParser(parser);
  • 0397 _name = makeStylesheetName("__stylesheet_");
  • 0398 }
  • 0399
  • 0400 public void setParentStylesheet(Stylesheet parent) {
  • 0401 _parentStylesheet = parent;
  • 0402 }
  • 0403
  • 0404 public Stylesheet getParentStylesheet() {
  • 0405 return _parentStylesheet;
  • 0406 }
  • 0407
  • 0408 public void setImportingStylesheet(Stylesheet parent) {
  • 0409 _importedFrom = parent;
  • 0410 parent.addIncludedStylesheet(this);
  • 0411 }
  • 0412
  • 0413 public void setIncludingStylesheet(Stylesheet parent) {
  • 0414 _includedFrom = parent;
  • 0415 parent.addIncludedStylesheet(this);
  • 0416 }
  • 0417
  • 0418 public void addIncludedStylesheet(Stylesheet child) {
  • 0419 if (_includedStylesheets == null) {
  • 0420 _includedStylesheets = new Vector();
  • 0421 }
  • 0422 _includedStylesheets.addElement(child);
  • 0423 }
  • 0424
  • 0425 public void setSystemId(String systemId) {
  • 0426 if (systemId != null) {
  • 0427 _systemId = SystemIDResolver.getAbsoluteURI(systemId);
  • 0428 }
  • 0429 }
  • 0430
  • 0431 public String getSystemId() {
  • 0432 return _systemId;
  • 0433 }
  • 0434
  • 0435 public void setSourceLoader(SourceLoader loader) {
  • 0436 _loader = loader;
  • 0437 }
  • 0438
  • 0439 public SourceLoader getSourceLoader() {
  • 0440 return _loader;
  • 0441 }
  • 0442
  • 0443 private QName makeStylesheetName(String prefix) {
  • 0444 return getParser().getQName(prefix+getXSLTC().nextStylesheetSerial());
  • 0445 }
  • 0446
  • 0447 /**
  • 0448 * Returns true if this stylesheet has global vars or params.
  • 0449 */
  • 0450 public boolean hasGlobals() {
  • 0451 return _globals.size() > 0;
  • 0452 }
  • 0453
  • 0454 /**
  • 0455 * Returns true if at least one template in the stylesheet has params
  • 0456 * defined. Uses the variable <code>_hasLocalParams</code> to cache the
  • 0457 * result.
  • 0458 */
  • 0459 public boolean hasLocalParams() {
  • 0460 if (_hasLocalParams == null) {
  • 0461 Vector templates = getAllValidTemplates();
  • 0462 final int n = templates.size();
  • 0463 for (int i = 0; i < n; i++) {
  • 0464 final Template template = (Template)templates.elementAt(i);
  • 0465 if (template.hasParams()) {
  • 0466 _hasLocalParams = new Boolean(true);
  • 0467 return true;
  • 0468 }
  • 0469 }
  • 0470 _hasLocalParams = new Boolean(false);
  • 0471 return false;
  • 0472 }
  • 0473 else {
  • 0474 return _hasLocalParams.booleanValue();
  • 0475 }
  • 0476 }
  • 0477
  • 0478 /**
  • 0479 * Adds a single prefix mapping to this syntax tree node.
  • 0480 * @param prefix Namespace prefix.
  • 0481 * @param uri Namespace URI.
  • 0482 */
  • 0483 protected void addPrefixMapping(String prefix, String uri) {
  • 0484 if (prefix.equals(EMPTYSTRING) && uri.equals(XHTML_URI)) return;
  • 0485 super.addPrefixMapping(prefix, uri);
  • 0486 }
  • 0487
  • 0488 /**
  • 0489 * Store extension URIs
  • 0490 */
  • 0491 private void extensionURI(String prefixes, SymbolTable stable) {
  • 0492 if (prefixes != null) {
  • 0493 StringTokenizer tokens = new StringTokenizer(prefixes);
  • 0494 while (tokens.hasMoreTokens()) {
  • 0495 final String prefix = tokens.nextToken();
  • 0496 final String uri = lookupNamespace(prefix);
  • 0497 if (uri != null) {
  • 0498 _extensions.put(uri, prefix);
  • 0499 }
  • 0500 }
  • 0501 }
  • 0502 }
  • 0503
  • 0504 public boolean isExtension(String uri) {
  • 0505 return (_extensions.get(uri) != null);
  • 0506 }
  • 0507
  • 0508 public void excludeExtensionPrefixes(Parser parser) {
  • 0509 final SymbolTable stable = parser.getSymbolTable();
  • 0510 final String excludePrefixes = getAttribute("exclude-result-prefixes");
  • 0511 final String extensionPrefixes = getAttribute("extension-element-prefixes");
  • 0512
  • 0513 // Exclude XSLT uri
  • 0514 stable.excludeURI(Constants.XSLT_URI);
  • 0515 stable.excludeNamespaces(excludePrefixes);
  • 0516 stable.excludeNamespaces(extensionPrefixes);
  • 0517 extensionURI(extensionPrefixes, stable);
  • 0518 }
  • 0519
  • 0520 /**
  • 0521 * Parse the version and uri fields of the stylesheet and add an
  • 0522 * entry to the symbol table mapping the name <tt>__stylesheet_</tt>
  • 0523 * to an instance of this class.
  • 0524 */
  • 0525 public void parseContents(Parser parser) {
  • 0526 final SymbolTable stable = parser.getSymbolTable();
  • 0527
  • 0528 /*
  • 0529 // Make sure the XSL version set in this stylesheet
  • 0530 if ((_version == null) || (_version.equals(EMPTYSTRING))) {
  • 0531 reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR,"version");
  • 0532 }
  • 0533 // Verify that the version is 1.0 and nothing else
  • 0534 else if (!_version.equals("1.0")) {
  • 0535 reportError(this, parser, ErrorMsg.XSL_VERSION_ERR, _version);
  • 0536 }
  • 0537 */
  • 0538
  • 0539 // Add the implicit mapping of 'xml' to the XML namespace URI
  • 0540 addPrefixMapping("xml", "http://www.w3.org/XML/1998/namespace");
  • 0541
  • 0542 // Report and error if more than one stylesheet defined
  • 0543 final Stylesheet sheet = stable.addStylesheet(_name, this);
  • 0544 if (sheet != null) {
  • 0545 // Error: more that one stylesheet defined
  • 0546 ErrorMsg err = new ErrorMsg(ErrorMsg.MULTIPLE_STYLESHEET_ERR,this);
  • 0547 parser.reportError(Constants.ERROR, err);
  • 0548 }
  • 0549
  • 0550 // If this is a simplified stylesheet we must create a template that
  • 0551 // grabs the root node of the input doc ( <xsl:template match="/"/> ).
  • 0552 // This template needs the current element (the one passed to this
  • 0553 // method) as its only child, so the Template class has a special
  • 0554 // method that handles this (parseSimplified()).
  • 0555 if (_simplified) {
  • 0556 stable.excludeURI(XSLT_URI);
  • 0557 Template template = new Template();
  • 0558 template.parseSimplified(this, parser);
  • 0559 }
  • 0560 // Parse the children of this node
  • 0561 else {
  • 0562 parseOwnChildren(parser);
  • 0563 }
  • 0564 }
  • 0565
  • 0566 /**
  • 0567 * Parse all direct children of the <xsl:stylesheet/> element.
  • 0568 */
  • 0569 public final void parseOwnChildren(Parser parser) {
  • 0570 final Vector contents = getContents();
  • 0571 final int count = contents.size();
  • 0572
  • 0573 // We have to scan the stylesheet element's top-level elements for
  • 0574 // variables and/or parameters before we parse the other elements
  • 0575 for (int i = 0; i < count; i++) {
  • 0576 SyntaxTreeNode child = (SyntaxTreeNode)contents.elementAt(i);
  • 0577 if ((child instanceof VariableBase) ||
  • 0578 (child instanceof NamespaceAlias)) {
  • 0579 parser.getSymbolTable().setCurrentNode(child);
  • 0580 child.parseContents(parser);
  • 0581 }
  • 0582 }
  • 0583
  • 0584 // Now go through all the other top-level elements...
  • 0585 for (int i = 0; i < count; i++) {
  • 0586 SyntaxTreeNode child = (SyntaxTreeNode)contents.elementAt(i);
  • 0587 if (!(child instanceof VariableBase) &&
  • 0588 !(child instanceof NamespaceAlias)) {
  • 0589 parser.getSymbolTable().setCurrentNode(child);
  • 0590 child.parseContents(parser);
  • 0591 }
  • 0592
  • 0593 // All template code should be compiled as methods if the
  • 0594 // <xsl:apply-imports/> element was ever used in this stylesheet
  • 0595 if (!_templateInlining && (child instanceof Template)) {
  • 0596 Template template = (Template)child;
  • 0597 String name = "template$dot$" + template.getPosition();
  • 0598 template.setName(parser.getQName(name));
  • 0599 }
  • 0600 }
  • 0601 }
  • 0602
  • 0603 public void processModes() {
  • 0604 if (_defaultMode == null)
  • 0605 _defaultMode = new Mode(null, this, Constants.EMPTYSTRING);
  • 0606 _defaultMode.processPatterns(_keys);
  • 0607 final Enumeration modes = _modes.elements();
  • 0608 while (modes.hasMoreElements()) {
  • 0609 final Mode mode = (Mode)modes.nextElement();
  • 0610 mode.processPatterns(_keys);
  • 0611 }
  • 0612 }
  • 0613
  • 0614 private void compileModes(ClassGenerator classGen) {
  • 0615 _defaultMode.compileApplyTemplates(classGen);
  • 0616 final Enumeration modes = _modes.elements();
  • 0617 while (modes.hasMoreElements()) {
  • 0618 final Mode mode = (Mode)modes.nextElement();
  • 0619 mode.compileApplyTemplates(classGen);
  • 0620 }
  • 0621 }
  • 0622
  • 0623 public Mode getMode(QName modeName) {
  • 0624 if (modeName == null) {
  • 0625 if (_defaultMode == null) {
  • 0626 _defaultMode = new Mode(null, this, Constants.EMPTYSTRING);
  • 0627 }
  • 0628 return _defaultMode;
  • 0629 }
  • 0630 else {
  • 0631 Mode mode = (Mode)_modes.get(modeName);
  • 0632 if (mode == null) {
  • 0633 final String suffix = Integer.toString(_nextModeSerial++);
  • 0634 _modes.put(modeName, mode = new Mode(modeName, this, suffix));
  • 0635 }
  • 0636 return mode;
  • 0637 }
  • 0638 }
  • 0639
  • 0640 /**
  • 0641 * Type check all the children of this node.
  • 0642 */
  • 0643 public Type typeCheck(SymbolTable stable) throws TypeCheckError {
  • 0644 final int count = _globals.size();
  • 0645 for (int i = 0; i < count; i++) {
  • 0646 final VariableBase var = (VariableBase)_globals.elementAt(i);
  • 0647 var.typeCheck(stable);
  • 0648 }
  • 0649 return typeCheckContents(stable);
  • 0650 }
  • 0651
  • 0652 /**
  • 0653 * Translate the stylesheet into JVM bytecodes.
  • 0654 */
  • 0655 public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
  • 0656 translate();
  • 0657 }
  • 0658
  • 0659 private void addDOMField(ClassGenerator classGen) {
  • 0660 final FieldGen fgen = new FieldGen(ACC_PUBLIC,
  • 0661 Util.getJCRefType(DOM_INTF_SIG),
  • 0662 DOM_FIELD,
  • 0663 classGen.getConstantPool());
  • 0664 classGen.addField(fgen.getField());
  • 0665 }
  • 0666
  • 0667 /**
  • 0668 * Add a static field
  • 0669 */
  • 0670 private void addStaticField(ClassGenerator classGen, String type,
  • 0671 String name)
  • 0672 {
  • 0673 final FieldGen fgen = new FieldGen(ACC_PROTECTED|ACC_STATIC,
  • 0674 Util.getJCRefType(type),
  • 0675 name,
  • 0676 classGen.getConstantPool());
  • 0677 classGen.addField(fgen.getField());
  • 0678
  • 0679 }
  • 0680
  • 0681 /**
  • 0682 * Translate the stylesheet into JVM bytecodes.
  • 0683 */
  • 0684 public void translate() {
  • 0685 _className = getXSLTC().getClassName();
  • 0686
  • 0687 // Define a new class by extending TRANSLET_CLASS
  • 0688 final ClassGenerator classGen =
  • 0689 new ClassGenerator(_className,
  • 0690 TRANSLET_CLASS,
  • 0691 Constants.EMPTYSTRING,
  • 0692 ACC_PUBLIC | ACC_SUPER,
  • 0693 null, this);
  • 0694
  • 0695 addDOMField(classGen);
  • 0696
  • 0697 // Compile transform() to initialize parameters, globals & output
  • 0698 // and run the transformation
  • 0699 compileTransform(classGen);
  • 0700
  • 0701 // Translate all non-template elements and filter out all templates
  • 0702 final Enumeration elements = elements();
  • 0703 while (elements.hasMoreElements()) {
  • 0704 Object element = elements.nextElement();
  • 0705 // xsl:template
  • 0706 if (element instanceof Template) {
  • 0707 // Separate templates by modes
  • 0708 final Template template = (Template)element;
  • 0709 //_templates.addElement(template);
  • 0710 getMode(template.getModeName()).addTemplate(template);
  • 0711 }
  • 0712 // xsl:attribute-set
  • 0713 else if (element instanceof AttributeSet) {
  • 0714 ((AttributeSet)element).translate(classGen, null);
  • 0715 }
  • 0716 else if (element instanceof Output) {
  • 0717 // save the element for later to pass to compileConstructor
  • 0718 Output output = (Output)element;
  • 0719 if (output.enabled()) _lastOutputElement = output;
  • 0720 }
  • 0721 else {
  • 0722 // Global variables and parameters are handled elsewhere.
  • 0723 // Other top-level non-template elements are ignored. Literal
  • 0724 // elements outside of templates will never be output.
  • 0725 }
  • 0726 }
  • 0727
  • 0728 checkOutputMethod();
  • 0729 processModes();
  • 0730 compileModes(classGen);
  • 0731 compileStaticInitializer(classGen);
  • 0732 compileConstructor(classGen, _lastOutputElement);
  • 0733
  • 0734 if (!getParser().errorsFound()) {
  • 0735 getXSLTC().dumpClass(classGen.getJavaClass());
  • 0736 }
  • 0737 }
  • 0738
  • 0739 /**
  • 0740 * Compile the namesArray, urisArray and typesArray into
  • 0741 * the static initializer. They are read-only from the
  • 0742 * translet. All translet instances can share a single
  • 0743 * copy of this informtion.
  • 0744 */
  • 0745 private void compileStaticInitializer(ClassGenerator classGen) {
  • 0746 final ConstantPoolGen cpg = classGen.getConstantPool();
  • 0747 final InstructionList il = new InstructionList();
  • 0748
  • 0749 final MethodGenerator staticConst =
  • 0750 new MethodGenerator(ACC_PUBLIC|ACC_STATIC,
  • 0751 com.sun.org.apache.bcel.internal.generic.Type.VOID,
  • 0752 null, null, "<clinit>",
  • 0753 _className, il, cpg);
  • 0754
  • 0755 addStaticField(classGen, "[" + STRING_SIG, STATIC_NAMES_ARRAY_FIELD);
  • 0756 addStaticField(classGen, "[" + STRING_SIG, STATIC_URIS_ARRAY_FIELD);
  • 0757 addStaticField(classGen, "[I", STATIC_TYPES_ARRAY_FIELD);
  • 0758 addStaticField(classGen, "[" + STRING_SIG, STATIC_NAMESPACE_ARRAY_FIELD);
  • 0759 // Create fields of type char[] that will contain literal text from
  • 0760 // the stylesheet.
  • 0761 final int charDataFieldCount = getXSLTC().getCharacterDataCount();
  • 0762 for (int i = 0; i < charDataFieldCount; i++) {
  • 0763 addStaticField(classGen, STATIC_CHAR_DATA_FIELD_SIG,
  • 0764 STATIC_CHAR_DATA_FIELD+i);
  • 0765 }
  • 0766
  • 0767 // Put the names array into the translet - used for dom/translet mapping
  • 0768 final Vector namesIndex = getXSLTC().getNamesIndex();
  • 0769 int size = namesIndex.size();
  • 0770 String[] namesArray = new String[size];
  • 0771 String[] urisArray = new String[size];
  • 0772 int[] typesArray = new int[size];
  • 0773
  • 0774 int index;
  • 0775 for (int i = 0; i < size; i++) {
  • 0776 String encodedName = (String)namesIndex.elementAt(i);
  • 0777 if ((index = encodedName.lastIndexOf(':')) > -1) {
  • 0778 urisArray[i] = encodedName.substring(0, index);
  • 0779 }
  • 0780
  • 0781 index = index + 1;
  • 0782 if (encodedName.charAt(index) == '@') {
  • 0783 typesArray[i] = DTM.ATTRIBUTE_NODE;
  • 0784 index++;
  • 0785 } else if (encodedName.charAt(index) == '?') {
  • 0786 typesArray[i] = DTM.NAMESPACE_NODE;
  • 0787 index++;
  • 0788 } else {
  • 0789 typesArray[i] = DTM.ELEMENT_NODE;
  • 0790 }
  • 0791
  • 0792 if (index == 0) {
  • 0793 namesArray[i] = encodedName;
  • 0794 }
  • 0795 else {
  • 0796 namesArray[i] = encodedName.substring(index);
  • 0797 }
  • 0798 }
  • 0799
  • 0800 il.append(new PUSH(cpg, size));
  • 0801 il.append(new ANEWARRAY(cpg.addClass(STRING)));
  • 0802
  • 0803 for (int i = 0; i < size; i++) {
  • 0804 final String name = namesArray[i];
  • 0805 il.append(DUP);
  • 0806 il.append(new PUSH(cpg, i));
  • 0807 il.append(new PUSH(cpg, name));
  • 0808 il.append(AASTORE);
  • 0809 }
  • 0810 il.append(new PUTSTATIC(cpg.addFieldref(_className,
  • 0811 STATIC_NAMES_ARRAY_FIELD,
  • 0812 NAMES_INDEX_SIG)));
  • 0813
  • 0814 il.append(new PUSH(cpg, size));
  • 0815 il.append(new ANEWARRAY(cpg.addClass(STRING)));
  • 0816
  • 0817 for (int i = 0; i < size; i++) {
  • 0818 final String uri = urisArray[i];
  • 0819 il.append(DUP);
  • 0820 il.append(new PUSH(cpg, i));
  • 0821 il.append(new PUSH(cpg, uri));
  • 0822 il.append(AASTORE);
  • 0823 }
  • 0824 il.append(new PUTSTATIC(cpg.addFieldref(_className,
  • 0825 STATIC_URIS_ARRAY_FIELD,
  • 0826 URIS_INDEX_SIG)));
  • 0827
  • 0828 il.append(new PUSH(cpg, size));
  • 0829 il.append(new NEWARRAY(BasicType.INT));
  • 0830
  • 0831 for (int i = 0; i < size; i++) {
  • 0832 final int nodeType = typesArray[i];
  • 0833 il.append(DUP);
  • 0834 il.append(new PUSH(cpg, i));
  • 0835 il.append(new PUSH(cpg, nodeType));
  • 0836 il.append(IASTORE);
  • 0837 }
  • 0838 il.append(new PUTSTATIC(cpg.addFieldref(_className,
  • 0839 STATIC_TYPES_ARRAY_FIELD,
  • 0840 TYPES_INDEX_SIG)));
  • 0841
  • 0842 // Put the namespace names array into the translet
  • 0843 final Vector namespaces = getXSLTC().getNamespaceIndex();
  • 0844 il.append(new PUSH(cpg, namespaces.size()));
  • 0845 il.append(new ANEWARRAY(cpg.addClass(STRING)));
  • 0846
  • 0847 for (int i = 0; i < namespaces.size(); i++) {
  • 0848 final String ns = (String)namespaces.elementAt(i);
  • 0849 il.append(DUP);
  • 0850 il.append(new PUSH(cpg, i));
  • 0851 il.append(new PUSH(cpg, ns));
  • 0852 il.append(AASTORE);
  • 0853 }
  • 0854 il.append(new PUTSTATIC(cpg.addFieldref(_className,
  • 0855 STATIC_NAMESPACE_ARRAY_FIELD,
  • 0856 NAMESPACE_INDEX_SIG)));
  • 0857
  • 0858 // Grab all the literal text in the stylesheet and put it in a char[]
  • 0859 final int charDataCount = getXSLTC().getCharacterDataCount();
  • 0860 final int toCharArray = cpg.addMethodref(STRING, "toCharArray", "()[C");
  • 0861 for (int i = 0; i < charDataCount; i++) {
  • 0862 il.append(new PUSH(cpg, getXSLTC().getCharacterData(i)));
  • 0863 il.append(new INVOKEVIRTUAL(toCharArray));
  • 0864 il.append(new PUTSTATIC(cpg.addFieldref(_className,
  • 0865 STATIC_CHAR_DATA_FIELD+i,
  • 0866 STATIC_CHAR_DATA_FIELD_SIG)));
  • 0867 }
  • 0868
  • 0869 il.append(RETURN);
  • 0870
  • 0871 staticConst.stripAttributes(true);
  • 0872 staticConst.setMaxLocals();
  • 0873 staticConst.setMaxStack();
  • 0874 classGen.addMethod(staticConst.getMethod());
  • 0875
  • 0876 }
  • 0877
  • 0878 /**
  • 0879 * Compile the translet's constructor
  • 0880 */
  • 0881 private void compileConstructor(ClassGenerator classGen, Output output) {
  • 0882
  • 0883 final ConstantPoolGen cpg = classGen.getConstantPool();
  • 0884 final InstructionList il = new InstructionList();
  • 0885
  • 0886 final MethodGenerator constructor =
  • 0887 new MethodGenerator(ACC_PUBLIC,
  • 0888 com.sun.org.apache.bcel.internal.generic.Type.VOID,
  • 0889 null, null, "<init>",
  • 0890 _className, il, cpg);
  • 0891
  • 0892 // Call the constructor in the AbstractTranslet superclass
  • 0893 il.append(classGen.loadTranslet());
  • 0894 il.append(new INVOKESPECIAL(cpg.addMethodref(TRANSLET_CLASS,
  • 0895 "<init>", "()V")));
  • 0896
  • 0897 il.append(classGen.loadTranslet());
  • 0898 il.append(new GETSTATIC(cpg.addFieldref(_className,
  • 0899 STATIC_NAMES_ARRAY_FIELD,
  • 0900 NAMES_INDEX_SIG)));
  • 0901 il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
  • 0902 NAMES_INDEX,
  • 0903 NAMES_INDEX_SIG)));
  • 0904
  • 0905 il.append(classGen.loadTranslet());
  • 0906 il.append(new GETSTATIC(cpg.addFieldref(_className,
  • 0907 STATIC_URIS_ARRAY_FIELD,
  • 0908 URIS_INDEX_SIG)));
  • 0909 il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
  • 0910 URIS_INDEX,
  • 0911 URIS_INDEX_SIG)));
  • 0912
  • 0913 il.append(classGen.loadTranslet());
  • 0914 il.append(new GETSTATIC(cpg.addFieldref(_className,
  • 0915 STATIC_TYPES_ARRAY_FIELD,
  • 0916 TYPES_INDEX_SIG)));
  • 0917 il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
  • 0918 TYPES_INDEX,
  • 0919 TYPES_INDEX_SIG)));
  • 0920
  • 0921 il.append(classGen.loadTranslet());
  • 0922 il.append(new GETSTATIC(cpg.addFieldref(_className,
  • 0923 STATIC_NAMESPACE_ARRAY_FIELD,
  • 0924 NAMESPACE_INDEX_SIG)));
  • 0925 il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
  • 0926 NAMESPACE_INDEX,
  • 0927 NAMESPACE_INDEX_SIG)));
  • 0928
  • 0929 il.append(classGen.loadTranslet());
  • 0930 il.append(new PUSH(cpg, AbstractTranslet.CURRENT_TRANSLET_VERSION));
  • 0931 il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
  • 0932 TRANSLET_VERSION_INDEX,
  • 0933 TRANSLET_VERSION_INDEX_SIG)));
  • 0934
  • 0935 if (_hasIdCall) {
  • 0936 il.append(classGen.loadTranslet());
  • 0937 il.append(new PUSH(cpg, Boolean.TRUE));
  • 0938 il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
  • 0939 HASIDCALL_INDEX,
  • 0940 HASIDCALL_INDEX_SIG)));
  • 0941 }
  • 0942
  • 0943 // Compile in code to set the output configuration from <xsl:output>
  • 0944 if (output != null) {
  • 0945 // Set all the output settings files in the translet
  • 0946 output.translate(classGen, constructor);
  • 0947 }
  • 0948
  • 0949 // Compile default decimal formatting symbols.
  • 0950 // This is an implicit, nameless xsl:decimal-format top-level element.
  • 0951 if (_numberFormattingUsed)
  • 0952 DecimalFormatting.translateDefaultDFS(classGen, constructor);
  • 0953
  • 0954 il.append(RETURN);
  • 0955
  • 0956 constructor.stripAttributes(true);
  • 0957 constructor.setMaxLocals();
  • 0958 constructor.setMaxStack();
  • 0959 classGen.addMethod(constructor.getMethod());
  • 0960 }
  • 0961
  • 0962 /**
  • 0963 * Compile a topLevel() method into the output class. This method is
  • 0964 * called from transform() to handle all non-template top-level elements.
  • 0965 * Returns the signature of the topLevel() method.
  • 0966 *
  • 0967 * Global variables/params and keys are first sorted to resolve
  • 0968 * dependencies between them. The XSLT 1.0 spec does not allow a key
  • 0969 * to depend on a variable. However, for compatibility with Xalan
  • 0970 * interpretive, that type of dependency is allowed. Note also that
  • 0971 * the buildKeys() method is still generated as it is used by the
  • 0972 * LoadDocument class, but it no longer called from transform().
  • 0973 */
  • 0974 private String compileTopLevel(ClassGenerator classGen) {
  • 0975
  • 0976 final ConstantPoolGen cpg = classGen.getConstantPool();
  • 0977
  • 0978 final com.sun.org.apache.bcel.internal.generic.Type[] argTypes = {
  • 0979 Util.getJCRefType(DOM_INTF_SIG),
  • 0980 Util.getJCRefType(NODE_ITERATOR_SIG),
  • 0981 Util.getJCRefType(TRANSLET_OUTPUT_SIG)
  • 0982 };
  • 0983
  • 0984 final String[] argNames = {
  • 0985 DOCUMENT_PNAME, ITERATOR_PNAME, TRANSLET_OUTPUT_PNAME
  • 0986 };
  • 0987
  • 0988 final InstructionList il = new InstructionList();
  • 0989
  • 0990 final MethodGenerator toplevel =
  • 0991 new MethodGenerator(ACC_PUBLIC,
  • 0992 com.sun.org.apache.bcel.internal.generic.Type.VOID,
  • 0993 argTypes, argNames,
  • 0994 "topLevel", _className, il,
  • 0995 classGen.getConstantPool());
  • 0996
  • 0997 toplevel.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException");
  • 0998
  • 0999 // Define and initialize 'current' variable with the root node
  • 1000 final LocalVariableGen current =
  • 1001 toplevel.addLocalVariable("current",
  • 1002 com.sun.org.apache.bcel.internal.generic.Type.INT,
  • 1003 il.getEnd(), null);
  • 1004
  • 1005 final int setFilter = cpg.addInterfaceMethodref(DOM_INTF,
  • 1006 "setFilter",
  • 1007 "(Lcom/sun/org/apache/xalan/internal/xsltc/StripFilter;)V");
  • 1008
  • 1009 il.append(new PUSH(cpg, DTM.ROOT_NODE));
  • 1010 il.append(new ISTORE(current.getIndex()));
  • 1011
  • 1012 // Create a new list containing variables/params + keys
  • 1013 Vector varDepElements = new Vector(_globals);
  • 1014 Enumeration elements = elements();
  • 1015 while (elements.hasMoreElements()) {
  • 1016 final Object element = elements.nextElement();
  • 1017 if (element instanceof Key) {
  • 1018 varDepElements.add(element);
  • 1019 }
  • 1020 }
  • 1021
  • 1022 // Determine a partial order for the variables/params and keys
  • 1023 varDepElements = resolveDependencies(varDepElements);
  • 1024
  • 1025 // Translate vars/params and keys in the right order
  • 1026 final int count = varDepElements.size();
  • 1027 for (int i = 0; i < count; i++) {
  • 1028 final TopLevelElement tle = (TopLevelElement) varDepElements.elementAt(i);
  • 1029 tle.translate(classGen, toplevel);
  • 1030 if (tle instanceof Key) {
  • 1031 final Key key = (Key) tle;
  • 1032 _keys.put(key.getName(), key);
  • 1033 }
  • 1034 }
  • 1035
  • 1036 // Compile code for other top-level elements
  • 1037 Vector whitespaceRules = new Vector();
  • 1038 elements = elements();
  • 1039 while (elements.hasMoreElements()) {
  • 1040 final Object element = elements.nextElement();
  • 1041 // xsl:decimal-format
  • 1042 if (element instanceof DecimalFormatting) {
  • 1043 ((DecimalFormatting)element).translate(classGen,toplevel);
  • 1044 }
  • 1045 // xsl:strip/preserve-space
  • 1046 else if (element instanceof Whitespace) {
  • 1047 whitespaceRules.addAll(((Whitespace)element).getRules());
  • 1048 }
  • 1049 }
  • 1050
  • 1051 // Translate all whitespace strip/preserve rules
  • 1052 if (whitespaceRules.size() > 0) {
  • 1053 Whitespace.translateRules(whitespaceRules,classGen);
  • 1054 }
  • 1055
  • 1056 if (classGen.containsMethod(STRIP_SPACE, STRIP_SPACE_PARAMS) != null) {
  • 1057 il.append(toplevel.loadDOM());
  • 1058 il.append(classGen.loadTranslet());
  • 1059 il.append(new INVOKEINTERFACE(setFilter, 2));
  • 1060 }
  • 1061
  • 1062 il.append(RETURN);
  • 1063
  • 1064 // Compute max locals + stack and add method to class
  • 1065 toplevel.stripAttributes(true);
  • 1066 toplevel.setMaxLocals();
  • 1067 toplevel.setMaxStack();
  • 1068 toplevel.removeNOPs();
  • 1069
  • 1070 classGen.addMethod(toplevel.getMethod());
  • 1071
  • 1072 return("("+DOM_INTF_SIG+NODE_ITERATOR_SIG+TRANSLET_OUTPUT_SIG+")V");
  • 1073 }
  • 1074
  • 1075 /**
  • 1076 * This method returns a vector with variables/params and keys in the
  • 1077 * order in which they are to be compiled for initialization. The order
  • 1078 * is determined by analyzing the dependencies between them. The XSLT 1.0
  • 1079 * spec does not allow a key to depend on a variable. However, for
  • 1080 * compatibility with Xalan interpretive, that type of dependency is
  • 1081 * allowed and, therefore, consider to determine the partial order.
  • 1082 */
  • 1083 private Vector resolveDependencies(Vector input) {
  • 1084 /* DEBUG CODE - INGORE
  • 1085 for (int i = 0; i < input.size(); i++) {
  • 1086 final TopLevelElement e = (TopLevelElement) input.elementAt(i);
  • 1087 System.out.println("e = " + e + " depends on:");
  • 1088 Vector dep = e.getDependencies();
  • 1089 for (int j = 0; j < (dep != null ? dep.size() : 0); j++) {
  • 1090 System.out.println("\t" + dep.elementAt(j));
  • 1091 }
  • 1092 }
  • 1093 System.out.println("=================================");
  • 1094 */
  • 1095
  • 1096 Vector result = new Vector();
  • 1097 while (input.size() > 0) {
  • 1098 boolean changed = false;
  • 1099 for (int i = 0; i < input.size(); ) {
  • 1100 final TopLevelElement vde = (TopLevelElement) input.elementAt(i);
  • 1101 final Vector dep = vde.getDependencies();
  • 1102 if (dep == null || result.containsAll(dep)) {
  • 1103 result.addElement(vde);
  • 1104 input.remove(i);
  • 1105 changed = true;
  • 1106 }
  • 1107 else {
  • 1108 i++;
  • 1109 }
  • 1110 }
  • 1111
  • 1112 // If nothing was changed in this pass then we have a circular ref
  • 1113 if (!changed) {
  • 1114 ErrorMsg err = new ErrorMsg(ErrorMsg.CIRCULAR_VARIABLE_ERR,
  • 1115 input.toString(), this);
  • 1116 getParser().reportError(Constants.ERROR, err);
  • 1117 return(result);
  • 1118 }
  • 1119 }
  • 1120
  • 1121 /* DEBUG CODE - INGORE
  • 1122 System.out.println("=================================");
  • 1123 for (int i = 0; i < result.size(); i++) {
  • 1124 final TopLevelElement e = (TopLevelElement) result.elementAt(i);
  • 1125 System.out.println("e = " + e);
  • 1126 }
  • 1127 */
  • 1128
  • 1129 return result;
  • 1130 }
  • 1131
  • 1132 /**
  • 1133 * Compile a buildKeys() method into the output class. Note that keys
  • 1134 * for the input document are created in topLevel(), not in this method.
  • 1135 * However, we still need this method to create keys for documents loaded
  • 1136 * via the XPath document() function.
  • 1137 */
  • 1138 private String compileBuildKeys(ClassGenerator classGen) {
  • 1139 final ConstantPoolGen cpg = classGen.getConstantPool();
  • 1140
  • 1141 final com.sun.org.apache.bcel.internal.generic.Type[] argTypes = {
  • 1142 Util.getJCRefType(DOM_INTF_SIG),
  • 1143 Util.getJCRefType(NODE_ITERATOR_SIG),
  • 1144 Util.getJCRefType(TRANSLET_OUTPUT_SIG),
  • 1145 com.sun.org.apache.bcel.internal.generic.Type.INT
  • 1146 };
  • 1147
  • 1148 final String[] argNames = {
  • 1149 DOCUMENT_PNAME, ITERATOR_PNAME, TRANSLET_OUTPUT_PNAME, "current"
  • 1150 };
  • 1151
  • 1152 final InstructionList il = new InstructionList();
  • 1153
  • 1154 final MethodGenerator buildKeys =
  • 1155 new MethodGenerator(ACC_PUBLIC,
  • 1156 com.sun.org.apache.bcel.internal.generic.Type.VOID,
  • 1157 argTypes, argNames,
  • 1158 "buildKeys", _className, il,
  • 1159 classGen.getConstantPool());
  • 1160
  • 1161 buildKeys.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException");
  • 1162
  • 1163 final Enumeration elements = elements();
  • 1164 while (elements.hasMoreElements()) {
  • 1165 // xsl:key
  • 1166 final Object element = elements.nextElement();
  • 1167 if (element instanceof Key) {
  • 1168 final Key key = (Key)element;
  • 1169 key.translate(classGen, buildKeys);
  • 1170 _keys.put(key.getName(),key);
  • 1171 }
  • 1172 }
  • 1173
  • 1174 il.append(RETURN);
  • 1175
  • 1176 // Compute max locals + stack and add method to class
  • 1177 buildKeys.stripAttributes(true);
  • 1178 buildKeys.setMaxLocals();
  • 1179 buildKeys.setMaxStack();
  • 1180 buildKeys.removeNOPs();
  • 1181
  • 1182 classGen.addMethod(buildKeys.getMethod());
  • 1183
  • 1184 return("("+DOM_INTF_SIG+NODE_ITERATOR_SIG+TRANSLET_OUTPUT_SIG+"I)V");
  • 1185 }
  • 1186
  • 1187 /**
  • 1188 * Compile transform() into the output class. This method is used to
  • 1189 * initialize global variables and global parameters. The current node
  • 1190 * is set to be the document's root node.
  • 1191 */
  • 1192 private void compileTransform(ClassGenerator classGen) {
  • 1193 final ConstantPoolGen cpg = classGen.getConstantPool();
  • 1194
  • 1195 /*
  • 1196 * Define the the method transform with the following signature:
  • 1197 * void transform(DOM, NodeIterator, HandlerBase)
  • 1198 */
  • 1199 final com.sun.org.apache.bcel.internal.generic.Type[] argTypes =
  • 1200 new com.sun.org.apache.bcel.internal.generic.Type[3];
  • 1201 argTypes[0] = Util.getJCRefType(DOM_INTF_SIG);
  • 1202 argTypes[1] = Util.getJCRefType(NODE_ITERATOR_SIG);
  • 1203 argTypes[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG);
  • 1204
  • 1205 final String[] argNames = new String[3];
  • 1206 argNames[0] = DOCUMENT_PNAME;
  • 1207 argNames[1] = ITERATOR_PNAME;
  • 1208 argNames[2] = TRANSLET_OUTPUT_PNAME;
  • 1209
  • 1210 final InstructionList il = new InstructionList();
  • 1211 final MethodGenerator transf =
  • 1212 new MethodGenerator(ACC_PUBLIC,
  • 1213 com.sun.org.apache.bcel.internal.generic.Type.VOID,
  • 1214 argTypes, argNames,
  • 1215 "transform",
  • 1216 _className,
  • 1217 il,
  • 1218 classGen.getConstantPool());
  • 1219 transf.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException");
  • 1220
  • 1221 // Define and initialize current with the root node
  • 1222 final LocalVariableGen current =
  • 1223 transf.addLocalVariable("current",
  • 1224 com.sun.org.apache.bcel.internal.generic.Type.INT,
  • 1225 il.getEnd(), null);
  • 1226 final String applyTemplatesSig = classGen.getApplyTemplatesSig();
  • 1227 final int applyTemplates = cpg.addMethodref(getClassName(),
  • 1228 "applyTemplates",
  • 1229 applyTemplatesSig);
  • 1230 final int domField = cpg.addFieldref(getClassName(),
  • 1231 DOM_FIELD,
  • 1232 DOM_INTF_SIG);
  • 1233
  • 1234 // push translet for PUTFIELD
  • 1235 il.append(classGen.loadTranslet());
  • 1236 // prepare appropriate DOM implementation
  • 1237
  • 1238 if (isMultiDocument()) {
  • 1239 il.append(new NEW(cpg.addClass(MULTI_DOM_CLASS)));
  • 1240 il.append(DUP);
  • 1241 }
  • 1242
  • 1243 il.append(classGen.loadTranslet());
  • 1244 il.append(transf.loadDOM());
  • 1245 il.append(new INVOKEVIRTUAL(cpg.addMethodref(TRANSLET_CLASS,
  • 1246 "makeDOMAdapter",
  • 1247 "("+DOM_INTF_SIG+")"+
  • 1248 DOM_ADAPTER_SIG)));
  • 1249 // DOMAdapter is on the stack
  • 1250
  • 1251 if (isMultiDocument()) {
  • 1252 final int init = cpg.addMethodref(MULTI_DOM_CLASS,
  • 1253 "<init>",
  • 1254 "("+DOM_INTF_SIG+")V");
  • 1255 il.append(new INVOKESPECIAL(init));
  • 1256 // MultiDOM is on the stack
  • 1257 }
  • 1258
  • 1259 //store to _dom variable
  • 1260 il.append(new PUTFIELD(domField));
  • 1261
  • 1262 // continue with globals initialization
  • 1263 il.append(new PUSH(cpg, DTM.ROOT_NODE));
  • 1264 il.append(new ISTORE(current.getIndex()));
  • 1265
  • 1266 // Transfer the output settings to the output post-processor
  • 1267 il.append(classGen.loadTranslet());
  • 1268 il.append(transf.loadHandler());
  • 1269 final int index = cpg.addMethodref(TRANSLET_CLASS,
  • 1270 "transferOutputSettings",
  • 1271 "("+OUTPUT_HANDLER_SIG+")V");
  • 1272 il.append(new INVOKEVIRTUAL(index));
  • 1273
  • 1274 /*
  • 1275 * Compile buildKeys() method. Note that this method is not
  • 1276 * invoked here as keys for the input document are now created
  • 1277 * in topLevel(). However, this method is still needed by the
  • 1278 * LoadDocument class.
  • 1279 */
  • 1280 final String keySig = compileBuildKeys(classGen);
  • 1281 final int keyIdx = cpg.addMethodref(getClassName(),
  • 1282 "buildKeys", keySig);
  • 1283
  • 1284 // Look for top-level elements that need handling
  • 1285 final Enumeration toplevel = elements();
  • 1286 if (_globals.size() > 0 || toplevel.hasMoreElements()) {
  • 1287 // Compile method for handling top-level elements
  • 1288 final String topLevelSig = compileTopLevel(classGen);
  • 1289 // Get a reference to that method
  • 1290 final int topLevelIdx = cpg.addMethodref(getClassName(),
  • 1291 "topLevel",
  • 1292 topLevelSig);
  • 1293 // Push all parameters on the stack and call topLevel()
  • 1294 il.append(classGen.loadTranslet()); // The 'this' pointer
  • 1295 il.append(classGen.loadTranslet());
  • 1296 il.append(new GETFIELD(domField)); // The DOM reference
  • 1297 il.append(transf.loadIterator());
  • 1298 il.append(transf.loadHandler()); // The output handler
  • 1299 il.append(new INVOKEVIRTUAL(topLevelIdx));
  • 1300 }
  • 1301
  • 1302 // start document
  • 1303 il.append(transf.loadHandler());
  • 1304 il.append(transf.startDocument());
  • 1305
  • 1306 // push first arg for applyTemplates
  • 1307 il.append(classGen.loadTranslet());
  • 1308 // push translet for GETFIELD to get DOM arg
  • 1309 il.append(classGen.loadTranslet());
  • 1310 il.append(new GETFIELD(domField));
  • 1311 // push remaining 2 args
  • 1312 il.append(transf.loadIterator());
  • 1313 il.append(transf.loadHandler());
  • 1314 il.append(new INVOKEVIRTUAL(applyTemplates));
  • 1315 // endDocument
  • 1316 il.append(transf.loadHandler());
  • 1317 il.append(transf.endDocument());
  • 1318
  • 1319 il.append(RETURN);
  • 1320
  • 1321 // Compute max locals + stack and add method to class
  • 1322 transf.stripAttributes(true);
  • 1323 transf.setMaxLocals();
  • 1324 transf.setMaxStack();
  • 1325 transf.removeNOPs();
  • 1326
  • 1327 classGen.addMethod(transf.getMethod());
  • 1328 }
  • 1329
  • 1330 /**
  • 1331 * Peephole optimization: Remove sequences of [ALOAD, POP].
  • 1332 */
  • 1333 private void peepHoleOptimization(MethodGenerator methodGen) {
  • 1334 final String pattern = "`aload'`pop'`instruction'";
  • 1335 final InstructionList il = methodGen.getInstructionList();
  • 1336 final InstructionFinder find = new InstructionFinder(il);
  • 1337 for(Iterator iter=find.search(pattern); iter.hasNext(); ) {
  • 1338 InstructionHandle[] match = (InstructionHandle[])iter.next();
  • 1339 try {
  • 1340 il.delete(match[0], match[1]);
  • 1341 }
  • 1342 catch (TargetLostException e) {
  • 1343 // TODO: move target down into the list
  • 1344 }
  • 1345 }
  • 1346 }
  • 1347
  • 1348 public int addParam(Param param) {
  • 1349 _globals.addElement(param);
  • 1350 return _globals.size() - 1;
  • 1351 }
  • 1352
  • 1353 public int addVariable(Variable global) {
  • 1354 _globals.addElement(global);
  • 1355 return _globals.size() - 1;
  • 1356 }
  • 1357
  • 1358 public void display(int indent) {
  • 1359 indent(indent);
  • 1360 Util.println("Stylesheet");
  • 1361 displayContents(indent + IndentIncrement);
  • 1362 }
  • 1363
  • 1364 // do we need this wrapper ?????
  • 1365 public String getNamespace(String prefix) {
  • 1366 return lookupNamespace(prefix);
  • 1367 }
  • 1368
  • 1369 public String getClassName() {
  • 1370 return _className;
  • 1371 }
  • 1372
  • 1373 public Vector getTemplates() {
  • 1374 return _templates;
  • 1375 }
  • 1376
  • 1377 public Vector getAllValidTemplates() {
  • 1378 // Return templates if no imported/included stylesheets
  • 1379 if (_includedStylesheets == null) {
  • 1380 return _templates;
  • 1381 }
  • 1382
  • 1383 // Is returned value cached?
  • 1384 if (_allValidTemplates == null) {
  • 1385 Vector templates = new Vector();
  • 1386 templates.addAll(_templates);
  • 1387 int size = _includedStylesheets.size();
  • 1388 for (int i = 0; i < size; i++) {
  • 1389 Stylesheet included =(Stylesheet)_includedStylesheets.elementAt(i);
  • 1390 templates.addAll(included.getAllValidTemplates());
  • 1391 }
  • 1392 //templates.addAll(_templates);
  • 1393
  • 1394 // Cache results in top-level stylesheet only
  • 1395 if (_parentStylesheet != null) {
  • 1396 return templates;
  • 1397 }
  • 1398 _allValidTemplates = templates;
  • 1399 }
  • 1400
  • 1401 return _allValidTemplates;
  • 1402 }
  • 1403
  • 1404 protected void addTemplate(Template template) {
  • 1405 _templates.addElement(template);
  • 1406 }
  • 1407}

文件:Stylesheet.java
包名:com.sun.org.apache.xalan.internal.xsltc.compiler
类名:Stylesheet
继承:SyntaxTreeNode
接口: