Source Code Cross Referenced for Controller.java in  » XML » XPath-Saxon » net » sf » saxon » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » XML » XPath Saxon » net.sf.saxon 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package net.sf.saxon;
0002:
0003:        import net.sf.saxon.event.*;
0004:        import net.sf.saxon.expr.XPathContext;
0005:        import net.sf.saxon.expr.XPathContextMajor;
0006:        import net.sf.saxon.functions.Component;
0007:        import net.sf.saxon.instruct.*;
0008:        import net.sf.saxon.om.*;
0009:        import net.sf.saxon.sort.IntHashMap;
0010:        import net.sf.saxon.tinytree.TinyBuilder;
0011:        import net.sf.saxon.trace.*;
0012:        import net.sf.saxon.trans.*;
0013:        import net.sf.saxon.tree.TreeBuilder;
0014:        import net.sf.saxon.value.DateTimeValue;
0015:        import org.xml.sax.SAXParseException;
0016:
0017:        import javax.xml.transform.*;
0018:        import javax.xml.transform.dom.DOMSource;
0019:        import javax.xml.transform.stream.StreamResult;
0020:        import java.io.OutputStream;
0021:        import java.io.PrintStream;
0022:        import java.util.*;
0023:
0024:        /**
0025:         * The Controller is Saxon's implementation of the JAXP Transformer class, and represents
0026:         * an executing instance of a transformation or query. Multiple concurrent executions of
0027:         * the same transformation or query will use different Controller instances. This class is
0028:         * therefore not thread-safe.
0029:         * <p>
0030:         * The Controller is serially reusable, as required by JAXP: when one transformation or query
0031:         * is finished, it can be used to run another. However, there is no advantage in doing this
0032:         * rather than allocating a new Controller each time.
0033:         * <p>
0034:         * The Controller can also be used when running Java applications that use neither XSLT nor
0035:         * XQuery. A dummy Controller is created when running free-standing XPath expressions.
0036:         * <p>
0037:         * The Controller holds those parts of the dynamic context that do not vary during the course
0038:         * of a transformation or query, or that do not change once their value has been computed.
0039:         * This also includes those parts of the static context that are required at run-time.
0040:         * <p>
0041:         * Wherever possible XSLT applications should use the JAXP Transformer class directly,
0042:         * rather than relying on Saxon-specific methods in the Controller. However, some
0043:         * features are currently available only through this class. This applies especially
0044:         * to new features specific to XSLT 2.0, since the JAXP interface still supports
0045:         * only XSLT 1.0. Such methods may be superseded in the future by JAXP methods.
0046:         * <p>
0047:         * Many methods on the Controller are designed for internal use and should not be
0048:         * considered stable. From release 8.4 onwards, those methods that are considered sufficiently
0049:         * stable to constitute path of the Saxon public API are labelled with the JavaDoc tag "since":
0050:         * the value indicates the release at which the method was added to the public API.
0051:         *
0052:         * @author Michael H. Kay
0053:         * @since 8.4
0054:         */
0055:
0056:        public class Controller extends Transformer implements 
0057:                InstructionInfoProvider {
0058:
0059:            private Configuration config;
0060:            private DocumentInfo principalSourceDocument;
0061:            private Bindery bindery; // holds values of global and local variables
0062:            private NamePool namePool;
0063:            private Emitter messageEmitter;
0064:            private RuleManager ruleManager;
0065:            private Properties outputProperties;
0066:            private GlobalParameterSet parameters;
0067:            private PreparedStylesheet preparedStylesheet;
0068:            private TraceListener traceListener;
0069:            private boolean tracingPaused;
0070:            private URIResolver standardURIResolver;
0071:            private URIResolver userURIResolver;
0072:            private Result principalResult;
0073:            private String principalResultURI;
0074:            private OutputURIResolver outputURIResolver;
0075:            private ErrorListener errorListener;
0076:            private Executable executable;
0077:            private int treeModel = Builder.TINY_TREE;
0078:            private Template initialTemplate = null;
0079:            private HashSet allOutputDestinations;
0080:            private DocumentPool sourceDocumentPool;
0081:            private HashMap userDataTable;
0082:            private DateTimeValue currentDateTime;
0083:            private boolean dateTimePreset = false;
0084:            private int initialMode = -1;
0085:            private NodeInfo lastRememberedNode = null;
0086:            private int lastRememberedNumber = -1;
0087:            private ClassLoader classLoader;
0088:
0089:            //    private int nextLocalDocumentNumber = -1;
0090:
0091:            /**
0092:             * Create a Controller and initialise variables. Constructor is protected,
0093:             * the Controller should be created using newTransformer() in the PreparedStylesheet
0094:             * class.
0095:             *
0096:             * @param config The Configuration used by this Controller
0097:             */
0098:
0099:            public Controller(Configuration config) {
0100:                this .config = config;
0101:                // create a dummy executable
0102:                executable = new Executable();
0103:                executable.setConfiguration(config);
0104:                executable.setHostLanguage(config.getHostLanguage());
0105:                sourceDocumentPool = new DocumentPool();
0106:                reset();
0107:            }
0108:
0109:            /**
0110:             * Create a Controller and initialise variables. Constructor is protected,
0111:             * the Controller should be created using newTransformer() in the PreparedStylesheet
0112:             * class.
0113:             *
0114:             * @param config The Configuration used by this Controller
0115:             * @param executable The executable used by this Controller
0116:             */
0117:
0118:            public Controller(Configuration config, Executable executable) {
0119:                this .config = config;
0120:                this .executable = executable;
0121:                sourceDocumentPool = new DocumentPool();
0122:                reset();
0123:            }
0124:
0125:            /**
0126:             * <p>Reset this <code>Transformer</code> to its original configuration.</p>
0127:             * <p/>
0128:             * <p><code>Transformer</code> is reset to the same state as when it was created with
0129:             * {@link javax.xml.transform.TransformerFactory#newTransformer()},
0130:             * {@link javax.xml.transform.TransformerFactory#newTransformer(javax.xml.transform.Source source)} or
0131:             * {@link javax.xml.transform.Templates#newTransformer()}.
0132:             * <code>reset()</code> is designed to allow the reuse of existing <code>Transformer</code>s
0133:             * thus saving resources associated with the creation of new <code>Transformer</code>s.</p>
0134:             * <p>
0135:             * <i>The above is from the JAXP specification. With Saxon, it's unlikely that reusing a Transformer will
0136:             * give any performance benefits over creating a new one. The one case where it might be beneficial is
0137:             * to reuse the document pool (the set of documents that have been loaded using the doc() or document()
0138:             * functions). Therefore, this method does not clear the document pool. If you want to clear the document
0139:             * pool, call the method {@link #clearDocumentPool} as well.</i>
0140:             * <p/>
0141:             * <p>The reset <code>Transformer</code> is not guaranteed to have the same {@link javax.xml.transform.URIResolver}
0142:             * or {@link javax.xml.transform.ErrorListener} <code>Object</code>s, e.g. {@link Object#equals(Object obj)}.
0143:             * It is guaranteed to have a functionally equal <code>URIResolver</code>
0144:             * and <code>ErrorListener</code>.</p>
0145:             *
0146:             * @since 1.5
0147:             */
0148:
0149:            public void reset() {
0150:                bindery = new Bindery();
0151:                namePool = NamePool.getDefaultNamePool();
0152:                standardURIResolver = config.getSystemURIResolver();
0153:                userURIResolver = config.getURIResolver();
0154:
0155:                outputURIResolver = config.getOutputURIResolver();
0156:                errorListener = config.getErrorListener();
0157:                if (errorListener instanceof  StandardErrorListener) {
0158:                    // if using a standard error listener, make a fresh one
0159:                    // for each transformation, because it is stateful - and also because the
0160:                    // host language is now known (a Configuration can serve multiple host languages)
0161:                    PrintStream ps = ((StandardErrorListener) errorListener)
0162:                            .getErrorOutput();
0163:                    errorListener = ((StandardErrorListener) errorListener)
0164:                            .makeAnother(executable.getHostLanguage());
0165:                    ((StandardErrorListener) errorListener).setErrorOutput(ps);
0166:                    ((StandardErrorListener) errorListener)
0167:                            .setRecoveryPolicy(config.getRecoveryPolicy());
0168:                }
0169:
0170:                userDataTable = new HashMap(20);
0171:
0172:                traceListener = null;
0173:                tracingPaused = false;
0174:                TraceListener tracer = config.getTraceListener();
0175:                if (tracer != null) {
0176:                    addTraceListener(tracer);
0177:                }
0178:
0179:                setTreeModel(config.getTreeModel());
0180:                principalSourceDocument = null;
0181:                messageEmitter = null;
0182:                outputProperties = null;
0183:                parameters = null;
0184:
0185:                principalResult = null;
0186:                principalResultURI = null;
0187:                initialTemplate = null;
0188:                allOutputDestinations = null;
0189:                currentDateTime = null;
0190:                dateTimePreset = false;
0191:                initialMode = -1;
0192:                lastRememberedNode = null;
0193:                lastRememberedNumber = -1;
0194:                classLoader = null;
0195:
0196:            }
0197:
0198:            /**
0199:             * Get the Configuration associated with this Controller. The Configuration holds
0200:             * settings that potentially apply globally to many different queries and transformations.
0201:             * @return the Configuration object
0202:             * @since 8.4
0203:             */
0204:            public Configuration getConfiguration() {
0205:                return config;
0206:            }
0207:
0208:            /**
0209:             * Set the initial mode for the transformation.
0210:             * <p>
0211:             * XSLT 2.0 allows a transformation to be started in a mode other than the default mode.
0212:             * The transformation then starts by looking for the template rule in this mode that best
0213:             * matches the initial context node.
0214:             * <p>
0215:             * This method may eventually be superseded by a standard JAXP method.
0216:             *
0217:             * @param expandedModeName the name of the initial mode.  The mode is
0218:             *     supplied as an expanded QName, that is "localname" if there is no
0219:             *     namespace, or "{uri}localname" otherwise
0220:             * @since 8.4
0221:             */
0222:
0223:            public void setInitialMode(String expandedModeName) {
0224:                if (expandedModeName == null)
0225:                    return;
0226:                if (expandedModeName.equals(""))
0227:                    return;
0228:                initialMode = namePool.allocateClarkName(expandedModeName);
0229:            }
0230:
0231:            ////////////////////////////////////////////////////////////////////////////////
0232:            // Methods for managing output destinations and formatting
0233:            ////////////////////////////////////////////////////////////////////////////////
0234:
0235:            /**
0236:             * Set the output properties for the transformation.  These
0237:             * properties will override properties set in the templates
0238:             * with xsl:output.
0239:             * <p>
0240:             * As well as the properties defined in the JAXP OutputKeys class,
0241:             * Saxon defines an additional set of properties in {@link SaxonOutputKeys}.
0242:             * These fall into two categories: Constants representing serialization
0243:             * properties defined in XSLT 2.0 (which are not yet supported by JAXP),
0244:             * and constants supporting Saxon extensions to the set of serialization
0245:             * properties.
0246:             *
0247:             * @param properties the output properties to be used for the
0248:             *     transformation. If the value is null, the properties are reset to
0249:             *     be the properties of the Templates object (that is, for XSLT 2.0,
0250:             *     the properties set in the unnamed xsl:output object).
0251:             * @see SaxonOutputKeys
0252:             * @since 8.4
0253:             */
0254:
0255:            public void setOutputProperties(Properties properties) {
0256:                if (properties == null) {
0257:                    outputProperties = null;
0258:                } else {
0259:                    Enumeration keys = properties.propertyNames();
0260:                    while (keys.hasMoreElements()) {
0261:                        String key = (String) keys.nextElement();
0262:                        setOutputProperty(key, properties.getProperty(key));
0263:                    }
0264:                }
0265:            }
0266:
0267:            /**
0268:             * Get the output properties for the transformation.
0269:             * <p>
0270:             * As well as the properties defined in the JAXP OutputKeys class,
0271:             * Saxon defines an additional set of properties in {@link SaxonOutputKeys}.
0272:             * These fall into two categories: Constants representing serialization
0273:             * properties defined in XSLT 2.0 (which are not yet supported by JAXP),
0274:             * and constants supporting Saxon extensions to the set of serialization
0275:             * properties.
0276:             *
0277:             * @return the output properties being used for the transformation,
0278:             *     including properties defined in the stylesheet for the unnamed
0279:             *     output format
0280:             * @see SaxonOutputKeys
0281:             * @since 8.4
0282:             */
0283:
0284:            public Properties getOutputProperties() {
0285:                if (outputProperties == null) {
0286:                    if (executable == null) {
0287:                        return new Properties();
0288:                    } else {
0289:                        outputProperties = executable
0290:                                .getDefaultOutputProperties();
0291:                    }
0292:                }
0293:
0294:                // Make a copy, so that modifications to the returned properties have no effect
0295:
0296:                Properties newProps = new Properties();
0297:                Enumeration keys = outputProperties.propertyNames();
0298:                while (keys.hasMoreElements()) {
0299:                    String key = (String) keys.nextElement();
0300:                    newProps.put(key, outputProperties.getProperty(key));
0301:                }
0302:                return newProps;
0303:            }
0304:
0305:            /**
0306:             * Set an output property for the transformation.
0307:             * <p>
0308:             * As well as the properties defined in the JAXP OutputKeys class,
0309:             * Saxon defines an additional set of properties in {@link SaxonOutputKeys}.
0310:             * These fall into two categories: Constants representing serialization
0311:             * properties defined in XSLT 2.0 (which are not yet supported by JAXP),
0312:             * and constants supporting Saxon extensions to the set of serialization
0313:             * properties.
0314:             *
0315:             * @param name the name of the property
0316:             * @param value the value of the property
0317:             * @see SaxonOutputKeys
0318:             * @since 8.4
0319:             */
0320:
0321:            public void setOutputProperty(String name, String value) {
0322:                if (outputProperties == null) {
0323:                    outputProperties = getOutputProperties();
0324:                }
0325:                try {
0326:                    SaxonOutputKeys.checkOutputProperty(name, value,
0327:                            getConfiguration().getNameChecker());
0328:                } catch (DynamicError err) {
0329:                    throw new IllegalArgumentException(err.getMessage());
0330:                }
0331:                outputProperties.put(name, value);
0332:            }
0333:
0334:            /**
0335:             * Get the value of an output property.
0336:             * <p>
0337:             * As well as the properties defined in the JAXP OutputKeys class,
0338:             * Saxon defines an additional set of properties in {@link SaxonOutputKeys}.
0339:             * These fall into two categories: Constants representing serialization
0340:             * properties defined in XSLT 2.0 (which are not yet supported by JAXP),
0341:             * and constants supporting Saxon extensions to the set of serialization
0342:             * properties.
0343:             *
0344:             * @param name the name of the requested property
0345:             * @return the value of the requested property
0346:             * @see SaxonOutputKeys
0347:             * @since 8.4
0348:             */
0349:
0350:            public String getOutputProperty(String name) {
0351:                try {
0352:                    SaxonOutputKeys.checkOutputProperty(name, null,
0353:                            getConfiguration().getNameChecker());
0354:                } catch (DynamicError err) {
0355:                    throw new IllegalArgumentException(err.getMessage());
0356:                }
0357:                if (outputProperties == null) {
0358:                    if (executable == null) {
0359:                        return null;
0360:                    } else {
0361:                        outputProperties = executable
0362:                                .getDefaultOutputProperties();
0363:                    }
0364:                }
0365:                return outputProperties.getProperty(name);
0366:            }
0367:
0368:            /**
0369:             * Set the base output URI.
0370:             * This defaults to the system ID of the principal Result object, but
0371:             * a different value can be set for use where there is no principal result.
0372:             * The command line interface sets this to the current working directory.
0373:             * <p>
0374:             * The concept of the base output URI is new in XSLT 2.0: it defines the
0375:             * base URI for resolving relative URIs in the <code>href</code> attribute
0376:             * of the <code>xsl:result-document</code> instruction. This method may be
0377:             * superseded by a standard JAXP method when JAXP is updated to support XSLT 2.0.
0378:             *
0379:             * @param uri the base output URI
0380:             * @since 8.4
0381:             */
0382:
0383:            public void setBaseOutputURI(String uri) {
0384:                principalResultURI = uri;
0385:            }
0386:
0387:            /**
0388:             * Get the base output URI.
0389:             * This defaults to the system ID of the principal Result object, but
0390:             * a different value can be set for use where there is no principal result.
0391:             * The command line interface sets this to the current working directory.
0392:             * <p>
0393:             * The concept of the base output URI is new in XSLT 2.0: it defines the
0394:             * base URI for resolving relative URIs in the <code>href</code> attribute
0395:             * of the <code>xsl:result-document</code> instruction. This method may be
0396:             * superseded by a standard JAXP method when JAXP is updated to support XSLT 2.0.
0397:             *
0398:             * @return the base output URI
0399:             * @since 8.4
0400:             */
0401:
0402:            public String getBaseOutputURI() {
0403:                return principalResultURI;
0404:            }
0405:
0406:            /**
0407:             * Get the principal result destination.
0408:             * <p>
0409:             * This method is intended for internal use only.
0410:             */
0411:
0412:            public Result getPrincipalResult() {
0413:                return principalResult;
0414:            }
0415:
0416:            /**
0417:             * Check that an output destination has not been used before.
0418:             * <p>
0419:             * This method is intended for internal use only.
0420:             */
0421:
0422:            public boolean checkUniqueOutputDestination(String uri) {
0423:                if (allOutputDestinations == null) {
0424:                    allOutputDestinations = new HashSet(20);
0425:                }
0426:                if (allOutputDestinations.contains(uri)) {
0427:                    return false;
0428:                }
0429:                allOutputDestinations.add(uri);
0430:                return true;
0431:            }
0432:
0433:            ///////////////////////////////////////////////////////////////////////////////
0434:
0435:            /**
0436:             * Set the initial named template to be used as the entry point.
0437:             * <p>
0438:             * XSLT 2.0 allows a transformation to start by executing a named template, rather than
0439:             * by matching an initial context node in a source document. This method may eventually
0440:             * be superseded by a standard JAXP method once JAXP supports XSLT 2.0.
0441:             * <p>
0442:             * Although the Saxon command line interface does not allow both a source document and
0443:             * an initial template to be specified, this API has no such restriction.
0444:             * <p>
0445:             * Note that any parameters supplied using {@link #setParameter} are used as the values
0446:             * of global stylesheet parameters. There is no way to supply values for local parameters
0447:             * of the initial template.
0448:             *
0449:             * @param expandedName The expanded name of the template in {uri}local format
0450:             * @throws XPathException if there is no named template with this name
0451:             * @since 8.4
0452:             */
0453:
0454:            public void setInitialTemplate(String expandedName)
0455:                    throws XPathException {
0456:                int fingerprint = namePool.allocateClarkName(expandedName);
0457:                Template t = getExecutable().getNamedTemplate(fingerprint);
0458:                if (t == null) {
0459:                    DynamicError err = new DynamicError(
0460:                            "There is no named template with expanded name "
0461:                                    + expandedName);
0462:                    err.setErrorCode("XTDE0040");
0463:                    throw err;
0464:                } else {
0465:                    initialTemplate = t;
0466:                }
0467:            }
0468:
0469:            ///////////////////////////////////////////////////////////////////////////////
0470:
0471:            /**
0472:             * Make a PipelineConfiguration based on the properties of this Controller.
0473:             * <p>
0474:             * This interface is intended primarily for internal use, although it may be necessary
0475:             * for applications to call it directly for use in conjunction with the experimental pull
0476:             * API.
0477:             */
0478:
0479:            public PipelineConfiguration makePipelineConfiguration() {
0480:                PipelineConfiguration pipe = new PipelineConfiguration();
0481:                pipe.setConfiguration(getConfiguration());
0482:                pipe.setErrorListener(getErrorListener());
0483:                pipe
0484:                        .setURIResolver(userURIResolver == null ? standardURIResolver
0485:                                : userURIResolver);
0486:                pipe.setController(this );
0487:                if (getExecutable() != null) {
0488:                    // can be null for an IdentityTransformer
0489:                    pipe.setLocationProvider(getExecutable().getLocationMap());
0490:                }
0491:                return pipe;
0492:            }
0493:
0494:            /**
0495:             * Make an Emitter to be used for xsl:message output.
0496:             * <p>
0497:             * This method is intended for internal use only.
0498:             *
0499:             * @exception XPathException if any dynamic error occurs; in
0500:             *     particular, if the registered MessageEmitter class is not an
0501:             *     Emitter
0502:             * @return The newly constructed message Emitter
0503:             */
0504:
0505:            public Emitter makeMessageEmitter() throws XPathException {
0506:                String emitterClass = config.getMessageEmitterClass();
0507:
0508:                Object emitter = config.getInstance(emitterClass,
0509:                        getClassLoader());
0510:                if (!(emitter instanceof  Emitter)) {
0511:                    throw new DynamicError(emitterClass + " is not an Emitter");
0512:                }
0513:                setMessageEmitter((Emitter) emitter);
0514:                return messageEmitter;
0515:            }
0516:
0517:            /**
0518:             * Set the Emitter to be used for xsl:message output.
0519:             * <p>
0520:             * Recent versions of the JAXP interface specify that by default the
0521:             * output of xsl:message is sent to the registered ErrorListener. Saxon
0522:             * does not yet implement this convention. Instead, the output is sent
0523:             * to a default message emitter, which is a slightly customised implementation
0524:             * of the standard Saxon Emitter interface.
0525:             * <p>
0526:             * This interface can be used to change the way in which Saxon outputs
0527:             * xsl:message output.
0528:             * <p>
0529:             * It is not necessary to use this interface in order to change the destination
0530:             * to which messages are written: that can be achieved by obtaining the standard
0531:             * message emitter and calling its {@link Emitter#setWriter} method.
0532:             * <p>
0533:             * This method is intended for use by advanced applications. The Emitter interface
0534:             * itself is not part of the stable Saxon public API.
0535:             *
0536:             * @param emitter The emitter to receive xsl:message output.
0537:             */
0538:
0539:            public void setMessageEmitter(Emitter emitter) {
0540:                messageEmitter = emitter;
0541:                messageEmitter
0542:                        .setPipelineConfiguration(makePipelineConfiguration());
0543:            }
0544:
0545:            /**
0546:             * Get the Emitter used for xsl:message output. This returns the emitter
0547:             * previously supplied to the {@link #setMessageEmitter} method, or the
0548:             * default message emitter otherwise.
0549:             *
0550:             * @return the Emitter being used for xsl:message output
0551:             */
0552:
0553:            public Emitter getMessageEmitter() {
0554:                return messageEmitter;
0555:            }
0556:
0557:            /**
0558:             * Make a CharacterMapExpander to handle the character map definitions in the serialization
0559:             * properties.
0560:             * <p>
0561:             * This method is intended for internal use only.
0562:             *
0563:             * @param useMaps the expanded use-character-maps property: a space-separated list of names
0564:             * of character maps to be used, each one expressed as an expanded-QName in Clark notation
0565:             * (that is, {uri}local-name).
0566:             * @return a CharacterMapExpander if one is required, or null if not (for example, if the
0567:             * useMaps argument is an empty string).
0568:             * @throws XPathException if a name in the useMaps property cannot be resolved to a declared
0569:             * character map.
0570:             */
0571:
0572:            public CharacterMapExpander makeCharacterMapExpander(String useMaps)
0573:                    throws XPathException {
0574:                CharacterMapExpander characterMapExpander = null;
0575:                IntHashMap characterMapIndex = getExecutable()
0576:                        .getCharacterMapIndex();
0577:                if (useMaps != null && characterMapIndex != null) {
0578:                    List characterMaps = new ArrayList(5);
0579:                    StringTokenizer st = new StringTokenizer(useMaps);
0580:                    while (st.hasMoreTokens()) {
0581:                        String expandedName = st.nextToken();
0582:                        int f = namePool
0583:                                .getFingerprintForExpandedName(expandedName);
0584:                        IntHashMap map = (IntHashMap) characterMapIndex.get(f);
0585:                        if (map == null) {
0586:                            throw new DynamicError("Character map '"
0587:                                    + expandedName + "' has not been defined");
0588:                        }
0589:                        characterMaps.add(map);
0590:                    }
0591:                    if (characterMaps.size() > 0) {
0592:                        characterMapExpander = new CharacterMapExpander();
0593:                        characterMapExpander.setCharacterMaps(characterMaps);
0594:                    }
0595:                }
0596:                return characterMapExpander;
0597:            }
0598:
0599:            /**
0600:             * Get the policy for handling recoverable errors.
0601:             * <p>
0602:             * This method is intended for internal use
0603:             *
0604:             * @return the current policy. This is obtained from the error listener; if the error listener is
0605:             * not a StandardErrorListener, the value RECOVER_WITH_WARNINGS is returned.
0606:             */
0607:
0608:            public int getRecoveryPolicy() {
0609:                if (errorListener instanceof  StandardErrorListener) {
0610:                    return ((StandardErrorListener) errorListener)
0611:                            .getRecoveryPolicy();
0612:                } else {
0613:                    return Configuration.RECOVER_WITH_WARNINGS;
0614:                }
0615:            }
0616:
0617:            /**
0618:             * Set the error listener.
0619:             *
0620:             * @param listener the ErrorListener to be used
0621:             */
0622:
0623:            public void setErrorListener(ErrorListener listener) {
0624:                errorListener = listener;
0625:            }
0626:
0627:            /**
0628:             * Get the error listener.
0629:             *
0630:             * @return the ErrorListener in use
0631:             */
0632:
0633:            public ErrorListener getErrorListener() {
0634:                return errorListener;
0635:            }
0636:
0637:            /**
0638:             * Report a recoverable error. This is an XSLT concept: by default, such an error results in a warning
0639:             * message, and processing continues. In XQuery, however, there are no recoverable errors so a fatal
0640:             * error is reported.
0641:             * <p>
0642:             * This method is intended for internal use only.
0643:             *
0644:             * @param err An exception holding information about the error
0645:             * @exception DynamicError if the error listener decides not to
0646:             *     recover from the error
0647:             */
0648:
0649:            public void recoverableError(XPathException err)
0650:                    throws DynamicError {
0651:                try {
0652:                    if (executable.getHostLanguage() == Configuration.XQUERY) {
0653:                        reportFatalError(err);
0654:                        throw err;
0655:                    } else {
0656:                        errorListener.error(err);
0657:                    }
0658:                } catch (TransformerException e) {
0659:                    DynamicError de = DynamicError.makeDynamicError(e);
0660:                    de.setHasBeenReported();
0661:                    throw de;
0662:                }
0663:            }
0664:
0665:            /**
0666:             * Report a fatal error
0667:             */
0668:
0669:            public void reportFatalError(XPathException err) {
0670:                if (!err.hasBeenReported()) {
0671:                    try {
0672:                        getErrorListener().fatalError(err);
0673:                    } catch (TransformerException e) {
0674:                        //
0675:                    }
0676:                    err.setHasBeenReported();
0677:                }
0678:            }
0679:
0680:            /////////////////////////////////////////////////////////////////////////////////////////
0681:            // Methods for managing the various runtime control objects
0682:            /////////////////////////////////////////////////////////////////////////////////////////
0683:
0684:            /**
0685:             * Get the Executable object.
0686:             * <p>
0687:             * This method is intended for internal use only.
0688:             *
0689:             * @return the Executable (which represents the compiled stylesheet)
0690:             */
0691:
0692:            public Executable getExecutable() {
0693:                return executable;
0694:            }
0695:
0696:            /**
0697:             * Get the document pool. This is used only for source documents, not for stylesheet modules.
0698:             * <p>
0699:             * This method is intended for internal use only.
0700:             *
0701:             * @return the source document pool
0702:             */
0703:
0704:            public DocumentPool getDocumentPool() {
0705:                return sourceDocumentPool;
0706:            }
0707:
0708:            /**
0709:             * Clear the document pool.
0710:             * This is sometimes useful when re-using the same Transformer
0711:             * for a sequence of transformations, but it isn't done automatically, because when
0712:             * the transformations use common look-up documents, the caching is beneficial.
0713:             */
0714:
0715:            public void clearDocumentPool() {
0716:                sourceDocumentPool = new DocumentPool();
0717:            }
0718:
0719:            /**
0720:             * Set the principal source document (used for evaluating global variables).
0721:             * When a transformation is invoked using the {@link #transform} method, the
0722:             * principal source document is set automatically. This method is useful in XQuery,
0723:             * to define an initial context node for evaluating global variables, and also
0724:             * in XSLT 2.0, when the transformation is started by invoking a named template.
0725:             *
0726:             * @param doc The principal source document
0727:             * @since 8.4
0728:             */
0729:
0730:            public void setPrincipalSourceDocument(DocumentInfo doc) {
0731:                principalSourceDocument = doc;
0732:            }
0733:
0734:            /**
0735:             * Get the current bindery.
0736:             * <p>
0737:             * This method is intended for internal use only.
0738:             *
0739:             * @return the Bindery (in which values of all variables are held)
0740:             */
0741:
0742:            public Bindery getBindery() {
0743:                return bindery;
0744:            }
0745:
0746:            /**
0747:             * Get the principal source document. This returns the document
0748:             * previously supplied to the {@link #setPrincipalSourceDocument} method, or the
0749:             * principal source document set implicitly using methods such as {@link #transform}.
0750:             * @return the principal source document
0751:             * @since 8.4
0752:             */
0753:
0754:            public DocumentInfo getPrincipalSourceDocument() {
0755:                return principalSourceDocument;
0756:            }
0757:
0758:            /**
0759:             * Set an object that will be used to resolve URIs used in
0760:             * document(), etc.
0761:             *
0762:             * @param resolver An object that implements the URIResolver interface, or
0763:             *      null.
0764:             */
0765:
0766:            public void setURIResolver(URIResolver resolver) {
0767:                userURIResolver = resolver;
0768:            }
0769:
0770:            /**
0771:             * Get the URI resolver.
0772:             *
0773:             * <p><i>This method changed in Saxon 8.5, to conform to the JAXP specification. If there
0774:             * is no user-specified URIResolver, it now returns null; previously it returned the system
0775:             * default URIResolver.</i></p>
0776:             *
0777:             * @return the user-supplied URI resolver if there is one, or null otherwise.
0778:             */
0779:
0780:            public URIResolver getURIResolver() {
0781:                return userURIResolver;
0782:            }
0783:
0784:            /**
0785:             * Get the fallback URI resolver. This is the URIResolver that Saxon uses when
0786:             * the user-supplied URI resolver returns null.
0787:             * <p>
0788:             * This method is intended for internal use only.
0789:             *
0790:             * @return the the system-defined URIResolver
0791:             */
0792:
0793:            public URIResolver getStandardURIResolver() {
0794:                return standardURIResolver;
0795:            }
0796:
0797:            /**
0798:             * Set the URI resolver for secondary output documents.
0799:             * <p>
0800:             * XSLT 2.0 introduces the <code>xsl:result-document</code instruction,
0801:             * allowing a transformation to have multiple result documents. JAXP does
0802:             * not yet support this capability. This method allows an OutputURIResolver
0803:             * to be specified that takes responsibility for deciding the destination
0804:             * (and, if it wishes, the serialization properties) of secondary output files.
0805:             * <p>
0806:             * This method may eventually be superseded by a standard JAXP method.
0807:             *
0808:             * @param resolver An object that implements the OutputURIResolver
0809:             *     interface, or null.
0810:             * @since 8.4
0811:             */
0812:
0813:            public void setOutputURIResolver(OutputURIResolver resolver) {
0814:                if (resolver == null) {
0815:                    outputURIResolver = StandardOutputResolver.getInstance();
0816:                } else {
0817:                    outputURIResolver = resolver;
0818:                }
0819:            }
0820:
0821:            /**
0822:             * Get the output URI resolver.
0823:             *
0824:             * @return the user-supplied URI resolver if there is one, or the
0825:             *     system-defined one otherwise.
0826:             * @see #setOutputURIResolver
0827:             * @since 8.4
0828:             */
0829:
0830:            public OutputURIResolver getOutputURIResolver() {
0831:                return outputURIResolver;
0832:            }
0833:
0834:            /**
0835:             * Get the KeyManager.
0836:             * <p>
0837:             * This method is intended for internal use only.
0838:             *
0839:             * @return the KeyManager, which holds details of all key declarations
0840:             */
0841:
0842:            public KeyManager getKeyManager() {
0843:                return executable.getKeyManager();
0844:            }
0845:
0846:            /**
0847:             * Get the name pool in use. The name pool is responsible for mapping QNames used in source
0848:             * documents and compiled stylesheets and queries into numeric codes. All source documents
0849:             * used by a given transformation or query must use the same name pool as the compiled stylesheet
0850:             * or query.
0851:             *
0852:             * @return the name pool in use
0853:             * @since 8.4
0854:             */
0855:
0856:            public NamePool getNamePool() {
0857:                return namePool;
0858:            }
0859:
0860:            /**
0861:             * Set the tree data model to use. This affects all source documents subsequently constructed using a
0862:             * Builder obtained from this Controller. This includes a document built from a StreamSource or
0863:             * SAXSource supplied as a parameter to the {@link #transform} method.
0864:             *
0865:             * @param model the required tree model: {@link Builder#STANDARD_TREE} or
0866:             *     {@link Builder#TINY_TREE}
0867:             * @see net.sf.saxon.event.Builder
0868:             * @since 8.4
0869:             */
0870:
0871:            public void setTreeModel(int model) {
0872:                treeModel = model;
0873:            }
0874:
0875:            /**
0876:             * Make a builder for the selected tree model.
0877:             *
0878:             * @return an instance of the Builder for the chosen tree model
0879:             * @since 8.4
0880:             */
0881:
0882:            public Builder makeBuilder() {
0883:                Builder b;
0884:                if (treeModel == Builder.TINY_TREE) {
0885:                    b = new TinyBuilder();
0886:                } else {
0887:                    b = new TreeBuilder();
0888:                }
0889:                b.setTiming(config.isTiming());
0890:                b.setLineNumbering(config.isLineNumbering());
0891:                b.setPipelineConfiguration(makePipelineConfiguration());
0892:                return b;
0893:            }
0894:
0895:            /**
0896:             * Make a Stripper configured to implement the whitespace stripping rules.
0897:             * In the case of XSLT the whitespace stripping rules are normally defined
0898:             * by <code>xsl:strip-space</code> and <code>xsl:preserve-space</code elements
0899:             * in the stylesheet. Alternatively, stripping of all whitespace text nodes
0900:             * may be defined at the level of the Configuration, using the method
0901:             * {@link Configuration#setStripsAllWhiteSpace(boolean)}.
0902:             *
0903:             * @param b the Receiver to which the events filtered by this stripper are
0904:             *     to be sent (often a Builder). May be null if the stripper is not being used for filtering
0905:             *     into a Builder or other Receiver.
0906:             * @return the required Stripper. A Stripper may be used in two ways. It acts as
0907:             * a filter applied to an event stream, that can be used to remove the events
0908:             * representing whitespace text nodes before they reach a Builder. Alternatively,
0909:             * it can be used to define a view of an existing tree in which the whitespace
0910:             * text nodes are dynamically skipped while navigating the XPath axes.
0911:             * @since 8.4 - Generalized in 8.5 to accept any Receiver as an argument
0912:             */
0913:
0914:            public Stripper makeStripper(Receiver b) {
0915:                if (config.isStripsAllWhiteSpace()) {
0916:                    if (b == null) {
0917:                        return AllElementStripper.getInstance();
0918:                    } else {
0919:                        Stripper s = new AllElementStripper();
0920:                        s.setUnderlyingReceiver(b);
0921:                        return s;
0922:                    }
0923:                }
0924:                Stripper stripper;
0925:                if (executable == null) {
0926:                    stripper = new Stripper(new Mode(Mode.STRIPPER_MODE));
0927:                } else {
0928:                    stripper = executable.newStripper();
0929:                }
0930:                stripper.setPipelineConfiguration(makePipelineConfiguration());
0931:                //stripper.setController(this);
0932:                if (b != null) {
0933:                    stripper.setUnderlyingReceiver(b);
0934:                }
0935:
0936:                return stripper;
0937:            }
0938:
0939:            /**
0940:             * Add a document to the document pool.
0941:             * <p>
0942:             * This method is intended for internal use only.
0943:             *
0944:             * @param doc the root node of the document to be added
0945:             * @param systemId thesystem ID of this document
0946:             */
0947:            public void registerDocument(DocumentInfo doc, String systemId) {
0948:                sourceDocumentPool.add(doc, systemId);
0949:            }
0950:
0951:            ////////////////////////////////////////////////////////////////////////////////
0952:            // Methods for registering and retrieving handlers for template rules
0953:            ////////////////////////////////////////////////////////////////////////////////
0954:
0955:            /**
0956:             * Set the RuleManager, used to manage template rules for each mode.
0957:             * <p>
0958:             * This method is intended for internal use only.
0959:             *
0960:             * @param r the Rule Manager
0961:             */
0962:            public void setRuleManager(RuleManager r) {
0963:                ruleManager = r;
0964:            }
0965:
0966:            /**
0967:             * Get the Rule Manager.
0968:             * <p>
0969:             * This method is intended for internal use only.
0970:             *
0971:             * @return the Rule Manager, used to hold details of template rules for
0972:             *     all modes
0973:             */
0974:            public RuleManager getRuleManager() {
0975:                return ruleManager;
0976:            }
0977:
0978:            /////////////////////////////////////////////////////////////////////////
0979:            // Methods for tracing
0980:            /////////////////////////////////////////////////////////////////////////
0981:
0982:            /**
0983:             * Get the TraceListener. By default, there is no TraceListener, and this
0984:             * method returns null. A TraceListener may be added using the method
0985:             * {@link #addTraceListener}. If more than one TraceListener has been added,
0986:             * this method will return a composite TraceListener. Because this form
0987:             * this takes is implementation-dependent, this method is not part of the
0988:             * stable Saxon public API.
0989:             *
0990:             * @return the TraceListener used for XSLT or XQuery instruction tracing
0991:             */
0992:            public TraceListener getTraceListener() { // e.g.
0993:                return traceListener;
0994:            }
0995:
0996:            /**
0997:             * Test whether instruction execution is being traced. This will be true
0998:             * if (a) at least one TraceListener has been registered using the
0999:             * {@link #addTraceListener} method, and (b) tracing has not been temporarily
1000:             * paused using the {@link #pauseTracing} method.
1001:             *
1002:             * @return true if tracing is active, false otherwise
1003:             * @since 8.4
1004:             */
1005:
1006:            public final boolean isTracing() { // e.g.
1007:                return traceListener != null && !tracingPaused;
1008:            }
1009:
1010:            /**
1011:             * Pause or resume tracing. While tracing is paused, trace events are not sent to any
1012:             * of the registered TraceListeners.
1013:             *
1014:             * @param pause true if tracing is to pause; false if it is to resume
1015:             * @since 8.4
1016:             */
1017:            public final void pauseTracing(boolean pause) {
1018:                tracingPaused = pause;
1019:            }
1020:
1021:            /**
1022:             * Adds the specified trace listener to receive trace events from
1023:             * this instance. Note that although TraceListeners can be added
1024:             * or removed dynamically, this has no effect unless the stylesheet
1025:             * or query has been compiled with tracing enabled. This is achieved
1026:             * by calling {@link Configuration#setTraceListener} or by setting
1027:             * the attribute {@link FeatureKeys#TRACE_LISTENER} on the
1028:             * TransformerFactory. Conversely, if this property has been set in the
1029:             * Configuration or TransformerFactory, the TraceListener will automatically
1030:             * be added to every Controller that uses that Configuration.
1031:             *
1032:             * @param trace the trace listener.
1033:             * @since 8.4
1034:             */
1035:
1036:            public void addTraceListener(TraceListener trace) { // e.g.
1037:                traceListener = TraceEventMulticaster.add(traceListener, trace);
1038:            }
1039:
1040:            /**
1041:             * Removes the specified trace listener so that the listener will no longer
1042:             * receive trace events.
1043:             *
1044:             * @param trace the trace listener.
1045:             * @since 8.4
1046:             */
1047:
1048:            public void removeTraceListener(TraceListener trace) { // e.g.
1049:                traceListener = TraceEventMulticaster.remove(traceListener,
1050:                        trace);
1051:            }
1052:
1053:            /**
1054:             * Associate this Controller with a compiled stylesheet.
1055:             * <p>
1056:             * This method is intended for internal use only.
1057:             *
1058:             * @param sheet the compiled stylesheet
1059:             */
1060:
1061:            public void setPreparedStylesheet(PreparedStylesheet sheet) {
1062:                preparedStylesheet = sheet;
1063:                executable = sheet.getExecutable();
1064:                //setOutputProperties(sheet.getOutputProperties());
1065:                // above line deleted for bug 490964 - may have side-effects
1066:            }
1067:
1068:            /**
1069:             * Associate this Controller with an Executable. This method is used by the XQuery
1070:             * processor. The Executable object is overkill in this case - the only thing it
1071:             * currently holds are copies of the collation table.
1072:             * <p>
1073:             * This method is intended for internal use only
1074:             * @param exec the Executable
1075:             */
1076:
1077:            public void setExecutable(Executable exec) {
1078:                executable = exec;
1079:            }
1080:
1081:            /**
1082:             * Initialize the controller ready for a new transformation. This method should not normally be called by
1083:             * users (it is done automatically when transform() is invoked). However, it is available as a low-level API
1084:             * especially for use with XQuery.
1085:             */
1086:
1087:            public void initializeController() throws XPathException {
1088:                setRuleManager(executable.getRuleManager());
1089:                //setDecimalFormatManager(executable.getDecimalFormatManager());
1090:
1091:                if (traceListener != null) {
1092:                    traceListener.open();
1093:                }
1094:
1095:                // get a new bindery, to clear out any variables from previous runs
1096:
1097:                bindery = new Bindery();
1098:                executable.initialiseBindery(bindery);
1099:
1100:                // create an initial stack frame, used for evaluating standalone expressions,
1101:                // e.g. expressions within the filter of a match pattern. This stack frame
1102:                // never gets closed, but no one will notice.
1103:
1104:                //bindery.openStackFrame();
1105:
1106:                // if parameters were supplied, set them up
1107:
1108:                defineGlobalParameters(bindery);
1109:            }
1110:
1111:            /**
1112:             * Define the global parameters of the transformation or query.
1113:             * <p>
1114:             * This method is intended for internal use only
1115:             * @param bindery The Bindery, which holds values of global variables and parameters
1116:             */
1117:
1118:            public void defineGlobalParameters(Bindery bindery)
1119:                    throws XPathException {
1120:                executable.checkAllRequiredParamsArePresent(parameters);
1121:                bindery.defineGlobalParameters(parameters);
1122:            }
1123:
1124:            /////////////////////////////////////////////////////////////////////////
1125:            // Allow user data to be associated with nodes on a tree
1126:            /////////////////////////////////////////////////////////////////////////
1127:
1128:            /**
1129:             * Get user data associated with a key. To retrieve user data, two objects are required:
1130:             * an arbitrary object that may be regarded as the container of the data (originally, and
1131:             * typically still, a node in a tree), and a name. The name serves to distingush data objects
1132:             * associated with the same node by different client applications.
1133:             * <p>
1134:             * This method is intended primarily for internal use, though it may also be
1135:             * used by advanced applications.
1136:             *
1137:             * @param key an object acting as a key for this user data value. This must be equal
1138:             * (in the sense of the equals() method) to the key supplied when the data value was
1139:             * registered using {@link #setUserData}.
1140:             * @param name the name of the required property
1141:             * @return the value of the required property
1142:             */
1143:
1144:            public Object getUserData(Object key, String name) {
1145:                String keyValue = key.hashCode() + " " + name;
1146:                // System.err.println("getUserData " + name + " on object returning " + userDataTable.get(key));
1147:                return userDataTable.get(keyValue);
1148:            }
1149:
1150:            /**
1151:             * Set user data associated with a key. To store user data, two objects are required:
1152:             * an arbitrary object that may be regarded as the container of the data (originally, and
1153:             * typically still, a node in a tree), and a name. The name serves to distingush data objects
1154:             * associated with the same node by different client applications.
1155:             * <p>
1156:             * This method is intended primarily for internal use, though it may also be
1157:             * used by advanced applications.
1158:             *
1159:             * @param key an object acting as a key for this user data value. This must be equal
1160:             * (in the sense of the equals() method) to the key supplied when the data value was
1161:             * registered using {@link #setUserData}. If data for the given object and name already
1162:             * exists, it is overwritten.
1163:             * @param name the name of the required property
1164:             * @param data the value of the required property
1165:             */
1166:
1167:            public void setUserData(Object key, String name, Object data) {
1168:                // System.err.println("setUserData " + name + " on object to " + data);
1169:                String keyVal = key.hashCode() + " " + name;
1170:                if (data == null) {
1171:                    userDataTable.remove(keyVal);
1172:                } else {
1173:                    userDataTable.put(keyVal, data);
1174:                }
1175:            }
1176:
1177:            /////////////////////////////////////////////////////////////////////////
1178:            // implement the javax.xml.transform.Transformer methods
1179:            /////////////////////////////////////////////////////////////////////////
1180:
1181:            /**
1182:             * Perform a transformation from a Source document to a Result document.
1183:             *
1184:             * @exception XPathException if the transformation fails. As a
1185:             *     special case, the method throws a TerminationException (a subclass
1186:             *     of XPathException) if the transformation was terminated using
1187:             *      xsl:message terminate="yes".
1188:             * @param source The input for the source tree. May be null if and only if an
1189:             * initial template has been supplied.
1190:             * @param result The destination for the result tree.
1191:             */
1192:
1193:            public void transform(Source source, Result result)
1194:                    throws TransformerException {
1195:                if (preparedStylesheet == null) {
1196:                    throw new DynamicError("Stylesheet has not been prepared");
1197:                }
1198:
1199:                if (!dateTimePreset) {
1200:                    currentDateTime = null; // reset at start of each transformation
1201:                }
1202:
1203:                try {
1204:                    NodeInfo startNode = null;
1205:                    boolean wrap = true;
1206:                    int validationMode = config.getSchemaValidationMode();
1207:                    Source underSource = source;
1208:                    if (source instanceof  AugmentedSource) {
1209:                        Boolean localWrap = ((AugmentedSource) source)
1210:                                .getWrapDocument();
1211:                        if (localWrap != null) {
1212:                            wrap = localWrap.booleanValue();
1213:                        }
1214:                        int localValidate = ((AugmentedSource) source)
1215:                                .getSchemaValidation();
1216:                        if (localValidate != Validation.DEFAULT) {
1217:                            validationMode = localValidate;
1218:                        }
1219:                        if (validationMode == Validation.STRICT
1220:                                || validationMode == Validation.LAX) {
1221:                            // If validation of a DOMSource or NodeInfo is requested, we must copy it, we can't wrap it
1222:                            wrap = false;
1223:                        }
1224:                        underSource = ((AugmentedSource) source)
1225:                                .getContainedSource();
1226:                    }
1227:                    Source s2 = config.getSourceResolver().resolveSource(
1228:                            underSource, config);
1229:                    if (s2 != null) {
1230:                        underSource = s2;
1231:                    }
1232:                    if (wrap
1233:                            && (underSource instanceof  NodeInfo || underSource instanceof  DOMSource)) {
1234:                        startNode = prepareInputTree(underSource);
1235:                        registerDocument(startNode.getDocumentRoot(),
1236:                                underSource.getSystemId());
1237:
1238:                    } else if (source == null) {
1239:                        if (initialTemplate == null) {
1240:                            throw new DynamicError(
1241:                                    "Either a source document or an initial template must be specified");
1242:                        }
1243:
1244:                    } else {
1245:                        // The input is a SAXSource or StreamSource, or
1246:                        // a DOMSource with wrap=no: build the document tree
1247:
1248:                        Builder sourceBuilder = makeBuilder();
1249:                        Sender sender = new Sender(makePipelineConfiguration());
1250:                        Receiver r = sourceBuilder;
1251:                        if (config.isStripsAllWhiteSpace()
1252:                                || executable.stripsWhitespace()
1253:                                || validationMode == Validation.STRICT
1254:                                || validationMode == Validation.LAX) {
1255:                            r = makeStripper(sourceBuilder);
1256:                        }
1257:                        if (executable.stripsInputTypeAnnotations()) {
1258:                            r = config.getAnnotationStripper(r);
1259:                        }
1260:                        sender.send(source, r);
1261:                        DocumentInfo doc = (DocumentInfo) sourceBuilder
1262:                                .getCurrentRoot();
1263:                        registerDocument(doc, source.getSystemId());
1264:                        startNode = doc;
1265:                    }
1266:
1267:                    transformDocument(startNode, result);
1268:
1269:                } catch (TerminationException err) {
1270:                    //System.err.println("Processing terminated using xsl:message");
1271:                    throw err;
1272:                } catch (XPathException err) {
1273:                    Throwable cause = err.getException();
1274:                    if (cause != null && cause instanceof  SAXParseException) {
1275:                        // This generally means the error was already reported.
1276:                        // But if a RuntimeException occurs in Saxon during a callback from
1277:                        // the Crimson parser, Crimson wraps this in a SAXParseException without
1278:                        // reporting it further.
1279:                        SAXParseException spe = (SAXParseException) cause;
1280:                        cause = spe.getException();
1281:                        if (cause instanceof  RuntimeException) {
1282:                            reportFatalError(err);
1283:                        }
1284:                    } else {
1285:                        reportFatalError(err);
1286:                    }
1287:                    throw err;
1288:                }
1289:            }
1290:
1291:            /**
1292:             * Prepare an input tree for processing. This is used when either the initial
1293:             * input, or a Source returned by the document() function, is a NodeInfo or a
1294:             * DOMSource. The preparation consists of wrapping a DOM document inside a wrapper
1295:             * that implements the NodeInfo interface, and/or adding a space-stripping wrapper
1296:             * if the stylesheet strips whitespace nodes.
1297:             * <p>
1298:             * This method is intended for internal use.
1299:             *
1300:             * @param source the input tree. Must be either a DOMSource or a NodeInfo
1301:             * @return the NodeInfo representing the input node, suitably wrapped.
1302:             */
1303:
1304:            public NodeInfo prepareInputTree(Source source) {
1305:                NodeInfo start = unravel(source, getConfiguration());
1306:                if (executable.stripsWhitespace()) {
1307:                    DocumentInfo docInfo = start.getDocumentRoot();
1308:                    StrippedDocument strippedDoc = new StrippedDocument(
1309:                            docInfo, makeStripper(null));
1310:                    start = strippedDoc.wrap(start);
1311:                }
1312:                return start;
1313:            }
1314:
1315:            /**
1316:             * Get a NodeInfo corresponding to a DOM Node, either by wrapping or unwrapping the DOM Node.
1317:             * <p>
1318:             * This method is intended for internal use.
1319:             */
1320:
1321:            public static NodeInfo unravel(Source source, Configuration config) {
1322:                List externalObjectModels = config.getExternalObjectModels();
1323:                for (int m = 0; m < externalObjectModels.size(); m++) {
1324:                    ExternalObjectModel model = (ExternalObjectModel) externalObjectModels
1325:                            .get(m);
1326:                    NodeInfo node = model.unravel(source, config);
1327:                    if (node != null) {
1328:                        return node;
1329:                    }
1330:                }
1331:                if (source instanceof  NodeInfo) {
1332:                    return (NodeInfo) source;
1333:                }
1334:                return null;
1335:            }
1336:
1337:            /**
1338:             * Transform a source XML document supplied as a tree. <br>
1339:             * A new output destination should be created for each source document,
1340:             * by using setOutputDetails().
1341:             * <p>
1342:             * This method is intended for internal use. External applications should use
1343:             * the {@link #transform} method, which is part of the JAXP interface. Note that
1344:             * <code>NodeInfo</code> implements the JAXP <code>Source</code> interface, so
1345:             * it may be supplied directly to the transform() method.
1346:             *
1347:             * @exception XPathException if any dynamic error occurs
1348:             * @param startNode A Node that identifies the source document to be
1349:             *     transformed and the node where the transformation should start.
1350:             *     May be null if the transformation is to start using an initial template.
1351:             * @param result The output destination
1352:             */
1353:
1354:            public void transformDocument(NodeInfo startNode, Result result)
1355:                    throws TransformerException {
1356:
1357:                if (executable == null) {
1358:                    throw new DynamicError("Stylesheet has not been compiled");
1359:                }
1360:
1361:                // Determine whether we need to close the output stream at the end. We
1362:                // do this if the Result object is a StreamResult and is supplied as a
1363:                // system ID, not as a Writer or OutputStream
1364:
1365:                boolean mustClose = (result instanceof  StreamResult && ((StreamResult) result)
1366:                        .getOutputStream() == null);
1367:
1368:                principalResult = result;
1369:                if (principalResultURI == null) {
1370:                    principalResultURI = result.getSystemId();
1371:                }
1372:
1373:                XPathContextMajor initialContext = newXPathContext();
1374:                initialContext.setOrigin(this );
1375:
1376:                if (startNode != null) {
1377:                    DocumentInfo sourceDoc;
1378:                    if (startNode instanceof  DocumentInfo) {
1379:                        sourceDoc = (DocumentInfo) startNode;
1380:                    } else {
1381:                        sourceDoc = startNode.getDocumentRoot();
1382:                        if (sourceDoc == null) {
1383:                            throw new DynamicError(
1384:                                    "Source tree must have a document node as its root");
1385:                        }
1386:                    }
1387:
1388:                    principalSourceDocument = sourceDoc;
1389:
1390:                    if (sourceDoc.getConfiguration() == null) {
1391:                        // must be a non-standard document implementation
1392:                        throw new TransformerException(
1393:                                "The supplied source document must be associated with a Configuration");
1394:                        //sourceDoc.setConfiguration(getConfiguration());
1395:                    }
1396:
1397:                    if (sourceDoc.getNamePool() != preparedStylesheet
1398:                            .getTargetNamePool()) {
1399:                        throw new DynamicError(
1400:                                "Source document and stylesheet must use the same name pool");
1401:                    }
1402:                    SequenceIterator currentIter = SingletonIterator
1403:                            .makeIterator(sourceDoc);
1404:                    currentIter.next();
1405:                    initialContext.setCurrentIterator(currentIter);
1406:                }
1407:
1408:                initializeController();
1409:
1410:                // In tracing/debugging mode, evaluate all the global variables first
1411:                if (getConfiguration().getTraceListener() != null) {
1412:                    preEvaluateGlobals(initialContext);
1413:                }
1414:
1415:                Properties xslOutputProps = executable
1416:                        .getDefaultOutputProperties();
1417:
1418:                // overlay the output properties defined via the API
1419:                if (outputProperties != null) {
1420:                    Enumeration props = outputProperties.propertyNames();
1421:                    while (props.hasMoreElements()) {
1422:                        String p = (String) props.nextElement();
1423:                        String v = outputProperties.getProperty(p);
1424:                        xslOutputProps.put(p, v);
1425:                    }
1426:                }
1427:
1428:                // deal with stylesheet chaining
1429:                String nextInChain = xslOutputProps
1430:                        .getProperty(SaxonOutputKeys.NEXT_IN_CHAIN);
1431:                if (nextInChain != null) {
1432:                    String baseURI = xslOutputProps
1433:                            .getProperty(SaxonOutputKeys.NEXT_IN_CHAIN_BASE_URI);
1434:                    result = prepareNextStylesheet(nextInChain, baseURI, result);
1435:                }
1436:
1437:                initialContext.changeOutputDestination(xslOutputProps, result,
1438:                        true, Validation.PRESERVE, null);
1439:                initialContext.getReceiver().startDocument(0);
1440:
1441:                // Process the source document using the handlers that have been set up
1442:
1443:                if (initialTemplate == null) {
1444:                    AxisIterator single = SingletonIterator
1445:                            .makeIterator(startNode);
1446:                    initialContext.setCurrentIterator(single);
1447:                    principalSourceDocument = (startNode == null ? null
1448:                            : startNode.getDocumentRoot());
1449:                    if (principalSourceDocument == null) {
1450:                        throw new DynamicError(
1451:                                "Source tree must be rooted at a document node");
1452:                    }
1453:                    TailCall tc = ApplyTemplates.applyTemplates(initialContext
1454:                            .getCurrentIterator(), getRuleManager().getMode(
1455:                            initialMode), null, null, initialContext, false, 0);
1456:                    while (tc != null) {
1457:                        tc = tc.processLeavingTail(initialContext);
1458:                    }
1459:                } else {
1460:                    Template t = initialTemplate;
1461:                    XPathContextMajor c2 = initialContext.newContext();
1462:                    c2.setOrigin(this );
1463:                    c2.openStackFrame(t.getStackFrameMap());
1464:                    c2.setLocalParameters(new ParameterSet());
1465:                    c2.setTunnelParameters(new ParameterSet());
1466:
1467:                    TailCall tc = t.expand(c2);
1468:                    while (tc != null) {
1469:                        tc = tc.processLeavingTail(c2);
1470:                    }
1471:                }
1472:
1473:                if (traceListener != null) {
1474:                    traceListener.close();
1475:                }
1476:
1477:                initialContext.getReceiver().endDocument();
1478:                initialContext.getReceiver().close();
1479:
1480:                if (mustClose && result instanceof  StreamResult) {
1481:                    OutputStream os = ((StreamResult) result).getOutputStream();
1482:                    if (os != null) {
1483:                        try {
1484:                            os.close();
1485:                        } catch (java.io.IOException err) {
1486:                            throw new DynamicError(err);
1487:                        }
1488:                    }
1489:                }
1490:
1491:            }
1492:
1493:            /**
1494:             * Pre-evaluate global variables (when debugging/tracing).
1495:             * <p>
1496:             * This method is intended for internal use.
1497:             */
1498:
1499:            public void preEvaluateGlobals(XPathContext context)
1500:                    throws XPathException {
1501:                IntHashMap vars = getExecutable().getCompiledGlobalVariables();
1502:                Iterator iter = vars.valueIterator();
1503:                while (iter.hasNext()) {
1504:                    GlobalVariable var = (GlobalVariable) iter.next();
1505:                    var.evaluateVariable(context);
1506:                }
1507:            }
1508:
1509:            /**
1510:             * Prepare another stylesheet to handle the output of this one.
1511:             * <p>
1512:             * This method is intended for internal use, to support the
1513:             * <code>saxon:next-in-chain</code> extension.
1514:             *
1515:             * @exception XPathException if any dynamic error occurs
1516:             * @param href URI of the next stylesheet to be applied
1517:             * @param baseURI base URI for resolving href if it's a relative
1518:             *     URI
1519:             * @param result the output destination of the current stylesheet
1520:             * @return a replacement destination for the current stylesheet
1521:             */
1522:
1523:            public Result prepareNextStylesheet(String href, String baseURI,
1524:                    Result result) throws TransformerException {
1525:
1526:                // TODO: should cache the results, we are recompiling the referenced
1527:                // stylesheet each time it's used
1528:
1529:                Source source = null;
1530:                if (userURIResolver != null) {
1531:                    source = userURIResolver.resolve(href, baseURI);
1532:                }
1533:                if (source == null) {
1534:                    source = standardURIResolver.resolve(href, baseURI);
1535:                }
1536:                TransformerFactoryImpl factory = new TransformerFactoryImpl();
1537:                factory.setConfiguration(config);
1538:                Templates next = factory.newTemplates(source);
1539:                TransformerReceiver nextTransformer = new TransformerReceiver(
1540:                        (Controller) next.newTransformer());
1541:
1542:                nextTransformer.setSystemId(principalResultURI);
1543:                nextTransformer
1544:                        .setPipelineConfiguration(makePipelineConfiguration());
1545:                nextTransformer.setResult(result);
1546:
1547:                return nextTransformer;
1548:            }
1549:
1550:            //////////////////////////////////////////////////////////////////////////
1551:            // Handle parameters to the transformation
1552:            //////////////////////////////////////////////////////////////////////////
1553:
1554:            /**
1555:             * Set a parameter for the transformation.
1556:             * <p>
1557:             * The following table shows some of the classes that are supported
1558:             * by this method. (Others may also be supported, but continued support is
1559:             * not guaranteed.) Each entry in the table shows first the Java class of the
1560:             * supplied object, and then the type of the resulting XPath value.
1561:             * <p>
1562:             * <table>
1563:             * <thead>
1564:             *   <tr><th>Java Class</th><th>XPath 2.0 type</th></tr>
1565:             * </thead>
1566:             * <tbody>
1567:             *   <tr><td>String</td><td>xs:string</td></tr>
1568:             *   <tr><td>Boolean</td><td>xs:boolean</td></tr>
1569:             *   <tr><td>Integer</td><td>xs:integer</td></tr>
1570:             *   <tr><td>Long</td><td>xs:integer</td></tr>
1571:             *   <tr><td>Double</td><td>xs:double</td></tr>
1572:             *   <tr><td>Float</td><td>xs:float</td></tr>
1573:             *   <tr><td>BigDecimal</td><td>xs:decimal</td></tr>
1574:             *   <tr><td>BigInteger</td><td>xs:integer</td></tr>
1575:             *   <tr><td>Date</td><td>xs:dateTime</td></tr>
1576:             *   <tr><td>Array or List of any of the above</td><td>sequence of the above</td></tr>
1577:             *   <tr><td>null</td><td>empty sequence</td></tr>
1578:             * </tbody></table>
1579:             * <p>
1580:             * A node may be supplied as a <code>NodeInfo</code> object, a sequence of nodes
1581:             * as an array or List of <code>NodeInfo</code> objects.
1582:             * <p>
1583:             * In addition, any object that implements the Saxon {@link net.sf.saxon.value.Value} interface
1584:             * may be supplied, and will be used without conversion.
1585:             * <p>
1586:             * A node belong to an external object model (such as DOM, JDOM, or XOM) may be supplied provided (a)
1587:             * that the external object model is registered with the Configuration, and (b) that the node is part
1588:             * of a document tree that has been registered in the document pool.
1589:             *
1590:             * @param expandedName The name of the parameter in {uri}local format
1591:             * @param value The value object.  This must follow the rules above.
1592:             * Other formats in addition to those listed above may be accepted.
1593:             * @since 8.4
1594:             */
1595:
1596:            public void setParameter(String expandedName, Object value) {
1597:
1598:                if (parameters == null) {
1599:                    parameters = new GlobalParameterSet();
1600:                }
1601:
1602:                int fingerprint = namePool.allocateClarkName(expandedName);
1603:                parameters.put(fingerprint, value);
1604:
1605:            }
1606:
1607:            /**
1608:             * Reset the parameters to a null list.
1609:             */
1610:
1611:            public void clearParameters() {
1612:                parameters = null;
1613:            }
1614:
1615:            /**
1616:             * Get a parameter to the transformation. This returns the value of a parameter
1617:             * that has been previously set using the {@link #setParameter} method. The value
1618:             * is returned exactly as supplied, that is, before any conversion to an XPath value.
1619:             *
1620:             * @param expandedName the name of the required parameter, in
1621:             *     "{uri}local-name" format
1622:             * @return the value of the parameter, if it exists, or null otherwise
1623:             */
1624:
1625:            public Object getParameter(String expandedName) {
1626:                if (parameters == null) {
1627:                    return null;
1628:                }
1629:                int f = namePool.allocateClarkName(expandedName);
1630:                return parameters.get(f);
1631:            }
1632:
1633:            /**
1634:             * Set the current date and time for this query or transformation.
1635:             * This method is provided primarily for testing purposes, to allow tests to be run with
1636:             * a fixed date and time. The supplied date/time must include a timezone, which is used
1637:             * as the implicit timezone. Calls are ignored if a current date/time has already been
1638:             * established by calling getCurrentDateTime().
1639:             *
1640:             * <p>Note that comparisons of date/time values currently use the implicit timezone
1641:             * taken from the system clock, not from the value supplied here.</p>
1642:             */
1643:
1644:            public void setCurrentDateTime(DateTimeValue dateTime)
1645:                    throws XPathException {
1646:                if (currentDateTime == null) {
1647:                    if (dateTime.getComponent(Component.TIMEZONE) == null) {
1648:                        throw new DynamicError(
1649:                                "No timezone is present in supplied value of current date/time");
1650:                    }
1651:                    currentDateTime = dateTime;
1652:                    dateTimePreset = true;
1653:                }
1654:            }
1655:
1656:            /**
1657:             * Get the current date and time for this query or transformation.
1658:             * All calls during one transformation return the same answer.
1659:             * <p>
1660:             * This method is intended for internal use.
1661:             *
1662:             * @return Get the current date and time. This will deliver the same value
1663:             *      for repeated calls within the same transformation
1664:             */
1665:
1666:            public DateTimeValue getCurrentDateTime() {
1667:                if (currentDateTime == null) {
1668:                    currentDateTime = new DateTimeValue(
1669:                            new GregorianCalendar(), true);
1670:                }
1671:                return currentDateTime;
1672:            }
1673:
1674:            /////////////////////////////////////////
1675:            // Methods for handling dynamic context
1676:            /////////////////////////////////////////
1677:
1678:            /**
1679:             * Make an XPathContext object for expression evaluation.
1680:             * <p>
1681:             * This method is intended for internal use.
1682:             *
1683:             * @return the new XPathContext
1684:             */
1685:
1686:            public XPathContextMajor newXPathContext() {
1687:                return new XPathContextMajor(this );
1688:            }
1689:
1690:            /**
1691:             * Set the last remembered node, for node numbering purposes.
1692:             * <p>
1693:             * This method is strictly for internal use only.
1694:             *
1695:             * @param node the node in question
1696:             * @param number the number of this node
1697:             */
1698:
1699:            public void setRememberedNumber(NodeInfo node, int number) {
1700:                lastRememberedNode = node;
1701:                lastRememberedNumber = number;
1702:            }
1703:
1704:            /**
1705:             * Get the number of a node if it is the last remembered one.
1706:             * <p>
1707:             * This method is strictly for internal use only.
1708:             *
1709:             * @param node the node for which remembered information is required
1710:             * @return the number of this node if known, else -1.
1711:             */
1712:
1713:            public int getRememberedNumber(NodeInfo node) {
1714:                if (lastRememberedNode == node) {
1715:                    return lastRememberedNumber;
1716:                }
1717:                return -1;
1718:            }
1719:
1720:            /**
1721:             * Get diagnostic information about this context.
1722:             * <p>
1723:             * This method is intended for internal use.
1724:             */
1725:
1726:            public InstructionInfo getInstructionInfo() {
1727:                InstructionDetails details = new InstructionDetails();
1728:                details.setConstructType(Location.CONTROLLER);
1729:                return details;
1730:            }
1731:
1732:            /**
1733:             * Set a ClassLoader to be used when loading external classes. Examples of classes that are
1734:             * loaded include SAX parsers, localization modules for formatting numbers and dates,
1735:             * extension functions, external object models. In an environment such as Eclipse that uses
1736:             * its own ClassLoader, this ClassLoader should be nominated to ensure that any class loaded
1737:             * by Saxon is identical to a class of the same name loaded by the external environment.
1738:             * <p>
1739:             * This method is for application use, but is experimental and subject to change.
1740:             *
1741:             * @param loader the ClassLoader to be used.
1742:             */
1743:
1744:            public void setClassLoader(ClassLoader loader) {
1745:                this .classLoader = loader;
1746:            }
1747:
1748:            /**
1749:             * Get the ClassLoader supplied using the method {@link #setClassLoader}.
1750:             * If none has been supplied, return null.
1751:             * <p>
1752:             * This method is for application use, but is experimental and subject to change.
1753:             *
1754:             * @return the ClassLoader in use.
1755:             */
1756:
1757:            public ClassLoader getClassLoader() {
1758:                return classLoader;
1759:            }
1760:
1761:            /**
1762:             * Allocate a local document number: that is, a document number for a document
1763:             * that is used only locally within this query or transformation (a temporary tree).
1764:             * Local document numbers are allocated by the controller to avoid the synchronization
1765:             * overhead of allocating a global document number from the NamePool. Local document
1766:             * numbers are always negative, global document numbers are positive.
1767:             */
1768:
1769:            //    public int allocateLocalDocumentNumber() {
1770:            //        return nextLocalDocumentNumber--;
1771:            //    }
1772:
1773:        }
1774:
1775:        //
1776:        // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
1777:        // you may not use this file except in compliance with the License. You may obtain a copy of the
1778:        // License at http://www.mozilla.org/MPL/
1779:        //
1780:        // Software distributed under the License is distributed on an "AS IS" basis,
1781:        // WITHOUT WARRANTY OF ANY KIND, either express or implied.
1782:        // See the License for the specific language governing rights and limitations under the License.
1783:        //
1784:        // The Original Code is: all this file.
1785:        //
1786:        // The Initial Developer of the Original Code is Michael H. Kay.
1787:        //
1788:        // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
1789:        //
1790:        // Contributor(s):
1791:        // Portions marked "e.g." are from Edwin Glaser (edwin@pannenleiter.de)
1792:        //
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.