Exemple #1
0
 public ChangeVO updateRow(
     int windowNo,
     int AD_Tab_ID,
     int queryResultID,
     int relRowNo,
     Map<String, String> context,
     boolean force) {
   if (context == null || context.size() == 0)
     return new ChangeVO(true, Msg.translate(m_context, "NoContext"));
   ArrayList<String[]> data = m_results.get(queryResultID);
   if (data == null || data.size() == 0)
     return new ChangeVO(true, Msg.translate(m_context, "CachedDataNotFound"));
   UITab tab = getTab(AD_Tab_ID);
   if (tab == null) {
     log.config("Not found AD_Tab_ID=" + AD_Tab_ID);
     return new ChangeVO(true, Msg.translate(m_context, "@NotFound@ @AD_Tab_ID@=" + AD_Tab_ID));
   }
   CContext ctx = new CContext(m_context.entrySet());
   ctx.addWindow(windowNo, context);
   ChangeVO retValue;
   if (force) retValue = tab.saveRow(ctx, windowNo, false, null);
   else retValue = tab.saveRow(ctx, windowNo, false, data.get(relRowNo));
   if (retValue.hasError()) return retValue;
   // Update Results
   String[] dataRow = retValue.rowData.clone();
   data.set(relRowNo, dataRow);
   postProcessChangeVO(retValue, windowNo, context, dataRow, tab);
   retValue.trxInfo = GridTab.getTrxInfo(tab.getTableName(), ctx, windowNo, tab.getTabNo());
   if (retValue.isRefreshAll()) {}
   return retValue;
 }
Exemple #2
0
 private void postProcessChangeVO(
     ChangeVO change, int windowNo, Map<String, String> context, String[] dataRow, UITab tab) {
   // make an updated context to get the necessary listboxvos
   Map<String, String> contextAfterUpdate = new HashMap<String, String>(context);
   int j = 0;
   for (UIField field : tab.getFields()) {
     contextAfterUpdate.put(field.getColumnName(), dataRow[j]);
     j++;
   }
   // now change rowData to remove password, and reload the changed
   // listboxes
   j = 0;
   for (UIField field : tab.getFields()) {
     // return an empty string for passwords etc
     if (field.isEncryptedField()
         || field.isEncryptedColumn()
         || "Password".equals(field.getColumnName())) change.rowData[j] = "";
     if (FieldType.isClientLookup(field.getAD_Reference_ID()) && field.isDependentValue()) {
       if (change.changedDropDowns == null)
         change.changedDropDowns = new HashMap<String, ArrayList<NamePair>>();
       ArrayList<NamePair> values;
       if (field.getAD_Reference_ID() == DisplayTypeConstants.Search) {
         ArrayList<String> t = new ArrayList<String>(1);
         t.add(context.get(field.getColumnName()));
         values = getLookupValueDirect(field.getAD_Field_ID(), t, true);
       } else values = getLookupData(windowNo, field.getAD_Field_ID(), context, true);
       change.changedDropDowns.put(field.getColumnName(), values);
     }
     j++;
   }
 }
Exemple #3
0
  /**
   * Get Field Lookup Value Direct
   *
   * @param windowNo Window
   * @param AD_Field_ID
   * @param keyValues array of id values
   * @param cache
   * @return list of display values
   */
  public ArrayList<NamePair> getLookupValueDirect(
      int AD_Field_ID, ArrayList<String> keyValues, boolean cache) {
    int windowNo = 0; // No Context
    ArrayList<NamePair> displayValues = new ArrayList<NamePair>();
    UIField field = getField(AD_Field_ID, windowNo);

    // if (cache && field.isLookup())
    // field.getLookup().removeAllElements();
    if (field == null) log.warning("Cannot find AD_Field_ID=" + AD_Field_ID);
    //
    for (int i = 0; i < keyValues.size(); i++) {
      String key = keyValues.get(i);
      String value = null;
      if (field != null) value = field.getLookupDisplay(m_context, windowNo, key, cache);
      if (value == null) {
        /*
         * if(key == null) value = ""; else value = "<" + key + ">";
         */
        value = "";
      }
      NamePair pp = new ValueNamePair(key, value);
      displayValues.add(pp);
    }
    return displayValues;
  } // getLookupValueDirect
