/** @see com.thinkparity.network.NetworkConnection#connect() */
 @Override
 public void connect() throws NetworkException {
   logger.logTraceId();
   logger.logInfo("{0} - Connect.", getId());
   Exception lastX = null;
   connected = false;
   for (final NetworkProxy proxy : proxies) {
     this.proxy = proxy;
     try {
       connectViaProxy();
       setSocketOptions();
       setSocketStreams();
       logger.logInfo("{0} - Connected.", getId());
       logger.logDebug(
           "{0} - Local:  {1}:{2}",
           getId(), socket.getLocalAddress().getHostAddress(), socket.getLocalPort());
       final InetSocketAddress remoteSocketAddress =
           (InetSocketAddress) socket.getRemoteSocketAddress();
       logger.logDebug(
           "{0} - Remote:  {1}:{2}",
           getId(),
           remoteSocketAddress.getAddress().getHostAddress(),
           remoteSocketAddress.getPort());
       connected = true;
       break;
     } catch (final SocketException sx) {
       lastX = sx;
     } catch (final IOException iox) {
       lastX = iox;
     }
   }
   if (false == connected) {
     throw new NetworkException(lastX);
   }
 }
  /**
   * Set socket options pulled from the network configuration.
   *
   * @throws SocketException
   */
  private void setSocketOptions() throws SocketException {
    final NetworkConfiguration configuration = networkImpl.getConfiguration();
    final Integer soLinger = configuration.getSoLinger(protocol, address, proxy, this);
    final boolean linger = -1 < soLinger ? true : false;
    logger.logDebug("{0} - linger:{1}", getId(), linger);
    logger.logDebug("{0} - soLinger:{1}", getId(), soLinger);
    final Integer soTimeout = configuration.getSoTimeout(protocol, address, proxy, this);
    logger.logDebug("{0} - soTimeout:{1}", getId(), soTimeout);
    final Boolean tcpNoDelay = configuration.getTcpNoDelay(protocol, address, proxy, this);
    logger.logDebug("{0} - tcpNoDelay:{1}", getId(), tcpNoDelay);

    socket.setSoLinger(linger, linger ? soLinger : -1);
    socket.setSoTimeout(soTimeout);
    socket.setTcpNoDelay(tcpNoDelay);
  }
  /**
   * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method,
   *     java.lang.Object[])
   */
  public Object invoke(final Object proxy, final Method method, final Object[] args)
      throws Throwable {
    LOGGER.logTrace("Invoking method {0} on {1} in {2}.", method, model, workspace);
    if (null != args && 0 < args.length && LOGGER.isDebugEnabled()) {
      for (int i = 0; i < args.length; i++) LOGGER.logDebug("args[{0}]:{1}", i, args[i]);
    }
    final Object lock;
    switch (extractLock(method)) {
      case NONE:
        lock = new Object();
        break;
      case EXCLUSIVE: // deliberate fall-through
      case LOCAL_READ: // deliberate fall-through
      default:
        lock = workspace;
    }
    synchronized (lock) {
      final Transaction transaction = workspace.getTransaction();
      final TransactionContext transactionContext = newXAContext(method);
      beginXA(transaction, transactionContext);
      try {
        /* if the method is annotated as online, ensure that we are
         * online */
        if (isOnline(method)) model.ensureOnline();
        model.setInvocationContext(
            new ModelInvocationContext() {
              public Object[] getArguments() {
                return null == args ? NO_ARGS : args;
              }

              public Method getMethod() {
                return method;
              }
            });
        final Object metricsContext = newMetricsContext(lock, method);
        ModelInvocationMetrics.begin(metricsContext);
        final Object result = method.invoke(model, args);
        ModelInvocationMetrics.end(metricsContext);
        model.notifyListeners();
        return LOGGER.logVariable("result", result);
      } catch (final InvocationTargetException itx) {
        rollbackXA(transaction, transactionContext);
        throw itx.getTargetException();
      } catch (final Throwable t) {
        rollbackXA(transaction, transactionContext);
        throw t;
      } finally {
        completeXA(transaction, transactionContext);
      }
    }
  }