gt:             _stmt = session.getConnection().prepareStatement(stmtString);
context: /*
   * This is free software, licensed under the Gnu Public License (GPL) get a copy from <http://www.gnu.org/licenses/gpl.html>
   * 
   * author: Henner Zeller <H.Zeller@acm.org>
   */
  package henplus.commands;
  
  import henplus.AbstractCommand;
  import henplus.CommandDispatcher;
  import henplus.HenPlus;
  import henplus.Interruptable;
  import henplus.SQLSession;
  import henplus.SigIntHandler;
  import henplus.importparser.IgnoreTypeParser;
  import henplus.importparser.ImportParser;
  import henplus.importparser.QuotedStringParser;
  import henplus.importparser.TypeParser;
  import henplus.importparser.ValueRecipient;
  import henplus.logging.Logger;
  import henplus.view.util.NameCompleter;
  
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.io.Reader;
  import java.nio.charset.Charset;
  import java.sql.PreparedStatement;
  import java.util.ArrayList;
  import java.util.Calendar;
  import java.util.Collection;
  import java.util.Iterator;
  import java.util.List;
  import java.util.StringTokenizer;
  import java.util.zip.GZIPInputStream;
  
  /*
   * Todo: - where clause with regexp - fix quoting handling
   */
  
  /**
   * document me.
   */
  public class ImportCommand extends AbstractCommand {
  
      private static final String DEFAULT_ROW_DELIM = "\n";
      private static final String DEFAULT_COL_DELIM = "\t";
      private static final String COMMAND_QUOTES = "\"\"''()";
  
      private final ListUserObjectsCommand _tableCompleter;
  
      /**
       * returns the command-strings this command can handle.
       */
      @Override
      public String[] getCommandList() {
          return new String[] { "import", "import-check", "import-print" };
      }
  
      public ImportCommand(final ListUserObjectsCommand tc) {
          _tableCompleter = tc;
      }
  
      @Override
      public boolean requiresValidSession(final String cmd) {
          return "import".equals(cmd);
      }
  
      @Override
      public Iterator<String> complete(final CommandDispatcher disp, String partialCommand, final String lastWord) {
          final ConfigurationParser parser = new ConfigurationParser(_tableCompleter);
          if ("".equals(lastWord)) {
              partialCommand += " ";
          } else if (!partialCommand.endsWith(lastWord)) {
              partialCommand += lastWord;
          }
          return parser.complete(stripCommand(partialCommand));
      }
  
      private String stripCommand(final String cmd) {
          final int len = cmd.length();
          for (int i = 0; i < len; ++i) {
              if (Character.isWhitespace(cmd.charAt(i))) {
                  return cmd.substring(i);
              }
          }
          return "";
      }
  
      /**
       * execute the command given.
       */
      @Override
      public int execute(final SQLSession session, final String cmd, final String param) {
          /*
           * HenPlus.msg().println("cmd='" + cmd + "';" + "param='" + param +
           * "'");
           */
          final ConfigurationParser parser = new ConfigurationParser(param);
          final String error = parser.getParseError();
          if (error != null) {
              HenPlus.msg().println(error);
              return SYNTAX_ERROR;
          }
          final ImportConfiguration config = parser.getConfig();
  
          try {
              final long startTime = System.currentTimeMillis();
              final long startRow = config.getStartRow();
              final long rowCount = config.getRowCount();
              long endRow = -1;
              if (rowCount >= 0) {
                  endRow = startRow > 0 ? startRow + rowCount : rowCount;
              }
              RowCountingRecipient innerRecipient = null;
              if ("import-print".equals(cmd)) {
                  innerRecipient = new PrintRecipient(config.getColumns());
              } else if ("import-check".equals(cmd)) {
                  innerRecipient = new CountRecipient();
              } else if ("import".equals(cmd)) {
                  innerRecipient = new SqlImportProcessor(session, config);
              }
  
              final FilterRecipient filterRecipient = new FilterRecipient(startRow, endRow, innerRecipient);
              SigIntHandler.getInstance().pushInterruptable(filterRecipient);
              importFile(config, filterRecipient);
              final long readRows = filterRecipient.getRowCount();
              final long processedRows = innerRecipient.getRowCount();
  
              final long execTime = System.currentTimeMillis() - startTime;
  
              HenPlus.msg().print("reading " + readRows + " rows from '" + config.getFilename() + "' took ");
              TimeRenderer.printTime(execTime, HenPlus.msg());
              HenPlus.msg().print(" total; ");
              TimeRenderer.printFraction(execTime, readRows, HenPlus.msg());
              HenPlus.msg().println(" / row");
              HenPlus.msg().println("processed " + processedRows + " rows");
          } catch (final Exception e) {
              e.printStackTrace();
              return EXEC_FAILED;
          }
          return SUCCESS;
      }
  
      private void importFile(final ImportConfiguration config, final ValueRecipient recipient) throws Exception {
          final File file = new File(config.getFilename());
          final String encoding = config.getEncoding() != null ? config.getEncoding() : "ISO-8859-1";
          InputStream fileIn = new FileInputStream(file);
          if (config.getFilename().endsWith(".gz")) {
              fileIn = new GZIPInputStream(fileIn);
          }
          final Reader reader = new InputStreamReader(fileIn, encoding);
          final int colCount = config.getColumns().length;
  
          // TODO: parse type after colon.
          final TypeParser[] colParser = new TypeParser[colCount];
          int colIndex = 0;
          for (int i = 0; i < colCount; ++i) {
              final String colName = config.getColumns()[i];
              colParser[i] = colName == null ? (TypeParser) new IgnoreTypeParser() : (TypeParser) new QuotedStringParser(colIndex++);
          }
          try {
              final String colDelim = config.getColDelimiter() != null ? config.getColDelimiter() : DEFAULT_COL_DELIM;
              final String rowDelim = config.getRowDelimiter() != null ? config.getRowDelimiter() : DEFAULT_ROW_DELIM;
              final ImportParser parser = new ImportParser(colParser, colDelim, rowDelim);
              parser.parse(reader, recipient);
          } finally {
              reader.close();
          }
      }
  
      private interface RowCountingRecipient extends ValueRecipient {
  
          long getRowCount();
      }
  
      private static class FilterRecipient implements RowCountingRecipient, Interruptable {
  
          private final long _startRow;
          private final long _endRow;
          private final ValueRecipient _target;
          private long _rows;
          private volatile boolean _finished;
  
          public FilterRecipient(final long startRow, final long endRow, final ValueRecipient target) {
              _rows = 0;
              _startRow = startRow;
              _endRow = endRow;
              _target = target;
          }
  
          private boolean expressionMatches() {
              return true; // no expression match yet.
          }
  
          private boolean rangeValid() {
              if (_startRow >= 0) {
                  if (_rows < _startRow) {
                      return false;
                  }
              }
              if (_endRow >= 0) {
                  if (_rows >= _endRow) {
                      return false;
                  }
              }
              return true;
          }
  
          @Override
          public void setLong(final int fieldNumber, final long value) throws Exception {
              if (rangeValid()) {
                  _target.setLong(fieldNumber, value);
              }
          }
  
          @Override
          public void setString(final int fieldNumber, final String value) throws Exception {
              if (rangeValid()) {
                  _target.setString(fieldNumber, value);
              }
          }
  
          @Override
          public void setDate(final int fieldNumber, final Calendar cal) throws Exception {
              if (rangeValid()) {
                  _target.setDate(fieldNumber, cal);
              }
          }
  
          @Override
          public void interrupt() {
              _finished = true;
          }
  
          @Override
          public long getRowCount() {
              return _rows;
          }
  
          @Override
          public boolean finishRow() throws Exception {
              boolean deligeeFinish = false;
              if (rangeValid() && expressionMatches()) {
                  deligeeFinish = _target.finishRow();
              }
              _rows++;
              return deligeeFinish || _finished || _endRow >= 0 && _rows >= _endRow;
          }
      }
  
      private static final class CountRecipient implements RowCountingRecipient {
  
          private long _rows;
  
          CountRecipient() {
              _rows = 0;
          }
  
          @Override
          public void setLong(final int fieldNumber, final long value) {
          }
  
          @Override
          public void setString(final int fieldNumber, final String value) {
          }
  
          @Override
          public void setDate(final int fieldNumber, final Calendar cal) {
          }
  
          @Override
          public boolean finishRow() {
              ++_rows;
              return false;
          }
  
          @Override
          public long getRowCount() {
              return _rows;
          }
      }
  
      private static final class PrintRecipient implements RowCountingRecipient {
  
          private final String[] _paddedNames;
          private long _rows;
          private boolean _colWritten;
  
          public PrintRecipient(final String[] columnNames) {
              _rows = 0;
              int maxLen = -1;
              int maxIndex = 0;
              // find max length and col-number
              for (int i = 0; i < columnNames.length; ++i) {
                  final String colName = columnNames[i];
                  if (colName != null) {
                      if (colName.length() > maxLen) {
                          maxLen = colName.length();
                      }
                      maxIndex++;
                  }
              }
              _paddedNames = new String[maxIndex];
              int colIndex = 0;
              // precalculate padded names
              for (int i = 0; i < columnNames.length; ++i) {
                  final String colName = columnNames[i];
                  if (colName == null) {
                      continue;
                  }
                  _paddedNames[colIndex] = colName;
                  while (_paddedNames[colIndex].length() < maxLen) {
                      _paddedNames[colIndex] += " ";
                  }
                  _paddedNames[colIndex] += " : ";
                  colIndex++;
              }
              _colWritten = false;
          }
  
          private boolean printColName(final int fieldNumber) {
              if (fieldNumber > _paddedNames.length) {
                  return false;
              }
              final String colName = _paddedNames[fieldNumber];
              if (colName == null) {
                  return false;
              }
              if (!_colWritten) {
                  HenPlus.msg().attributeBold();
                  HenPlus.msg().println("----------------------- row " + _rows + " :");
                  HenPlus.msg().attributeReset();
                  _colWritten = true;
              }
              HenPlus.msg().attributeBold();
              HenPlus.msg().print(colName); // TODO: padding.
              HenPlus.msg().attributeReset();
              return true;
          }
  
          @Override
          public void setLong(final int fieldNumber, final long value) {
              if (printColName(fieldNumber)) {
                  HenPlus.msg().println(String.valueOf(value));
              }
          }
  
          @Override
          public void setString(final int fieldNumber, final String value) {
              if (printColName(fieldNumber)) {
                  HenPlus.msg().println(value);
              }
          }
  
          @Override
          public void setDate(final int fieldNumber, final Calendar cal) {
              if (printColName(fieldNumber)) {
                  HenPlus.msg().println(cal != null ? cal.getTime().toString() : null);
              }
          }
  
          @Override
          public long getRowCount() {
              return _rows;
          }
  
          @Override
          public boolean finishRow() throws Exception {
              _rows++;
              _colWritten = false;
              return false;
          }
      }
  
      private static final class SqlImportProcessor implements RowCountingRecipient {
  
          private long _rows;
          private final PreparedStatement _stmt;
  
          public SqlImportProcessor(final SQLSession session, final ImportConfiguration config) throws Exception {
              _rows = 0;
              final StringBuilder cmd = new StringBuilder("insert into ");
              cmd.append(config.getTable()).append(" (");
              boolean isFirst = true;
              for (int i = 0; i < config.getColumns().length; ++i) {
                  if (config.getColumns()[i] != null) {
                      if (!isFirst) {
                          cmd.append(",");
                      }
                      isFirst = false;
                      cmd.append(config.getColumns()[i]);
                  }
              }
              cmd.append(") values (");
              isFirst = true;
              for (int i = 0; i < config.getColumns().length; ++i) {
                  if (config.getColumns()[i] != null) {
                      if (!isFirst) {
                          cmd.append(",");
                      }
                      isFirst = false;
                      cmd.append("?");
                  }
              }
              cmd.append(")");
              final String stmtString = cmd.toString();
              Logger.info("INSERTING WITH " + stmtString);
  