Exemple #4
0
  /**
   * Save (Insert new) Row of Tab
   *
   * @param windowNo relative window
   * @param AD_Tab_ID tab
   * @param curRow insert after relative row number in results
   * @param context current (relevant) context of new row
   * @return error message or null
   */
  public ChangeVO insertRow(
      int windowNo, int AD_Tab_ID, int queryResultID, int curRow, Map<String, String> context) {
    if (context == null || context.size() == 0) return new ChangeVO(true, "No Context");
    UITab tab = getTab(AD_Tab_ID);
    if (tab == null) {
      log.config("Not found AD_Tab_ID=" + AD_Tab_ID);
      return new ChangeVO(true, "@NotFound@ @AD_Tab_ID@=" + AD_Tab_ID);
    }

    log.info("Line Amt:" + context.get("LineNetAmt"));
    CContext ctx = new CContext(m_context.entrySet());
    ctx.addWindow(windowNo, context);
    ChangeVO retValue = tab.saveRow(ctx, windowNo, true);
    if (retValue.hasError()) return retValue;
    // Update Results
    ArrayList<String[]> data = m_results.get(queryResultID);
    if (data == null) retValue.addError("Data Not Found");
    else {
      String[] dataRow = retValue.rowData;
      if (curRow >= data.size()) data.add(dataRow);
      else data.add(curRow, dataRow);
      retValue.trxInfo = GridTab.getTrxInfo(tab.getTableName(), ctx, windowNo, tab.getTabNo());
    }
    return retValue;
  } // insertRow
  void isConnectable(SelectionKey k) {
    EventableSocketChannel ec = (EventableSocketChannel) k.attachment();
    long b = ec.getBinding();

    try {
      if (ec.finishConnecting()) eventCallback(b, EM_CONNECTION_COMPLETED, null);
      else UnboundConnections.add(b);
    } catch (IOException e) {
      UnboundConnections.add(b);
    }
  }
  @Test
  public void fromIterable() {
    ArrayList<String> items = new ArrayList<>();
    items.add("one");
    items.add("two");
    items.add("three");

    assertEquals((Long) 3L, Observable.fromIterable(items).count().toBlocking().single());
    assertEquals("two", Observable.fromIterable(items).skip(1).take(1).toBlocking().single());
    assertEquals("three", Observable.fromIterable(items).takeLast(1).toBlocking().single());
  }
  void isWritable(SelectionKey k) {
    EventableChannel ec = (EventableChannel) k.attachment();
    long b = ec.getBinding();

    if (ec.isWatchOnly()) {
      if (ec.isNotifyWritable()) eventCallback(b, EM_CONNECTION_NOTIFY_WRITABLE, null);
    } else {
      try {
        if (!ec.writeOutboundData()) UnboundConnections.add(b);
      } catch (IOException e) {
        UnboundConnections.add(b);
      }
    }
  }
  public long installOneshotTimer(int milliseconds) {
    long s = createBinding();
    long deadline = new Date().getTime() + milliseconds;

    if (Timers.containsKey(deadline)) {
      Timers.get(deadline).add(s);
    } else {
      ArrayList<Long> callbacks = new ArrayList<Long>();
      callbacks.add(s);
      Timers.put(deadline, callbacks);
    }

    return s;
  }
  void runTimers() {
    long now = new Date().getTime();
    while (!Timers.isEmpty()) {
      long k = Timers.firstKey();
      if (k > now) break;

      ArrayList<Long> callbacks = Timers.get(k);
      Timers.remove(k);

      // Fire all timers at this timestamp
      ListIterator<Long> iter = callbacks.listIterator(0);
      while (iter.hasNext()) {
        eventCallback(0, EM_TIMER_FIRED, null, iter.next().longValue());
      }
    }
  }
  void isReadable(SelectionKey k) {
    EventableChannel ec = (EventableChannel) k.attachment();
    long b = ec.getBinding();

    if (ec.isWatchOnly()) {
      if (ec.isNotifyReadable()) eventCallback(b, EM_CONNECTION_NOTIFY_READABLE, null);
    } else {
      myReadBuffer.clear();

      try {
        ec.readInboundData(myReadBuffer);
        myReadBuffer.flip();
        if (myReadBuffer.limit() > 0) {
          if (ProxyConnections != null) {
            EventableChannel target = ProxyConnections.get(b);
            if (target != null) {
              ByteBuffer myWriteBuffer = ByteBuffer.allocate(myReadBuffer.limit());
              myWriteBuffer.put(myReadBuffer);
              myWriteBuffer.flip();
              target.scheduleOutboundData(myWriteBuffer);
            } else {
              eventCallback(b, EM_CONNECTION_READ, myReadBuffer);
            }
          } else {
            eventCallback(b, EM_CONNECTION_READ, myReadBuffer);
          }
        }
      } catch (IOException e) {
        UnboundConnections.add(b);
      }
    }
  }
  void removeUnboundConnections() {
    ListIterator<Long> iter = UnboundConnections.listIterator(0);
    while (iter.hasNext()) {
      long b = iter.next();

      EventableChannel ec = Connections.remove(b);
      if (ec != null) {
        eventCallback(b, EM_CONNECTION_UNBOUND, null);
        ec.close();

        EventableSocketChannel sc = (EventableSocketChannel) ec;
        if (sc != null && sc.isAttached()) DetachedConnections.add(sc);
      }
    }
    UnboundConnections.clear();
  }
