1 /***
2 * Copyright 2004 Steven Caswell
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package com.mungoknotwise.sqlcli;
17
18 import java.io.BufferedInputStream;
19 import java.io.BufferedOutputStream;
20 import java.io.BufferedReader;
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.FileNotFoundException;
24 import java.io.FileOutputStream;
25 import java.io.FileReader;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.InputStreamReader;
29 import java.io.PrintStream;
30 import java.io.PrintWriter;
31 import java.sql.Connection;
32 import java.sql.DriverManager;
33 import java.sql.SQLException;
34 import java.util.ArrayList;
35 import java.util.Date;
36 import java.util.HashSet;
37 import java.util.Iterator;
38 import java.util.List;
39 import java.util.Properties;
40 import java.util.Set;
41 import org.apache.commons.cli.BasicParser;
42 import org.apache.commons.cli.CommandLine;
43 import org.apache.commons.cli.CommandLineParser;
44 import org.apache.commons.cli.HelpFormatter;
45 import org.apache.commons.cli.MissingOptionException;
46 import org.apache.commons.cli.OptionBuilder;
47 import org.apache.commons.cli.Options;
48 import org.apache.commons.cli.UnrecognizedOptionException;
49 import org.apache.commons.lang.StringUtils;
50 import org.apache.log4j.Logger;
51
52 /***
53 * Main program for the SqlCli command line interface.
54 *
55 * @author Steven Caswell
56 * @version $Id: SqlCli.java,v 1.5 2004/10/19 19:46:06 mungoknotwise Exp $
57 */
58 public class SqlCli
59 {
60
61
62
63
64
65
66 private static Logger logger = Logger.getLogger(SqlCli.class);
67
68
69
70
71
72 /***
73 * Runs the program with the specified command line arguments.
74 *
75 * @param args the command line arguments
76 * @throws Exception if an error occurs
77 */
78 public static void main(final String[] args) throws Exception
79 {
80 SqlCli sqlCli = new SqlCli();
81 boolean parsed = sqlCli.parseArguments(args);
82 if(parsed)
83 {
84 try
85 {
86 sqlCli.run();
87 }
88 catch(Throwable t)
89 {
90 t.printStackTrace();
91 BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
92 reader.readLine();
93 }
94 }
95 }
96
97
98
99
100
101 private static final int LOGGER_FILE_NAME_INDEX = 3;
102 private static final int WRITE_TO_FILE_NAME_INDEX = 3;
103 private static final int WRITE_TO_FILE_COMMAND_MINIMUM_LENGTH = 3;
104 private static final int PRINT_USAGE_WIDTH = 255;
105 private static final String PROGRAM_NAME = "java " + SqlCli.class.getName();
106
107 private static final int CD_DIRECTIVE_MINIMUM_LENGTH = 3;
108 private static final int CD_COMMAND_MAXIMUM_OFFSET = 3;
109 private static final int PWD_DIRECTIVE_MINIMUM_LENGTH = 4;
110 private static final int PWD_COMMAND_MAXIMUM_OFFSET = 4;
111
112
113
114
115
116 private DescribeCommand describeCommand;
117 private String driverClassName;
118 private boolean inComment;
119 private List lines;
120 private boolean needToClear;
121 private String password;
122 private Properties properties;
123 private String propertiesFileName;
124 private SelectCommand selectCommand;
125 private ShowTablesCommand showTablesCommand;
126 private String url;
127 private UpdateCommand updateCommand;
128 private String username;
129 private Set printStreamed;
130 private File workingDirectory;
131 private PrintStream loggerPrintStream = null;
132
133
134
135
136
137 /***
138 * Constructs a new instance of
139 * <code>SqlCli</code>.
140 */
141 public SqlCli()
142 {
143 this.printStreamed = new HashSet();
144 }
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165 /***
166 * Parses the command line arguments.
167 *
168 * @param args the command line arguments
169 * @return <code>true</code> if processing should continue, <code>false</code>
170 * otherwise
171 * @throws Exception if an error occurs
172 */
173 public boolean parseArguments(final String[] args) throws Exception
174 {
175 Options helpOptions = new Options();
176 Options options = new Options();
177
178 {
179
180 OptionBuilder builder = OptionBuilder.withArgName("driverClassName");
181 builder = builder.hasArg();
182 builder = builder.withDescription("classname of the driver class");
183 builder = builder.isRequired(true);
184 options.addOption(builder.create("d"));
185 }
186
187 {
188
189 OptionBuilder builder = OptionBuilder.withArgName("connectionUrl");
190 builder = builder.hasArg();
191 builder = builder.withDescription("url of the connection");
192 builder = builder.isRequired(true);
193 options.addOption(builder.create("c"));
194 }
195
196 {
197
198 OptionBuilder builder = OptionBuilder.withArgName("propertiesFileName");
199 builder = builder.hasArg();
200 builder = builder.withDescription("name of file containing properties for the connection");
201 builder = builder.isRequired(false);
202 options.addOption(builder.create("f"));
203 }
204
205 {
206
207 OptionBuilder builder = OptionBuilder.withArgName("username");
208 builder = builder.hasArg();
209 builder = builder.withDescription("username for the connection; required if needed by the driver");
210 builder = builder.isRequired(false);
211 options.addOption(builder.create("u"));
212 }
213
214 {
215
216 OptionBuilder builder = OptionBuilder.withArgName("password");
217 builder = builder.hasArg();
218 builder = builder.withDescription("password for the connection; required if needed by the driver");
219 builder = builder.isRequired(false);
220 options.addOption(builder.create("p"));
221 }
222
223 {
224
225 OptionBuilder builder = OptionBuilder.withArgName("help");
226 builder = builder.hasArg(false);
227 builder = builder.withDescription("this help listing");
228 builder = builder.isRequired(false);
229 helpOptions.addOption(builder.create("h"));
230 options.addOption(builder.create("h"));
231 }
232
233 CommandLineParser parser = new BasicParser();
234 CommandLine line = null;
235 try
236 {
237 line = parser.parse(helpOptions, args);
238 }
239 catch(UnrecognizedOptionException e)
240 {
241 ;
242 }
243 if(line != null && line.hasOption("h"))
244 {
245 this.showHelp(options);
246 return false;
247 }
248
249 try
250 {
251 line = parser.parse(options, args);
252 }
253 catch(UnrecognizedOptionException e)
254 {
255 System.out.println(e.getMessage());
256 this.usage(options);
257 return false;
258 }
259 catch(MissingOptionException e)
260 {
261 System.out.println("Missing required option(s): " + e.getMessage());
262 this.usage(options);
263 return false;
264 }
265
266 if(line.hasOption("c"))
267 {
268 this.url = line.getOptionValue("c");
269 }
270 if(line.hasOption("u"))
271 {
272 this.username = line.getOptionValue("u");
273 }
274 if(line.hasOption("p"))
275 {
276 this.password = line.getOptionValue("p");
277 }
278 if(line.hasOption("f"))
279 {
280 this.password = line.getOptionValue("f");
281 }
282 if(line.hasOption("d"))
283 {
284 this.driverClassName = line.getOptionValue("d");
285 }
286 if(logger.isDebugEnabled())
287 {
288 logger.debug("username: " + (this.username == null ? "null" : this.username));
289 logger.debug("password: " + (this.password == null ? "null" : this.password));
290 logger.debug("connection: " + (this.url == null ? "null" : this.url));
291 logger.debug("driver: " + (this.driverClassName == null ? "null" : this.driverClassName));
292 logger.debug("properties: " + (this.propertiesFileName == null ? "null" : this.propertiesFileName));
293 }
294 if(this.propertiesFileName != null)
295 {
296 this.properties = new Properties();
297 InputStream in = new BufferedInputStream(new FileInputStream(this.propertiesFileName));
298 this.properties.load(in);
299 }
300
301 return true;
302 }
303
304 /***
305 * Runs the program logic.
306 *
307 * @throws IOException if an I/O exception occurs
308 * @throws SQLException if an SQL error occurs
309 * @throws ClassNotFoundException if the driver class is not found
310 */
311 public void run() throws IOException, SQLException, ClassNotFoundException
312 {
313 System.out.println("SqlCli v1.0-beta-2");
314 System.out.println("Enter //h for a list of commands");
315 PrintStreamedResultSetExtractor resultSetExtractor = new PrintStreamedResultSetExtractor();
316 resultSetExtractor.addPrintStream(System.out);
317 this.printStreamed.add(resultSetExtractor);
318
319 PrintStreamedExceptionHandler exceptionHandler = new PrintStreamedExceptionHandler();
320 exceptionHandler.addPrintStream(System.out);
321 this.printStreamed.add(exceptionHandler);
322
323 Connection connection = null;
324 connection = this.getConnection();
325
326 this.selectCommand = new SelectCommand();
327 this.selectCommand.setConnection(connection);
328 this.selectCommand.setResultSetExtractor(resultSetExtractor);
329 this.selectCommand.setExceptionHandler(exceptionHandler);
330
331 this.describeCommand = new DescribeCommand();
332 describeCommand.setConnection(connection);
333 PrintStreamedDescribeResultSetExtractor describeResultSetExtractor = new PrintStreamedDescribeResultSetExtractor();
334 this.printStreamed.add(describeResultSetExtractor);
335 describeResultSetExtractor.addPrintStream(System.out);
336 describeCommand.setResultSetExtractor(describeResultSetExtractor);
337 describeCommand.setExceptionHandler(exceptionHandler);
338
339 PrintStreamedUpdateRowcountHandler rowcountHandler = new PrintStreamedUpdateRowcountHandler();
340 rowcountHandler.addPrintStream(System.out);
341 this.printStreamed.add(rowcountHandler);
342 this.updateCommand = new UpdateCommand();
343 this.updateCommand.setConnection(connection);
344 this.updateCommand.setExceptionHandler(exceptionHandler);
345 this.updateCommand.setRowcountHandler(rowcountHandler);
346
347 PrintStreamedShowTablesResultSetExtractor showTableResultSetExtractor = new PrintStreamedShowTablesResultSetExtractor();
348 showTableResultSetExtractor.addPrintStream(System.out);
349 showTableResultSetExtractor.setDatabaseMetaData(connection.getMetaData());
350 this.printStreamed.add(showTableResultSetExtractor);
351 this.showTablesCommand = new ShowTablesCommand();
352 this.showTablesCommand.setConnection(connection);
353 this.showTablesCommand.setExceptionHandler(exceptionHandler);
354 this.showTablesCommand.setResultSetExtractor(showTableResultSetExtractor);
355
356 BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
357
358 this.needToClear = false;
359 this.lines = new ArrayList();
360 this.processInput(reader, lines, true);
361 this.outputToConsoleAndLog("Done");
362 this.closeLogFile();
363 }
364
365
366
367
368
369
370
371
372
373
374
375
376
377 private void processInput(final BufferedReader reader, final List buffer, final boolean prompt)
378 throws IOException
379 {
380 boolean loop = true;
381 this.inComment = false;
382 while(loop)
383 {
384 if(prompt)
385 {
386 System.out.print("SQL> ");
387 }
388 String line = StringUtils.trim(reader.readLine());
389 if(line == null)
390 {
391 break;
392 }
393
394 if(line.length() == 0)
395 {
396 continue;
397 }
398
399 if(this.inComment)
400 {
401
402 if(line.indexOf("*/") == -1)
403 {
404 continue;
405 }
406 }
407
408
409
410
411
412 boolean inQuote = false;
413 char[] lineBuffer = new char[line.length()];
414 int j = 0;
415 for(int i = 0; i < line.length(); i++)
416 {
417 if(line.charAt(i) == '\'')
418 {
419 inQuote = (inQuote ? false : true);
420 }
421 else if(line.startsWith("*/", i) && !inQuote)
422 {
423 this.inComment = false;
424 i += 2;
425 }
426 else if(line.startsWith("/*", i) && !inQuote)
427 {
428 this.inComment = true;
429 i += 2;
430 }
431 if(!inComment && i < line.length())
432 {
433 lineBuffer[j++] = line.charAt(i);
434 }
435 }
436 line = StringUtils.trim(new String(lineBuffer));
437
438 if(line.length() == 0)
439 {
440 continue;
441 }
442
443
444 if(line.indexOf("//") > -1)
445 {
446 line = line.substring(0, line.indexOf("//"));
447 }
448 if(line.indexOf("--") > -1)
449 {
450 line = line.substring(0, line.indexOf("--"));
451 }
452 if(line.length() == 0)
453 {
454 continue;
455 }
456
457 if(line.charAt(0) == '//')
458 {
459 if(line.length() == 1)
460 {
461 this.outputToConsoleAndLog("syntax error: unmatched //");
462 }
463 else if(line.charAt(1) == 'i')
464 {
465 loop = this.doCommand(line, buffer);
466 }
467 else if(line.charAt(1) == 'w')
468 {
469 loop = this.doCommand(line, buffer);
470 }
471 else if(line.charAt(1) == 'l')
472 {
473 loop = this.doCommand(line, buffer);
474 }
475 else if(line.length() >= CD_DIRECTIVE_MINIMUM_LENGTH && line.substring(1, CD_COMMAND_MAXIMUM_OFFSET).equals("cd"))
476 {
477 loop = this.doCommand(line, buffer);
478 }
479 else if(line.length() >= PWD_DIRECTIVE_MINIMUM_LENGTH && line.substring(1, PWD_COMMAND_MAXIMUM_OFFSET).equals("pwd"))
480 {
481 loop = this.doCommand(line, buffer);
482 }
483 else
484 {
485
486 List commandList = new ArrayList();
487 char[] command = new char[2];
488 for(int i = 0; i < line.length(); i++)
489 {
490 command[0] = line.charAt(i);
491 if(Character.isWhitespace(line.charAt(i)))
492 {
493 continue;
494 }
495 if(line.charAt(i) != '//')
496 {
497 this.outputToConsoleAndLog("syntax error: unexpected character '" + line.charAt(i) + "'");
498 break;
499 }
500 if(i+1 >= line.length())
501 {
502 this.outputToConsoleAndLog("syntax error: unmatched //");
503 break;
504 }
505 command[1] = line.charAt(i+1);
506 String commandString = new String(command);
507 commandList.add(commandString);
508 ++i;
509 }
510 boolean commandLoop = true;
511 for(Iterator iter = commandList.iterator(); iter.hasNext() && commandLoop;)
512 {
513 String commandString = (String) iter.next();
514 commandLoop = this.doCommand(commandString, buffer);
515 loop = commandLoop;
516 }
517 }
518 }
519 else
520 {
521
522 if(this.needToClear)
523 {
524 this.clearBuffer(buffer);
525 this.needToClear = false;
526 }
527
528 List commandList = new ArrayList();
529 char[] command = new char[2];
530 int k = line.length();
531 for(int i = line.length() - 1; i >= 1; i -= 2)
532 {
533 if(line.charAt(i-1) != '//')
534 {
535 break;
536 }
537 command[0] = line.charAt(i-1);
538 command[1] = line.charAt(i);
539 String commandString = new String(command);
540 commandList.add(0, commandString);
541 k -= 2;
542 }
543
544
545 buffer.add(line.substring(0, k));
546
547
548 if(commandList.size() > 0)
549 {
550 boolean commandLoop = true;
551 for(Iterator iter = commandList.iterator(); iter.hasNext() && commandLoop;)
552 {
553 String commandString = (String) iter.next();
554 commandLoop = this.doCommand(commandString, buffer);
555 loop = commandLoop;
556 }
557 }
558 }
559 }
560 }
561
562 private boolean doCommand(final String command, final List buffer) throws IOException
563 {
564 if(command.length() >= CD_DIRECTIVE_MINIMUM_LENGTH && command.substring(1, CD_COMMAND_MAXIMUM_OFFSET).equals("cd"))
565 {
566 this.changeWorkingDirectory(command);
567 this.showWorkingDirectory();
568 return true;
569 }
570 else if(command.length() >= PWD_DIRECTIVE_MINIMUM_LENGTH && command.substring(1, PWD_COMMAND_MAXIMUM_OFFSET).equals("pwd"))
571 {
572 this.showWorkingDirectory();
573 return true;
574 }
575 switch(command.charAt(1))
576 {
577 case 'q':
578 {
579 if(this.loggerPrintStream != null)
580 {
581 this.loggerPrintStream.flush();
582 this.loggerPrintStream = null;
583 }
584 return false;
585 }
586 case 'g':
587 {
588 this.executeBuffer(buffer);
589 this.needToClear = true;
590 break;
591 }
592 case 'p':
593 {
594 this.printBuffer(buffer);
595 this.needToClear = false;
596 break;
597 }
598 case 'l':
599 {
600 this.toggleLogFile(command);
601 break;
602 }
603 case 'i':
604 {
605 this.includeFile(command, buffer);
606 break;
607 }
608 case 'w':
609 {
610 this.writeToFile(command, buffer);
611 break;
612 }
613 case 'r':
614 {
615 this.clearBuffer(buffer);
616 break;
617 }
618 case 't':
619 {
620 this.displayTime();
621 break;
622 }
623 case 'h':
624 {
625 this.showCommands();
626 break;
627 }
628 default:
629 {
630 this.outputToConsoleAndLog("unknown command");
631 break;
632 }
633 }
634 return true;
635 }
636
637 private void changeWorkingDirectory(final String command)
638 {
639 String[] fields = StringUtils.split(command, " ");
640 if(fields.length < 2)
641 {
642
643 this.workingDirectory = null;
644 }
645 else
646 {
647
648 if(logger.isDebugEnabled())
649 {
650 logger.debug("cd argument: " + fields[1]);
651 }
652 File newWorkingDirectory = new File(fields[1]);
653 if(logger.isDebugEnabled())
654 {
655 logger.debug("isAbsolute: " + newWorkingDirectory.isAbsolute());
656 logger.debug("isDirectory: " + newWorkingDirectory.isDirectory());
657 }
658 if(!newWorkingDirectory.isAbsolute())
659 {
660 newWorkingDirectory = new File(this.workingDirectory, fields[1]);
661 }
662 if(newWorkingDirectory.isDirectory() && newWorkingDirectory.canRead() && newWorkingDirectory.canWrite())
663 {
664 this.workingDirectory = newWorkingDirectory;
665 }
666 else
667 {
668 this.outputToConsoleAndLog("Directory '" + newWorkingDirectory.getPath() + "' does not exist or is not accessible");
669 }
670 }
671 }
672
673 private void showWorkingDirectory()
674 {
675
676 this.outputToConsoleAndLog("current working directory: " + (this.workingDirectory == null ? "default working directory" : this.workingDirectory.getPath()));
677 }
678
679 private void clearBuffer(final List buffer)
680 {
681 buffer.clear();
682 }
683
684 private void describeTable(final String[] words)
685 {
686 if(words.length < 2)
687 {
688 this.outputToConsoleAndLog("Syntax error: expected table name (desc[ribe] table_name)");
689 }
690 else
691 {
692 this.describeCommand.setTableName(words[1]);
693 this.describeCommand.execute();
694 }
695 }
696
697 private void show(final String[] words)
698 {
699 boolean error = false;
700 if(words.length == 2)
701 {
702 if(words[1].equalsIgnoreCase("tables"))
703 {
704 this.showTables();
705 }
706 else
707 {
708 error = true;
709 }
710 }
711 else
712 {
713 error = true;
714 }
715 if(error)
716 {
717 this.outputToConsoleAndLog("Syntax error: unknown show command");
718 }
719 }
720
721 private void executeBuffer(final List lineBuffer)
722 {
723 List statements = lineBuffer;
724 for(Iterator iter = statements.iterator(); iter.hasNext();)
725 {
726 String line = (String) iter.next();
727
728
729
730
731 StringBuffer buffer = new StringBuffer(line.length());
732 buffer.append(line);
733 while(!line.endsWith(";") && iter.hasNext())
734 {
735 line = (String) iter.next();
736 buffer.append(" ");
737 buffer.append(line);
738 }
739 String commandLine = StringUtils.trim(buffer.toString());
740 String[] commands = StringUtils.split(commandLine, ";");
741 for(int i = 0; i < commands.length; i++)
742 {
743 String command = commands[i];
744
745 String[] words = StringUtils.split(command);
746 if(words[0].equalsIgnoreCase("desc"))
747 {
748
749 this.describeTable(words);
750 }
751 else if(words[0].equalsIgnoreCase("describe"))
752 {
753
754 this.describeTable(words);
755 }
756 else if(words[0].equalsIgnoreCase("show"))
757 {
758
759 this.show(words);
760 }
761 else if(words[0].equalsIgnoreCase("select"))
762 {
763 this.selectCommand.setCommand(command);
764 this.selectCommand.execute();
765 }
766 else
767 {
768
769 this.updateCommand.setCommand(command);
770 this.updateCommand.execute();
771 }
772 }
773 }
774 }
775
776 private void displayTime()
777 {
778 Date now = new Date();
779 this.outputToConsoleAndLog(now);
780 }
781
782 private void outputToConsoleAndLog(Object object)
783 {
784 System.out.println(object);
785 if(this.loggerPrintStream != null)
786 {
787 this.loggerPrintStream.println(object);
788 }
789 }
790
791 private void outputToConsoleAndLog(String string)
792 {
793 System.out.println(string);
794 if(this.loggerPrintStream != null)
795 {
796 this.loggerPrintStream.println(string);
797 }
798 }
799
800 private void printBuffer(final List buffer)
801 {
802 for(Iterator iter = buffer.iterator(); iter.hasNext();)
803 {
804 String line = (String) iter.next();
805 this.outputToConsoleAndLog(line);
806 }
807 }
808
809 private void toggleLogFile(final String command) throws IOException
810 {
811 if(this.loggerPrintStream == null)
812 {
813
814 String fileName = null;
815 int index = command.indexOf(' ');
816 if(index < 0)
817 {
818 fileName = "sqlcli.log";
819 }
820 else
821 {
822 fileName = command.substring(LOGGER_FILE_NAME_INDEX);
823 }
824
825 File file = new File(fileName);
826 if(!file.isAbsolute())
827 {
828 file = new File(this.workingDirectory, fileName);
829 }
830 this.loggerPrintStream = new PrintStream(new BufferedOutputStream(new FileOutputStream(file)));
831 for(Iterator iter = this.printStreamed.iterator(); iter.hasNext();)
832 {
833 PrintStreamed value = (PrintStreamed) iter.next();
834 value.addPrintStream(this.loggerPrintStream);
835 }
836 System.out.println("Logging enabled to file '" + fileName + "'");
837 }
838 else
839 {
840 for(Iterator iter = this.printStreamed.iterator(); iter.hasNext();)
841 {
842 PrintStreamed value = (PrintStreamed) iter.next();
843 value.removePrintStream(this.loggerPrintStream);
844 }
845 this.loggerPrintStream.flush();
846 this.loggerPrintStream = null;
847 System.out.println("Logging disabled.");
848 }
849 }
850
851 private void closeLogFile()
852 {
853 if(this.loggerPrintStream != null)
854 {
855 this.loggerPrintStream.flush();
856 this.loggerPrintStream = null;
857 }
858 }
859
860 private void includeFile(final String command, final List buffer) throws IOException
861 {
862 String[] tokens = StringUtils.split(command);
863 if(tokens.length < 2)
864 {
865 this.outputToConsoleAndLog("syntax error: //i requires file name");
866 }
867 else
868 {
869 String fileName = "";
870 for(int i = 1; i < tokens.length; i++)
871 {
872 if(i > 1)
873 {
874 fileName += " ";
875 }
876 fileName += tokens[i];
877 }
878 File includeFile = this.expandReadableFileName(fileName);
879 BufferedReader reader = null;
880 try
881 {
882 reader = new BufferedReader(new FileReader(includeFile));
883 this.processInput(reader, buffer, false);
884 }
885 catch(FileNotFoundException e)
886 {
887 this.outputToConsoleAndLog("file not found: " + tokens[1]);
888 }
889 }
890 }
891
892 private void writeToFile(final String command, final List buffer) throws IOException
893 {
894
895 if(command.length() <= WRITE_TO_FILE_COMMAND_MINIMUM_LENGTH)
896 {
897 System.out.println("syntax error: //w requires file name");
898 return;
899 }
900 else
901 {
902 String fileName = null;
903 try
904 {
905 fileName = command.substring(WRITE_TO_FILE_NAME_INDEX);
906 }
907 catch(IndexOutOfBoundsException e)
908 {
909 System.out.println("syntax error: //w requires file name");
910 return;
911 }
912 PrintStream writer = null;
913 try
914 {
915 writer = new PrintStream(new BufferedOutputStream(new FileOutputStream(fileName)));
916 for(Iterator iter = buffer.iterator(); iter.hasNext();)
917 {
918 String line = (String) iter.next();
919 writer.println(line);
920 }
921 }
922 finally
923 {
924 writer.close();
925 }
926 }
927
928 }
929
930 private void showCommands()
931 {
932 System.out.println("Directives:");
933 System.out.println(" //cd - change the working directory to the default directory");
934 System.out.println(" //cd <directory> - change the working directory to the directory specified");
935 System.out.println(" //g - execute the SQL commands in the input buffer");
936 System.out.println(" //h - print this list");
937 System.out.println(" //i <filename> - include the contents of the named file into the input buffer");
938 System.out.println(" //l <filename> - turn on logging of output to the named file if logging is off");
939 System.out.println(" //l - turn off logging if logging is on; otherwise turn on logging to the file 'sqlcli.log'");
940 System.out.println(" //pwd - print the working directory");
941 System.out.println(" //w <filename> - write the contents of the input buffer to the named file");
942 System.out.println(" //q - quit");
943 System.out.println("");
944 System.out.println("Extended commands:");
945 System.out.println(" describe <tablename> - print a list of the columns in the specified table");
946 System.out.println(" show tables - print a list of tables in the database");
947 }
948
949 private void showTables()
950 {
951 this.showTablesCommand.execute();
952 }
953
954 private Connection getConnection() throws ClassNotFoundException, SQLException
955 {
956 Class.forName(this.driverClassName);
957 if(this.properties != null)
958 {
959 DriverManager.getConnection(url, properties);
960 }
961 if(this.username != null)
962 {
963 return DriverManager.getConnection(this.url, this.username, this.password);
964 }
965 else
966 {
967 return DriverManager.getConnection(this.url);
968 }
969 }
970
971 private void showHelp(final Options options)
972 {
973 HelpFormatter helpFormatter = new HelpFormatter();
974 PrintWriter writer = new PrintWriter(System.out, true);
975 helpFormatter.printHelp(PRINT_USAGE_WIDTH, PROGRAM_NAME, null, options, null, true);
976 }
977
978 private void usage(final Options options)
979 {
980 HelpFormatter helpFormatter = new HelpFormatter();
981 PrintWriter writer = new PrintWriter(System.out, true);
982 helpFormatter.printUsage(writer, PRINT_USAGE_WIDTH, PROGRAM_NAME, options);
983 }
984
985 private File expandReadableFileName(final String fileName)
986 {
987 File file = null;
988 if(this.workingDirectory != null)
989 {
990 file = new File(this.workingDirectory.getPath() + File.separatorChar + fileName);
991 if(file != null && file.exists() && file.canRead())
992 {
993 return file;
994 }
995 else
996 {
997 file = new File(fileName);
998 if(file.exists())
999 {
1000 return file;
1001 }
1002 else
1003 {
1004 file = null;
1005 }
1006 }
1007 }
1008 if(file == null)
1009 {
1010 file = new File(fileName);
1011 }
1012 return file;
1013 }
1014
1015
1016
1017
1018
1019 }