/**
   * Initialize an {@link AtmosphereResource}.
   *
   * @param config The {@link org.atmosphere.cpr.AtmosphereConfig}
   * @param broadcaster The {@link org.atmosphere.cpr.Broadcaster}.
   * @param req The {@link AtmosphereRequest}
   * @param response The {@link AtmosphereResource}
   * @param asyncSupport The {@link AsyncSupport}
   * @param atmosphereHandler The {@link AtmosphereHandler}
   * @return this
   */
  @Override
  public AtmosphereResource initialize(
      AtmosphereConfig config,
      Broadcaster broadcaster,
      AtmosphereRequest req,
      AtmosphereResponse response,
      AsyncSupport asyncSupport,
      AtmosphereHandler atmosphereHandler) {
    this.req = req;
    this.response = response;
    this.broadcaster = broadcaster;
    this.config = config;
    this.asyncSupport = asyncSupport;
    this.atmosphereHandler = atmosphereHandler;
    this.event = new AtmosphereResourceEventImpl(this);

    String s = (String) req.getAttribute(SUSPENDED_ATMOSPHERE_RESOURCE_UUID);
    if (s == null) {
      s = response.getHeader(HeaderConfig.X_ATMOSPHERE_TRACKING_ID);
    }
    uuid = s == null ? UUID.randomUUID().toString() : s;

    if (config.isSupportSession()) {
      // Keep a reference to an HttpSession in case the associated request get recycled by the
      // underlying container.
      try {
        session = req.getSession(true);
      } catch (NullPointerException ex) {
        // http://java.net/jira/browse/GLASSFISH-18856
        logger.trace("http://java.net/jira/browse/GLASSFISH-18856", ex);
      }
    }
    transport = configureTransport();
    return this;
  }
 @Override
 public HttpSession session(boolean create) {
   if (config.isSupportSession() && session == null) {
     // http://java.net/jira/browse/GLASSFISH-18856
     session = req.getSession(create);
   }
   return session;
 }
  @Override
  public AtmosphereResource suspend(long timeout) {

    if (event.isSuspended() || disableSuspend) return this;

    if (config.isSupportSession()
        && req.getSession(false) != null
        && req.getSession().getMaxInactiveInterval() != -1
        && req.getSession().getMaxInactiveInterval() * 1000 < timeout) {
      throw new IllegalStateException(
          "Cannot suspend a "
              + "response longer than the session timeout. Increase the value of session-timeout in web.xml");
    }

    if (transport().equals(TRANSPORT.JSONP) || transport().equals(TRANSPORT.LONG_POLLING)) {
      resumeOnBroadcast.set(true);
    }

    onPreSuspend(event);

    // Recheck based on preSuspend
    if (event.isSuspended() || disableSuspend) return this;

    if (!event.isResumedOnTimeout()) {

      Enumeration<String> connection = req.getHeaders("Connection");
      if (connection == null) {
        connection = req.getHeaders("connection");
      }

      if (connection != null && connection.hasMoreElements()) {
        String[] e = connection.nextElement().toString().split(",");
        for (String upgrade : e) {
          if (upgrade.trim().equalsIgnoreCase(WEBSOCKET_UPGRADE)) {
            if (!asyncSupport.supportWebSocket()) {
              response.addHeader(X_ATMOSPHERE_ERROR, "Websocket protocol not supported");
            } else {
              req.setAttribute(FrameworkConfig.TRANSPORT_IN_USE, HeaderConfig.WEBSOCKET_TRANSPORT);
            }
          }
        }
      }

      if (req.getHeader(X_ATMOSPHERE_TRANSPORT) == null) {
        req.setAttribute(FrameworkConfig.TRANSPORT_IN_USE, HeaderConfig.LONG_POLLING_TRANSPORT);
      }

      req.setAttribute(PRE_SUSPEND, "true");
      action.type(Action.TYPE.SUSPEND);
      action.timeout(timeout);

      // TODO: We can possibly optimize that call by avoiding creating a Broadcaster if we are sure
      // the Broadcaster
      // is unique.
      boolean isJersey = req.getAttribute(FrameworkConfig.CONTAINER_RESPONSE) != null;

      boolean skipCreation = false;
      if (req.getAttribute(SKIP_BROADCASTER_CREATION) != null) {
        skipCreation = true;
      }

      // Null means SCOPE=REQUEST set by a Meteor
      if (!skipCreation
          && (broadcaster == null || broadcaster.getScope() == Broadcaster.SCOPE.REQUEST)
          && !isJersey) {
        String id = broadcaster != null ? broadcaster.getID() : getClass().getName();
        Class<? extends Broadcaster> clazz =
            broadcaster != null ? broadcaster.getClass() : DefaultBroadcaster.class;

        broadcaster = config.getBroadcasterFactory().lookup(clazz, id, false);
        if (broadcaster == null || broadcaster.getAtmosphereResources().size() > 0) {
          broadcaster =
              config.getBroadcasterFactory().lookup(clazz, id + "/" + UUID.randomUUID(), true);
        }
      }

      broadcaster.addAtmosphereResource(this);
      if (req.getAttribute(DefaultBroadcaster.CACHED) != null
          && transport() != null
          && (transport().equals(TRANSPORT.LONG_POLLING) || transport().equals(TRANSPORT.JSONP))) {
        action.type(Action.TYPE.CONTINUE);
        // Do nothing because we have found cached message which was written already, and the
        // handler resumed.
        logger.debug("Cached message found, not suspending {}", uuid());
        return this;
      }
      req.removeAttribute(PRE_SUSPEND);
      notifyListeners();
    }
    return this;
  }
 /**
  * Is {@link HttpSession} supported
  *
  * @return true if supported
  */
 protected boolean supportSession() {
   return config.isSupportSession();
 }