View Javadoc

1   package net.sf.tomp.xtcl;
2   
3   import org.apache.commons.cli.CommandLine;
4   import org.apache.commons.cli.HelpFormatter;
5   import org.apache.commons.cli.Option;
6   import org.apache.commons.cli.OptionBuilder;
7   import org.apache.commons.cli.Options;
8   import org.apache.commons.cli.PosixParser;
9   
10  import java.io.File;
11  import java.io.PrintWriter;
12  
13  /***
14   * Main XTCL entry point, allows execution of XTCL script from files or
15   * interactively command-by-command from comman line. <br/>
16   * 
17   * Usage examples: <br/>
18   * 
19   * Execution of the script file specified by option <tt>-f</tt> filename <br/>
20   * 
21   * <pre>java net.sf.tomp.xtcl.Main -q -f demo\echo.xcf</pre>
22   * 
23   * gives just <br/>
24   * 
25   * <pre>Echo!</pre>
26   * 
27   * The same in default verbose (non-quiet) mode: <br/>
28   * 
29   * <pre>java net.sf.tomp.xtcl.Main -f demo\echo.xcf</pre>
30   * 
31   * gives <br/>
32   * 
33   * <pre>XTCL - program from file 'demo\echo.xcf'
34  0.0: Echo!
35  OK ECHO Echo! (0 ms)
36  Execution time: 0 ms.</pre>
37   * 
38   * Execution of command specified directly on command line <br/>
39   * 
40   * <pre>java net.sf.tomp.xtcl.Main -q ECHO Hello!</pre>
41   * 
42   * gives <br/>
43   * 
44   * <pre>Hello!</pre>
45   * 
46   * The same in default verbose (non-quiet) mode: <br/>
47   * 
48   * <pre>java net.sf.tomp.xtcl.Main ECHO Hello!</pre>
49   * 
50   * gives <br/>
51   * 
52   * <pre>XTCL - command read from command line:
53  Hello!
54  OK ECHO Hello!Execution time: 0 ms.</pre>
55   * 
56   * Options -f and commands directly on command line may be combined. Example:
57   * <br/>First, execute the script <tt>demo\echo.xcf</tt> then the command
58   * <tt>ECHO Hello!</tt>.<br/>
59   * If <tt>-F</tt> is specified, the script
60   * file is executed after the command on the command line. <br/>
61   * 
62   * <pre>java net.sf.tomp.xtcl.Main -q -f demo\echo.xcf ECHO Hello!</pre>
63   * 
64   * gives <br/>
65   * 
66   * <pre>Echo!
67  Hello!</pre>
68   * 
69   * while <br/>
70   * 
71   * <pre>java net.sf.tomp.xtcl.Main -q -F demo\echo.xcf ECHO Hello!</pre>
72   * 
73   * gives <br/>
74   * 
75   * <pre>Hello!
76  Echo!</pre>
77   * 
78   * The two parameters -f and -F can even be combined:<br/>
79   * 
80   * <pre>java net.sf.tomp.xtcl.Main -q -f demo\echo.xcf -F demo\echo.xcf ECHO Hello!</pre>
81   * 
82   * gives <br/>
83   * 
84   * <pre>Echo!
85  Hello!
86  Echo!</pre>
87   * 
88   * Interactive mode: commands are entered to System.in and immediatelly executed
89   * until END is entered. <br/>
90   * 
91   * <pre>java net.sf.tomp.xtcl.Main -i -q</pre>
92   * 
93   * Interactive work may look like: <br/>
94   * 
95   * <pre>
96  XTCL 0&gt;echo gujh
97  gujh
98  
99  XTCL 1&gt;end</pre>
100  * 
101  * @author tomp
102  * @version 2004-07-29
103  */
104 public class Main {
105     /***
106      * Main XTCL entry point, allows execution of XTCL script from files or
107      * interactively command-by-command from command line.
108      * 
109      * @param args
110      *            the command line arguments
111      * @throws Exception
112      *             if execution fails
113      */
114     public static void main(String[] args) throws Exception {
115         // Create Context w/System.err as the error output
116         Context context = new Context();
117 
118         context.setOut(System.err);
119 
120         // Get its Compiler
121         Compiler comp = context.getCompiler();
122 
123         Command cs = null;
124 
125         // puts the System.out as standard $out variable
126         context.put("$out", System.out);
127 
128         int returnCode = 0;
129 
130         OptionBuilder.hasArgs(1);
131         OptionBuilder.withLongOpt("script");
132         OptionBuilder.withDescription("run the specified script");
133         OptionBuilder.withArgName("scripttext");
134 
135         Option oScript = OptionBuilder.create('s');
136 
137         OptionBuilder.hasArgs(1);
138         OptionBuilder.withLongOpt("script-after");
139         OptionBuilder.withDescription("run the specified script after the command on command line");
140         OptionBuilder.withArgName("scripttext");
141 
142         Option oAfterScript = OptionBuilder.create('S');
143 
144         OptionBuilder.hasArgs(1);
145         OptionBuilder.withLongOpt("script-file");
146         OptionBuilder.withDescription("run the specified script file");
147         OptionBuilder.withArgName("scriptfile");
148 
149         Option oFile = OptionBuilder.create('f');
150 
151         OptionBuilder.hasArgs(1);
152         OptionBuilder.withLongOpt("script-file-after");
153         OptionBuilder
154                 .withDescription("run the specified script file after the command on command line");
155         OptionBuilder.withArgName("scriptfile");
156 
157         Option oAfterFile = OptionBuilder.create('F');
158 
159         OptionBuilder.hasArgs(1);
160         OptionBuilder.withLongOpt("uri-resolver");
161         OptionBuilder.withDescription("use the specified URIResolver");
162         OptionBuilder.withArgName("URIResolver_classname");
163 
164         Option oUR = OptionBuilder.create('u');
165 
166         OptionBuilder.hasArgs(1);
167         OptionBuilder.withLongOpt("resolving-reader");
168         OptionBuilder.withDescription("use the specified resolving XMLReader");
169         OptionBuilder.withArgName("ResolvingXMLReader_classname");
170 
171         Option oRR = OptionBuilder.create('r');
172 
173         OptionBuilder.withLongOpt("ignore-errors");
174         OptionBuilder.withDescription("ignore errors and continue processing");
175 
176         Option oIgnore = OptionBuilder.create('g');
177 
178         OptionBuilder.withLongOpt("quiet");
179         OptionBuilder.withDescription("provide no info on processing");
180 
181         Option oVerb = OptionBuilder.create('q');
182 
183         OptionBuilder.withLongOpt("verbose");
184         OptionBuilder.withDescription("provide extra rich info on processing");
185 
186         Option oExtraVerb = OptionBuilder.create('v');
187 
188         OptionBuilder.withLongOpt("interactive");
189         OptionBuilder
190                 .withDescription("enter interactive mode, 'END' finishes execution");
191 
192         Option oInt = OptionBuilder.create('i');
193 
194         OptionBuilder.withLongOpt("usage");
195         OptionBuilder.withDescription("print just usage (not whole help)");
196 
197         Option oHelp = OptionBuilder.create('h');
198 
199         Options opts = new Options();
200 
201         opts.addOption(oScript);
202         opts.addOption(oAfterScript);
203         opts.addOption(oFile);
204         opts.addOption(oAfterFile);
205         opts.addOption(oUR);
206         opts.addOption(oRR);
207         opts.addOption(oIgnore);
208         opts.addOption(oVerb);
209         opts.addOption(oExtraVerb);
210         opts.addOption(oInt);
211         opts.addOption(oHelp);
212 
213         CommandLine cl = new PosixParser().parse(opts, args);
214 
215         context.setVerbose(!cl.hasOption('q'));
216         
217         boolean breakOnError = true;
218 
219         // no args - commands will be entered to the stdin
220         if (args.length == 0) {
221             // no args, print usage/help
222             PrintWriter pw = new PrintWriter(System.out);
223             //            new HelpFormatter().printUsage(pw, 80, "java
224             // net.sf.tomp.xtcl.Main", opts);
225             new HelpFormatter()
226                     .printHelp(
227                             pw,
228                             80,
229                             "java net.sf.tomp.xtcl.Main",
230                             "\nXTCL - simple XML Transformations Shell, http://tomp.sf.net",
231                             opts, 10, 25,
232                             "Copyright (c) 2003-2004 Tomas Pitner", true);
233             pw.flush();
234 
235         } else {
236             // set options
237             if (cl.hasOption('h')) {
238                 PrintWriter pw = new PrintWriter(System.out);
239                 //            new HelpFormatter().printUsage(pw, 80, "java
240                 // net.sf.tomp.xtcl.Main", opts);
241                 new HelpFormatter().printUsage(pw, 80,
242                         "java net.sf.tomp.xtcl.Main", opts);
243                 pw.flush();
244             }
245             if (cl.hasOption('u')) {
246                 Context.setUriResolverClass(Class.forName(cl
247                         .getOptionValue('u')));
248                 if (comp.getContext().isVerbose()) {
249                     System.out.println("Use UriResolverClass="
250                             + cl.getOptionValue('u'));
251                 }
252             }
253             if (cl.hasOption('r')) {
254                 Context.setResolvingXMLReaderClass(Class.forName(cl
255                         .getOptionValue('r')));
256                 if (context.isVerbose()) {
257                     System.out.println("Use ResolvingXMLReaderClass="
258                             + cl.getOptionValue('r'));
259                 }
260             }
261             if (cl.hasOption('g')) {
262                 breakOnError = false;
263                 if (comp.getContext().isVerbose()) {
264                     System.out.println("Ignore errors");
265                 }
266             }
267             // now distinguish among the run modes
268             // -s script - reads commands from script specified with this option 
269             if (cl.hasOption('s')) {
270                 String s = cl.getOptionValue('s');
271 
272                 if (context.isExtraVerbose()) {
273                     System.out.println("XTCL - program '" + s + "'");
274                 } else if (context.isVerbose()) {
275                     System.out.println("XTCL - program from script on command line");
276                 }
277 
278                 returnCode = execute(context, comp
279                         .compile(s));
280             }
281             // -f reads commands from file
282             if (cl.hasOption('f')) {
283                 File f = new File(cl.getOptionValue('f'));
284 
285                 if (context.isVerbose()) {
286                     System.out.println("XTCL - program from file '" + f + "'");
287                 }
288 
289                 returnCode = execute(context, comp
290                         .compile(new CommandLineReader(f)));
291             }
292             // has some args left? then has a command on CL!
293             if (cl.getArgs().length > 0) {
294                 if (context.isVerbose()) {
295                     System.out
296                             .println("XTCL - command read from command line:");
297                 }
298 
299                 cs = comp.compile(cl.getArgs(), new CommandLineReader());
300                 returnCode = execute(context, cs);
301                 // -i enters interactive mode
302             }
303             // -F also reads commands from file
304             if (cl.hasOption('F')) {
305                 File f = new File(cl.getOptionValue('F'));
306 
307                 if (context.isVerbose()) {
308                     System.out.println("XTCL - program from file '" + f + "'");
309                 }
310 
311                 returnCode = execute(context, comp
312                         .compile(new CommandLineReader(f)));
313             }
314             // -S script - reads commands from script specified with this option 
315             if (cl.hasOption('S')) {
316                 String s = cl.getOptionValue('S');
317 
318                 if (context.isExtraVerbose()) {
319                     System.out.println("XTCL - program '" + s + "'");
320                 } else if (context.isVerbose()) {
321                     System.out.println("XTCL - program from script on command line");
322                 }
323 
324                 returnCode = execute(context, comp
325                         .compile(s));
326             }
327             if (cl.hasOption('i')) {
328                 if (context.isVerbose()) {
329                     System.out
330                             .println("XTCL - interactive mode. Enter the commands (END for quit):");
331                 }
332 
333                 new InteractiveExecutor(context).interactive();
334             }
335         }
336 
337         System.exit(returnCode);
338     }
339 
340     /***
341      * Utility method. It executes a Command in a Context and returns
342      * the result. Also, it measures the execution time.
343      * 
344      * @param context
345      * @param cs
346      * @return return code (0 == OK, otherwise error)
347      * @throws Exception
348      */
349     private static int execute(Context context, Command cs) throws Exception {
350         if (cs == null)
351             return 0;
352         long start = System.currentTimeMillis();
353 
354         int returnCode = context.execute(cs);
355 
356         long end = System.currentTimeMillis();
357 
358         if (context.isVerbose()) {
359             System.out.println("Execution time: " + (end - start) + " ms.");
360         }
361         if (returnCode != 0)
362             System.exit(returnCode);
363         return returnCode;
364     }
365 }
366 
367 /*
368  * The contents of this file are subject to the Mozilla Public License Version
369  * 1.1 (the "License"); you may not use this file except in compliance with the
370  * License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
371  * Software distributed under the License is distributed on an "AS IS" basis,
372  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
373  * the specific language governing rights and limitations under the License. The
374  * Original Code is: all this file. The Initial Developer of the Original Code
375  * is: Tomas Pitner, Masaryk University in Brno, Czech Republic. Contributor(s):
376  */