[Mulgara-svn] r456 - branches/nw-interface/src/jar/itql/java/org/mulgara/itql

pag at mulgara.org pag at mulgara.org
Wed Sep 26 04:51:34 UTC 2007


Author: pag
Date: 2007-09-25 23:51:33 -0500 (Tue, 25 Sep 2007)
New Revision: 456

Modified:
   branches/nw-interface/src/jar/itql/java/org/mulgara/itql/TqlAutoInterpreter.java
   branches/nw-interface/src/jar/itql/java/org/mulgara/itql/TqlSession.java
   branches/nw-interface/src/jar/itql/java/org/mulgara/itql/TqlSessionUI.java
Log:
Major round of debugging on the new TqlSession front end.  Found some incorrect code paths I made in the port, but also discovered some bad and unused code in the original ItqlSessions. Pipe reading is particularly egregious.

Modified: branches/nw-interface/src/jar/itql/java/org/mulgara/itql/TqlAutoInterpreter.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/itql/TqlAutoInterpreter.java	2007-09-26 04:49:58 UTC (rev 455)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/itql/TqlAutoInterpreter.java	2007-09-26 04:51:33 UTC (rev 456)
@@ -19,6 +19,7 @@
 import org.mulgara.connection.Connection;
 import org.mulgara.connection.ConnectionException;
 import org.mulgara.connection.ConnectionFactory;
+import org.mulgara.connection.DummyConnection;
 import org.mulgara.parser.Interpreter;
 import org.mulgara.query.Answer;
 import org.mulgara.query.QueryException;
@@ -37,6 +38,8 @@
 public class TqlAutoInterpreter {
   /** The logger. */
   private final static Logger logger = Logger.getLogger(TqlAutoInterpreter.class.getName());
+  
+  private static Connection localStateConnection = new DummyConnection();
 
   /** The parser and AST builder for commands. */
   private Interpreter interpreter = new TqlInterpreter();
@@ -88,8 +91,8 @@
     // execute the operation
     try {
       // set up a connection, if required
-      Connection conn = cmd.isLocalOperation() ? null : establishConnection(cmd.getServerURI());
-      cmd.execute(conn);
+      Connection conn = establishConnection(cmd.getServerURI());
+      handleResult(cmd.execute(conn), cmd);
       updateOnConnectionState(conn);
       lastMessage = cmd.getResultMessage();
     } catch (Exception e) {
@@ -97,8 +100,8 @@
       lastMessage = "Error: " + e.getMessage();
     }
 
-    // test if the command wants the user to quit
-    return cmd.isLocalOperation() && ((LocalCommand)cmd).isQuitCommand();
+    // test if the command wants the user to quit - return false if it does
+    return !(cmd.isLocalOperation() && ((LocalCommand)cmd).isQuitCommand());
   }
 
 
@@ -153,6 +156,19 @@
 
 
   /**
+   * Process the result from a command.
+   * @param result The result to handle.
+   * @param cmd The command that gave the result. Used for type checking.
+   */
+  private void handleResult(Object result, Command cmd) {
+    if (result != null) {
+      if (cmd.isAnswerable()) lastAnswer = (Answer)result;
+      else logger.debug("Result: " + result);
+    }
+  }
+
+
+  /**
    * Returns a connection to the server with the given URI.
    * @param serverUri The URI for the server to get a connection to.
    * @return A connection to the server, cached if available.
@@ -160,8 +176,7 @@
    * @throws QueryException There is a transaction underway, but the new connection cannot turn off autocommit.
    */
   private Connection establishConnection(URI serverUri) throws ConnectionException, QueryException {
-    if (serverUri == null) throw new IllegalArgumentException("Server URI may not be null.");
-    Connection connection = connectionFactory.newConnection(serverUri);
+    Connection connection = (serverUri == null) ? localStateConnection : connectionFactory.newConnection(serverUri);
     // If in a transaction, turn off autocommit 
     if (inTransaction && connection.getAutoCommit()) {
       connection.setAutoCommit(false);

Modified: branches/nw-interface/src/jar/itql/java/org/mulgara/itql/TqlSession.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/itql/TqlSession.java	2007-09-26 04:49:58 UTC (rev 455)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/itql/TqlSession.java	2007-09-26 04:51:33 UTC (rev 456)
@@ -129,28 +129,37 @@
       // command line options as we can override the defaults
       tqlSession.executeLoadingScript(tqlSession.getPreLoadingScriptURL());
 
-      tqlSession.executeScript(tqlSession.getScript());
-
       if (log.isDebugEnabled()) log.debug("Executed pre-loading script");
 
       // if we can, execute this session using std in and std out
       if (startSession) tqlSession.runInterface();
-      else tqlSession.executeLoadingScript(tqlSession.getPostLoadingScriptURL());
+      else {
+        // otherwise, run the scripts we were given
+        tqlSession.executeScript(tqlSession.getScript());
+        tqlSession.executeLoadingScript(tqlSession.getPostLoadingScriptURL());
+        tqlSession.close();
+      }
 
     } catch (ItqlOptionParser.UnknownOptionException uoe) {
-      log.warn("Invalid command line option specified: " + uoe.getOptionName());
-      System.err.println("Invalid option: " + uoe.getOptionName());
-      tqlSession.printUsage(System.out);
+      errorTermination(tqlSession, "Invalid command line option: " + uoe.getOptionName());
     } catch (ItqlOptionParser.IllegalOptionValueException iove) {
-      String optionMsg = "-" + iove.getOption().shortForm() + ", --" +
-          iove.getOption().longForm() + " = " + iove.getValue();
-      log.warn("Invalid command line option value specified: " + optionMsg);
-      System.err.println("Invalid option value: " + optionMsg);
-      tqlSession.printUsage(System.out);
+      String optionMsg = "-" + iove.getOption().shortForm() + ", --" + iove.getOption().longForm() + " = " + iove.getValue();
+      errorTermination(tqlSession, "Invalid command line option value specified: " + optionMsg);
     }
-    tqlSession.close();
   }
 
