KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > Query


1 package net.sf.saxon;
2 import net.sf.saxon.event.Builder;
3 import net.sf.saxon.event.SaxonOutputKeys;
4 import net.sf.saxon.instruct.TerminationException;
5 import net.sf.saxon.om.DocumentInfo;
6 import net.sf.saxon.om.SequenceIterator;
7 import net.sf.saxon.om.Validation;
8 import net.sf.saxon.query.*;
9 import net.sf.saxon.trace.TraceListener;
10 import net.sf.saxon.trace.XQueryTraceListener;
11 import net.sf.saxon.trans.DynamicError;
12 import net.sf.saxon.trans.XPathException;
13 import net.sf.saxon.value.UntypedAtomicValue;
14 import org.xml.sax.InputSource JavaDoc;
15
16 import javax.xml.transform.Source JavaDoc;
17 import javax.xml.transform.TransformerFactoryConfigurationError JavaDoc;
18 import javax.xml.transform.sax.SAXSource JavaDoc;
19 import javax.xml.transform.stream.StreamResult JavaDoc;
20 import javax.xml.transform.stream.StreamSource JavaDoc;
21 import java.io.*;
22 import java.util.Date JavaDoc;
23 import java.util.Properties JavaDoc;
24
25 /**
26  * This <B>Query</B> class provides a command-line interface to the Saxon XQuery processor.<p>
27  *
28  * The XQuery syntax supported conforms to the W3C XQuery 1.0 drafts.
29  *
30  * @author Michael H. Kay
31  */