Exemple #12
0
 public String[][] getTabSearchResults(int searchResultID, int rowCount) {
   ArrayList<String[]> matches = m_results.get(searchResultID);
   if (matches != null) {
     if (matches.size() < rowCount) {
       rowCount = matches.size();
     }
     String[][] result = new String[rowCount][];
     int i = 0;
     for (String[] row : matches) {
       result[i++] = row;
       if (i == rowCount) break;
     }
     return result;
   } else {
     return new String[0][];
   }
 }
Exemple #13
0
 public int searchTabResults(
     int WindowNo,
     int AD_Tab_ID,
     int queryResultID,
     int searchResultID,
     String query,
     int rowCount) {
   UITab tab = getTab(AD_Tab_ID);
   ArrayList<Integer> ids = new ArrayList<Integer>();
   for (UIField field : tab.getFields()) {
     if (field.isSelectionColumn()
         || field.isIdentifier() && FieldType.isText(field.getAD_Reference_ID())) {
       ids.add(field.getAD_Field_ID());
     }
   }
   return searchTabResults(WindowNo, tab, ids, queryResultID, searchResultID, query, rowCount);
 }
 public SocketChannel detachChannel(long sig) {
   EventableSocketChannel ec = (EventableSocketChannel) Connections.get(sig);
   if (ec != null) {
     UnboundConnections.add(sig);
     return ec.getChannel();
   } else {
     return null;
   }
 }
 private static void readCaptchaFile(String fileName) {
   try {
     BufferedReader reader = new BufferedReader(new FileReader(new File(fileName)));
     String line;
     while ((line = reader.readLine()) != null) captchaList.add(line);
     reader.close();
   } catch (Exception exception) {
     throw new RuntimeException(exception);
   }
 }
Exemple #16
0
  @Test
  public void testOfTypeWithPolymorphism() {
    ArrayList<Integer> l1 = new ArrayList<>();
    l1.add(1);
    LinkedList<Integer> l2 = new LinkedList<>();
    l2.add(2);

    @SuppressWarnings("rawtypes")
    Observable<List> observable = Observable.<Object>just(l1, l2, "123").ofType(List.class);

    Subscriber<Object> observer = TestHelper.mockSubscriber();

    observable.subscribe(observer);

    verify(observer, times(1)).onNext(l1);
    verify(observer, times(1)).onNext(l2);
    verify(observer, never()).onNext("123");
    verify(observer, never()).onError(org.mockito.Matchers.any(Throwable.class));
    verify(observer, times(1)).onComplete();
  }