+  
+  /**
+   * Convenience method to log errors and terminate the program.
+   * @param session The current session to close.
+   * @param message The error message to log.
+   */
+  private static void errorTermination(TqlSession session, String message) {
+    log.warn(message);
+    System.err.println(message);
+    session.printUsage(System.out);
+    session.close();
+  }
 
   /**
    * Constructor.  Creates a new TQL session.
@@ -217,6 +226,15 @@
     }
   }
 
+  /**
+   * Executes a script given by URL name. {@see executeScript} for implementation.
+   * @param script The string for the script URL.
+   * @throws MalformedURLException The given script name cannot be represented as a URL.
+   */
+  private void executeScript(String script) throws MalformedURLException {
+    if (script == null) return;
+    executeScript(new URL(script));
+  }
 
   /**
    * Executes a script.  This is done separately to {@link org.mulgara.query.operation.ExecuteScript}
@@ -279,7 +297,7 @@
     mainWindow.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
     mainWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
 
-    gui = new TqlSessionUI(this);
+    gui = new TqlSessionUI(this, System.in, System.out);
     mainWindow.getContentPane().add(gui);
 
     if (log.isInfoEnabled()) log.info("Starting TQL interpreter");
@@ -308,11 +326,10 @@
 
   /**
    * Returns the location of the script to run.
-   * @return the location of the script to run.
-   * @throws MalformedURLException The script location is not a valid URL.
+   * @return A string with the location of the script to run.
    */
-  private URL getScript() throws MalformedURLException {
-    return new URL(scriptLocation);
+  private String getScript() throws MalformedURLException {
+    return scriptLocation;
   }
 
 
@@ -464,7 +481,8 @@
         }
 
         // If there is a script to run, then return false, else true for no script