32
33 public class Query {
34
35     Configuration config;
36
37    /**
38      * Set the configuration. This is designed to be
39      * overridden in a subclass
40      */

41
42     protected Configuration makeConfiguration() {
43         return new Configuration();
44     }
45
46     /**
47      * Get the configuration in use
48      * @return the configuration
49      */

50
51     protected Configuration getConfiguration() {
52         return config;
53     }
54
55     /**
56      * Main program, can be used directly from the command line.
57      * <p>The format is:</P>
58      * <p>java net.sf.saxon.Query [options] <I>query-file</I> &gt;<I>output-file</I></P>
59      * <p>followed by any number of parameters in the form {keyword=value}... which can be
60      * referenced from within the query.</p>
61      * <p>This program executes the query in query-file.</p>
62      *
63      * @param args List of arguments supplied on operating system command line
64      * @exception Exception Indicates that a compile-time or
65      * run-time error occurred
66      */

67
68     public static void main (String JavaDoc args[])
69         throws Exception JavaDoc
70     {
71         // the real work is delegated to another routine so that it can be used in a subclass
72
(new Query()).doMain(args, "java net.sf.saxon.Query");
73     }
74
75     /**
76      * Support method for main program. This support method can also be invoked from subclasses
77      * that support the same command line interface
78      *
79      * @param args the command-line arguments
80      * @param name name of the class, to be used in error messages
81      */

82
83     protected void doMain(String JavaDoc args[], String JavaDoc name) {
84         config = makeConfiguration();
85         config.setHostLanguage(Configuration.XQUERY);
86         boolean schemaAware = config.isSchemaAware(Configuration.XQUERY);
87         boolean showTime = false;
88         int repeat = 1;
89         StaticQueryContext staticEnv = new StaticQueryContext(config);
90         DynamicQueryContext dynamicEnv = new DynamicQueryContext(config);
91         String JavaDoc sourceFileName = null;
92         String JavaDoc queryFileName = null;
93         File sourceFile;
94         File outputFile;
95         boolean useURLs = false;
96         String JavaDoc outputFileName = null;
97         boolean explain = false;
98         boolean wrap = false;
99         boolean pullMode = false;
100
101         Properties JavaDoc outputProps = new Properties JavaDoc();
102
103         // Check the command-line arguments.
104

105         try {
106             int i = 0;
107             while (i < args.length) {
108
109                 if (args[i].charAt(0)=='-') {
110
111                     if (args[i].equals("-cr")) {
112                         i++;
113                         if (args.length < i+1) badUsage(name, "No output file name");
114                         String JavaDoc crclass = args[i++];
115                         Object JavaDoc resolver = config.getInstance(crclass, null);
116                         if (!(resolver instanceof CollectionURIResolver)) {
117                             quit(crclass + " is not a CollectionURIResolver", 2);
118                         }
119                         config.setCollectionURIResolver((CollectionURIResolver)resolver);
120
121                     }
122
123                     else if (args[i].equals("-ds")) {
124                         config.setTreeModel(Builder.STANDARD_TREE);
125                         i++;
126                     }
127
128                     else if (args[i].equals("-dt")) {
129                         config.setTreeModel(Builder.TINY_TREE);
130                         i++;
131                     }
132
133                     else if (args[i].equals("-e")) {
134                         explain = true;
135                         i++;
136                     }
137
138                     else if (args[i].equals("-l")) {
139                         config.setLineNumbering(true);
140                         i++;
141                     }
142
143                     else if (args[i].equals("-3")) { // undocumented option: do it thrice
144
i++;
145                         repeat = 3;
146                     }
147
148                     else if (args[i].equals("-9")) { // undocumented option: do it nine times
149
i++;
150                         repeat = 9;
151                     }
152
153                     else if (args[i].equals("-mr")) {
154                         i++;
155                         if (args.length < i+1) badUsage(name, "No ModuleURIResolver class");
156                         String JavaDoc r = args[i++];
157                         config.setModuleURIResolver(r);
158                     }
159
160                     else if (args[i].equals("-noext")) {
161                         i++;
162                         config.setAllowExternalFunctions(false);
163                     }
164
165                     else if (args[i].equals("-o")) {
166                         i++;
167                         if (args.length < i+1) badUsage(name, "No output file name");
168                         outputFileName = args[i++];
169                     }
170
171                     else if (args[i].equals("-p")) {
172                         i++;
173                         setPOption(config);
174                         useURLs = true;
175                     }
176
177                     else if (args[i].equals("-pull")) {
178                         i++;
179                         pullMode = true;
180                     }
181
182                     else if (args[i].equals("-r")) {
183                         i++;
184                         if (args.length < i+1) badUsage(name, "No URIResolver class");
185                         String JavaDoc r = args[i++];
186                         config.setURIResolver(config.makeURIResolver(r));
187                         dynamicEnv.setURIResolver(config.makeURIResolver(r));
188                     }
189
190                     else if (args[i].equals("-s")) {
191                         i++;
192                         if (args.length < i+1) badUsage(name, "No source file name");
193                         sourceFileName = args[i++];
194                     }
195
196                     else if (args[i].equals("-strip")) {
197                         config.setStripsAllWhiteSpace(true);
198                         i++;
199                     }
200
201                     else if (args[i].equals("-t")) {
202                         System.err.println(config.getProductTitle());
203                         System.err.println("Java version " + System.getProperty("java.version"));
204                         config.setTiming(true);
205                         showTime = true;
206                         i++;
207                     }
208
209                     else if (args[i].equals("-T")) {
210                         config.setTraceListener(new XQueryTraceListener());
211                         i++;
212                     }
213
214                     else if (args[i].equals("-TJ")) {
215                         i++;
216                         config.setTraceExternalFunctions(true);
217                     }
218
219                     else if (args[i].equals("-TL")) {
220                         if (args.length < i+2) badUsage(name, "No TraceListener class specified");
221                         TraceListener traceListener = config.makeTraceListener(args[++i]);
222                         config.setTraceListener(traceListener);
223                         config.setLineNumbering(true);
224                         i++;
225                     }
226
227                     else if (args[i].equals("-u")) {
228                         useURLs = true;
229                         i++;
230                     }
231
232                     else if (args[i].equals("-val")) {
233                         if (schemaAware) {
234                             config.setSchemaValidationMode(Validation.STRICT);
235                         } else {
236                             quit("The -val option requires a schema-aware processor", 2);
237                         }
238                         i++;
239                     }
240
241                     else if (args[i].equals("-vlax")) {
242                         if (schemaAware) {
243                             config.setSchemaValidationMode(Validation.LAX);
244                         } else {
245                             quit("The -vlax option requires a schema-aware processor", 2);
246                         }
247                         i++;
248                     }
249
250                     else if (args[i].equals("-vw")) {
251                         if (schemaAware) {
252                             config.setValidationWarnings(true);
253                         } else {
254                             quit("The -vw option requires a schema-aware processor", 2);
255                         }
256                         i++;
257                     }
258
259                     else if (args[i].equals("-wrap")) {
260                         wrap = true;
261                         i++;
262                     }
263
264                     else if (args[i].equals("-?")) {
265                         badUsage(name, "");
266                     }
267
268                     else if (args[i].equals("-")) {
269                         queryFileName = "-";
270                         i++;
271                     }
272
273                     else badUsage(name, "Unknown option " + args[i]);
274                 }
275
276                 else break;
277             }
278
279             if (!("-".equals(queryFileName))) {
280                 if (args.length < i+1) {
281                     badUsage(name, "No query file name");
282                 }
283                 queryFileName = args[i++];
284             }
285
286             for (int p=i; p<args.length; p++) {
287                 String JavaDoc arg = args[p];
288                 int eq = arg.indexOf("=");
289                 if (eq<1 || eq>=arg.length()-1) {
290                     badUsage(name, "Bad param=value pair on command line: " + arg);
291                 }
292                 String JavaDoc argname = arg.substring(0,eq);
293                 if (argname.startsWith("!")) {
294                     // parameters starting with "!" are taken as output properties
295
outputProps.setProperty(argname.substring(1), arg.substring(eq+1));
296                 } else if (argname.startsWith("+")) {
297                     // parameters starting with "+" are taken as input documents
298
Object JavaDoc sources = Transform.loadDocuments(arg.substring(eq+1), useURLs, config, true);
299                     dynamicEnv.setParameter(argname.substring(1), sources);
300                 } else {
301                     dynamicEnv.setParameter(argname, new UntypedAtomicValue(arg.substring(eq+1)));
302                 }
303             }
304
305             config.displayLicenseMessage();
306             if (pullMode) {
307                 config.setLazyConstructionMode(true);
308             }
309
310             Source JavaDoc sourceInput = null;
311
312             if (sourceFileName != null) {
313                 if (useURLs || sourceFileName.startsWith("http:") || sourceFileName.startsWith("file:")) {
314                     sourceInput = config.getURIResolver().resolve(sourceFileName, null);
315                     if (sourceInput == null) {
316                         sourceInput = config.getSystemURIResolver().resolve(sourceFileName, null);
317                     }
318                 } else if (sourceFileName.equals("-")) {
319                     // take input from stdin
320
sourceInput = new SAXSource JavaDoc(new InputSource JavaDoc(System.in));
321                 } else {
322                     sourceFile = new File(sourceFileName);
323                     if (!sourceFile.exists()) {
324                         quit("Source file " + sourceFile + " does not exist", 2);
325                     }
326
327                     InputSource JavaDoc eis = new InputSource JavaDoc(sourceFile.toURI().toString());
328                     sourceInput = new SAXSource JavaDoc(eis);
329                 }
330             }
331
332             long startTime = (new Date JavaDoc()).getTime();
333             if (showTime) {
334                 System.err.println("Compiling query from " + queryFileName);
335             }
336
337             XQueryExpression exp;
338
339             try {
340                 if (queryFileName.equals("-")) {
341                     Reader queryReader = new InputStreamReader(System.in);
342                     exp = staticEnv.compileQuery(queryReader);
343                 } else if (queryFileName.startsWith("{") && queryFileName.endsWith("}")) {
344                     // query is inline on the command line
345
String JavaDoc q = queryFileName.substring(1, queryFileName.length()-1);
346                     exp = staticEnv.compileQuery(q);
347                 } else if (useURLs || queryFileName.startsWith("http:") || queryFileName.startsWith("file:")) {
348                     ModuleURIResolver resolver = config.getModuleURIResolver();
349                     String JavaDoc[] locations = {queryFileName};
350                     StreamSource JavaDoc[] sources = resolver.resolve(null, null, locations);
351                     if (sources.length != 1) {
352                         quit("Module URI Resolver must return a single StreamSource", 2);
353                     }
354                     String JavaDoc queryText = QueryReader.readSourceQuery(sources[0]);
355                     exp = staticEnv.compileQuery(queryText);
356                 } else {
357                     InputStream queryStream = new FileInputStream(queryFileName);
358                     staticEnv.setBaseURI(new File(queryFileName).toURI().toString());
359                     exp = staticEnv.compileQuery(queryStream, null);
360                 }
361                 staticEnv = exp.getStaticContext(); // the original staticContext is copied
362

363                 if (showTime) {
364                     long endTime = (new Date JavaDoc()).getTime();
365                     System.err.println("Compilation time: " + (endTime-startTime) + " milliseconds");
366                     startTime = endTime;
367                 }
368
369             } catch (XPathException err) {
370                 int line = -1;
371                 String JavaDoc module = null;
372                 if (err.getLocator() != null) {
373                     line = err.getLocator().getLineNumber();
374                     module = err.getLocator().getSystemId();
375                 }
376                 if (err.hasBeenReported()) {
377                     quit("Failed to compile query", 2);
378                 } else {
379                     if (line == -1) {
380                         System.err.println("Failed to compile query: " + err.getMessage());
381                     } else {
382                         System.err.println("Static error at line " + line + " of " + module + ':');
383                         System.err.println(err.getMessage());
384                     }
385                 }
386                 exp = null;
387                 System.exit(2);
388             }
389
390             if (explain) {
391                 staticEnv.explainGlobalVariables();
392                 staticEnv.explainGlobalFunctions();
393                 exp.explain(staticEnv.getNamePool());
394             }
395
396             OutputStream destination;
397             if (outputFileName != null) {
398                 outputFile = new File(outputFileName);
399                 if (outputFile.isDirectory()) {
400                         quit("Output is a directory", 2);
401                 }
402                 destination = new FileOutputStream(outputFile);
403             } else {
404                 destination = System.out;
405             }
406
407             for (int r=0; r<repeat; r++) { // repeat is for internal testing/timing
408

409                 if (sourceInput != null) {
410                     if (showTime) {
411                         System.err.println("Processing " + sourceInput.getSystemId());
412                     }
413                     DocumentInfo doc = staticEnv.buildDocument(sourceInput);
414                     dynamicEnv.setContextNode(doc);
415                 }
416
417                 try {
418                     if (wrap) {
419                         SequenceIterator results = exp.iterator(dynamicEnv);
420                         DocumentInfo resultDoc = QueryResult.wrap(results, config);
421                         QueryResult.serialize(resultDoc,
422                                 new StreamResult JavaDoc(destination),
423                                 outputProps,
424                                 config);
425                         destination.close();
426                     } else if (pullMode) {
427                         if (wrap) {
428                             outputProps.setProperty(SaxonOutputKeys.WRAP, "yes");
429                         }
430                         try {
431                             exp.pull(dynamicEnv, new StreamResult JavaDoc(destination), outputProps);
432                         } catch (XPathException err) {
433                             if (!err.hasBeenReported()) {
434                                 config.getErrorListener().fatalError(err);
435                             }
436                             throw err;
437                         }
438                     } else {
439                         exp.run(dynamicEnv, new StreamResult JavaDoc(destination), outputProps);
440                     }
441                 } catch (TerminationException err) {
442                     throw err;
443                 } catch (XPathException err) {
444                     if (err.hasBeenReported()) {
445                         throw new DynamicError("Run-time errors were reported");
446                     } else {
447                         throw err;
448                     }
449                 }
450
451                 if (showTime) {
452                     long endTime = (new Date JavaDoc()).getTime();
453                     System.err.println("Execution time: " + (endTime-startTime) + " milliseconds");
454                     startTime = endTime;
455                 }
456             }
457
458         } catch (TerminationException err) {
459             quit(err.getMessage(), 1);
460         } catch (XPathException err) {
461             quit("Query processing failed: " + err.getMessage(), 2);
462         } catch (TransformerFactoryConfigurationError JavaDoc err) {
463             err.printStackTrace();
464             quit("Query processing failed", 2);
465         } catch (Exception JavaDoc err2) {
466             err2.printStackTrace();
467             quit("Fatal error during transformation: " + err2.getMessage(), 2);
468         }
469     }
470
471     /**
472      * Exit with a message
473      *
474      * @param message The message to be output
475      * @param code The result code to be returned to the operating
476      * system shell
477      */

478
479     protected static void quit(String JavaDoc message, int code) {
480         System.err.println(message);
481         System.exit(code);
482     }
483
484     public void setPOption(Configuration config) {
485         config.getSystemURIResolver().setRecognizeQueryParameters(true);
486     }
487
488     /**
489      * Report incorrect usage of the command line, with a list of the options and arguments that are available
490      *
491      * @param name The name of the command being executed (allows subclassing)
492      * @param message The error message
493      */

494     protected void badUsage(String JavaDoc name, String JavaDoc message) {
495         if (!"".equals(message)) {
496             System.err.println(message);
497         }
498         System.err.println(config.getProductTitle());
499         System.err.println("Usage: " + name + " [options] query {param=value}...");
500         System.err.println("Options: ");
501         System.err.println(" -cr classname Use specified CollectionURIResolver class");
502         System.err.println(" -ds Use standard tree data structure");
503         System.err.println(" -dt Use tinytree data structure (default)");
504         System.err.println(" -e Explain optimized query expression");
505         System.err.println(" -mr classname Use specified ModuleURIResolver class");
506         System.err.println(" -noext Disallow calls to Java methods");
507         System.err.println(" -o filename Send output to named file");
508         if (config.isSchemaAware(Configuration.XSLT)) {
509             System.err.println(" -p Recognize Saxon file extensions and query parameters");
510         }
511         System.err.println(" -pull Run query in pull mode");
512         System.err.println(" -r classname Use specified URIResolver class");
513         System.err.println(" -s file|URI Provide initial context document");
514         System.err.println(" -strip Strip whitespace text nodes");
515         System.err.println(" -t Display version and timing information");
516         System.err.println(" -T Trace query execution");
517         System.err.println(" -TJ Trace calls to external Java functions");
518         System.err.println(" -TL classname Trace query execution to user-defined trace listener");
519         System.err.println(" -u Names are URLs not filenames");
520         if (config.isSchemaAware(Configuration.XQUERY)) {
521             System.err.println(" -val Validate source documents using schema");
522             System.err.println(" -vlax Lax validation of source documents using schema");
523             System.err.println(" -vw Treat validation errors on result document as warnings");
524         }
525         System.err.println(" -wrap Wrap result sequence in XML elements");
526         System.err.println(" -? Display this message ");
527         System.err.println(" param=value Set stylesheet string parameter");
528         System.err.println(" +param=value Set stylesheet document parameter");
529         System.err.println(" !option=value Set serialization option");
530         if ("".equals(message)) {
531             System.exit(0);
532         } else {
533             System.exit(2);
534         }
535     }
536
537 }
538
539 //
540
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
541
// you may not use this file except in compliance with the License. You may obtain a copy of the
542
// License at http://www.mozilla.org/MPL/
543
//
544
// Software distributed under the License is distributed on an "AS IS" basis,
545
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
546
// See the License for the specific language governing rights and limitations under the License.
547
//
548
// The Original Code is: all this file.
549
//
550
// The Initial Developer of the Original Code is Michael H. Kay.
551
//
552
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
553
//
554
// Contributor(s): changes to allow source and/or stylesheet from stdin contributed by
555
// Gunther Schadow [gunther@aurora.regenstrief.org]
556
//
557
Popular Tags