/** * 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(); } } }
@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; }