/** Open/Activate the session */
  public void open() {
    if (LOG_OPEN.isDebugEnabled())
      LOG_OPEN.debug("[{}] {}.open()", policy.getBehavior(), this.getClass().getSimpleName());

    if (remote != null) {
      // already opened
      return;
    }

    try (ThreadClassLoaderScope scope = new ThreadClassLoaderScope(classLoader)) {
      // Upgrade success
      connection.getIOState().onConnected();

      // Connect remote
      remote = new WebSocketRemoteEndpoint(connection, outgoingHandler, getBatchMode());
      if (LOG_OPEN.isDebugEnabled())
        LOG_OPEN.debug(
            "[{}] {}.open() remote={}",
            policy.getBehavior(),
            this.getClass().getSimpleName(),
            remote);

      // Open WebSocket
      websocket.openSession(this);

      // Open connection
      connection.getIOState().onOpened();

      if (LOG.isDebugEnabled()) {
        LOG.debug("open -> {}", dump());
      }
    } catch (CloseException ce) {
      LOG.warn(ce);
      close(ce.getStatusCode(), ce.getMessage());
    } catch (Throwable t) {
      LOG.warn(t);
      // Exception on end-user WS-Endpoint.
      // Fast-fail & close connection with reason.
      int statusCode = StatusCode.SERVER_ERROR;
      if (policy.getBehavior() == WebSocketBehavior.CLIENT) {
        statusCode = StatusCode.POLICY_VIOLATION;
      }
      close(statusCode, t.getMessage());
    }
  }
 @Override
 public String toString() {
   StringBuilder builder = new StringBuilder();
   builder.append("WebSocketSession[");
   builder.append("websocket=").append(websocket);
   builder.append(",behavior=").append(policy.getBehavior());
   builder.append(",connection=").append(connection);
   builder.append(",remote=").append(remote);
   builder.append(",incoming=").append(incomingHandler);
   builder.append(",outgoing=").append(outgoingHandler);
   builder.append("]");
   return builder.toString();
 }
  @Override
  public RemoteEndpoint getRemote() {
    if (LOG_OPEN.isDebugEnabled())
      LOG_OPEN.debug("[{}] {}.getRemote()", policy.getBehavior(), this.getClass().getSimpleName());
    ConnectionState state = connection.getIOState().getConnectionState();

    if ((state == ConnectionState.OPEN) || (state == ConnectionState.CONNECTED)) {
      return remote;
    }

    throw new WebSocketException(
        "RemoteEndpoint unavailable, current state [" + state + "], expecting [OPEN or CONNECTED]");
  }
  private void unhandled(Throwable t) {
    TARGET_LOG.warn("Unhandled Error (closing connection)", t);
    onError(t);

    // Unhandled Error, close the connection.
    switch (policy.getBehavior()) {
      case SERVER:
        terminateConnection(StatusCode.SERVER_ERROR, t.getClass().getSimpleName());
        break;
      case CLIENT:
        terminateConnection(StatusCode.POLICY_VIOLATION, t.getClass().getSimpleName());
        break;
    }
  }
 @Override
 public void onOpened(Connection connection) {
   if (LOG_OPEN.isDebugEnabled())
     LOG_OPEN.debug("[{}] {}.onOpened()", policy.getBehavior(), this.getClass().getSimpleName());
   open();
 }