From: SVN by r. <sv...@ca...> - 2008-08-03 20:01:52
|
Author: roy Date: 2008-08-03 22:01:43 +0200 (Sun, 03 Aug 2008) New Revision: 280 Modified: src/main/java/nl/improved/sqlclient/SQLShell.java Log: made deprecated Modified: src/main/java/nl/improved/sqlclient/SQLShell.java =================================================================== --- src/main/java/nl/improved/sqlclient/SQLShell.java 2008-08-03 12:15:17 UTC (rev 279) +++ src/main/java/nl/improved/sqlclient/SQLShell.java 2008-08-03 20:01:43 UTC (rev 280) @@ -15,1617 +15,18 @@ */ package nl.improved.sqlclient; -import java.io.*; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.LinkedHashMap; -import java.util.logging.Level; -import java.util.logging.Logger; -import jcurses.widgets.Window; -import jcurses.system.InputChar; -import jcurses.system.Toolkit; -import jcurses.system.CharColor; -import jcurses.widgets.PopUpMenu; -import nl.improved.sqlclient.commands.*; +import nl.improved.sqlclient.jcurses.SQLShellWindow; + /** * The SQLShell main class. * This class provides a (textbased) window for entering sql commands. */ -public class SQLShell extends Window { +public class SQLShell { - /** - * The current command thread executing a SQLShell command. - */ - private CommandThread commandThread; - /** - * True when the prompt should be visible. - * Normally it is not visible during the execution of a command - */ - private boolean showPrompt = true; - - /** - * The (default) maximum matches to show in a selection dialog. - */ - private static final int MAX_MATCH_SIZE = 15; - private int MAX_LINE_LENGTH; // not static and final.. since it can change on window resize - - /** - * Page up count 0 means were at the bottom of our screen. - * Increasement of the pageup count moves the visible part of the screen up. - */ - private int pageUpCount = 0; - /** - * All lines in a screen. - */ - private List<CharSequence> screenBuffer = new LimitedArrayList<CharSequence>(1000); - /** - * The current command lines. - */ - private SQLCommand commandLines; - /** - * All commands in history. - */ - private List<SQLCommand> commandHistory = new LimitedArrayList<SQLCommand>(50); - /** - * Index for browsing commands. - */ - private int commandIndex = 0; - /** - * An empty line for easy line completion (fill with spaces). - */ - private String emptyLine; - /** - * The cursor position in the command lines list. - * 0,0 means it is at the first line at the first character - * 10,5 means it is at the 11th character at the 6th line - */ - private Point cursorPosition = new Point(0,0); - /** - * The prompt to show when entering sql commands. - */ - private static final String PROMPT = "SQL"; - /** - * Some debug info holding the last trace of an exception. - */ - private String lastExceptionDetails; - - /** - * The output file when spool is on. - */ - private Writer spoolWriter; - /** - * A manager for available commands. - */ - private CommandManager commands = new CommandManager(); - - /** - * A map of string key representation to a action that should be executed when a specific key is pressed. - */ - private Map<String, KeyAction> actionKeys = new LinkedHashMap<String, KeyAction>(); - - /** - * Constructor. - */ - public SQLShell() { - super(Toolkit.getScreenWidth(),Toolkit.getScreenHeight(), true, "SQLShell"); - char[] emptyLineChar = new char[Toolkit.getScreenWidth()]; - Arrays.fill(emptyLineChar, ' '); - emptyLine = new String(emptyLineChar); - - // initialize the command shell - commandLines = new SQLCommand(); - commandHistory.add(commandLines); - newLine(); - - // Register all known commands - commands.register("CONNECT[\\s]*.*", new ConnectCommand()); - commands.register("DISCONNECT[\\s]*", new DisConnectCommand()); - commands.register("SHOW[\\s]+[A-Z]+(|[A-Z]|_|\\.)*(|[\\s]+HAVING[\\s][A-Z]*.*)", new ShowCommand()); - commands.register("DESC[\\s]+[A-Z]+(|[0-9]|[A-Z]|_|-|\\.)*", new DescCommand()); - commands.register("WINDOW[\\s]+[A-Z]+", new WindowCommand()); - commands.register("INFO[\\s]*", new InfoCommand()); - commands.register("HELP[\\s]*.*", new HelpCommand()); - commands.register("HISTORY[\\s]*.*", new HistoryCommand()); - commands.register("SPOOL[\\s]*.*", new SpoolCommand()); - commands.register("QUIT[\\s]*", new QuitCommand("quit")); - commands.register("EXIT[\\s]*", new QuitCommand("exit")); - //commands.register("\\\\Q[\\s]*", new QuitCommand("\\q")); - commands.register("@.*", new ExecuteBatchCommand()); - commands.register("(SELECT|UPDATE|ALTER|INSERT|DELETE).*;[\\s]*", new QueryCommand()); - - // keys - actionKeys.put(Integer.toString(InputChar.KEY_LEFT), new KeyAction() { - public void execute() { - if (cursorPosition.x > 0) { - cursorPosition.x--; - } else if (cursorPosition.y > 0) { - cursorPosition.y--; - cursorPosition.x = commandLines.getLines().get(cursorPosition.y).length(); - } - } - public CharSequence getHelp() { - return "Arrow Left:\tMove cursor to the left"; - } - }); - actionKeys.put(Integer.toString(InputChar.KEY_RIGHT), new KeyAction() { - public void execute() { - CharSequence tmp = commandLines.getLines().get(cursorPosition.y); - if (cursorPosition.x < tmp.length()) { - cursorPosition.x++; - } else if (cursorPosition.y < commandLines.getLines().size()-1) { - cursorPosition.x = 0; - cursorPosition.y++; - } - } - public CharSequence getHelp() { - return "Arrow Right:\tMove cursor to the right"; - } - }); - actionKeys.put(Integer.toString(InputChar.KEY_UP), new KeyAction() { - public void execute() { - if (commandIndex > 0) { - commandLines = commandHistory.get(--commandIndex); - cursorPosition.y = commandLines.getLines().size()-1; - CharSequence lineBuffer = commandLines.getLines().get(cursorPosition.y); - cursorPosition.x = lineBuffer.length(); - } - } - public CharSequence getHelp() { - return "Arrow Up:\tBrowse to previous command in the history"; - } - }); - actionKeys.put(Integer.toString(InputChar.KEY_DOWN), new KeyAction() { - public void execute() { - if (commandIndex < commandHistory.size()-1) { - commandLines = commandHistory.get(++commandIndex); - cursorPosition.y = commandLines.getLines().size()-1; - CharSequence lineBuffer = commandLines.getLines().get(cursorPosition.y); - cursorPosition.x = lineBuffer.length(); - } - } - public CharSequence getHelp() { - return "Arrow Down:\tBrowse to next command in the history"; - } - }); - actionKeys.put(Integer.toString(InputChar.KEY_END),new KeyAction() { - public void execute() { - int curLineEnd = commandLines.getLines().get(cursorPosition.y).length(); - if (cursorPosition.x == curLineEnd) { - cursorPosition.y = commandLines.getLines().size()-1; - CharSequence lineBuffer = commandLines.getLines().get(cursorPosition.y); - cursorPosition.x = lineBuffer.length(); - } else { - cursorPosition.x = curLineEnd; - } - } - public CharSequence getHelp() { - return "End:\tMove the cursor to the end of the line, of if already there to the end of the command"; - } - }); - actionKeys.put(Integer.toString(InputChar.KEY_HOME), new KeyAction() { - public void execute() { - if (cursorPosition.x == 0) { - cursorPosition.y = 0; - } - cursorPosition.x = 0; - } - public CharSequence getHelp() { - return "Home:\tMove the cursor to the start of the line, of if already there to the start of the command"; - } - }); - actionKeys.put(Integer.toString(InputChar.KEY_BACKSPACE), new KeyAction() { - public void execute() { - if (cursorPosition.x == 0) { - if (cursorPosition.y > 0) { - joinLine(); - } - } else { - StringBuilder tmp = getEditableCommand().getEditableLines().get(cursorPosition.y); - if (cursorPosition.x > 0) { - tmp.deleteCharAt(cursorPosition.x-1); - cursorPosition.x--; - } - } - } - public CharSequence getHelp() { - return "Backspace:\tRemove the character before the cursor position"; - } - }); - actionKeys.put(Integer.toString(InputChar.KEY_DC), new KeyAction() { - public void execute() { - StringBuilder lineBuffer = commandLines.getEditableLines().get(cursorPosition.y); - if (cursorPosition.x < lineBuffer.length()) { - StringBuilder tmp = getEditableCommand().getEditableLines().get(cursorPosition.y); - tmp.deleteCharAt(cursorPosition.x); - } - } - public CharSequence getHelp() { - return "Del:\tDelete the charactor at the current cursor position"; - } - }); - actionKeys.put("", new KeyAction() { - public void execute() { // ctrl+w - if (cursorPosition.x == 0) { - if (cursorPosition.y > 0) { - joinLine(); - } - return; - } - StringBuilder lineBuffer = commandLines.getEditableLines().get(cursorPosition.y); - int previousBreak = SQLUtil.getLastBreakIndex(lineBuffer.substring(0, cursorPosition.x-1)); - if (lineBuffer.charAt(previousBreak) == ' ' || lineBuffer.charAt(previousBreak) == '\t') { - previousBreak++; - } - lineBuffer.delete(previousBreak, cursorPosition.x); - cursorPosition.x = previousBreak; - } - public CharSequence getHelp() { - return "Control-W:\tRemove word before cursor position"; - } - }); - actionKeys.put("", new KeyAction() { // ctrl+u - public void execute() { - if (cursorPosition.x > 0) { - StringBuilder lineBuffer = commandLines.getEditableLines().get(cursorPosition.y); - lineBuffer.delete(0, cursorPosition.x); - cursorPosition.x = 0; - } else if (cursorPosition.y > 0) { - StringBuilder lineBuffer = commandLines.getEditableLines().get(cursorPosition.y); - if (lineBuffer.length() == 0) { - commandLines.getEditableLines().remove(cursorPosition.y); - } - cursorPosition.y--; - lineBuffer = commandLines.getEditableLines().get(cursorPosition.y); - lineBuffer.delete(0, lineBuffer.length()); - } - } - public CharSequence getHelp() { - return "Control-U:\tRemove all characters before the cursor position"; - } - }); - actionKeys.put(Integer.toString(InputChar.KEY_PPAGE), new KeyAction() { - public void execute() { - if ((screenBuffer.size() + commandLines.getLines().size() - - (Toolkit.getScreenHeight()/2) * pageUpCount) > 0) { - pageUpCount++; - - } - } - public CharSequence getHelp() { - return "PageUp:\tMove back in screen history"; - } - }); - actionKeys.put(Integer.toString(InputChar.KEY_NPAGE), new KeyAction() { - public void execute() { - if (pageUpCount > 0) { - pageUpCount--; - } - } - public CharSequence getHelp() { - return "PageDown:\tMove forward in screen history"; - } - }); - actionKeys.put("", new KeyAction() { // ctrl+a - public void execute() { - output("Abort requested"); - if (commandThread.isAlive() && commandThread.getCommand().abort()) { - output("Abort done.."); - } - } - public CharSequence getHelp() { - return "Control-A:\tAbort current command (if it is supported by that command)"; - } - }); - actionKeys.put("", new KeyAction() { //Ctrl+D - public void execute() { - if (commandLines.getCommandString().length() == 0) { //Quit on empty commandline, ignore otherwise - executeCommand(new InputCommand("quit")); - } - } - public CharSequence getHelp() { - return "Control-D:\tExit sqlshell"; - } - }); - - MAX_LINE_LENGTH = Toolkit.getScreenWidth()-(PROMPT.length()+2+1); // prompt + "> " - - output("Welcome to the SQLShell client."); - output("Type 'help' to get a list of available commands other then the default sql input."); + public static void main(String[] args) throws InterruptedException { + System.out.println("This class is no longer used. Please start nl.improved.sqlclient.jcurses.SQLShellWindow"); + Thread.sleep(2000); + SQLShellWindow.main(args); } - - - /** - * Returns the connection to the database - * @return the connection to the database - */ - public Connection getConnection() { - return DBConnector.getInstance().getConnection(); - } - /** - * Shows this window. - * Override to make sure paint content is called. - */ - @Override - public void show() { - super.show(); - paint(); - } - - /** - * Hides this window. - * Override to make sure the spool writer is closed when it was open - */ - @Override - public void hide() { - try { - if (spoolWriter != null) { - try { - spoolWriter.close(); - spoolWriter = null; - } catch(Exception e) {/*ignore*/} - } - } finally { - super.hide(); - } - } - - /** - * Returns a string representation of the current command. - * @return a string representation of the current command. - */ - private SQLCommand getCommand() { - return commandLines; - } - - /** - * Add a new line to the command lines buffer. - */ - private StringBuilder newLine() { - cursorPosition.x = 0; - StringBuilder newLine = new StringBuilder(); - getEditableCommand().getEditableLines().add(newLine); - cursorPosition.y = commandLines.getLines().size()-1; - return newLine; - } - - /** - * Handle key input. - * @param inp the character that is being pressed by the user. - */ - protected void handleInput(InputChar inp) { - //debug("Input: " + inp.getCode()); - try { - if (inp.getCode() != InputChar.KEY_PPAGE && inp.getCode() != InputChar.KEY_NPAGE) { - pageUpCount = 0; // some character entered, so reset pageup count - } - if (inp.isSpecialCode()) { - KeyAction ke = actionKeys.get(Integer.toString(inp.getCode()));// || inp.toString().equals("") || inp.toString().equals("")) { - if (ke != null) { - ke.execute(); - } else { - debug("Unknown character: "+ inp.getCode()); - } - } else { - KeyAction ke = actionKeys.get(inp.toString()); - if (ke != null) { - ke.execute(); - } else { - if (inp.getCharacter() == '\n') { // newline... see if the command can be executed - // execute the command - SQLCommand sqlCommand = getCommand(); - String command = sqlCommand.getCommandString(); - // search command... - if (command.length() > 0 && command.charAt(0) == '/') { // search in history - String matchPattern=".*"+command.substring(1,command.length())+".*"; - for (int cIndex = commandHistory.size()-1; cIndex >=0; cIndex--) { - if (cIndex == commandIndex) { - continue; // skip current command - } - SQLCommand newSqlCommand = commandHistory.get(cIndex); - String commandString = newSqlCommand.getCommandString(); - if (commandString.matches(matchPattern)) { - commandHistory.remove(commandIndex); - commandIndex = commandHistory.indexOf(newSqlCommand); - commandLines = newSqlCommand; - cursorPosition.y = 0; - cursorPosition.x = 0; - paint(); // force repaint - return; - } - } - Toolkit.beep(); // TODO clear search?? - return; - } else if (executeCommand(sqlCommand)) { - // clear command history - if (commandIndex != commandHistory.size()-1) { - SQLCommand tmpLines = commandLines; - commandLines = commandHistory.get(commandHistory.size()-1); - if (commandLines.getCommandString().equals("")) { - commandHistory.add(commandHistory.size()-1, tmpLines); - } else { - commandHistory.add(tmpLines); - commandLines = tmpLines; - } - } - if (!commandLines.getCommandString().equals("")) { - commandLines = new SQLCommand(); - commandHistory.add(commandLines); - newLine(); - } - commandIndex = commandHistory.size()-1; - cursorPosition.y = commandLines.getLines().size()-1; - cursorPosition.x = commandLines.getLines().get(cursorPosition.y).length(); - paint(); // force repaint - return; - } - } - CharSequence newText; - if (inp.getCharacter() == '\t') { - try { - newText = getTabCompletion(commandLines, cursorPosition); - } catch(IllegalStateException e) { - output(getCommand().getCommandString()); // add command as well... - error(e); - return; - } - } else { - newText = Character.toString(inp.getCharacter()); - } - if (newText.equals("\n")) { - newLine(); // TODO Fix return in middle of an other line - } else { - List<StringBuilder> editableLines = getEditableCommand().getEditableLines(); - StringBuilder currentLine = editableLines.get(cursorPosition.y); - currentLine.insert(cursorPosition.x, newText); - cursorPosition.x += newText.length(); - // check if the new line is becoming too long - if (currentLine.length() > MAX_LINE_LENGTH) { - // TODO search for lastspace that is not between '' ?? - int lastSpace = SQLUtil.getLastBreakIndex(currentLine.toString());//currentLine.lastIndexOf(" "); - if (lastSpace == -1) { - lastSpace = currentLine.length(); - } - // check if there are enough 'next' lines - // if not.. add one - if (editableLines.size()-1 == cursorPosition.y) { - StringBuilder newLine = new StringBuilder(); - editableLines.add(newLine); - } - // check if the nextline has enough room for the new word - // if not.. add a new line - if (editableLines.get(cursorPosition.y+1).length() - + (currentLine.length()-lastSpace+1) > MAX_LINE_LENGTH) { - StringBuilder newLine = new StringBuilder(); - editableLines.add(cursorPosition.y+1, newLine); - } - // fetch the next line - StringBuilder nextLine = editableLines.get(cursorPosition.y+1); - // if the nextline already has some text.. add a space in front of it - if (nextLine.length() > 0) { - nextLine.insert(0, ' '); - } - // insert the new text at the beginning - nextLine.insert(0, currentLine.subSequence(lastSpace+1, currentLine.length())); - currentLine.delete(lastSpace, currentLine.length()); - // check if the cursor postition > the new line length - // calculate new x and go to nextline - if (cursorPosition.x >= lastSpace) { - cursorPosition.x = cursorPosition.x - (lastSpace+1); - cursorPosition.y++; - } - } - } - } - } - } catch(Throwable t) { - error(t); - } - paint(); - } - - /** - * Return the editable version of the commandlines. - * If editing a previous command clone it and return the clone - * @return the editable version of the commandlines. - */ - protected SQLCommand getEditableCommand() { - if (commandHistory.indexOf(commandLines) != commandHistory.size()-1) { - List<? extends CharSequence> tmp = commandLines.getLines(); - if (commandHistory.get(commandHistory.size()-1).getLines().size() == 1 - && commandHistory.get(commandHistory.size()-1).getLines().get(0).length() == 0) { - commandLines = commandHistory.get(commandHistory.size()-1); - commandLines.getEditableLines().remove(0); - } else { - commandLines = new SQLCommand(); - commandHistory.add(commandLines); - } - for (int i = 0; i < tmp.size(); i++) { - commandLines.getEditableLines().add(new StringBuilder(tmp.get(i))); - } - commandIndex = commandHistory.size()-1; - } - return commandLines; - } - - /** - * Output data to the screen. - * @param data the data to print to the screen. - */ - protected synchronized void output(CharSequence data) { - screenBuffer.addAll(getLines(data)); - if (spoolWriter != null) { - try { - spoolWriter.write(data.toString()); - spoolWriter.write("\n"); - } catch(IOException e) { - screenBuffer.add("WARNING: Could not write to spool file"); - error(e); - } - } - } - - /** - * Output error exception to the screen. - * @param e the error to print to the screen - */ - protected synchronized void error(Throwable e) { - output(e.getMessage() == null ? e.toString() : e.getMessage()); - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - sw.flush(); - lastExceptionDetails = sw.toString(); - //output(sw.toString()); - } - - /** - * Return a list of table names available for the current connection. - * @return a list of table names available for the current connection. - */ - protected List<String> getTableNames() { - List<String> returnValue = new ArrayList<String>(); - try { - ResultSet rs = getConnection().getMetaData().getTables(getConnection().getCatalog(), DBConnector.getInstance().getSchema(), null, new String[]{"TABLE"}); - while (rs.next()) { - if (!returnValue.contains(rs.getString("TABLE_NAME"))) { - returnValue.add(rs.getString("TABLE_NAME")); - } - } - return returnValue; - } catch (SQLException ex) { - ex.printStackTrace(); - Logger.getLogger(SQLShell.class.getName()).log(Level.SEVERE, null, ex); - return null; - } - } - - /** - * Return a list of column names for the specified list of table names. - * @param tableNames a list of tableNames - * @return a list of column names for the specified list of table names. - */ - protected List<String> getColumnNames(List<String> tableNames) { - List<String> returnValues = new ArrayList<String>(); - Iterator<String> iTableNames = tableNames.iterator(); - while (iTableNames.hasNext()) { - String tableName = DBConnector.getInstance().translateDbVar(iTableNames.next().trim()); - try { - ResultSet rs = getConnection().getMetaData().getColumns(getConnection().getCatalog(), DBConnector.getInstance().getSchema(), tableName, "%"); - while (rs.next()) { - if (!returnValues.contains(rs.getString("COLUMN_NAME"))) { - returnValues.add(rs.getString("COLUMN_NAME")); - } - } - } catch (SQLException ex) { - throw new IllegalStateException("Failed to find columnnames for table: "+ tableName, ex); - } - } - return returnValues; - } - - /** - * Try to find a match in the provided list starging with sub. - * If more matches apply show the user a dialog to choose a match or simply display all matches in the window - * @param values all possible values to choose from (not limited with the sub parameter) - * @param sub the start of the match - * @return the match starting with sub minus the sub itself in the correct casing - */ - protected CharSequence findMatch(List<String> values, String sub) { - List<String> matches = new ArrayList<String>(); - Iterator<String> iValues = values.iterator(); - while (iValues.hasNext()) { - String value = iValues.next(); - if (value.toUpperCase().startsWith(sub.toUpperCase())) { - matches.add(value); - } - } - //debug("Matches found: "+ matches.size() +" --> "+ sub +" / "+ values); - String match = null; - if (matches.size() == 1) { - match = matches.get(0); - } else if (matches.size() > 1 && matches.size() < MAX_MATCH_SIZE) { - int y; - if (screenBuffer.size() + cursorPosition.y > Toolkit.getScreenHeight()-3) { - y = Toolkit.getScreenHeight()-4; - } else { - y = screenBuffer.size() + cursorPosition.y; - } - PopUpMenu menu = new PopUpMenu(cursorPosition.x,Math.max(2, y-matches.size()), "Find match"); - Iterator<String> iMatches = matches.iterator(); - while (iMatches.hasNext()) { - menu.add(iMatches.next()); - } - menu.show(); - match = menu.getSelectedItem(); - } else if (matches.size() > 1) { - output("\n"+toColumns(matches)); - } - if (match != null) { - if (sub.length() > 0) { - /*if (Character.isUpperCase(sub.charAt(0))) { - match = match.toUpperCase(); - } else { - match = match.toLowerCase(); - }*/ - match = DBConnector.getInstance().translateDbVar(match); - } - return match.substring(sub.length()); - } - return null; - } - - /** - * Simple method to change a null value to an empty charsequence. - * @param s the charsequence to convert to empty if it is null - * @return empty when s was null or return s when s is not null - */ - protected CharSequence nullToEmpty(CharSequence s) { - if (s == null) { - return ""; - } - return s; - } - /** - * return the tab completion value. - * @param commandLines the current command - * @param cursorPosition the position where the tab completion was invocated - * @return the tab completion value. - */ - protected CharSequence getTabCompletion(SQLCommand commandLines, Point cursorPosition) { - TabCompletionInfo info = null; - String cmd = commandLines.getCommandString(); - if (cmd.length() > 0) { - if (cmd.indexOf(' ') > 0) { - cmd = cmd.substring(0, cmd.indexOf(' ')).trim(); - } - Command tmpCommand = commands.findCommand(cmd); - if (tmpCommand == null) { - for (Command c : commands.getCommands()) { - if (cmd.equalsIgnoreCase(c.getCommandString().toString())) { - tmpCommand = c; - break; - } - } - } - if (tmpCommand != null) { - info = tmpCommand.getTabCompletionInfo(commandLines, cursorPosition); - } - } - if (info == null) { - info = SQLUtil.getTabCompletionInfo(commandLines, cursorPosition); - } - if (info.getMatchType() == TabCompletionInfo.MatchType.SQL_KEYWORD) { - return nullToEmpty(findMatch(info.getPossibleMatches(), info.getStart())); - } - if (info.getMatchType() == TabCompletionInfo.MatchType.TABLE_NAMES) { - //debug("table completion for \""+info.getStart()+"\""); - return nullToEmpty(findMatch(getTableNames(), info.getStart())); - } - if (info.getMatchType() == TabCompletionInfo.MatchType.COLUMN_NAMES) { - return nullToEmpty(findMatch(getColumnNames(info.getPossibleMatches()), info.getStart())); - } - if (info.getMatchType() == TabCompletionInfo.MatchType.OTHER) { - return nullToEmpty(findMatch(info.getPossibleMatches(), info.getStart())); - } - Toolkit.beep(); - return ""; - } - - /** - * (Try) to execute a command) and return true if it succeeded. - * @param command the command to try and execute - * @return true if it succeeded. - */ - protected boolean executeCommand(SQLCommand sqlCommand) { - return executeCommand(sqlCommand, false); - } - - private boolean executeCommand(final SQLCommand sqlCommand, boolean direct) { - final String commandString = sqlCommand.getCommandString(); - if (commandString.equalsIgnoreCase("printStackTrace")) { - if (lastExceptionDetails == null) { - output("No known last exception to print"); - } else { - output(lastExceptionDetails); - } - return true; - } - Command command = createCommand(commandString); // first try to find a match without ; - if (command == null) { - command = createCommand(sqlCommand.getUntrimmedCommandString()); // then with ; for sql statements... - } - if (command == null) { - return false; - } - // make sure only one command is run at once - if (commandThread != null && commandThread.isAlive()) { - try { - commandThread.join(); - } catch (InterruptedException ex) { - Logger.getLogger(SQLShell.class.getName()).log(Level.SEVERE, null, ex); - } - } - output(commandString); - if (direct || !command.backgroundProcessSupported()) { - output(command.execute(sqlCommand)); - } else { - commandThread = new CommandThread(command) { - @Override - void execute() { - output(getCommand().execute(sqlCommand)); - } - }; - commandThread.start(); - } - return true; - } - private Command createCommand(String commandString) { - Command command = commands.findCommand(commandString); - if (command != null) { - return command; - } - if (commandString.matches(".*;[\\s]*")) { - return new QueryCommand(); // TODO is this ever reached??? - } - return null; - } - - - /** - * Paint the screen. - */ - @Override - protected synchronized void paint() { - CharColor color = new CharColor(CharColor.BLACK, CharColor.WHITE, CharColor.BOLD, CharColor.BOLD); - - List<CharSequence> tmpList = new ArrayList<CharSequence>(); - tmpList.addAll(screenBuffer); - - //add prompt - List<? extends CharSequence> currentLines = commandLines.getLines(); - for (int i = 0; i < currentLines.size(); i++) { - if (i == 0 && showPrompt) { - tmpList.add(PROMPT+"> "+currentLines.get(i)); - } else { - String nrI = Integer.toString(i+1); - tmpList.add(emptyLine.substring(0,PROMPT.length() - nrI.length()) + nrI+"> "+currentLines.get(i)); - } - } - int startLine; - if (tmpList.size() > Toolkit.getScreenHeight()-1) { - startLine = tmpList.size() - (Toolkit.getScreenHeight()-1); - if (pageUpCount > 0) { - startLine -= (pageUpCount * Toolkit.getScreenHeight()/2); - if (startLine < 0) { - startLine = 0; - } - } - } else { - startLine = 0; - } - int lineNr; - for (lineNr = startLine;lineNr < tmpList.size() && lineNr - startLine < Toolkit.getScreenHeight()-1; lineNr++) { - CharSequence linePart = tmpList.get(lineNr); - String line = linePart.length() >= emptyLine.length() ? linePart.toString() : linePart + emptyLine.substring(linePart.length()); - Toolkit.printString(line - , 0, lineNr-startLine, color); - } - for (int lNr = lineNr; lNr < Toolkit.getScreenHeight(); lNr++) { - Toolkit.printString(emptyLine, 0, lNr, color); - } - - // paint cursor - color = new CharColor(CharColor.BLACK, CharColor.WHITE, CharColor.REVERSE, CharColor.REVERSE); - String cursorChar = " "; - if (commandLines.getLines().size() > 0) { - String tmp = commandLines.getLines().get(cursorPosition.y).toString(); - if (cursorPosition.x < 0) { - debug("Cursor position was: "+ cursorPosition +" fixing"); - cursorPosition.x = 0; - } - if (cursorPosition.x < tmp.length()) { - cursorChar = tmp.substring(cursorPosition.x, cursorPosition.x+1); - } - } - Toolkit.printString(cursorChar, PROMPT.length() +"> ".length() + cursorPosition.x, lineNr-(commandLines.getLines().size() -cursorPosition.y)-startLine, color); - } - - private void debug(String debug) { - CharColor color = new CharColor(CharColor.BLUE, CharColor.YELLOW); - Toolkit.printString(debug, 1, Toolkit.getScreenHeight()-1, color); - } - - /** - * Method to convert a long string to a displayable list of strings with a max with of the screen width. - * @param text a (long) string - * @return the text devided into multiple lines to match the screen width - */ - private static List<CharSequence> getLines(CharSequence text) { - int maxWidth = Toolkit.getScreenWidth(); - List<CharSequence> list = new ArrayList<CharSequence>(); - StringBuilder buffer = new StringBuilder(); - for (int i=0; i<text.length(); i++) { - char c = text.charAt(i); - if (c=='\n' || buffer.length() == maxWidth) { - String line = buffer.toString(); - list.add(line); - buffer = new StringBuilder(); - if (c != '\n') { - buffer.append(c); - } - } else if (c == '\r') { - //ignore - } else { - buffer.append(c); - } - } - if (buffer.length() > 0) { - list.add(buffer.toString()); - } - return list; - } - - /** - * Convert a list to a presentable text devided into multiple columns. - */ - private StringBuilder toColumns(List<? extends CharSequence> values) { - int maxWidth = 0; - Iterator<? extends CharSequence> iValues = values.iterator(); - while (iValues.hasNext()) { - maxWidth = Math.max(maxWidth, iValues.next().length()); - } - maxWidth+=2;// add extra space - int nrOfColumns = (Toolkit.getScreenWidth()) / maxWidth; - StringBuilder returnValue = new StringBuilder(); - for (int row = 0; row < values.size(); row+=nrOfColumns) { - for (int col = 0; col < nrOfColumns && row + col < values.size(); col++) { - returnValue.append(values.get(row+col) + emptyLine.substring(0, maxWidth - values.get(row+col).length())); - } - returnValue.append('\n'); - } - return returnValue; - } - - /** - * A list which contains a limited number of lines. - */ - private class LimitedArrayList<E> extends ArrayList<E> { - private int maxSize; - /** - * Constructor. - * @param maxSize the maximum number of lines the list may contain - */ - public LimitedArrayList(int maxSize) { - super(maxSize); // some sane default - this.maxSize = maxSize; - } - - @Override - public boolean add(E object) { - if (size() == maxSize) { - remove(0); - } - return super.add(object); - } - @Override - public void add(int index, E object) { - if (size() == maxSize) { - remove(0); - } - super.add(index, object); - } - } - - /** - * Connect command for setting up a connection to a database. - */ - private static class ConnectCommand implements Command { - /** - * Execute the connection command and return a readable result. - * @param command the command string for setting up a connection - * @return a readable result of the execution of this command. - */ - @Override - public CharSequence execute(SQLCommand cmd) { - String command = cmd.getCommandString(); - try { - String cmdString = command.substring("connect".length()).trim(); - if (cmdString.length() > 0 && cmdString.charAt(cmdString.length()-1) == ';') { - cmdString = cmdString.substring(0, cmdString.length()-1); - } - DBConnector.getInstance().connect(cmdString); - return "Connected.\n\n"; - } catch(SQLException e) { - throw new IllegalStateException("Failed to connect: " + e.getMessage(), e); - } - } - @Override - public CharSequence getCommandString() { - return "connect"; - } - - /** - * Returns some tab completion info for the specified command. - * @param commandInfo the command lines - * @param commandPoint the cursor position - * @return some tab completion info for the specified command. - */ - @Override - public TabCompletionInfo getTabCompletionInfo(SQLCommand command, Point commandPoint) { - List commandInfo = command.getLines(); - - String startOfCommand = SQLUtil.getStartOfCommand(commandInfo, commandPoint); - if (startOfCommand.indexOf('@') >= 0) { - String end = startOfCommand.substring(startOfCommand.lastIndexOf('@')+1); - List<String> identifiers = new ArrayList<String>(DBConnector.getInstance().getPredefinedConnectionIdentifiers()); - Collections.sort(identifiers); - return new TabCompletionInfo(TabCompletionInfo.MatchType.OTHER, identifiers, end); - } - return null; - } - - @Override - public CharSequence getHelp() { - StringBuffer buf = new StringBuffer(); - Iterator<String> idents = DBConnector.getInstance().getPredefinedConnectionIdentifiers().iterator(); - while (idents.hasNext()) { - buf.append(' '); - String ident = idents.next(); - buf.append(ident); - if (ident.equals(DBConnector.getInstance().getDefaultIdentifier())) { - buf.append(" *"); - } - if (idents.hasNext()) { - buf.append('\n'); - } - } - return "Create a conection to the database\n" + - " user/pass@ident -> connect the user with password pass to the ident\n" + - " user/@ident -> connect the user with an empty password pass to the ident\n"+ - " user@ident -> connect the user to the ident and prompt for password\n"+ - " @ident -> connect to the ident connection.\n"+ - " If default user and/or password are specified these will be used, \n"+ - " otherwise you will be prompted for a username and/or password.\n" + - "Currently configured connection identifiers:\n"+ - buf.toString(); - } - - @Override - public boolean abort() { - return false;// not implemented - } - @Override - public boolean backgroundProcessSupported() { - return false; - } - } - /** - * Command that enables the user to close a connection. - */ - private static class DisConnectCommand implements Command { - @Override - public CharSequence execute(SQLCommand cmd) { - try { - DBConnector.getInstance().disconnect(); - return "Disconnected.\n\n"; - } catch(SQLException e) { - throw new IllegalStateException("Failed to disconnect: " + e.getMessage(), e); - } - } - @Override - public CharSequence getCommandString() { - return "disconnect"; - } - - /** - * Returns some tab completion info for the specified command. - * @param commandInfo the command lines - * @param commandPoint the cursor position - * @return some tab completion info for the specified command. - */ - @Override - public TabCompletionInfo getTabCompletionInfo(SQLCommand command, Point commandPoint) { - return null; - } - @Override - public CharSequence getHelp() { - return "Close the current conection to the database"; - } - @Override - public boolean abort() { - return false;// not implemented - } - @Override - public boolean backgroundProcessSupported() { - return false; - } - } - - /** - * Some basic window settings like resize. - */ - private class WindowCommand implements Command { - @Override - public CharSequence execute(SQLCommand cmd) { - String command = cmd.getCommandString(); - String argument = command.trim().substring("window".length()).trim(); - if (argument.equalsIgnoreCase("resize")) { - resize(Toolkit.getScreenWidth(),Toolkit.getScreenHeight()); - return "Window resized to " + Toolkit.getScreenWidth() +"x"+Toolkit.getScreenHeight(); - } - return "Uknown command '"+ argument+"'"; - } - - @Override - public CharSequence getCommandString() { - return "window"; - } - - /** - * Returns some tab completion info for the specified command. - * @param commandInfo the command lines - * @param commandPoint the cursor position - * @return some tab completion info for the specified command. - */ - @Override - public TabCompletionInfo getTabCompletionInfo(SQLCommand command, Point commandPoint) { - return null; - } - @Override - public CharSequence getHelp() { - return "window resize: notify the sql client of a screen resize"; - } - @Override - public boolean abort() { - return false;// not implemented - } - @Override - public boolean backgroundProcessSupported() { - return false; - } - } - - /** - * Provide a list of commands executed. - */ - private class HistoryCommand implements Command { - @Override - public CharSequence execute(SQLCommand command) { - StringBuilder returnValue = new StringBuilder(); - Iterator<SQLCommand> iCommands = commandHistory.iterator(); - while (iCommands.hasNext()) { - SQLCommand cmd = iCommands.next(); - returnValue.append(cmd.getCommandString()); - returnValue.append('\n'); - } - return returnValue; - } - @Override - public CharSequence getCommandString() { - return "history"; - } - - /** - * Returns some tab completion info for the specified command. - * @param commandInfo the command lines - * @param commandPoint the cursor position - * @return some tab completion info for the specified command. - */ - @Override - public TabCompletionInfo getTabCompletionInfo(SQLCommand command, Point commandPoint) { - return null; - } - @Override - public CharSequence getHelp() { - return "Show history of executed statements\n" + - "By using '/<search>' you can search the command history" ; - } - @Override - public boolean abort() { - return false;// not implemented - } - @Override - public boolean backgroundProcessSupported() { - return false; - } - } - - /** - * Exit the client. - */ - private class QuitCommand implements Command { - private String cmd; - - public QuitCommand(String cmd) { - this.cmd = cmd; - } - @Override - public CharSequence execute(SQLCommand command) { - hide(); - return "Application terminated."; - } - @Override - public CharSequence getHelp() { - return "Quit(exit) the application."; - } - @Override - public CharSequence getCommandString() { - return cmd; - } - /** - * Returns some tab completion info for the specified command. - * @param commandInfo the command lines - * @param commandPoint the cursor position - * @return some tab completion info for the specified command. - */ - @Override - public TabCompletionInfo getTabCompletionInfo(SQLCommand command, Point commandPoint) { - return null; - } - @Override - public boolean abort() { - return false;// not implemented - } - @Override - public boolean backgroundProcessSupported() { - return false; - } - } - /** - * Provide help to the user. - */ - private class HelpCommand implements Command { - @Override - public CharSequence execute(SQLCommand sqlCommand) { - // the execution of help consists of: - // 1. is general help.. - // 2. is detailed help about a specific command - // 3. help -k something --> search help for a specific keyword - String command = sqlCommand.getCommandString().trim(); - String cmdString = command.substring("help".length()).trim(); - if (cmdString.endsWith(";")) { - cmdString = cmdString.substring(0, cmdString.length()-1); - } - List<CharSequence> availableCommands = new ArrayList<CharSequence>(); - if (cmdString.length() > 0) { - if (cmdString.startsWith("-k")) { - String keyword = cmdString.subSequence(cmdString.indexOf(" "), cmdString.length()).toString().trim(); - StringBuilder returnValue = new StringBuilder(); - Iterator<Command> iCommands = commands.getCommands().iterator(); - while (iCommands.hasNext()) { - Command cmd= iCommands.next(); - if (cmd.getHelp().toString().indexOf(keyword) >=0 - || cmd.getCommandString().toString().indexOf(keyword) >=0) { - if (returnValue.length() == 0) { - returnValue.append("See the following commands for more details:\n"); - } - returnValue.append(" "); - returnValue.append(cmd.getCommandString()); - returnValue.append("\n"); - } - } - if (returnValue.length() == 0) { - return "Don't know what you mean by '"+ keyword+"'"; - } - return returnValue; - } else { - Iterator<Command> iCommands = commands.getCommands().iterator(); - while (iCommands.hasNext()) { - Command cmd= iCommands.next(); - if (cmd.getCommandString().equals(cmdString)) { - return cmd.getCommandString()+": " - + cmd.getHelp().toString().replaceAll("\n" - , "\n"+emptyLine.substring(0, cmd.getCommandString().length()+3)); - } - } - } - return "Unkown command '"+ cmdString+"'"; - } - // default print all commands - // TODO iterate - StringBuilder returnValue = new StringBuilder(); - returnValue.append("Available key mappings:\n"); - int max = 0; - Iterator<KeyAction> iKeyActions = actionKeys.values().iterator(); - while (iKeyActions.hasNext()) { - max = Math.max(max, iKeyActions.next().getHelp().toString().indexOf('\t')); - } - iKeyActions = actionKeys.values().iterator(); - while (iKeyActions.hasNext()) { - returnValue.append(" "); - //returnValue.append(iKeyActions.next().getHelp()); - String help = iKeyActions.next().getHelp().toString(); - int index = help.indexOf('\t'); - returnValue.append(help.substring(0, index)); - for (int i = index; i < max; i++) { - returnValue.append(' '); - } - returnValue.append(help.substring(index)); - returnValue.append('\n'); - } - returnValue.append("\n\nAvailable commands:\n"); - Iterator<Command> iCommands = commands.getCommands().iterator(); - while (iCommands.hasNext()) { - Command cmd = iCommands.next(); - availableCommands.add(cmd.getCommandString()); - } - returnValue.append(toColumns(availableCommands)); - String helpHeader = "\nHelp for SQLShell client "+SQLProperties.getProperty(SQLProperties.PropertyName.VERSION, "SVN Snapshot")+"\n"+ - "Here you find a list of available commands. "+ - "To get more information about a specific command enter:\n"+ - " help command (for example 'help help')\n\n"+ - "If the list is not sufficient enough you could try searching help using:\n"+ - " help -k searchstring (for example help -k column)\n"+ - "This results in a list of commands matching the searchstring\n\n"; - returnValue.insert(0, helpHeader); - return returnValue; - } - @Override - public CharSequence getCommandString() { - return "help"; - } - - /** - * Returns some tab completion info for the specified command. - * @param commandInfo the command lines - * @param commandPoint the cursor position - * @return some tab completion info for the specified command. - */ - @Override - public TabCompletionInfo getTabCompletionInfo(SQLCommand command, Point commandPoint) { - return null; - } - @Override - public CharSequence getHelp() { - return "this command. Please use 'help' to get a list of available commands you can use."; - } - @Override - public boolean abort() { - return false;// not implemented - } - @Override - public boolean backgroundProcessSupported() { - return false; - } - } - - /** - * Convert '~/' to the username dir. - * @param fileName the filename to convert - * @return the converted filename - */ - private static String toFileName(String fileName) { - if (fileName.startsWith("~/")) { - return System.getProperty("user.home")+fileName.substring(1); - } - return fileName; - } - - /** - * Writes in/output to a file. - */ - private class SpoolCommand implements Command { - private String fileName; - - @Override - public CharSequence execute(SQLCommand cmd) { - String command = cmd.getCommandString(); - String nextPart = command.substring("spool".length()).trim(); - if (nextPart.equalsIgnoreCase("off")) { - if (spoolWriter != null) { - try { - spoolWriter.close(); - } catch(Exception e) {/*ignore*/} - spoolWriter = null; - return "Spool closed."; - } else { - return "No spool to close."; - } - } else { - try { - File f = new File(toFileName(nextPart.trim())); - fileName = f.getAbsolutePath(); - if ((f.exists() && !f.canWrite()) || (!f.exists() && !f.createNewFile())) { - throw new IllegalStateException("Failed to create spool to file: '"+fileName+"'"); - } - spoolWriter = new FileWriter(fileName); - } catch (IOException e) { - throw new IllegalStateException("Failed to create spool ("+fileName+"): " + e.toString(), e); - } - return "Spool to "+fileName+" created."; - } - } - - @Override - public CharSequence getCommandString() { - return "spool"; - } - - /** - * Returns some tab completion info for the specified command. - * @param commandInfo the command lines - * @param commandPoint the cursor position - * @return some tab completion info for the specified command. - */ - @Override - public TabCompletionInfo getTabCompletionInfo(SQLCommand command, Point commandPoint) { - return null; - } - @Override - public CharSequence getHelp() { - return "filename: Spool all output and queries to the specified file\n"+ - "off : Stop spooling data to the file.\n" + - "Current status:"+(spoolWriter != null ? "on, writing to '"+fileName+"'" : "off"); - } - @Override - public boolean abort() { - return false;// not implemented - } - @Override - public boolean backgroundProcessSupported() { - return false; - } - } - - private class ExecuteBatchCommand implements Command { - private boolean cancelled; - private Command currentCommand; - @Override - public CharSequence execute(SQLCommand sqlCommand) { - cancelled = false; - currentCommand = null; - String command = sqlCommand.getCommandString(); - // read file from file system and execute - FileInputStream fin = null; - try { - fin = new FileInputStream(toFileName(command.substring(1))); - output("Reading file: "+ toFileName(command.substring(1))); - BufferedReader reader = new BufferedReader(new InputStreamReader(fin)); - StringBuilder cmd = new StringBuilder(); - String line; - while ( ((line = reader.readLine()) != null)) { - if (cancelled) { - return "Aborted"; - } - if (line.startsWith("--")) { - continue; - } - cmd.append(line); - if (line.endsWith(";")) { - // Exec cmd - String commandString = cmd.toString(); - currentCommand = createCommand(commandString); - output(commandString); - output(currentCommand.execute(new InputCommand(commandString))); - cmd=new StringBuilder(); - new Thread() { public void run() { paint();}}.start(); - } - ... [truncated message content] |