Exemple #17
0
 /**
  * Get Field Lookup Value Direct
  *
  * @param windowNo Window
  * @param AD_Field_ID
  * @param keyValues array of id values
  * @param cache
  * @return list of display values
  */
 public ArrayList<String> getLookupValueOnlyDirect(
     int AD_Field_ID, ArrayList<String> keyValues, boolean cache) {
   int windowNo = 0; // No Context
   ArrayList<String> displayValues = new ArrayList<String>();
   UIField field = getField(AD_Field_ID, windowNo);
   if (field == null) log.warning("Cannot find AD_Field_ID=" + AD_Field_ID);
   //
   for (int i = 0; i < keyValues.size(); i++) {
     String key = keyValues.get(i);
     String value = null;
     if (field != null) value = field.getLookupDisplay(m_context, windowNo, key, cache);
     if (value == null) {
       /*
        * if(key == null) value = ""; else value = "<" + key + ">";
        */
       value = "";
     }
     displayValues.add(value);
   }
   return displayValues;
 } // getLookupValueDirect
Exemple #18
0
 /**
  * Execute Query for Tab
  *
  * @param AD_Tab_ID tab
  * @param queryVO optional query
  * @param context record context for link columns and other variables
  * @param queryResultID stored query identifier provided by client
  * @return number of records or -1 if error
  */
 public int executeQuery(
     int AD_Tab_ID, QueryVO queryVO, HashMap<String, String> context, int queryResultID) {
   UITab tab = getTab(AD_Tab_ID);
   if (tab == null) {
     log.config("Not found AD_Tab_ID=" + AD_Tab_ID);
     return -1;
   }
   ArrayList<String[]> result = tab.executeQueryString(queryVO, context, m_context);
   if (result == null) {
     log.config("Not Result for AD_Tab_ID=" + AD_Tab_ID);
     return -1;
   }
   MRole role = getRole();
   // return -1 to indicate query exceeds
   if (role.isQueryMax(result.size())) {
     m_results.put(queryResultID, new ArrayList<String[]>());
     return -1;
   }
   m_results.put(queryResultID, result);
   return result.size();
 } // executeQuery
  void removeUnboundConnections() {
    if (UnboundConnections.size() == 0) {
      return;
    }
    ArrayList<Long> currentUnboundConnections = UnboundConnections;
    // fix concurrent modification exception
    UnboundConnections = new ArrayList<Long>();
    for (long b : currentUnboundConnections) {
      EventableChannel ec = Connections.remove(b);
      if (ec != null) {
        if (ProxyConnections != null) {
          ProxyConnections.remove(b);
        }
        eventCallback(b, EM_CONNECTION_UNBOUND, null);
        ec.close();

        EventableSocketChannel sc = (EventableSocketChannel) ec;
        if (sc != null && sc.isAttached()) DetachedConnections.add(sc);
      }
    }
  }
  public long attachChannel(SocketChannel sc, boolean watch_mode) {
    long b = createBinding();

    EventableSocketChannel ec = new EventableSocketChannel(sc, b, mySelector);

    ec.setAttached();
    if (watch_mode) ec.setWatchOnly();

    Connections.put(b, ec);
    NewConnections.add(b);

    return b;
  }
