PageRenderTime 53ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/saxonB/net/sf/saxon/Query.java

https://bitbucket.org/dmwelch/phdxnat_pipeline
Java | 1037 lines | 824 code | 69 blank | 144 comment | 345 complexity | 84e0c8da679a58f604ebf8bfacd422ca MD5 | raw file
  1. package net.sf.saxon;
  2. import net.sf.saxon.event.Builder;
  3. import net.sf.saxon.event.ProxyReceiver;
  4. import net.sf.saxon.event.Receiver;
  5. import net.sf.saxon.event.SaxonOutputKeys;
  6. import net.sf.saxon.expr.PathMap;
  7. import net.sf.saxon.instruct.TerminationException;
  8. import net.sf.saxon.om.*;
  9. import net.sf.saxon.query.*;
  10. import net.sf.saxon.trace.ExpressionPresenter;
  11. import net.sf.saxon.trace.XQueryTraceListener;
  12. import net.sf.saxon.trans.XPathException;
  13. import net.sf.saxon.type.SchemaException;
  14. import net.sf.saxon.value.UntypedAtomicValue;
  15. import net.sf.saxon.value.Whitespace;
  16. import org.xml.sax.InputSource;
  17. import javax.xml.transform.OutputKeys;
  18. import javax.xml.transform.Source;
  19. import javax.xml.transform.TransformerException;
  20. import javax.xml.transform.TransformerFactoryConfigurationError;
  21. import javax.xml.transform.sax.SAXSource;
  22. import javax.xml.transform.stream.StreamResult;
  23. import javax.xml.transform.stream.StreamSource;
  24. import java.io.*;
  25. import java.util.*;
  26. /**
  27. * This <B>Query</B> class provides a command-line interface to the Saxon XQuery processor.<p>
  28. * <p/>
  29. * The XQuery syntax supported conforms to the W3C XQuery 1.0 drafts.
  30. *
  31. * @author Michael H. Kay
  32. */
  33. public class Query {
  34. protected Configuration config;
  35. protected boolean showTime = false;
  36. protected int repeat = 1;
  37. protected String sourceFileName = null;
  38. protected String queryFileName = null;
  39. protected boolean useURLs = false;
  40. protected String outputFileName = null;
  41. protected String moduleURIResolverClass = null;
  42. protected String uriResolverClass = null;
  43. protected boolean explain = false;
  44. protected boolean wrap = false;
  45. protected boolean pullMode = false;
  46. protected boolean projection = false;
  47. protected boolean updating = false;
  48. protected boolean writeback = false;
  49. protected boolean backup = true;
  50. protected String explainOutputFileName = null;
  51. //private PrintStream traceDestination = System.err;
  52. private boolean closeTraceDestination = false;
  53. private boolean schemaAware = false;
  54. /**
  55. * Set the configuration. This is designed to be
  56. * overridden in a subclass
  57. *
  58. * @param schemaAware true if a schema-aware configuration is required (in this case Saxon-SA must
  59. * be installed and licensed)
  60. * @param className the name of the class to be loaded, representing the Configuration. This
  61. * allows additional control of the loading process under .NET
  62. * @return the successfully loaded Configuration
  63. */
  64. protected Configuration makeConfiguration(boolean schemaAware, String className) {
  65. if (schemaAware) {
  66. config = Configuration.makeSchemaAwareConfiguration(null, className);
  67. } else {
  68. config = new Configuration();
  69. // In basic XQuery, all nodes are untyped when calling from the command line
  70. config.setAllNodesUntyped(true);
  71. }
  72. return config;
  73. }
  74. /**
  75. * Get the configuration in use
  76. *
  77. * @return the configuration
  78. */
  79. protected Configuration getConfiguration() {
  80. return config;
  81. }
  82. /**
  83. * Main program, can be used directly from the command line.
  84. * <p>The format is:</P>
  85. * <p>java net.sf.saxon.Query [options] <I>query-file</I> &gt;<I>output-file</I></P>
  86. * <p>followed by any number of parameters in the form {keyword=value}... which can be
  87. * referenced from within the query.</p>
  88. * <p>This program executes the query in query-file.</p>
  89. *
  90. * @param args List of arguments supplied on operating system command line
  91. * @throws Exception Indicates that a compile-time or
  92. * run-time error occurred
  93. */
  94. public static void main(String args[])
  95. throws Exception {
  96. // the real work is delegated to another routine so that it can be used in a subclass
  97. (new Query()).doQuery(args, "java net.sf.saxon.Query");
  98. }
  99. /**
  100. * Support method for main program. This support method can also be invoked from subclasses
  101. * that support the same command line interface
  102. *
  103. * @param args the command-line arguments
  104. * @param command name of the class, to be used in error messages
  105. */
  106. protected void doQuery(String args[], String command) {
  107. schemaAware = testIfSchemaAware(args);
  108. config = makeConfiguration(schemaAware, null);
  109. config.setHostLanguage(Configuration.XQUERY);
  110. StaticQueryContext staticEnv = new StaticQueryContext(config);
  111. DynamicQueryContext dynamicEnv = new DynamicQueryContext(config);
  112. Properties outputProps = new Properties();
  113. // Check the command-line arguments.
  114. try {
  115. parseOptions(args, command, dynamicEnv, outputProps);
  116. if (updating) {
  117. staticEnv.setUpdatingEnabled(true);
  118. }
  119. if (moduleURIResolverClass != null) {
  120. Object mr = config.getInstance(moduleURIResolverClass, null);
  121. if (!(mr instanceof ModuleURIResolver)) {
  122. badUsage(command, moduleURIResolverClass + " is not a ModuleURIResolver");
  123. }
  124. staticEnv.setModuleURIResolver((ModuleURIResolver)mr);
  125. }
  126. if (uriResolverClass != null) {
  127. config.setURIResolver(config.makeURIResolver(uriResolverClass));
  128. dynamicEnv.setURIResolver(config.makeURIResolver(uriResolverClass));
  129. }
  130. config.displayLicenseMessage();
  131. if (pullMode) {
  132. //config.setLazyConstructionMode(true);
  133. }
  134. if (explain) {
  135. config.setOptimizerTracing(true);
  136. }
  137. Source sourceInput = null;
  138. if (sourceFileName != null) {
  139. sourceInput = processSourceFile(sourceFileName, useURLs);
  140. }
  141. long startTime = (new Date()).getTime();
  142. if (showTime) {
  143. System.err.println("Analyzing query from " + queryFileName);
  144. }
  145. // Compile the query
  146. XQueryExpression exp;
  147. try {
  148. exp = compileQuery(staticEnv, queryFileName, useURLs);
  149. if (showTime) {
  150. long endTime = (new Date()).getTime();
  151. System.err.println("Analysis time: " + (endTime - startTime) + " milliseconds");
  152. startTime = endTime;
  153. }
  154. } catch (XPathException err) {
  155. int line = -1;
  156. String module = null;
  157. if (err.getLocator() != null) {
  158. line = err.getLocator().getLineNumber();
  159. module = err.getLocator().getSystemId();
  160. }
  161. if (err.hasBeenReported()) {
  162. quit("Static error(s) in query", 2);
  163. } else {
  164. if (line == -1) {
  165. System.err.println("Static error in query: " + err.getMessage());
  166. } else {
  167. System.err.println("Static error at line " + line + " of " + module + ':');
  168. System.err.println(err.getMessage());
  169. }
  170. }
  171. exp = null;
  172. System.exit(2);
  173. }
  174. if (explain) {
  175. explain(exp);
  176. }
  177. // Load the source file (applying document projection if requested)
  178. exp.setAllowDocumentProjection(projection);
  179. processSource(sourceInput, exp, dynamicEnv);
  180. // Run the query (repeatedly, if the -repeat option was set)
  181. long totalTime = 0;
  182. int r;
  183. for (r = 0; r < repeat; r++) { // repeat is for internal testing/timing
  184. try {
  185. OutputStream destination;
  186. if (outputFileName != null) {
  187. File outputFile = new File(outputFileName);
  188. if (outputFile.isDirectory()) {
  189. quit("Output is a directory", 2);
  190. }
  191. destination = new FileOutputStream(outputFile);
  192. } else {
  193. destination = System.out;
  194. }
  195. runQuery(exp, dynamicEnv, destination, outputProps);
  196. } catch (TerminationException err) {
  197. throw err;
  198. } catch (XPathException err) {
  199. if (err.hasBeenReported()) {
  200. //err.printStackTrace();
  201. throw new XPathException("Run-time errors were reported");
  202. } else {
  203. throw err;
  204. }
  205. }
  206. if (showTime) {
  207. long endTime = (new Date()).getTime();
  208. if (r > 3) {
  209. totalTime += (endTime - startTime);
  210. }
  211. if (repeat != 100) {
  212. System.err.println("Execution time: " + (endTime - startTime) + " milliseconds");
  213. } else if (totalTime > 100000) {
  214. break;
  215. }
  216. startTime = endTime;
  217. }
  218. }
  219. if (repeat > 3) {
  220. System.err.println("Average execution time: " + (totalTime / (double)(r - 3)) + " milliseconds");
  221. }
  222. } catch (TerminationException err) {
  223. quit(err.getMessage(), 1);
  224. } catch (XPathException err) {
  225. quit("Query processing failed: " + err.getMessage(), 2);
  226. } catch (TransformerFactoryConfigurationError err) {
  227. err.printStackTrace();
  228. quit("Query processing failed", 2);
  229. } catch (SchemaException err) {
  230. quit("Schema processing failed: " + err.getMessage(), 2);
  231. } catch (Exception err2) {
  232. err2.printStackTrace();
  233. quit("Fatal error during query: " + err2.getClass().getName() + ": " +
  234. (err2.getMessage() == null ? " (no message)" : err2.getMessage()), 2);
  235. }
  236. }
  237. /**
  238. * Prescan the command line arguments to see if any of them imply use of a schema-aware processor
  239. * @param args the command line arguments
  240. * @return true if a schema-aware processor is needed
  241. */
  242. protected boolean testIfSchemaAware(String[] args) {
  243. for (int i = 0; i < args.length; i++) {
  244. if (args[i].equals("-sa") ||
  245. args[i].startsWith("-val:") ||
  246. args[i].equals("-val") ||
  247. args[i].equals("-vlax") ||
  248. args[i].equals("-p") ||
  249. args[i].equals("-xsd:") ||
  250. args[i].startsWith("-xsdversion:") ||
  251. args[i].startsWith("-projection:") ||
  252. args[i].startsWith("-update:")) {
  253. return true;
  254. }
  255. }
  256. return false;
  257. }
  258. /**
  259. * Parse the options supplied on the command line
  260. * @param args the command line arguments
  261. * @param command the name of the command that was used (for diagnostics only)
  262. * @param dynamicEnv the XQuery dynamic context
  263. * @param outputProps the serialization properties
  264. * @throws TransformerException if failures occur. Note, the method may also invoke System.exit().
  265. */
  266. protected void parseOptions(String[] args, String command, DynamicQueryContext dynamicEnv, Properties outputProps)
  267. throws TransformerException {
  268. int i = 0;
  269. String additionalSchemas = null;
  270. while (i < args.length) {
  271. if (args[i].charAt(0) == '-') {
  272. String option;
  273. String value = null;
  274. int colon = args[i].indexOf(':');
  275. if (colon > 0 && colon < args[i].length() - 1) {
  276. option = args[i].substring(1, colon);
  277. value = args[i].substring(colon + 1);
  278. } else {
  279. option = args[i].substring(1);
  280. }
  281. if (option.equals("backup")) {
  282. if (!("on".equals(value) || "off".equals(value))) {
  283. badUsage(command, "-backup option must be -backup:on or -backup:off");
  284. }
  285. backup = "on".equals(value);
  286. i++;
  287. } else if (option.equals("cr")) { // collection resolver
  288. i++;
  289. if (value == null) {
  290. if (args.length < i + 2) {
  291. badUsage(command, "No resolver after -cr");
  292. }
  293. value = args[i++];
  294. }
  295. Object resolver = config.getInstance(value, null);
  296. if (!(resolver instanceof CollectionURIResolver)) {
  297. quit(value + " is not a CollectionURIResolver", 2);
  298. }
  299. config.setCollectionURIResolver((CollectionURIResolver)resolver);
  300. } else if (option.equals("ds")) { // linked tree
  301. config.setTreeModel(Builder.LINKED_TREE);
  302. i++;
  303. } else if (option.equals("dt")) { // tiny tree (default)
  304. config.setTreeModel(Builder.TINY_TREE);
  305. i++;
  306. } else if (option.equals("dtd")) {
  307. if (!("on".equals(value) || "off".equals(value))) {
  308. badUsage(command, "-dtd option must be -dtd:on or -dtd:off");
  309. }
  310. config.setValidation("on".equals(value));
  311. i++;
  312. } else if (option.equals("e")) { // explain
  313. explain = true;
  314. i++;
  315. } else if (option.equals("expand")) {
  316. if (!("on".equals(value) || "off".equals(value))) {
  317. badUsage(command, "-expand option must be 'on' or 'off'");
  318. }
  319. config.setExpandAttributeDefaults("on".equals(value));
  320. i++;
  321. } else if (option.equals("explain")) { // explain
  322. explain = true;
  323. i++;
  324. } else if (option.startsWith("explain:")) { // explain:filename
  325. explain = true;
  326. explainOutputFileName = value;
  327. i++;
  328. } else if (option.equals("ext")) {
  329. if (!("on".equals(value) || "off".equals(value))) {
  330. badUsage(command, "-ext option must be -ext:on or -ext:off");
  331. }
  332. config.setAllowExternalFunctions("on".equals(value));
  333. i++;
  334. } else if (option.equals("l")) {
  335. if (!(value == null || "on".equals(value) || "off".equals(value))) {
  336. badUsage(command, "-l option must be -l:on or -l:off");
  337. }
  338. config.setLineNumbering(!"off".equals(value));
  339. i++;
  340. //i++;
  341. } else if (option.equals("mr")) {
  342. i++;
  343. if (value == null) {
  344. if (args.length < i + 2) {
  345. badUsage(command, "No resolver after -cr");
  346. }
  347. value = args[i++];
  348. }
  349. moduleURIResolverClass = value;
  350. } else if (option.equals("-noext")) {
  351. i++;
  352. config.setAllowExternalFunctions(false);
  353. } else if (option.equals("o")) {
  354. i++;
  355. if (value == null) {
  356. if (args.length < i + 2) {
  357. badUsage(command, "No output file name after -o");
  358. }
  359. value = args[i++];
  360. }
  361. outputFileName = value;
  362. } else if (option.equals("outval")) {
  363. if (schemaAware) {
  364. if (!(value == null || "recover".equals(value) || "fatal".equals(value))) {
  365. badUsage(command, "-outval option must be 'recover' or 'fatal'");
  366. }
  367. config.setValidationWarnings("recover".equals(value));
  368. } else {
  369. quit("The -outval option requires a schema-aware processor", 2);
  370. }
  371. i++;
  372. } else if (option.equals("p")) {
  373. i++;
  374. if (!(value == null || "on".equals(value) || "off".equals(value))) {
  375. badUsage(command, "-p option must be -p:on or -p:off");
  376. }
  377. if (!"off".equals(value)) {
  378. config.setParameterizedURIResolver();
  379. useURLs = true;
  380. }
  381. } else if (option.equals("pipe")) {
  382. i++;
  383. if (!("push".equals(value) || "pull".equals(value))) {
  384. badUsage(command, "-pipe option must be -p:push or -p:pull");
  385. }
  386. if ("pull".equals(value)) {
  387. pullMode = true;
  388. }
  389. } else if (option.equals("projection")) {
  390. i++;
  391. if (!(value == null || "on".equals(value) || "off".equals(value))) {
  392. badUsage(command, "-projection option must be -projection:on or projection:off");
  393. }
  394. if (!"off".equals(value)) {
  395. projection = true;
  396. }
  397. } else if (option.equals("pull")) {
  398. i++;
  399. pullMode = true;
  400. } else if (option.equals("q")) {
  401. i++;
  402. queryFileName = value;
  403. } else if (option.equals("qs")) {
  404. i++;
  405. queryFileName = "{" + value + "}";
  406. } else if (option.equals("r")) {
  407. i++;
  408. if (value == null) {
  409. if (args.length < i + 2) {
  410. badUsage(command, "No URIResolver class after -r");
  411. }
  412. value = args[i++];
  413. }
  414. uriResolverClass = value;
  415. } else if (option.equals("repeat")) {
  416. i++;
  417. if (value == null) {
  418. badUsage(command, "No number after -repeat");
  419. } else {
  420. try {
  421. repeat = Integer.parseInt(value);
  422. } catch (NumberFormatException err) {
  423. badUsage(command, "Bad number after -repeat");
  424. }
  425. }
  426. } else if (option.equals("s")) {
  427. i++;
  428. if (value == null) {
  429. if (args.length < i + 2) {
  430. badUsage(command, "No source file name after -s");
  431. }
  432. value = args[i++];
  433. }
  434. sourceFileName = value;
  435. } else if (option.equals("sa")) {
  436. // already handled
  437. i++;
  438. } else if (option.equals("snone")) {
  439. config.setStripsWhiteSpace(Whitespace.NONE);
  440. i++;
  441. } else if (option.equals("sall")) {
  442. config.setStripsWhiteSpace(Whitespace.ALL);
  443. i++;
  444. } else if (option.equals("signorable")) {
  445. config.setStripsWhiteSpace(Whitespace.IGNORABLE);
  446. i++;
  447. } else if (option.equals("strip")) {
  448. i++;
  449. if (value == null) {
  450. value = "all";
  451. }
  452. if ("none".equals(value)) {
  453. // no action|| || "ignorable".equals(value)) {
  454. } else if ("all".equals(value)) {
  455. config.setStripsWhiteSpace(Whitespace.ALL);
  456. } else if ("ignorable".equals(value)) {
  457. config.setStripsWhiteSpace(Whitespace.IGNORABLE);
  458. } else {
  459. badUsage(command, "-strip must be none, all, or ignorable");
  460. }
  461. } else if (option.equals("t")) {
  462. System.err.println(config.getProductTitle());
  463. System.err.println(Configuration.getPlatform().getPlatformVersion());
  464. config.setTiming(true);
  465. showTime = true;
  466. i++;
  467. } else if (option.equals("traceout")) {
  468. i++;
  469. if (value.equals("#err")) {
  470. // no action, this is the default
  471. } else if (value.equals("#out")) {
  472. dynamicEnv.setTraceFunctionDestination(System.out);
  473. } else if (value.equals("#null")) {
  474. dynamicEnv.setTraceFunctionDestination(null);
  475. } else {
  476. try {
  477. dynamicEnv.setTraceFunctionDestination(
  478. new PrintStream(new FileOutputStream(new File(value))));
  479. closeTraceDestination = true;
  480. } catch (FileNotFoundException e) {
  481. badUsage(command, "Trace output file " + value + " cannot be created");
  482. }
  483. }
  484. } else if (option.equals("tree")) {
  485. if ("linked".equals(value)) {
  486. config.setTreeModel(Builder.LINKED_TREE);
  487. } else if ("tiny".equals(value)) {
  488. config.setTreeModel(Builder.TINY_TREE);
  489. } else {
  490. badUsage(command, "-tree option must be 'linked' or 'tiny'");
  491. }
  492. i++;
  493. } else if (option.equals("T")) {
  494. i++;
  495. if (value == null) {
  496. config.setTraceListener(new XQueryTraceListener());
  497. } else {
  498. config.setTraceListenerClass(value);
  499. }
  500. config.setLineNumbering(true);
  501. } else if (option.equals("TJ")) {
  502. i++;
  503. config.setTraceExternalFunctions(true);
  504. } else if (option.equals("TL")) {
  505. if (args.length < i + 2) {
  506. badUsage(command, "No TraceListener class specified");
  507. }
  508. config.setTraceListenerClass(args[++i]);
  509. config.setLineNumbering(true);
  510. i++;
  511. } else if (option.equals("u")) {
  512. useURLs = true;
  513. i++;
  514. } else if (option.equals("update")) {
  515. i++;
  516. if (!(value == null || "on".equals(value) || "off".equals(value) || "discard".equals(value))) {
  517. badUsage(command, "-update option must be on|off|discard");
  518. }
  519. if (!"off".equals(value)) {
  520. updating = true;
  521. }
  522. writeback = !("discard".equals(value));
  523. } else if (option.equals("untyped")) {
  524. // TODO: this is an experimental undocumented option. It should be checked for consistency
  525. config.setAllNodesUntyped(true);
  526. i++;
  527. } else if (option.equals("v")) {
  528. config.setValidation(true);
  529. i++;
  530. } else if (option.equals("val")) {
  531. if (!schemaAware) {
  532. quit("The -val option requires a schema-aware processor", 2);
  533. } else if (value == null || "strict".equals(value)) {
  534. config.setSchemaValidationMode(Validation.STRICT);
  535. } else if ("lax".equals(value)) {
  536. config.setSchemaValidationMode(Validation.LAX);
  537. } else {
  538. badUsage(command, "-val option must be 'strict' or 'lax'");
  539. }
  540. i++;
  541. } else if (option.equals("vlax")) {
  542. if (schemaAware) {
  543. config.setSchemaValidationMode(Validation.LAX);
  544. } else {
  545. quit("The -vlax option requires a schema-aware processor", 2);
  546. }
  547. i++;
  548. } else if (option.equals("vw")) {
  549. if (schemaAware) {
  550. config.setValidationWarnings(true);
  551. } else {
  552. quit("The -vw option requires a schema-aware processor", 2);
  553. }
  554. i++;
  555. } else if (option.equals("wrap")) {
  556. if (!(value == null || "on".equals(value) || "off".equals(value))) {
  557. badUsage(command, "-wrap option must be -wrap:on or -wrap:off");
  558. }
  559. if (!"off".equals(value)) {
  560. wrap = true;
  561. }
  562. i++;
  563. } else if (option.equals("x")) {
  564. i++;
  565. config.setSourceParserClass(value);
  566. } else if (option.equals("xi")) {
  567. if (!(value == null || "on".equals(value) || "off".equals(value))) {
  568. badUsage(command, "-xi option must be -xi:on or -xi:off");
  569. }
  570. if (!"off".equals(value)) {
  571. config.setXIncludeAware(true);
  572. }
  573. i++;
  574. } else if (option.equals("1.1")) {
  575. config.setXMLVersion(Configuration.XML11);
  576. i++;
  577. } else if (option.equals("xmlversion")) {
  578. i++;
  579. if ("1.0".equals(value)) {
  580. config.setXMLVersion(Configuration.XML10);
  581. } else if ("1.1".equals(value)) {
  582. config.setXMLVersion(Configuration.XML11);
  583. } else {
  584. badUsage(command, "-xmlversion must be 1.0 or 1.1");
  585. }
  586. } else if (option.equals("xsd")) {
  587. i++;
  588. additionalSchemas = value;
  589. } else if (option.equals("xsdversion")) { // XSD 1.1
  590. i++;
  591. if (!("1.0".equals(value) | "1.1".equals(value))) {
  592. badUsage(command, "-xsdversion must be 1.0 or 1.1");
  593. }
  594. config.setConfigurationProperty(FeatureKeys.XSD_VERSION, value);
  595. } else if (option.equals("xsiloc")) {
  596. i++;
  597. if ("off".equals(value)) {
  598. config.setConfigurationProperty(FeatureKeys.USE_XSI_SCHEMA_LOCATION, Boolean.FALSE);
  599. } else if ("on".equals(value)) {
  600. config.setConfigurationProperty(FeatureKeys.USE_XSI_SCHEMA_LOCATION, Boolean.TRUE);
  601. } else {
  602. badUsage(value, "format: -xsiloc:(on|off)");
  603. }
  604. } else if (args[i].equals("-?")) {
  605. badUsage(command, "");
  606. } else if (args[i].equals("-")) {
  607. queryFileName = "-";
  608. i++;
  609. } else {
  610. badUsage(command, "Unknown option " + args[i]);
  611. }
  612. } else {
  613. break;
  614. }
  615. }
  616. if (queryFileName == null) {
  617. if (args.length < i + 1) {
  618. badUsage(command, "No query file name");
  619. }
  620. queryFileName = args[i++];
  621. }
  622. for (int p = i; p < args.length; p++) {
  623. String arg = args[p];
  624. int eq = arg.indexOf("=");
  625. if (eq < 1 || eq >= arg.length()) {
  626. badUsage(command, "Bad param=value pair on command line: " + arg);
  627. }
  628. String argname = arg.substring(0, eq);
  629. String argvalue = (eq == arg.length() ? "" : arg.substring(eq + 1));
  630. if (argname.startsWith("!")) {
  631. // parameters starting with "!" are taken as output properties
  632. outputProps.setProperty(argname.substring(1), argvalue);
  633. } else if (argname.startsWith("+")) {
  634. // parameters starting with "+" are taken as input documents
  635. Object sources = Transform.loadDocuments(argvalue, useURLs, config, true);
  636. dynamicEnv.setParameter(argname.substring(1), sources);
  637. } else {
  638. dynamicEnv.setParameter(argname, new UntypedAtomicValue(argvalue));
  639. }
  640. }
  641. if (additionalSchemas != null) {
  642. loadAdditionalSchemas(config, additionalSchemas);
  643. }
  644. }
  645. protected static void loadAdditionalSchemas(Configuration config, String additionalSchemas)
  646. throws TransformerException {
  647. StringTokenizer st = new StringTokenizer(additionalSchemas, ";");
  648. while (st.hasMoreTokens()) {
  649. String schema = st.nextToken();
  650. File schemaFile = new File(schema);
  651. if (!schemaFile.exists()) {
  652. throw new TransformerException("Schema document " + schema + " not found");
  653. }
  654. config.addSchemaSource(new StreamSource(schemaFile));
  655. }
  656. }
  657. protected Source processSourceFile(String sourceFileName, boolean useURLs) throws TransformerException {
  658. Source sourceInput;
  659. if (useURLs || sourceFileName.startsWith("http:") || sourceFileName.startsWith("file:")) {
  660. sourceInput = config.getURIResolver().resolve(sourceFileName, null);
  661. if (sourceInput == null) {
  662. sourceInput = config.getSystemURIResolver().resolve(sourceFileName, null);
  663. }
  664. } else if (sourceFileName.equals("-")) {
  665. // take input from stdin
  666. sourceInput = new StreamSource(System.in);
  667. } else {
  668. File sourceFile = new File(sourceFileName);
  669. if (!sourceFile.exists()) {
  670. quit("Source file " + sourceFile + " does not exist", 2);
  671. }
  672. if (Configuration.getPlatform().isJava()) {
  673. InputSource eis = new InputSource(sourceFile.toURI().toString());
  674. sourceInput = new SAXSource(eis);
  675. } else {
  676. sourceInput = new StreamSource(sourceFile.toURI().toString());
  677. }
  678. }
  679. return sourceInput;
  680. }
  681. /**
  682. * Compile the query
  683. *
  684. * @param staticEnv the static query context
  685. * @param queryFileName the filename holding the query (or "-" for the standard input)
  686. * @param useURLs true if the filename is in the form of a URI
  687. * @return the compiled query
  688. * @throws XPathException if query compilation fails
  689. * @throws IOException if the query cannot be read
  690. */
  691. protected XQueryExpression compileQuery(StaticQueryContext staticEnv, String queryFileName, boolean useURLs)
  692. throws XPathException, IOException {
  693. XQueryExpression exp;
  694. if (queryFileName.equals("-")) {
  695. Reader queryReader = new InputStreamReader(System.in);
  696. exp = staticEnv.compileQuery(queryReader);
  697. } else if (queryFileName.startsWith("{") && queryFileName.endsWith("}")) {
  698. // query is inline on the command line
  699. String q = queryFileName.substring(1, queryFileName.length() - 1);
  700. exp = staticEnv.compileQuery(q);
  701. } else if (useURLs || queryFileName.startsWith("http:") || queryFileName.startsWith("file:")) {
  702. ModuleURIResolver resolver = staticEnv.getModuleURIResolver();
  703. boolean isStandardResolver = false;
  704. if (resolver == null) {
  705. resolver = staticEnv.getConfiguration().getStandardModuleURIResolver();
  706. isStandardResolver = true;
  707. }
  708. while (true) {
  709. String[] locations = {queryFileName};
  710. Source[] sources;
  711. try {
  712. sources = resolver.resolve(null, null, locations);
  713. } catch (Exception e) {
  714. if (e instanceof XPathException) {
  715. throw (XPathException)e;
  716. } else {
  717. XPathException err = new XPathException("Exception in ModuleURIResolver: ", e);
  718. err.setErrorCode("XQST0059");
  719. throw err;
  720. }
  721. }
  722. if (sources == null) {
  723. if (isStandardResolver) {
  724. // this should not happen
  725. quit("System problem: standard ModuleURIResolver returned null", 4);
  726. } else {
  727. resolver = staticEnv.getConfiguration().getStandardModuleURIResolver();
  728. isStandardResolver = true;
  729. }
  730. } else {
  731. if (sources.length != 1 || !(sources[0] instanceof StreamSource)) {
  732. quit("Module URI Resolver must return a single StreamSource", 2);
  733. }
  734. String queryText = QueryReader.readSourceQuery((StreamSource)sources[0], config.getNameChecker());
  735. exp = staticEnv.compileQuery(queryText);
  736. break;
  737. }
  738. }
  739. } else {
  740. InputStream queryStream = new FileInputStream(queryFileName);
  741. staticEnv.setBaseURI(new File(queryFileName).toURI().toString());
  742. exp = staticEnv.compileQuery(queryStream, null);
  743. }
  744. return exp;
  745. }
  746. /**
  747. * Explain the results of query compilation
  748. *
  749. * @param exp the compiled expression
  750. * @throws FileNotFoundException if the destination for the explanation doesn't exist
  751. * @throws XPathException if other failures occur
  752. */
  753. protected void explain(XQueryExpression exp) throws FileNotFoundException, XPathException {
  754. OutputStream explainOutput;
  755. if (explainOutputFileName == null) {
  756. explainOutput = System.err;
  757. } else {
  758. explainOutput = new FileOutputStream(new File(explainOutputFileName));
  759. }
  760. Properties props = new Properties();
  761. props.setProperty(OutputKeys.METHOD, "xml");
  762. props.setProperty(OutputKeys.INDENT, "yes");
  763. props.setProperty(SaxonOutputKeys.INDENT_SPACES, "2");
  764. Receiver diag = config.getSerializerFactory().getReceiver(
  765. new StreamResult(explainOutput),
  766. config.makePipelineConfiguration(),
  767. props);
  768. ExpressionPresenter expressionPresenter = new ExpressionPresenter(config, diag);
  769. exp.explain(expressionPresenter);
  770. }
  771. /**
  772. * Process the supplied source file
  773. *
  774. * @param sourceInput the supplied source
  775. * @param exp the compiled XQuery expression
  776. * @param dynamicEnv the dynamic query context
  777. * @throws XPathException if processing fails
  778. */
  779. protected void processSource(Source sourceInput, XQueryExpression exp, DynamicQueryContext dynamicEnv) throws XPathException {
  780. if (sourceInput != null) {
  781. if (showTime) {
  782. System.err.println("Processing " + sourceInput.getSystemId());
  783. }
  784. if (!exp.usesContextItem()) {
  785. System.err.println("Source document ignored - query does not access the context item");
  786. sourceInput = null;
  787. } else if (projection) {
  788. PathMap map = exp.getPathMap();
  789. PathMap.PathMapRoot contextRoot = map.getContextRoot();
  790. if (explain) {
  791. System.err.println("DOCUMENT PROJECTION: PATH MAP");
  792. map.diagnosticDump(System.err);
  793. }
  794. if (contextRoot != null) {
  795. if (contextRoot.hasUnknownDependencies()) {
  796. System.err.println("Document projection for the context document is not possible, " +
  797. "because the query uses paths that defy analysis");
  798. } else {
  799. ProxyReceiver filter = config.makeDocumentProjector(contextRoot);
  800. sourceInput = AugmentedSource.makeAugmentedSource(sourceInput);
  801. ((AugmentedSource)sourceInput).addFilter(filter);
  802. }
  803. } else {
  804. System.err.println("Source document supplied, but query does not access the context item");
  805. }
  806. }
  807. if (sourceInput != null) {
  808. DocumentInfo doc = config.buildDocument(sourceInput);
  809. dynamicEnv.setContextItem(doc);
  810. }
  811. }
  812. }
  813. /**
  814. * Run the query
  815. *
  816. * @param exp the compiled query expression
  817. * @param dynamicEnv the dynamic query context
  818. * @param destination the destination for serialized results
  819. * @param outputProps serialization properties defining the output format
  820. * @throws XPathException if the query fails
  821. * @throws IOException if input or output fails
  822. */
  823. protected void runQuery(XQueryExpression exp, DynamicQueryContext dynamicEnv,
  824. OutputStream destination, final Properties outputProps)
  825. throws XPathException, IOException {
  826. if (exp.getExpression().isUpdatingExpression() && updating) {
  827. if (writeback) {
  828. final List errors = new ArrayList(3);
  829. UpdateAgent agent = new UpdateAgent() {
  830. public void update(NodeInfo node, Controller controller) throws XPathException {
  831. try {
  832. DocumentPool pool = controller.getDocumentPool();
  833. String documentURI = pool.getDocumentURI(node);
  834. if (documentURI != null) {
  835. QueryResult.rewriteToDisk(node, outputProps, backup, (showTime ? System.err : null));
  836. } else if (showTime) {
  837. System.err.println("Updated document discarded because it was not read using doc()");
  838. }
  839. } catch (XPathException err) {
  840. System.err.println(err.getMessage());
  841. errors.add(err);
  842. }
  843. }
  844. };
  845. exp.runUpdate(dynamicEnv, agent);
  846. if (!errors.isEmpty()) {
  847. throw (XPathException)errors.get(0);
  848. }
  849. } else {
  850. Set affectedDocuments = exp.runUpdate(dynamicEnv);
  851. if (affectedDocuments.contains(dynamicEnv.getContextItem())) {
  852. QueryResult.serialize((NodeInfo)dynamicEnv.getContextItem(),
  853. new StreamResult(destination),
  854. outputProps);
  855. }
  856. }
  857. } else if (wrap && !pullMode) {
  858. SequenceIterator results = exp.iterator(dynamicEnv);
  859. DocumentInfo resultDoc = QueryResult.wrap(results, config);
  860. QueryResult.serialize(resultDoc,
  861. new StreamResult(destination),
  862. outputProps);
  863. destination.close();
  864. } else if (pullMode) {
  865. if (wrap) {
  866. outputProps.setProperty(SaxonOutputKeys.WRAP, "yes");
  867. }
  868. //outputProps.setProperty(OutputKeys.METHOD, "xml");
  869. //outputProps.setProperty(OutputKeys.INDENT, "yes");
  870. exp.pull(dynamicEnv, new StreamResult(destination), outputProps);
  871. } else {
  872. exp.run(dynamicEnv, new StreamResult(destination), outputProps);
  873. }
  874. if (closeTraceDestination) {
  875. dynamicEnv.getTraceFunctionDestination().close();
  876. }
  877. }
  878. /**
  879. * Exit with a message
  880. *
  881. * @param message The message to be output
  882. * @param code The result code to be returned to the operating
  883. * system shell
  884. */
  885. protected static void quit(String message, int code) {
  886. System.err.println(message);
  887. System.exit(code);
  888. }
  889. // public void setPOption(Configuration config) {
  890. // config.getSystemURIResolver().setRecognizeQueryParameters(true);
  891. // }
  892. /**
  893. * Report incorrect usage of the command line, with a list of the options and arguments that are available
  894. *
  895. * @param name The name of the command being executed (allows subclassing)
  896. * @param message The error message
  897. */
  898. protected void badUsage(String name, String message) {
  899. if (!"".equals(message)) {
  900. System.err.println(message);
  901. }
  902. System.err.println(config.getProductTitle());
  903. System.err.println("Usage: " + name + " [options] query {param=value}...");
  904. System.err.println("Options: ");
  905. System.err.println(" -backup:on|off Save updated documents before overwriting");
  906. System.err.println(" -cr:classname Use specified CollectionURIResolver class");
  907. System.err.println(" -dtd:on|off Validate using DTD");
  908. System.err.println(" -expand:on|off Expand defaults defined in schema/DTD");
  909. System.err.println(" -explain[:filename] Display compiled expression tree");
  910. System.err.println(" -ext:[on|off] Allow|Disallow external Java functions");
  911. System.err.println(" -l:on|off Line numbering for source document");
  912. System.err.println(" -mr:classname Use specified ModuleURIResolver class");
  913. System.err.println(" -o:filename Send output to named file");
  914. System.err.println(" -outval:recover|fatal Handling of validation errors on result document");
  915. System.err.println(" -p Recognize Saxon file extensions and query parameters");
  916. System.err.println(" -pipe:push|pull Execute internally in push or pull mode");
  917. System.err.println(" -projection:[on|off] Use|Don't use source document projection");
  918. System.err.println(" -q:filename Query file name");
  919. System.err.println(" -qs:string Query string (usually in quotes)");
  920. System.err.println(" -r:classname Use URIResolver class");
  921. System.err.println(" -repeat:N Repeat N times for performance measurement");
  922. System.err.println(" -s:file|URI Provide initial context document");
  923. System.err.println(" -sa Schema-aware query (requires Saxon-SA)");
  924. System.err.println(" -strip:all|none|ignorable Strip whitespace text nodes");
  925. System.err.println(" -t Display version and timing information");
  926. System.err.println(" -traceout:file|#null Destination for fn:trace() output");
  927. System.err.println(" -tree:tiny|linked Select tree model");
  928. System.err.println(" -T[:classname] Use TraceListener class");
  929. System.err.println(" -TJ Trace calls to external Java functions");
  930. System.err.println(" -u Names are URLs not filenames");
  931. System.err.println(" -update:on|off|discard Enable|Disable XQuery Update (needs Saxon-SA)");
  932. System.err.println(" -val:strict|lax Validate using schema");
  933. System.err.println(" -wrap:on|off Wrap result sequence in XML elements");
  934. System.err.println(" -x:classname Parser (XMLReader) used for source files");
  935. System.err.println(" -xi:on|off Expand XInclude on all documents");
  936. System.err.println(" -xmlversion:1.0|1.1 Version of XML to be handled");
  937. System.err.println(" -xsd:file;file.. Additional schema documents to be loaded");
  938. System.err.println(" -xsdlversion:1.0|1.1 Version of XML Schema to be used");
  939. System.err.println(" -xsiloc:on|off Take note of xsi:schemaLocation");
  940. System.err.println(" -? Display this message ");
  941. System.err.println(" param=value Set query string parameter");
  942. System.err.println(" +param=value Set query document parameter");
  943. System.err.println(" !option=value Set serialization option");
  944. if ("".equals(message)) {
  945. System.exit(0);
  946. } else {
  947. System.exit(2);
  948. }
  949. }
  950. }
  951. //
  952. // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
  953. // you may not use this file except in compliance with the License. You may obtain a copy of the
  954. // License at http://www.mozilla.org/MPL/
  955. //
  956. // Software distributed under the License is distributed on an "AS IS" basis,
  957. // WITHOUT WARRANTY OF ANY KIND, either express or implied.
  958. // See the License for the specific language governing rights and limitations under the License.
  959. //
  960. // The Original Code is: all this file.
  961. //
  962. // The Initial Developer of the Original Code is Michael H. Kay.
  963. //
  964. // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
  965. //
  966. // Contributor(s): changes to allow source and/or stylesheet from stdin contributed by
  967. // Gunther Schadow [gunther@aurora.regenstrief.org]
  968. //