void invokeAtmosphereHandler(AtmosphereResourceImpl r) throws IOException { if (!r.isInScope()) return; AtmosphereRequest req = r.getRequest(false); String disableOnEvent = r.getAtmosphereConfig().getInitParameter(ApplicationConfig.DISABLE_ONSTATE_EVENT); try { if (disableOnEvent == null || !disableOnEvent.equals(String.valueOf(true))) { AtmosphereHandler atmosphereHandler = (AtmosphereHandler) req.getAttribute(FrameworkConfig.ATMOSPHERE_HANDLER); synchronized (r) { atmosphereHandler.onStateChange(r.getAtmosphereResourceEvent()); Meteor m = (Meteor) req.getAttribute(AtmosphereResourceImpl.METEOR); if (m != null) { m.destroy(); } } req.removeAttribute(FrameworkConfig.ATMOSPHERE_RESOURCE); } } catch (IOException ex) { try { r.onThrowable(ex); } catch (Throwable t) { logger.warn("failed calling onThrowable()", ex); } } }
@Override public void action(AtmosphereResourceImpl r) { super.action(r); if (r.action().type() == Action.TYPE.RESUME && r.isInScope()) { HttpEvent event = (HttpEvent) r.getRequest(false).getAttribute(HTTP_EVENT); if (event != null && !r.transport().equals(AtmosphereResource.TRANSPORT.WEBSOCKET)) { close(event); } } }
public void timedOut() { try { ((AsynchronousProcessor) r.cometSupport) .timedout(r.getRequest(false), r.getResponse(false)); } catch (IOException e) { logger.debug("", e); } catch (ServletException e) { logger.debug("", e); } }
public void closed() { try { ((AsynchronousProcessor) r.cometSupport) .cancelled(r.getRequest(false), r.getResponse(false)); } catch (IOException e) { logger.debug("", e); } catch (ServletException e) { logger.debug("", e); } }
/** {@inheritDoc} */ @Override public void action(AtmosphereResourceImpl r) { super.action(r); if (r.isResumed() && r.getRequest().getAttribute(ASYNCHRONOUS_HOOK) != null) { if (r.getRequest().getAttribute(CHANNEL) == null) return; try { ((AsyncIOWriter) r.getRequest().getAttribute(CHANNEL)).close(); } catch (IOException e) { logger.trace("", e); } } }
/** {@inheritDoc} */ @Override public void action(AtmosphereResourceImpl resource) { super.action(resource); if (resource.action().type() == Action.TYPE.RESUME && resource.isInScope()) { try { CometEvent event = (CometEvent) resource.getRequest().getAttribute(COMET_EVENT); if (event == null) return; // Resume without closing the underlying suspended connection. if (config.getInitParameter(ApplicationConfig.RESUME_AND_KEEPALIVE) == null || config .getInitParameter(ApplicationConfig.RESUME_AND_KEEPALIVE) .equalsIgnoreCase("false")) { bz51881(event); } } catch (IOException ex) { logger.debug("action failed", ex); } } }
/** * All proprietary Comet based {@link Servlet} must invoke the cancelled method when the * underlying WebServer detect that the client closed the connection. * * @param req the {@link AtmosphereRequest} * @param res the {@link AtmosphereResponse} * @return action the Action operation. * @throws java.io.IOException * @throws javax.servlet.ServletException */ public Action cancelled(AtmosphereRequest req, AtmosphereResponse res) throws IOException, ServletException { synchronized (req) { AtmosphereResourceImpl r = null; try { if (trackActiveRequest) { long l = (Long) req.getAttribute(MAX_INACTIVE); if (l == -1) { // The closedDetector closed the connection. return timedoutAction; } req.setAttribute(MAX_INACTIVE, (long) -1); } logger.debug("Cancelling the connection for request {}", req); r = (AtmosphereResourceImpl) req.getAttribute(FrameworkConfig.ATMOSPHERE_RESOURCE); if (r != null) { r.getAtmosphereResourceEvent().setCancelled(true); invokeAtmosphereHandler(r); try { r.getResponse().sendError(503); r.getResponse().getOutputStream().close(); } catch (Throwable t) { try { r.getResponse().getWriter().close(); } catch (Throwable t2) { } } } } catch (Throwable ex) { // Something wrong happenned, ignore the exception logger.debug("failed to cancel resource: " + r, ex); } finally { try { if (r != null) { r.notifyListeners(); r.setIsInScope(false); r.cancel(); } } catch (Throwable t) { logger.trace("cancel", t); } finally { if (r != null) { destroyResource(r); } } } } return cancelledAction; }
@Override public AsyncSupport complete(AtmosphereResourceImpl r) { final HttpEvent event = (HttpEvent) r.getRequest(false).getAttribute(HTTP_EVENT); // Prevent Deadlock // https://github.com/Atmosphere/atmosphere/issues/1782 if (event != null) { if (!r.isResumed()) { ExecutorsFactory.getScheduler(config) .schedule( new Runnable() { @Override public void run() { close(event); } }, 500, TimeUnit.MILLISECONDS); } else { close(event); } } return this; }
/** {@inheritDoc} */ @Override public void action(AtmosphereResourceImpl r) { try { super.action(r); if (r.action().type() == Action.TYPE.RESUME) { AtmosphereRequest req = r.getRequest(false); CountDownLatch latch = null; if (req.getAttribute(LATCH) != null) { latch = (CountDownLatch) req.getAttribute(LATCH); } String s = config.getInitParameter(ApplicationConfig.RESUME_AND_KEEPALIVE); if (latch != null && (s == null || s.equalsIgnoreCase("false"))) { latch.countDown(); } else if (req.getAttribute(AtmosphereResourceImpl.PRE_SUSPEND) == null) { logger.trace("Unable to resume the suspended connection"); } } } catch (Exception ex) { logger.error("", ex); } }
@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; }
/** * 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; }
/** {@inheritDoc} */ public void action(AtmosphereResourceImpl r) { if (trackActiveRequest) { aliveRequests.remove(r.getRequest(false)); } }
/** * 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(); }