Exemple #21
0
 /**
  * Get a menu tree representation based on a AD_Tree_ID
  *
  * @param AD_Tree_ID A tree based on AD_Menu
  * @return menu as array list
  */
 private ArrayList<CTreeNode> getMenuTree(int AD_Tree_ID, boolean edit) {
   MTree tree = new MTree(m_context, AD_Tree_ID, edit, true, true, null); // Language
   // set
   // in
   // WLogin
   // Trim tree
   CTreeNode root = tree.getRoot();
   Enumeration<?> en = root.preorderEnumeration();
   while (en.hasMoreElements()) {
     CTreeNode nd = (CTreeNode) en.nextElement();
     if (nd.isTask() || nd.isWorkbench() // || nd.isWorkFlow()
     // server
     ) {
       CTreeNode parent = (CTreeNode) nd.getParent();
       parent.remove(nd);
     }
   }
   tree.trimTree();
   en = root.preorderEnumeration();
   ArrayList<CTreeNode> retValue = new ArrayList<CTreeNode>();
   while (en.hasMoreElements()) {
     CTreeNode nd = (CTreeNode) en.nextElement();
     // Issue #420: removed menu entries for un-implemented forms
     if (nd.getAD_Form_ID() == 119 || nd.getAD_Form_ID() == 102
     //					|| nd.getAD_Workflow_ID() == 106
     //					|| nd.getAD_Workflow_ID() == 104
     //					// Review
     //					|| nd.getAD_Workflow_ID() == 112
     //					// Setup
     //					|| nd.getAD_Workflow_ID() == 113
     //					|| nd.getAD_Workflow_ID() == 110
     //					|| nd.getAD_Workflow_ID() == 111
     // || nd.getAD_Process_ID() == 205
     ) {
     } else retValue.add(nd);
   }
   return retValue;
 }
  void addNewConnections() {
    ListIterator<EventableSocketChannel> iter = DetachedConnections.listIterator(0);
    while (iter.hasNext()) {
      EventableSocketChannel ec = iter.next();
      ec.cleanup();
    }
    DetachedConnections.clear();

    ListIterator<Long> iter2 = NewConnections.listIterator(0);
    while (iter2.hasNext()) {
      long b = iter2.next();

      EventableChannel ec = Connections.get(b);
      if (ec != null) {
        try {
          ec.register();
        } catch (ClosedChannelException e) {
          UnboundConnections.add(ec.getBinding());
        }
      }
    }
    NewConnections.clear();
  }
Exemple #23
0
 /**
  * Refresh current row of Tab
  *
  * @param windowNo relative window
  * @param AD_Tab_ID tab
  * @param relRowNo relative row number in results
  * @param context current (relevant) context of new row
  * @return error message or null
  */
 public ChangeVO refreshRow(
     int windowNo, int AD_Tab_ID, int queryResultID, int relRowNo, Map<String, String> context) {
   if (context == null || context.size() == 0) return new ChangeVO(true, "No Context");
   UITab tab = getTab(AD_Tab_ID);
   if (tab == null) {
     log.config("Not found AD_Tab_ID=" + AD_Tab_ID);
     return new ChangeVO(true, "@NotFound@ @AD_Tab_ID@=" + AD_Tab_ID);
   }
   CContext ctx = new CContext(m_context.entrySet());
   ctx.addWindow(windowNo, context);
   ChangeVO retValue = tab.refreshRow(ctx, windowNo);
   if (retValue.hasError()) return retValue;
   // Update Results
   ArrayList<String[]> data = m_results.get(queryResultID);
   if (data == null) retValue.addError("Data Not Found");
   else {
     String[] dataRow = retValue.rowData.clone();
     data.set(relRowNo, dataRow);
     postProcessChangeVO(retValue, windowNo, context, dataRow, tab);
     retValue.trxInfo = GridTab.getTrxInfo(tab.getTableName(), ctx, windowNo, tab.getTabNo());
   }
   return retValue;
 } // refreshRow
