@Test public void testHeartbeat() throws IOException, ServletException { // Open connection AtmosphereRequest request = new AtmosphereRequest.Builder().pathInfo("/heartbeat").method("GET").build(); request.header(X_ATMOSPHERE_TRANSPORT, WEBSOCKET_TRANSPORT); framework.doCometSupport(request, AtmosphereResponse.newInstance()); // Check suspend final AtmosphereResource res = r.get(); assertNotNull(res); // Send heartbeat request = new AtmosphereRequest.Builder() .pathInfo("/heartbeat") .method("GET") .body(Heartbeat.paddingData) .build(); request.header(X_ATMOSPHERE_TRANSPORT, WEBSOCKET_TRANSPORT); request.setAttribute(HeartbeatInterceptor.INTERCEPTOR_ADDED, ""); res.initialize( res.getAtmosphereConfig(), res.getBroadcaster(), request, AtmosphereResponse.newInstance(), framework.getAsyncSupport(), res.getAtmosphereHandler()); request.setAttribute(FrameworkConfig.INJECTED_ATMOSPHERE_RESOURCE, res); framework.doCometSupport(request, AtmosphereResponse.newInstance()); assertNotNull(message.get()); assertEquals(message.get(), Heartbeat.paddingData); }
@Override public void onStateChange(AtmosphereResourceEvent event) throws IOException { AtmosphereResource r = event.getResource(); AtmosphereResponse res = r.getResponse(); if (event.isSuspended()) { String body = event.getMessage().toString(); ChatData data = new Gson().fromJson(body, ChatData.class); res.getWriter().write(new ChatData(data.getAuthor(), data.getText()).toString()); switch (r.transport()) { case JSONP: case AJAX: case LONG_POLLING: event.getResource().resume(); break; default: res.getWriter().flush(); break; } } else if (!event.isResuming()) { event.broadcaster().broadcast(new ChatData("Someone", "say bye bye!").toString()); } }
@Test public void setCookieTest() throws IOException, ServletException, ExecutionException, InterruptedException { final AtomicReference<Cookie> cValue = new AtomicReference<Cookie>(); final AtomicReference<AtmosphereResource> r = new AtomicReference<AtmosphereResource>(); framework.addAtmosphereHandler( "/*", new AtmosphereHandler() { @Override public void onRequest(AtmosphereResource resource) throws IOException { resource.getResponse().addCookie(resource.getRequest().getCookies()[0]); r.set(resource); resource.getBroadcaster().addAtmosphereResource(resource); } @Override public void onStateChange(AtmosphereResourceEvent event) throws IOException { Cookie[] c = event.getResource().getRequest().getCookies(); cValue.set(c[0]); } @Override public void destroy() {} }); Set<Cookie> c = new HashSet<Cookie>(); Cookie a = new Cookie("yo", "man"); a.setComment("kdaskjdaskda"); a.setDomain("dasdasdasd"); a.setHttpOnly(true); a.setPath("/ya"); c.add(a); AtmosphereRequest request = new AtmosphereRequestImpl.Builder().cookies(c).pathInfo("/a").build(); AtmosphereResponse response = AtmosphereResponseImpl.newInstance().delegateToNativeResponse(false); response.destroyable(false); framework.doCometSupport(request, response); r.get().getBroadcaster().broadcast("yo").get(); assertNotNull(cValue.get()); Cookie i = c.iterator().next(); assertEquals(i.getName(), cValue.get().getName()); assertEquals(i.getValue(), cValue.get().getValue()); assertEquals( "yo=man; Domain=dasdasdasd; Path=/ya; HttpOnly", response.headers().get("Set-Cookie")); }
public void cancel() throws IOException { if (!isCancelled.getAndSet(true)) { logger.trace("Cancelling {}", uuid); if (config.getBroadcasterFactory().getDefault() != null) { config.getBroadcasterFactory().getDefault().removeAllAtmosphereResource(this); if (transport.equals(TRANSPORT.WEBSOCKET)) { String parentUUID = (String) req.getAttribute(SUSPENDED_ATMOSPHERE_RESOURCE_UUID); AtmosphereResource p = AtmosphereResourceFactory.getDefault().find(parentUUID); if (p != null) { config.getBroadcasterFactory().getDefault().removeAllAtmosphereResource(p); } } } asyncSupport.complete(this); SessionTimeoutSupport.restoreTimeout(req); action.type(Action.TYPE.CANCELLED); if (asyncSupport != null) asyncSupport.action(this); // We must close the underlying WebSocket as well. if (AtmosphereResponse.class.isAssignableFrom(response.getClass())) { AtmosphereResponse.class.cast(response).close(); AtmosphereResponse.class.cast(response).destroy(); } if (AtmosphereRequest.class.isAssignableFrom(req.getClass())) { AtmosphereRequest.class.cast(req).destroy(); } req.removeAttribute(FrameworkConfig.ATMOSPHERE_RESOURCE); event.destroy(); } }
public synchronized void cancel() throws IOException { action.type(Action.TYPE.RESUME); if (isCancelled.getAndSet(true)) return; if (asyncSupport instanceof AsynchronousProcessor) { try { AsynchronousProcessor.class.cast(asyncSupport).resumed(req, response); } catch (ServletException e) { logger.trace("", e); } } asyncSupport.action(this); // We must close the underlying WebSocket as well. if (AtmosphereResponse.class.isAssignableFrom(response.getClass())) { AtmosphereResponse.class.cast(response).close(); AtmosphereResponse.class.cast(response).destroy(); } if (AtmosphereRequest.class.isAssignableFrom(req.getClass())) { AtmosphereRequest.class.cast(req).destroy(); } // TODO: Grab some measurement. // req = null; // response = null; // Just in case if (broadcaster != null) { broadcaster.removeAtmosphereResource(this); } event.destroy(); }
/** * 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 AtmosphereResource write(byte[] o) { response.write(o); if (resumeOnBroadcast()) { resume(); } return this; }
@Override public AtmosphereResource write(String s) { response.write(s); if (resumeOnBroadcast()) { resume(); } return this; }
@Override public void onMessage(AtmosphereResponse response, TatamiNotification notification) throws IOException { if (log.isDebugEnabled()) { log.debug("Received Atmosphere message: " + notification); } String json = jsonObjectMapper.writeValueAsString(notification); response.getWriter().write(json); }
@Test public void testPut() throws IOException, ServletException { AtmosphereRequest request = new AtmosphereRequest.Builder().pathInfo("/d").method("PUT").build(); framework.doCometSupport(request, AtmosphereResponse.newInstance()); assertNotNull(r.get()); r.get().resume(); }
@Test public void testSuspend() throws IOException, ServletException { AtmosphereRequest request = new AtmosphereRequest.Builder().pathInfo("/j").method("GET").build(); request.header(X_ATMOSPHERE_TRANSPORT, LONG_POLLING_TRANSPORT); framework.doCometSupport(request, AtmosphereResponse.newInstance()); assertNotNull(r.get()); }
@Test public void testInputStreamMessage() throws IOException, ServletException { AtmosphereRequest request = new AtmosphereRequest.Builder().pathInfo("/inputStreamInjection").method("GET").build(); framework.doCometSupport(request, AtmosphereResponse.newInstance()); assertNotNull(r.get()); r.get().resume(); assertNotNull(message.get()); assertEquals(message.get(), "message"); }
/** * 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; }
@Test public void createTest() { AtmosphereResource r = AtmosphereResourceFactory.getDefault() .create( mock(AtmosphereConfig.class), mock(Broadcaster.class), AtmosphereResponse.newInstance().request(AtmosphereRequest.create()), mock(AsyncSupport.class), mock(AtmosphereHandler.class)); assertNotNull(r); }
@Test public void testOverrideBroadcaster() throws IOException, ServletException { framework.setDefaultBroadcasterClassName(SimpleBroadcaster.class.getName()); AtmosphereRequest request = new AtmosphereRequest.Builder().pathInfo("/override").method("GET").build(); request.header(X_ATMOSPHERE_TRANSPORT, LONG_POLLING_TRANSPORT); framework.doCometSupport(request, AtmosphereResponse.newInstance()); assertNotNull(r.get()); assertEquals(r.get().getBroadcaster().getClass().getName(), SimpleBroadcaster.class.getName()); }
@Test public void testOnClose() throws IOException, ServletException { framework.addAtmosphereHandler( "/a", new AbstractReflectorAtmosphereHandler() { @Override public void onRequest(AtmosphereResource resource) throws IOException {} @Override public void destroy() {} }); AtmosphereRequest request = new AtmosphereRequest.Builder().pathInfo("/a").build(); final AtomicReference<Boolean> closed = new AtomicReference<Boolean>(); final AtmosphereResourceEventListener listener = new AtmosphereResourceEventListenerAdapter() { @Override public void onClose(AtmosphereResourceEvent event) { closed.set(true); } }; framework.interceptor( new AtmosphereInterceptor() { @Override public void configure(AtmosphereConfig config) {} @Override public Action inspect(AtmosphereResource r) { r.addEventListener(listener).suspend(); try { r.getBroadcaster().broadcast("void").get(); } catch (InterruptedException e) { } catch (ExecutionException e) { } return Action.CONTINUE; } @Override public void postInspect(AtmosphereResource r) { try { r.close(); } catch (IOException e) { e.printStackTrace(); } } }); framework.doCometSupport(request, AtmosphereResponse.newInstance()); assertTrue(closed.get()); }
@Test public void testPriority() throws IOException, ServletException { AtmosphereRequest request = new AtmosphereRequest.Builder().pathInfo("/priority").method("GET").build(); request.header(X_ATMOSPHERE_TRANSPORT, LONG_POLLING_TRANSPORT); framework.doCometSupport(request, AtmosphereResponse.newInstance()); assertEquals( framework.getAtmosphereHandlers().get("/priority").interceptors.getFirst().toString(), "XXX"); assertNotNull(r.get()); }
@Test public void notFoundTest() { for (int i = 0; i < 10; i++) { BroadcasterFactory.getDefault().get(String.valueOf(i)); } AtmosphereResource r = AtmosphereResourceFactory.getDefault() .create( mock(AtmosphereConfig.class), BroadcasterFactory.getDefault().lookup("1"), AtmosphereResponse.newInstance().request(AtmosphereRequest.create()), mock(AsyncSupport.class), mock(AtmosphereHandler.class)); assertNotNull(r); assertNull(AtmosphereResourceFactory.getDefault().find(r.uuid())); }
@BeforeMethod public void setUp() throws Exception { AtmosphereConfig config = new AtmosphereFramework().getAtmosphereConfig(); DefaultBroadcasterFactory factory = new DefaultBroadcasterFactory(ExcludeSessionBroadcaster.class, "NEVER", config); broadcaster = factory.get(ExcludeSessionBroadcaster.class, "test"); atmosphereHandler = new AR(); ar = new AtmosphereResourceImpl( config, broadcaster, mock(AtmosphereRequest.class), AtmosphereResponse.create(), mock(BlockingIOCometSupport.class), atmosphereHandler); broadcaster.addAtmosphereResource(ar); }
@Test public void findTest() { Broadcaster b1 = BroadcasterFactory.getDefault().get("b1"); Broadcaster b2 = BroadcasterFactory.getDefault().get("b2"); AtmosphereResource r = AtmosphereResourceFactory.getDefault() .create( mock(AtmosphereConfig.class), b1, AtmosphereResponse.newInstance().request(AtmosphereRequest.create()), mock(AsyncSupport.class), mock(AtmosphereHandler.class)); assertNotNull(r); b2.addAtmosphereResource(r); assertNotNull(AtmosphereResourceFactory.getDefault().find(r.uuid())); }
public void cancel() throws IOException { if (!isCancelled.getAndSet(true)) { logger.trace("Cancelling {}", uuid); action.type(Action.TYPE.RESUME); asyncSupport.action(this); // We must close the underlying WebSocket as well. if (AtmosphereResponse.class.isAssignableFrom(response.getClass())) { AtmosphereResponse.class.cast(response).close(); AtmosphereResponse.class.cast(response).destroy(); } if (AtmosphereRequest.class.isAssignableFrom(req.getClass())) { AtmosphereRequest.class.cast(req).destroy(); } if (broadcaster != null) { broadcaster.removeAtmosphereResource(this); } event.destroy(); } }
@Override public Action inspect(final AtmosphereResource ar) { final AtmosphereResourceImpl r = AtmosphereResourceImpl.class.cast(ar); final AtmosphereRequest request = r.getRequest(false); final AtmosphereResponse response = r.getResponse(false); String uuid = request.getHeader(HeaderConfig.X_ATMOSPHERE_TRACKING_ID); String handshakeUUID = request.getHeader(HeaderConfig.X_ATMO_PROTOCOL); if (uuid != null && uuid.equals("0") && handshakeUUID != null) { request.header(HeaderConfig.X_ATMO_PROTOCOL, null); // Since 1.0.10 final StringBuffer message = new StringBuffer(r.uuid()).append(wsDelimiter).append(System.currentTimeMillis()); // https://github.com/Atmosphere/atmosphere/issues/993 boolean track = false; if (r.getBroadcaster().getBroadcasterConfig().hasFilters()) { for (BroadcastFilter bf : r.getBroadcaster().getBroadcasterConfig().filters()) { if (TrackMessageSizeFilter.class.isAssignableFrom(bf.getClass())) { track = true; break; } } } final AtomicReference<String> protocolMessage = new AtomicReference<String>(message.toString()); if (track) { protocolMessage.set( (String) f.filter(r, protocolMessage.get(), protocolMessage.get()).message()); } if (!Utils.resumableTransport(r.transport())) { OnSuspend a = new OnSuspend() { @Override public void onSuspend(AtmosphereResourceEvent event) { response.write(protocolMessage.get()); try { response.flushBuffer(); } catch (IOException e) { logger.trace("", e); } } }; // Pass the information to Servlet Based Framework request.setAttribute(CALLBACK_JAVASCRIPT_PROTOCOL, a); r.addEventListener(a); } else { response.write(protocolMessage.get()); } // We don't need to reconnect here if (r.transport() == AtmosphereResource.TRANSPORT.WEBSOCKET || r.transport() == AtmosphereResource.TRANSPORT.STREAMING || r.transport() == AtmosphereResource.TRANSPORT.SSE) { return Action.CONTINUE; } else { return Action.SKIP_ATMOSPHEREHANDLER; } } return Action.CONTINUE; }
public ObserverSender(AtmosphereResponse response, List<Observer> observers) { if (observers == null) throw new UtilException("Cannot create ObserverSender without observer"); this.response = response; this.observers = observers; this.writer = response.getAsyncIOWriter(); }
/** * 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(); } } }
/** * Delegate the request processing to an instance of {@link org.atmosphere.cpr.AsyncSupport} * * @param req the {@link javax.servlet.http.HttpServletRequest} * @param res the {@link javax.servlet.http.HttpServletResponse} * @throws java.io.IOException * @throws javax.servlet.ServletException */ @Override public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException { framework.doCometSupport(AtmosphereRequest.wrap(req), AtmosphereResponse.wrap(res)); }
@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; }
@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; }
/** * Invoke the {@link AtmosphereHandler#onRequest} method. * * @param req the {@link AtmosphereRequest} * @param res the {@link AtmosphereResponse} * @return action the Action operation. * @throws java.io.IOException * @throws javax.servlet.ServletException */ Action action(AtmosphereRequest req, AtmosphereResponse res) throws IOException, ServletException { boolean webSocketEnabled = false; if (req.getHeaders("Connection") != null && req.getHeaders("Connection").hasMoreElements()) { String[] e = req.getHeaders("Connection").nextElement().toString().split(","); for (String upgrade : e) { if (upgrade.equalsIgnoreCase("Upgrade")) { webSocketEnabled = true; break; } } } if (webSocketEnabled && !supportWebSocket()) { res.setStatus(501); res.addHeader(X_ATMOSPHERE_ERROR, "Websocket protocol not supported"); res.flushBuffer(); return new Action(); } if (config.handlers().isEmpty()) { logger.error( "No AtmosphereHandler found. Make sure you define it inside META-INF/atmosphere.xml"); throw new AtmosphereMappingException( "No AtmosphereHandler found. Make sure you define it insides META-INF/atmosphere.xml"); } if (supportSession()) { // Create the session needed to support the Resume // operation from disparate requests. HttpSession session = req.getSession(true); // Do not allow times out. if (session.getMaxInactiveInterval() == DEFAULT_SESSION_TIMEOUT) { session.setMaxInactiveInterval(-1); } } req.setAttribute(FrameworkConfig.SUPPORT_SESSION, supportSession()); AtmosphereHandlerWrapper handlerWrapper = map(req); // Check Broadcaster state. If destroyed, replace it. Broadcaster b = handlerWrapper.broadcaster; if (b.isDestroyed()) { synchronized (handlerWrapper) { config.getBroadcasterFactory().remove(b, b.getID()); handlerWrapper.broadcaster = config.getBroadcasterFactory().get(b.getID()); } } AtmosphereResourceImpl resource = new AtmosphereResourceImpl( config, handlerWrapper.broadcaster, req, res, this, handlerWrapper.atmosphereHandler); req.setAttribute(FrameworkConfig.ATMOSPHERE_RESOURCE, resource); req.setAttribute(FrameworkConfig.ATMOSPHERE_HANDLER, handlerWrapper.atmosphereHandler); try { handlerWrapper.atmosphereHandler.onRequest(resource); } catch (IOException t) { resource.onThrowable(t); throw t; } if (trackActiveRequest && resource.getAtmosphereResourceEvent().isSuspended() && req.getAttribute(FrameworkConfig.CANCEL_SUSPEND_OPERATION) == null) { req.setAttribute(MAX_INACTIVE, System.currentTimeMillis()); aliveRequests.put(req, resource); } return resource.action(); }