-        return null == parser.getOptionValue(ItqlOptionParser.SCRIPT);
+        scriptLocation = (String)parser.getOptionValue(ItqlOptionParser.SCRIPT);
+        return null == scriptLocation;
       }
     } catch (MalformedURLException e) {
       log.warn("Invalid URL on command line - " + e.getMessage());

Modified: branches/nw-interface/src/jar/itql/java/org/mulgara/itql/TqlSessionUI.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/itql/TqlSessionUI.java	2007-09-26 04:49:58 UTC (rev 455)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/itql/TqlSessionUI.java	2007-09-26 04:51:33 UTC (rev 456)
@@ -44,11 +44,15 @@
  *
  * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
  */
-import java.io.*;
 import java.util.*;
+import java.util.List;
 
 import java.awt.*;
 import java.awt.event.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
 import javax.swing.*;
 import javax.swing.text.*;
 
@@ -61,81 +65,48 @@
 public class TqlSessionUI extends JScrollPane implements Runnable,
     KeyListener, java.awt.event.MouseListener, ActionListener {
 
-  /**
-   * The logging category to log to
-   */
+  /** The logging category to log to */
   private final static Logger log = Logger.getLogger(TqlSessionUI.class);
+  
+  private static final String NEWLINE = System.getProperty("line.separator");
+  
+  /** The bold font used for output */
+  private final Font boldFont = new Font("Monospaced", Font.BOLD, 12);
+  
+  /** The iTQL session to send queries and used to send results. */
+  private TqlSession tqlSession;
 
-  /**
-   * Inputstream to take user input.
-   */
-  private InputStream in;
-
-  /**
-   * Outputstream to display user output.
-   */
-   private PrintStream out;
-
-  /**
-   * Used to pipe input.
-   */
+  /** Used to pipe input. */
   private InputStream inPipe;
 
-  /**
-   * Used to pipe output.
-   */
-  private OutputStream outPipe;
+  /** The list of history items. */
+  private ArrayList<String> history = new ArrayList<String>();
 
-  /**
-   * The iTQL session to send queries and used to send results.
-   */
-  private TqlSession tqlSession;
-
-  /**
-   * The list of history items.
-   */
-  private ArrayList history = new ArrayList();
-
-  /**
-   * Current index into the history.
-   */
+  /** Current index into the history. */
   private int historyIndex = 0;
 
-  /**
-   * Current cursor position.
-   */
+  /** Current cursor position. */
   private int cursorPosition = 0;
 
-  /**
-   * The UI widget for displaying all text.
-   */
+  /** The UI widget for displaying all text. */
   private JTextPane text;
 
-  /**
-   * The default styled document.
-   */
+  /** The default styled document. */
   private DefaultStyledDocument doc;
 
-  /**
-   * Popup menu for Windows users.
-   */
+  /** Popup menu for Windows users. */
   private JPopupMenu popupMenu = new JPopupMenu();
 
-  /**
-   * Whether we are running a command still.
-   */
+  /** Whether we are running a command still. */
   private volatile boolean runningCommand = false;
 
   /**
    * Create a new UI representation.
-   *
    * @param newItqlSession the itql session to call when we receive commands and
-   *   when we want to display them.
+   *        when we want to display them.
    */
-  public TqlSessionUI(TqlSession newTqlSession) {
-
+  public TqlSessionUI(TqlSession newTqlSession, InputStream inStream, OutputStream outStream) {
     super();
-
     tqlSession = newTqlSession;
     doc = new DefaultStyledDocument();
     text = new PasteablePane(doc);
@@ -157,25 +128,8 @@
     copyItem.addActionListener(this);
     pasteItem.addActionListener(this);
 
-    outPipe = new PipedOutputStream();
-    try {
+    inPipe = inStream;
 
-      in = new PipedInputStream((PipedOutputStream) outPipe);
-    } catch (IOException e) {
-
-      log.error("Error creating input stream", e);
-    }
-
-    PipedOutputStream pout = new PipedOutputStream();
-    out = new PrintStream(pout);
-    try {
-
-      inPipe = new PipedInputStream(pout);
-    } catch (IOException e) {
-
-      log.error("Error creating input pipe", e);
-    }
-
     // Start the inpipe watcher
     new Thread(this).start();
     requestFocus();
@@ -456,7 +410,7 @@
 
       // Put the command at the end of the array.
       history.add(command);
-      command = command + System.getProperty("line.separator");
+      command = command + NEWLINE;
 
       // If the array gets too large remove the last entry.
       if (history.size() > 30) {
@@ -552,8 +506,7 @@
    * @param message the message to display.
    */
   public void println(String message) {
-
-    print(message + System.getProperty("line.separator"));
+    print(message + NEWLINE);
     text.repaint();
   }
 
@@ -561,23 +514,17 @@
    * Prints empty line.
    */
   public void println() {
-
-    print(System.getProperty("line.separator"));
+    print(NEWLINE);
     text.repaint();
   }
 
   /**
-   * Prints a message to the UI.
-   *
+   * Prints a message to the UI. Sends a little "closure" to the UI thread.
    * @param message the message to display.
    */
   public void print(final String message) {
-
     invokeAndWait(new Runnable() {
-
       public void run() {
-
-
         append(message);
         cursorPosition = textLength();
         text.setCaretPosition(cursorPosition);
@@ -585,43 +532,37 @@
     });
   }
 
+
   /**
    * Print out an error message to the UI.
-   *
    * @param errorMessage the error message to display.
    */
   public void error(String errorMessage) {
-
     print(errorMessage, Color.red);
   }
 
+
   /**
    * Print out the message with the given color using the current font.
-   *
    * @param message the message to display.
    * @param color the color to use.
    */
   public void print(String message, Color color) {
-
     print(message, null, color);
   }
 
+
   /**
-   * Print out the message with the given font and colour.  Uses invoke and
-   * wait.
-   *
+   * Print out the message with the given font and colour.
+   * Uses invoke and wait to send a "closure" to the UI thread.
    * @param message the message to display.
    * @param font the font to use.
    * @param color the color to use.
    */
   public void print(final String message, final Font font, final Color color) {
-
     invokeAndWait(new Runnable() {
-
       public void run() {
-
         try {
-
           AttributeSet oldStyle = text.getCharacterAttributes();
           setStyle(font, color);
           append(message);
@@ -629,36 +570,37 @@
           text.setCaretPosition(cursorPosition);
           text.setCharacterAttributes(oldStyle, true);
         } catch (Exception e) {
-
           log.error("Error when printing: " + message, e);
         }
       }
     });
   }
 
+
   /**
+   * Print out the message followed by a newline with the given font and colour.
+   * @param message the message to display.
+   * @param font the font to use.
+   * @param color the color to use.
+   */
+  public void println(final String message, final Font font, final Color color) {
+    print(message + NEWLINE, font, color);
+    text.repaint();
+  }
+
+
+  /**
    * Sets the new style of a font and color to the text.
-   *
    * @param font the new font.
    * @param color the new color.
    * @return the attributes of the given font and color.
    */
   private AttributeSet setStyle(Font font, Color color) {
-
     MutableAttributeSet attr = new SimpleAttributeSet();
     StyleConstants.setForeground(attr, color);
-
     // Don't set if null
     if (font != null) {
-
-      if (font.isBold()) {
-
-        StyleConstants.setBold(attr, true);
-      } else {
-
-        StyleConstants.setBold(attr, false);
-      }
-
+      StyleConstants.setBold(attr, font.isBold());
       StyleConstants.setFontFamily(attr, font.getFamily());
       StyleConstants.setFontSize(attr, font.getSize());
     }
@@ -666,57 +608,51 @@
     return text.getCharacterAttributes();
   }
 
+
   /**
    * Append the given string to the existing string.
-   *
    * @param newString the string to append to.
    */
   private void append(String newString) {
-
     int length = textLength();
     text.select(length, length);
     text.replaceSelection(newString);
   }
 
+
   /**
-   * Thread that runs while waiting for input.
+   * Thread that reads the inPipe, and prints the output.
    */
   public void run() {
-
     try {
-
       byte[] buffer = new byte[255];
       int read;
-      while ((read = inPipe.read(buffer)) != -1) {
-
-        print(new String(buffer, 0, read));
-      }
+      log.info("Starting input reader");
+      while ((read = inPipe.read(buffer)) != -1) print(new String(buffer, 0, read));
     } catch (IOException e) {
-
       log.error("Error reading input", e);
     }
+    log.warn("End of input");
   }
 
+
   /**
-   * If not in the event thread run via SwingUtilities.invokeAndWait()
+   * If not in the event thread run via SwingUtilities.invokeAndWait().
+   * @param runnable The operation that a client wants the UI to perform. Like a "closure".
    */
   private void invokeAndWait(Runnable runnable) {
-
     if (!SwingUtilities.isEventDispatchThread()) {
-
       try {
-
         SwingUtilities.invokeAndWait(runnable);
       } catch (Exception e) {
-
         log.error("Error while executing invoke and wait", e);
       }
     } else {
-
       runnable.run();
     }
   }
 
+
   /**
    * Extension to JTextPane to put all pastes at the end of the command line.
    */
@@ -731,145 +667,113 @@
     }
   }
 
+  /** Class to listen for mouse press events. */
   class MouseListener implements AWTEventListener {
-
     public void eventDispatched(AWTEvent event) {
-
-      MouseEvent me = (MouseEvent) event;
-      if (me.getButton() == MouseEvent.BUTTON2) {
-
-        me.consume();
-      }
+      MouseEvent me = (MouseEvent)event;
+      if (me.getButton() == MouseEvent.BUTTON2) me.consume();
     }
   }
 
+
   /**
    * Executes the command in a separate thread and display the results.
    */
   class ExecutionThread extends Thread {
 
-    /**
-     * The command to execute.
-     */
+    /** The command to execute. */
     private String command;
 
     /**
      * Create a new execution thread.
-     *
      * @param threadName the name of the thread.
      * @param newCommand the iTQL command to execute.
      */
     public ExecutionThread(String threadName, String newCommand) {
-
       super(threadName);
       command = newCommand;
     }
 
+
     /**
      * Run the command and display answer results.
      */
     public void run() {
-
       tqlSession.executeCommand(command);
       println();
 
-      java.util.List answers = tqlSession.getLastAnswers();
-      java.util.List messages = tqlSession.getLastMessages();
+      List<Answer> answers = tqlSession.getLastAnswers();
+      List<String> messages = tqlSession.getLastMessages();
 
-      int answerIndex = 0;
-      String lastMessage;
-
-      while (answerIndex < answers.size()) {
-
-        lastMessage = (String) messages.get(answerIndex);
-
-        try {
-
-          // Assume the same number of answers and messages
-          Answer answer = (Answer) answers.get(answerIndex);
-
-          // If there's more than one answer print a heading.
-          if (answers.size() > 1) {
-
-            println();
-            // If there's more than one answer add an extra line before the
-            // heading.
-            print("Executing Query " + (answerIndex+1),
-                new Font("Monospaced", Font.BOLD, 12), Color.BLACK);
-            println();
-          }
-
-          // print the results
-          if (answer != null) {
-
-            boolean hasAnswers = true;
-
-            answer.beforeFirst();
-            long rowCount = 0;
-
-            if (answer.isUnconstrained()) {
-              println("[ true ]");
-              rowCount = 1;
-            } else {
-              if (!answer.next()) {
-                print("No results returned.",
-                    new Font("Monospaced", Font.BOLD, 12), Color.BLACK);
-                hasAnswers = false;
+      if (answers.isEmpty()) {
+        for (String message: messages) println(message, boldFont, Color.BLACK);
+      } else {
+        int answerIndex = 0;
+        while (answerIndex < answers.size()) {
+          String lastMessage = (String)messages.get(answerIndex);
+          try {
+            // Assume the same number of answers and messages
+            Answer answer = answers.get(answerIndex);
+  
+            // If there's more than one answer print a heading.
+            if (answers.size() > 1) {
+              println();
+              // If there's more than one answer add an extra line before the heading.
+              println("Executing Query " + (answerIndex+1), boldFont, Color.BLACK);
+            }
+  
+            // print the results
+            if (answer != null) {
+              boolean hasAnswers = true;
+  
+              long rowCount = 0;
+              answer.beforeFirst();
+              if (answer.isUnconstrained()) {
+                println("[ true ]");
+                rowCount = 1;
               } else {
-                do {
-                  rowCount++;
-                  print("[ ");
-                  for (int index = 0; index < answer.getNumberOfVariables();
-                      index++) {
-                    Object object = answer.getObject(index);
-
-                    assert(object instanceof Answer) ||
-                          (object instanceof Node  ) ||
-                          (object == null);
-
-                    print(String.valueOf(object));
-                    if (index < (answer.getNumberOfVariables() - 1)) {
-                      print(", ");
+                if (!answer.next()) {
+                  print("No results returned.", boldFont, Color.BLACK);
+                  hasAnswers = false;
+                } else {
+                  do {
+                    rowCount++;
+                    print("[ ");
+                    for (int index = 0; index < answer.getNumberOfVariables(); index++) {
+                      Object object = answer.getObject(index);
+                      assert(object instanceof Answer) ||
+                            (object instanceof Node  ) ||
+                            (object == null);
+                      print(String.valueOf(object));
+                      if (index < (answer.getNumberOfVariables() - 1)) print(", ");
                     }
-                  }
-                  println(" ]");
+                    println(" ]");
+                  } while (answer.next());
                 }
-                while (answer.next());
               }
+              if (hasAnswers) println(rowCount + " rows returned.", boldFont, Color.BLACK);
+              answer.close();
             }
-            if (hasAnswers) {
-              print(rowCount + " rows returned.",
-                  new Font("Monospaced", Font.BOLD, 12), Color.BLACK);
-            }
-
-            answer.close();
+          } catch (Exception te) {
+            // Failed to iterate over or retrieve the answer.
+            log.fatal("Failed to retrieve or iterate over answer", te);
+            error("Failed to get answer");
           }
-        } catch (Exception te) {
-
-          // Failed to iterate over or retrieve the answer.
-          log.fatal("Failed to retrieve or iterate over answer", te);
-          error("Failed to get answer");
+  
+          if ((lastMessage != null) && (lastMessage != "")) print(lastMessage, boldFont, Color.BLACK);
+  
+          // If there's more than one answer add a new line.
+          if (answers.size() > 1)  println();
+  
+          // Increment index
+          answerIndex++;
         }
-
-        if ((lastMessage != null) && (lastMessage != "")) {
-
-          print(lastMessage, new Font("Monospaced", Font.BOLD, 12),
-              Color.BLACK);
-        }
-
-        // If there's more than one answer add a new line.
-        if (answers.size() > 1) {
-
-          println();
-        }
-
-        // Increment index
-        answerIndex++;
       }
 
       // Signal that the command has finished and display prompt
       runningCommand = false;
       printPrompt();
     }
-  };
+  }
+  
 }




More information about the Mulgara-svn mailing list