/**
   * Write the broadcasted object using the {@link OutputStream}. If a {@link Serializer} is
   * defined, the operation will be delagated to it. If not, the <F> (Response) OutputStream will be
   * used by calling Object.toString.getBytes()
   *
   * @param os an {@link OutputStream}
   * @param o an Object
   * @throws IOException
   */
  @Override
  public AtmosphereResource write(OutputStream os, Object o) throws IOException {
    if (o == null) throw new IllegalStateException("Object cannot be null");

    if (serializer != null) {
      serializer.write(os, o);
    } else {
      response.getOutputStream().write(o.toString().getBytes());
    }
    return this;
  }
  /**
   * Write the {@link AtmosphereResourceEvent#getMessage()} back to the client using the {@link
   * org.atmosphere.cpr.AtmosphereResponse#getOutputStream()} or {@link
   * org.atmosphere.cpr.AtmosphereResponse#getWriter()}. If a {@link org.atmosphere.cpr.Serializer}
   * is defined, it will be invoked and the writ operation will be delegated to to it.
   *
   * <p>By default, this method will try to use {@link
   * org.atmosphere.cpr.AtmosphereResponse#getWriter()}.
   *
   * @param event the {@link AtmosphereResourceEvent#getMessage()}
   * @throws java.io.IOException
   */
  public void onStateChange(AtmosphereResourceEvent event) throws IOException {

    Object message = event.getMessage();
    AtmosphereResponse r = event.getResource().getResponse();
    if (message == null || event.isCancelled() || event.getResource().getRequest().destroyed())
      return;

    if (event.getResource().getSerializer() != null) {
      try {
        event
            .getResource()
            .getSerializer()
            .write(event.getResource().getResponse().getOutputStream(), message);
      } catch (Throwable ex) {
        logger.warn("Serializer exception: message: " + message, ex);
        throw new IOException(ex);
      }
    } else {
      boolean isUsingStream =
          (Boolean) event.getResource().getRequest().getAttribute(PROPERTY_USE_STREAM);

      if (!isUsingStream) {
        try {
          r.getWriter();
        } catch (IllegalStateException e) {
          isUsingStream = true;
        }
      }

      if (message instanceof List) {
        for (String s : (List<String>) message) {
          if (isUsingStream) {
            r.getOutputStream().write(s.getBytes(r.getCharacterEncoding()));
            r.getOutputStream().flush();
          } else {
            r.getWriter().write(s);
            r.getWriter().flush();
          }
        }
      } else {
        if (isUsingStream) {
          r.getOutputStream().write(message.toString().getBytes(r.getCharacterEncoding()));
          r.getOutputStream().flush();
        } else {
          r.getWriter().write(message.toString());
          r.getWriter().flush();
        }
      }

      Boolean resumeOnBroadcast = event.getResource().resumeOnBroadcast();
      if (!resumeOnBroadcast) {
        // For legacy reason, check the attribute as well
        Object o =
            event.getResource().getRequest().getAttribute(ApplicationConfig.RESUME_ON_BROADCAST);
        if (o != null && Boolean.class.isAssignableFrom(o.getClass())) {
          resumeOnBroadcast = Boolean.class.cast(o);
        }
      }

      if (resumeOnBroadcast != null && resumeOnBroadcast) {
        event.getResource().resume();
      }
    }
  }
