/** * Suspend the connection by blocking the current {@link Thread} * * @param action The {@link Action} * @param req the {@link AtmosphereRequest} * @param res the {@link AtmosphereResponse} * @throws java.io.IOException * @throws javax.servlet.ServletException */ protected void suspend(Action action, AtmosphereRequest req, AtmosphereResponse res) throws IOException, ServletException { CountDownLatch latch = new CountDownLatch(1); req.setAttribute(LATCH, latch); boolean ok = true; try { if (action.timeout() != -1) { ok = latch.await(action.timeout(), TimeUnit.MILLISECONDS); } else { latch.await(); } } catch (InterruptedException ex) { logger.trace("", ex); } finally { if (!ok) { timedout(req, res); } else { if (req.resource() != null) { AtmosphereResourceImpl.class.cast(req.resource()).cancel(); } } } }
/** * Invoked by the Tomcat AIO when a Comet request gets detected. * * @param req the {@link AtmosphereRequest} * @param res the {@link AtmosphereResponse} * @throws java.io.IOException * @throws javax.servlet.ServletException */ public Action service(AtmosphereRequest req, AtmosphereResponse res) throws IOException, ServletException { HttpEvent event = (HttpEvent) req.getAttribute(HTTP_EVENT); // Comet is not enabled. if (event == null) { logger.error("HttpEvent is null, JBoss APR Not Properly installed"); throw unableToDetectComet; } if (logger.isTraceEnabled()) { logger.trace("Event Type {} for {}", event.getType(), req.getRequestURL().toString()); } Action action = null; // For now, we are just interested in HttpEvent.REA AtmosphereResource r = req.resource(); if (event.getType() == HttpEvent.EventType.BEGIN) { action = suspended(req, res); if (action.type() == Action.TYPE.SUSPEND) { // Do nothing except setting the times out try { if (action.timeout() != -1) { event.setTimeout((int) action.timeout()); } else { event.setTimeout(Integer.MAX_VALUE); } req.setAttribute(SUSPENDED, true); } catch (UnsupportedOperationException ex) { // Swallow s Tomcat APR isn't supporting time out // TODO: Must implement the same functionality using a Scheduler } } else if (action.type() == Action.TYPE.RESUME) { close(event); } else { close(event); } } else if (event.getType() == HttpEvent.EventType.READ) { // Not implemented logger.debug("Receiving bytes, unable to process them."); } else if (event.getType() == HttpEvent.EventType.EOF || event.getType() == HttpEvent.EventType.ERROR || event.getType() == HttpEvent.EventType.END) { if (r != null && r.isResumed()) { AtmosphereResourceImpl.class.cast(req.resource()).cancel(); } else if (req.getAttribute(SUSPENDED) != null && closeConnectionOnInputStream) { req.setAttribute(SUSPENDED, null); action = cancelled(req, res); } else { close(event); } } else if (event.getType() == HttpEvent.EventType.TIMEOUT) { action = timedout(req, res); close(event); } return action; }
/** * Invoked by the Tomcat AIO when a Comet request gets detected. * * @param req the {@link AtmosphereRequest} * @param res the {@link AtmosphereResponse} * @throws java.io.IOException * @throws javax.servlet.ServletException */ @Override public Action service(AtmosphereRequest req, AtmosphereResponse res) throws IOException, ServletException { CometEvent event = (CometEvent) req.getAttribute(COMET_EVENT); // Comet is not enabled. if (event == null) { throw new IllegalStateException(unableToDetectComet()); } Action action = null; // For now, we are just interested in CometEvent.READ if (event.getEventType() == EventType.BEGIN) { action = suspended(req, res); if (action.type() == Action.TYPE.SUSPEND) { // Do nothing except setting the times out try { if (action.timeout() != -1) { event.setTimeout((int) action.timeout()); } else { event.setTimeout(Integer.MAX_VALUE); } } catch (UnsupportedOperationException ex) { // TODO: Must implement the same functionality using a Scheduler logger.trace( "Warning: CometEvent.setTimeout not supported on this Tomcat instance. " + " [The Tomcat native connector does not support timeouts on asynchronous I/O.]"); } req.setAttribute(SUSPENDED, true); } else if (action.type() == Action.TYPE.RESUME) { bz51881(event); } else { bz51881(event); } } else if (event.getEventType() == EventType.READ) { // Not implemented } else if (event.getEventSubType() == CometEvent.EventSubType.CLIENT_DISCONNECT) { if (req.getAttribute(SUSPENDED) != null) { req.setAttribute(SUSPENDED, null); action = cancelled(req, res); } bz51881(event); } else if (event.getEventSubType() == CometEvent.EventSubType.TIMEOUT) { action = timedout(req, res); bz51881(event); } else if (event.getEventType() == EventType.ERROR) { bz51881(event); } else if (event.getEventType() == EventType.END) { if (req.resource().isResumed()) { AtmosphereResourceImpl.class.cast(req.resource()).cancel(); } else if (req.getAttribute(SUSPENDED) != null && closeConnectionOnInputStream) { req.setAttribute(SUSPENDED, null); action = cancelled(req, res); } else { bz51881(event); } } return action; }
/** {@inheritDoc} */ public Action service(AtmosphereRequest req, AtmosphereResponse res) throws IOException, ServletException { Action action = null; try { action = suspended(req, res); if (action.type() == Action.TYPE.SUSPEND) { suspend(action, req, res); } else if (action.type() == Action.TYPE.RESUME) { CountDownLatch latch = (CountDownLatch) req.getAttribute(LATCH); if (latch == null || req.getAttribute(AtmosphereResourceImpl.PRE_SUSPEND) == null) { logger.debug("response wasn't suspended: {}", res); return action; } latch.countDown(); Action nextAction = resumed(req, res); if (nextAction.type() == Action.TYPE.SUSPEND) { suspend(action, req, res); } } } finally { Object event = req.getAttribute(TomcatCometSupport.COMET_EVENT); if (event != null) { try { Class.forName(org.apache.catalina.CometEvent.class.getName()); if (org.apache.catalina.CometEvent.class.isAssignableFrom(event.getClass())) { org.apache.catalina.CometEvent.class.cast(event).close(); } } catch (Throwable e) { logger.trace("", e); } try { Class.forName(org.apache.catalina.comet.CometEvent.class.getName()); if (org.apache.catalina.comet.CometEvent.class.isAssignableFrom(event.getClass())) { org.apache.catalina.comet.CometEvent.class.cast(event).close(); } } catch (Throwable e) { logger.trace("", e); } } try { event = req.getAttribute(JBossWebCometSupport.HTTP_EVENT); Class.forName(org.jboss.servlet.http.HttpEvent.class.getName()); if (event != null) { org.jboss.servlet.http.HttpEvent.class.cast(event).close(); } } catch (Throwable e) { logger.trace("", e); } } return action; }