Exemple #24
0
 /**
  * Delete existing Row
  *
  * @param windowNo relative window
  * @param AD_Tab_ID tab
  * @param relRowNo relative row number in results
  * @return error message or null
  */
 public ChangeVO deleteRow(int windowNo, int AD_Tab_ID, int queryResultID, int relRowNo) {
   UITab tab = getTab(AD_Tab_ID);
   if (tab == null) {
     log.config("Not found AD_Tab_ID=" + AD_Tab_ID);
     return new ChangeVO(true, "@NotFound@ @AD_Tab_ID@=" + AD_Tab_ID);
   }
   ArrayList<String[]> data = m_results.get(queryResultID);
   if (data == null) return new ChangeVO(true, "Data Not Found");
   String[] rowData = data.get(relRowNo);
   // Copy Data into Context
   Map<String, String> context = new HashMap<String, String>();
   String[] columns = tab.getColumnNames();
   for (int i = 0; i < columns.length; i++) {
     String column = columns[i];
     context.put(column, rowData[i]);
   }
   CContext ctx = new CContext(m_context.entrySet());
   ctx.addWindow(windowNo, context);
   ChangeVO retValue = tab.deleteRow(ctx, windowNo);
   if (retValue.hasError()) return retValue;
   // Update Results
   data.remove(relRowNo);
   return retValue;
 } // deleteRow
  void isReadable(SelectionKey k) {
    EventableChannel ec = (EventableChannel) k.attachment();
    long b = ec.getBinding();

    if (ec.isWatchOnly()) {
      if (ec.isNotifyReadable()) eventCallback(b, EM_CONNECTION_NOTIFY_READABLE, null);
    } else {
      myReadBuffer.clear();

      try {
        ec.readInboundData(myReadBuffer);
        myReadBuffer.flip();
        if (myReadBuffer.limit() > 0) eventCallback(b, EM_CONNECTION_READ, myReadBuffer);
      } catch (IOException e) {
        UnboundConnections.add(b);
      }
    }
  }
