1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 package groovy.ui;
47
48 import groovy.lang.GroovyShell;
49 import groovy.lang.MetaClass;
50 import groovy.lang.Script;
51
52 import java.io.BufferedReader;
53 import java.io.File;
54 import java.io.FileNotFoundException;
55 import java.io.FileReader;
56 import java.io.FileWriter;
57 import java.io.IOException;
58 import java.io.InputStreamReader;
59 import java.io.PrintWriter;
60 import java.util.Iterator;
61 import java.util.List;
62
63 import org.apache.commons.cli.CommandLine;
64 import org.apache.commons.cli.CommandLineParser;
65 import org.apache.commons.cli.HelpFormatter;
66 import org.apache.commons.cli.OptionBuilder;
67 import org.apache.commons.cli.Options;
68 import org.apache.commons.cli.ParseException;
69 import org.apache.commons.cli.PosixParser;
70 import org.apache.commons.cli.Option;
71 import org.codehaus.groovy.control.CompilationFailedException;
72 import org.codehaus.groovy.control.CompilerConfiguration;
73 import org.codehaus.groovy.runtime.InvokerHelper;
74
75 /***
76 * A Command line to execute groovy.
77 *
78 * @author Jeremy Rayner
79 * @author Yuri Schimke
80 * @version $Revision: 1.9 $
81 */
82 public class GroovyMain {
83
84 private List args;
85
86
87 private boolean isScriptFile;
88
89
90 private String script;
91
92
93 private boolean processFiles;
94
95
96 private boolean editFiles;
97
98
99 private boolean autoOutput;
100
101
102 private boolean processSockets;
103
104
105 private int port;
106
107
108 private String backupExtension;
109
110
111 private CompilerConfiguration conf = new CompilerConfiguration();
112
113 /***
114 * Main CLI interface.
115 *
116 * @param args
117 * all command line args.
118 */
119 public static void main(String args[]) {
120 MetaClass.setUseReflection(true);
121
122 Options options = buildOptions();
123
124 try {
125 CommandLine cmd = parseCommandLine(options, args);
126
127 if (cmd.hasOption('h')) {
128 HelpFormatter formatter = new HelpFormatter();
129 formatter.printHelp("groovy", options);
130 }
131 else if (cmd.hasOption('v')) {
132 String version = InvokerHelper.getVersion();
133 System.out.println("Groovy Version: " + version + " JVM: " + System.getProperty("java.vm.version"));
134 }
135 else {
136 process(cmd);
137 }
138 }
139 catch (ParseException pe) {
140 System.out.println("error: " + pe.getMessage());
141 HelpFormatter formatter = new HelpFormatter();
142 formatter.printHelp("groovy", options);
143 }
144 }
145
146 /***
147 * Parse the command line.
148 *
149 * @param options
150 * the options parser.
151 * @param args
152 * the command line args.
153 * @return parsed command line.
154 * @throws ParseException
155 * if there was a problem.
156 */
157 private static CommandLine parseCommandLine(Options options, String[] args) throws ParseException {
158 CommandLineParser parser = new PosixParser();
159 CommandLine cmd = parser.parse(options, args, true);
160 return cmd;
161 }
162
163 /***
164 * Build the options parser.
165 *
166 * @return an options parser.
167 */
168 private static Options buildOptions() {
169 Options options = new Options();
170
171 options.addOption(OptionBuilder.hasArg(false).withDescription("usage information").withLongOpt("help").create('h'));
172
173 options.addOption(OptionBuilder.hasArg(false).withDescription("display the Groovy and JVM versions").withLongOpt("version").create('v'));
174
175 options.addOption(OptionBuilder.withArgName("charset").hasArg().withDescription("specify the encoding of the files").withLongOpt("encoding").create('c'));
176
177 options.addOption(OptionBuilder.withArgName("script").hasArg().withDescription("specify a command line script").create('e'));
178
179 options.addOption(OptionBuilder.withArgName("extension").hasOptionalArg().withDescription("modify files in place").create('i'));
180
181 options.addOption(OptionBuilder.hasArg(false).withDescription("process files line by line").create('n'));
182
183 options.addOption(OptionBuilder.hasArg(false).withDescription("process files line by line and print result").create('p'));
184
185 options.addOption(OptionBuilder.withArgName("port").hasOptionalArg().withDescription("listen on a port and process inbound lines").create('l'));
186 return options;
187 }
188
189 /***
190 * Process the users request.
191 *
192 * @param line
193 * the parsed command line.
194 * @throws ParseException
195 * if invalid options are chosen
196 */
197 private static void process(CommandLine line) throws ParseException {
198 GroovyMain main = new GroovyMain();
199
200 List args = line.getArgList();
201
202
203 if (line.hasOption('c')) {
204 main.conf.setSourceEncoding(line.getOptionValue("encoding"));
205 }
206
207 main.isScriptFile = !line.hasOption('e');
208 main.processFiles = line.hasOption('p') || line.hasOption('n');
209 main.autoOutput = line.hasOption('p');
210 main.editFiles = line.hasOption('i');
211 if (main.editFiles) {
212 main.backupExtension = line.getOptionValue('i');
213 }
214
215 if (main.isScriptFile) {
216 if (args.isEmpty())
217 throw new ParseException("neither -e or filename provided");
218
219 main.script = (String) args.remove(0);
220 if (main.script.endsWith(".java"))
221 throw new ParseException("error: cannot compile file with .java extension: " + main.script);
222 }
223 else {
224 main.script = line.getOptionValue('e');
225 }
226
227 main.processSockets = line.hasOption('l');
228 if (main.processSockets) {
229 String p = line.getOptionValue('l',"1960");
230 main.port = new Integer(p).intValue();
231 }
232 main.args = args;
233
234 main.run();
235 }
236
237 public GroovyMain() {
238 }
239
240 /***
241 * Run the script.
242 */
243 private void run() {
244 try {
245 if (processSockets) {
246 processSockets();
247 } else if (processFiles) {
248 processFiles();
249 }
250 else {
251 processOnce();
252 }
253 }
254 catch (Exception e) {
255 System.out.println("Caught: " + e);
256 e.printStackTrace();
257 }
258 }
259
260 /***
261 * Process Sockets.
262 */
263 private void processSockets() throws CompilationFailedException, IOException {
264 GroovyShell groovy = new GroovyShell(conf);
265 Script s;
266 if (isScriptFile) {
267 s = groovy.parse(new File(script));
268 } else {
269 s = groovy.parse(script, "main");
270 }
271 new GroovySocketServer(groovy,isScriptFile,script,autoOutput,port);
272 }
273
274 /***
275 * Process the input files.
276 */
277 private void processFiles() throws CompilationFailedException, IOException {
278 GroovyShell groovy = new GroovyShell(conf);
279
280 Script s = null;
281
282 if (isScriptFile)
283 s = groovy.parse(new File(script));
284 else
285 s = groovy.parse(script, "main");
286
287 if (args.isEmpty()) {
288 BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
289 PrintWriter writer = new PrintWriter(System.out);
290
291 processReader(s, reader, writer);
292 }
293 else {
294 Iterator i = args.iterator();
295 while (i.hasNext()) {
296 String filename = (String) i.next();
297 File file = new File(filename);
298 processFile(s, file);
299 }
300 }
301 }
302
303 /***
304 * Process a single input file.
305 *
306 * @param s
307 * the script to execute.
308 * @param file
309 * the input file.
310 */
311 private void processFile(Script s, File file) throws IOException {
312 if (!file.exists())
313 throw new FileNotFoundException(file.getName());
314
315 if (!editFiles) {
316 BufferedReader reader = new BufferedReader(new FileReader(file));
317 try {
318 PrintWriter writer = new PrintWriter(System.out);
319 processReader(s, reader, writer);
320 writer.flush();
321 }
322 finally {
323 reader.close();
324 }
325 }
326 else {
327 File backup = null;
328 if (backupExtension == null) {
329 backup = File.createTempFile("groovy_", ".tmp");
330 backup.deleteOnExit();
331 }
332 else {
333 backup = new File(file.getPath() + backupExtension);
334 backup.delete();
335 }
336 if (!file.renameTo(backup))
337 throw new IOException("unable to rename " + file + " to " + backup);
338
339 BufferedReader reader = new BufferedReader(new FileReader(backup));
340 try {
341 PrintWriter writer = new PrintWriter(new FileWriter(file));
342 try {
343 processReader(s, reader, writer);
344 }
345 finally {
346 writer.close();
347 }
348 }
349 finally {
350 reader.close();
351 }
352 }
353 }
354
355 /***
356 * Process a script against a single input file.
357 *
358 * @param s
359 * script to execute.
360 * @param reader
361 * input file.
362 * @param pw
363 * output sink.
364 */
365 private void processReader(Script s, BufferedReader reader, PrintWriter pw) throws IOException {
366 String line = null;
367 s.setProperty("out", pw);
368 while ((line = reader.readLine()) != null) {
369 s.setProperty("line", line);
370 Object o = s.run();
371
372 if (autoOutput) {
373 pw.println(o);
374 }
375 }
376 }
377
378 /***
379 * Process the standard, single script with args.
380 */
381 private void processOnce() throws CompilationFailedException, IOException {
382 GroovyShell groovy = new GroovyShell(conf);
383
384 if (isScriptFile)
385 groovy.run(new File(script), args);
386 else
387 groovy.run(script, "main", args);
388 }
389 }