예제 #3
0
    @Override
    public void onStateChange(AtmosphereResourceEvent event) throws IOException {

      AtmosphereResponse response = event.getResource().getResponse();
      AtmosphereResource resource = event.getResource();

      if (event.isSuspended()) {

        // Set content type before do response.getWriter()
        // http://docs.oracle.com/javaee/5/api/javax/servlet/ServletResponse.html#setContentType(java.lang.String)
        response.setContentType("text/plain; charset=UTF-8");
        response.setCharacterEncoding("UTF-8");

        if (event.getMessage().getClass().isArray()) {

          LOG.fine("SEND MESSAGE ARRAY " + event.getMessage().toString());

          List<Object> list = Arrays.asList(event.getMessage());

          response.getOutputStream().write(MSG_SEPARATOR.getBytes(MSG_CHARSET));
          for (Object object : list) {
            String message = (String) object;
            message += MSG_SEPARATOR;
            response.getOutputStream().write(message.getBytes(MSG_CHARSET));
          }

        } else if (event.getMessage() instanceof List) {

          LOG.fine("SEND MESSAGE LIST " + event.getMessage().toString());

          @SuppressWarnings("unchecked")
          List<Object> list = List.class.cast(event.getMessage());

          response.getOutputStream().write(MSG_SEPARATOR.getBytes(MSG_CHARSET));
          for (Object object : list) {
            String message = (String) object;
            message += MSG_SEPARATOR;
            response.getOutputStream().write(message.getBytes(MSG_CHARSET));
          }

        } else if (event.getMessage() instanceof String) {

          LOG.fine("SEND MESSAGE " + event.getMessage().toString());

          String message = (String) event.getMessage();
          response.getOutputStream().write(message.getBytes(MSG_CHARSET));
        }

        try {

          response.flushBuffer();

          switch (resource.transport()) {
            case JSONP:
            case LONG_POLLING:
              event.getResource().resume();
              break;
            case WEBSOCKET:
            case STREAMING:
            case SSE:
              response.getOutputStream().flush();
              break;
            default:
              LOG.info("Unknown transport");
              break;
          }
        } catch (IOException e) {
          LOG.info("Error resuming resource response", e);
        }

      } else if (event.isResuming()) {

        LOG.fine("RESUMING");

      } else if (event.isResumedOnTimeout()) {

        LOG.fine("RESUMED ON TIMEOUT");

      } else if (event.isClosedByApplication() || event.isClosedByClient()) {

        LOG.fine("CONNECTION CLOSED");

        AtmosphereResourceSession resourceSession =
            AtmosphereResourceSessionFactory.getDefault().getSession(resource);

        AtmosphereChannel resourceChannel =
            resourceSession.getAttribute(WAVE_CHANNEL_ATTRIBUTE, AtmosphereChannel.class);

        if (resourceChannel != null) {
          resourceChannel.onDisconnect();
        }
      }
    }
  /**
   * All proprietary Comet based {@link Servlet} must invoke the timedout method when the underlying
   * WebServer time out the {@link AtmosphereResponse}. The returned value, of type {@link Action},
   * tells the proprietary Comet {@link Servlet} to resume (again), suspended or do nothing with the
   * current {@link AtmosphereResponse}.
   *
   * @param request the {@link AtmosphereRequest}
   * @param response the {@link AtmosphereResponse}
   * @return action the Action operation.
   * @throws java.io.IOException
   * @throws javax.servlet.ServletException
   */
  public Action timedout(AtmosphereRequest request, AtmosphereResponse response)
      throws IOException, ServletException {

    AtmosphereResourceImpl r = null;
    try {
      if (trackActiveRequest) {
        long l = (Long) request.getAttribute(MAX_INACTIVE);
        if (l == -1) {
          // The closedDetector closed the connection.
          return timedoutAction;
        }
        request.setAttribute(MAX_INACTIVE, (long) -1);
      }

      logger.debug("Timing out the connection for request {}", request);

      // Something went wrong.
      if (request == null || response == null) {
        logger.warn("Invalid Request/Response: {}/{}", request, response);
        return timedoutAction;
      }

      r = (AtmosphereResourceImpl) request.getAttribute(FrameworkConfig.ATMOSPHERE_RESOURCE);

      if (r != null && r.getAtmosphereResourceEvent().isSuspended()) {
        r.getAtmosphereResourceEvent().setIsResumedOnTimeout(true);

        Broadcaster b = r.getBroadcaster();
        if (b instanceof DefaultBroadcaster) {
          ((DefaultBroadcaster) b).broadcastOnResume(r);
        }

        if (request.getAttribute(ApplicationConfig.RESUMED_ON_TIMEOUT) != null) {
          r.getAtmosphereResourceEvent()
              .setIsResumedOnTimeout(
                  (Boolean) request.getAttribute(ApplicationConfig.RESUMED_ON_TIMEOUT));
        }

        invokeAtmosphereHandler(r);
      }
    } catch (Throwable t) {
      logger.error("failed to timeout resource {}", r, t);
    } finally {
      try {
        if (r != null) {
          r.notifyListeners();
          r.setIsInScope(false);
          r.cancel();
        }
      } catch (Throwable t) {
        logger.trace("timedout", t);
      } finally {

        try {
          response.getOutputStream().close();
        } catch (Throwable t) {
          try {
            response.getWriter().close();
          } catch (Throwable t2) {
          }
        }

        if (r != null) {
          destroyResource(r);
        }
      }
    }

    return timedoutAction;
  }