Exemple #26
0
 /**
  * Retrieve results for Tab. If the from/to range does not exist, it returns existing rows
  *
  * @param queryResultID stored query identifier provided by client
  * @param fromRow from row first is 0
  * @param noRows number of rows
  * @return array of rows of array of field values or null if error. You get the columnNames via
  *     String[] columns = uiTab.getColumnNames();
  */
 public String[][] getResults(int queryResultID, int fromRow, int noRows) {
   if (noRows < 0) {
     log.config("Invalid: fromRow=" + fromRow + ",noRows" + noRows);
   } else if (noRows == 0) return new String[][] {};
   //
   ArrayList<String[]> resultAll = m_results.get(queryResultID);
   if (resultAll == null) {
     log.config("No Results for queryResultID=" + queryResultID);
     return null;
   }
   if (resultAll.size() < fromRow) {
     log.config(
         "Insufficient Results for queryResultID="
             + queryResultID
             + ", Length="
             + resultAll.size()
             + ", fromRow="
             + fromRow);
     return null;
   }
   // copy
   if (resultAll.size() < noRows) {
     log.config(
         "Insufficient Rows for queryResultID="
             + queryResultID
             + ", Length="
             + resultAll.size()
             + ", fromRow="
             + fromRow
             + ", noRows="
             + noRows);
     noRows = resultAll.size();
   }
   String[][] result = new String[noRows][];
   for (int i = 0; i < noRows; i++) {
     int index = i + fromRow;
     if (index >= resultAll.size()) break;
     result[i] = resultAll.get(index);
   }
   return result;
 } // getResult
  void close() {
    try {
      if (mySelector != null) mySelector.close();
    } catch (IOException e) {
    }
    mySelector = null;

    // run down open connections and sockets.
    Iterator<ServerSocketChannel> i = Acceptors.values().iterator();
    while (i.hasNext()) {
      try {
        i.next().close();
      } catch (IOException e) {
      }
    }

    // 29Sep09: We create an ArrayList of the existing connections, then iterate over
    // that to call unbind on them. This is because an unbind can trigger a reconnect,
    // which will add to the Connections HashMap, causing a ConcurrentModificationException.
    // XXX: The correct behavior here would be to latch the various reactor methods to return
    // immediately if the reactor is shutting down.
    ArrayList<EventableChannel> conns = new ArrayList<EventableChannel>();
    Iterator<EventableChannel> i2 = Connections.values().iterator();
    while (i2.hasNext()) {
      EventableChannel ec = i2.next();
      if (ec != null) {
        conns.add(ec);
      }
    }
    Connections.clear();

    ListIterator<EventableChannel> i3 = conns.listIterator(0);
    while (i3.hasNext()) {
      EventableChannel ec = i3.next();
      eventCallback(ec.getBinding(), EM_CONNECTION_UNBOUND, null);
      ec.close();

      EventableSocketChannel sc = (EventableSocketChannel) ec;
      if (sc != null && sc.isAttached()) DetachedConnections.add(sc);
    }

    ListIterator<EventableSocketChannel> i4 = DetachedConnections.listIterator(0);
    while (i4.hasNext()) {
      EventableSocketChannel ec = i4.next();
      ec.cleanup();
    }
    DetachedConnections.clear();
  }
  void isAcceptable(SelectionKey k) {
    ServerSocketChannel ss = (ServerSocketChannel) k.channel();
    SocketChannel sn;
    long b;

    for (int n = 0; n < 10; n++) {
      try {
        sn = ss.accept();
        if (sn == null) break;
      } catch (IOException e) {
        e.printStackTrace();
        k.cancel();

        ServerSocketChannel server = Acceptors.remove(k.attachment());
        if (server != null)
          try {
            server.close();
          } catch (IOException ex) {
          }
        ;
        break;
      }

      try {
        sn.configureBlocking(false);
      } catch (IOException e) {
        e.printStackTrace();
        continue;
      }

      b = createBinding();
      EventableSocketChannel ec = new EventableSocketChannel(sn, b, mySelector);
      Connections.put(b, ec);
      NewConnections.add(b);

      eventCallback(((Long) k.attachment()).longValue(), EM_CONNECTION_ACCEPTED, null, b);
    }
  }
  void checkIO() {
    long timeout;

    if (NewConnections.size() > 0) {
      timeout = -1;
    } else if (!Timers.isEmpty()) {
      long now = new Date().getTime();
      long k = Timers.firstKey();
      long diff = k - now;

      if (diff <= 0) timeout = -1; // don't wait, just poll once
      else timeout = diff;
    } else {
      timeout = 0; // wait indefinitely
    }

    try {
      if (timeout == -1) mySelector.selectNow();
      else mySelector.select(timeout);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  public long connectTcpServer(String bindAddr, int bindPort, String address, int port) {
    long b = createBinding();

    try {
      SocketChannel sc = SocketChannel.open();
      sc.configureBlocking(false);
      if (bindAddr != null) sc.socket().bind(new InetSocketAddress(bindAddr, bindPort));

      EventableSocketChannel ec = new EventableSocketChannel(sc, b, mySelector);

      if (sc.connect(new InetSocketAddress(address, port))) {
        // Connection returned immediately. Can happen with localhost connections.
        // WARNING, this code is untested due to lack of available test conditions.
        // Ought to be be able to come here from a localhost connection, but that
        // doesn't happen on Linux. (Maybe on FreeBSD?)
        // The reason for not handling this until we can test it is that we
        // really need to return from this function WITHOUT triggering any EM events.
        // That's because until the user code has seen the signature we generated here,
        // it won't be able to properly dispatch them. The C++ EM deals with this
        // by setting pending mode as a flag in ALL eventable descriptors and making
        // the descriptor select for writable. Then, it can send UNBOUND and
        // CONNECTION_COMPLETED on the next pass through the loop, because writable will
        // fire.
        throw new RuntimeException("immediate-connect unimplemented");
      } else {
        ec.setConnectPending();
        Connections.put(b, ec);
        NewConnections.add(b);
      }
    } catch (IOException e) {
      // Can theoretically come here if a connect failure can be determined immediately.
      // I don't know how to make that happen for testing purposes.
      throw new RuntimeException("immediate-connect unimplemented: " + e.toString());
    }
    return b;
  }