protected Broadcaster getBroadcaster(boolean autoCreate) { if (broadcaster == null) { throw new IllegalStateException("No Broadcaster associated with this AtmosphereResource."); } String s = config.getInitParameter(ApplicationConfig.RECOVER_DEAD_BROADCASTER); if (s != null) { autoCreate = Boolean.parseBoolean(s); } if (autoCreate && broadcaster.isDestroyed() && config.getBroadcasterFactory() != null) { logger.debug( "Broadcaster {} has been destroyed and cannot be re-used. Recreating a new one with the same name. You can turn off this" + " mechanism by adding, in web.xml, {} set to false", broadcaster.getID(), ApplicationConfig.RECOVER_DEAD_BROADCASTER); Broadcaster.SCOPE scope = broadcaster.getScope(); synchronized (this) { String id = scope != Broadcaster.SCOPE.REQUEST ? broadcaster.getID() : broadcaster.getID() + ".recovered" + UUID.randomUUID(); // Another Thread may have added the Broadcaster. broadcaster = config.getBroadcasterFactory().lookup(id, true); broadcaster.setScope(scope); broadcaster.addAtmosphereResource(this); } } return broadcaster; }
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(); } }
/** * Create a {@link ScheduledExecutorService} used ot schedule I/O and non I/O events. * * @param config the {@link AtmosphereConfig} * @return {@link ScheduledExecutorService} */ public static ScheduledExecutorService getScheduler(final AtmosphereConfig config) { final boolean shared = config.framework().isShareExecutorServices(); if (!shared || config.properties().get("scheduler") == null) { ScheduledExecutorService scheduler = Executors.newScheduledThreadPool( Runtime.getRuntime().availableProcessors(), new ThreadFactory() { private final AtomicInteger count = new AtomicInteger(); @Override public Thread newThread(final Runnable runnable) { Thread t = new Thread(runnable, "Atmosphere-Scheduler-" + count.getAndIncrement()); t.setDaemon(true); return t; } }); if (shared) { config.properties().put("scheduler", scheduler); } return scheduler; } else { return (ScheduledExecutorService) config.properties().get("scheduler"); } }
@Override public void configure(AtmosphereConfig config) { try { String s = config.getInitParameter(ATMOSPHERE_SPRING_EXCLUDE_CLASSES); if (s != null) { String[] list = s.split(","); for (String clazz : list) { excludedFromInjection.add(IOUtils.loadClass(getClass(), clazz)); } if (list.length > 0) { preventSpringInjection = true; } } context = new AnnotationConfigApplicationContext(); context.setParent( WebApplicationContextUtils.getWebApplicationContext( config.framework().getServletContext())); context.refresh(); // Hack to make it injectable context.register(AtmosphereConfig.class); ((AtmosphereConfig) context.getBean(AtmosphereConfig.class.getCanonicalName(), config.framework())) .populate(config); } catch (Exception ex) { logger.warn("Unable to configure injection", ex); } }
@BeforeMethod public void setUp() throws Exception { AtmosphereFramework f = new AtmosphereFramework() .addInitParameter(ApplicationConfig.WEBSOCKET_SUPPRESS_JSR356, "true"); config = f.init().getAtmosphereConfig(); factory = config.getBroadcasterFactory(); factory.remove(Broadcaster.ROOT_MASTER); metaBroadcaster = config.metaBroadcaster(); }
/** {@inheritDoc} */ @Override protected BroadcasterConfig createBroadcasterConfig(AtmosphereConfig config) { BroadcasterConfig bc = (BroadcasterConfig) config.properties().get(BroadcasterConfig.class.getName()); if (bc == null) { bc = new BroadcasterConfig(config.framework().broadcasterFilters(), config, false, getID()); config.properties().put(BroadcasterConfig.class.getName(), bc); } return bc; }
/** * Checks in the {@link AtmosphereConfig} if the {@link #propertyName} is defined as an * init-param and instantiate the appropriate class. * * <p>If instantiation fails, the exception is logged and {@code null} is returned. * * @param desiredType the type to be returned * @param config the configuration that provides parameters * @param <T> the generic for modular call * @return the instance of the expected class, {@code null} if an error occurs */ public <T> T retrieve(final Class<T> desiredType, final AtmosphereConfig config) { final String initParameter = config.getInitParameter(this.propertyName); final String className = (initParameter != null) ? initParameter : defaultClass; try { final AtmosphereFramework fwk = config.framework(); final Object retval = fwk.newClassInstance( desiredType, desiredType.getClass().cast(Class.forName(className))); return desiredType.cast(retval); } catch (Exception e) { logger.error("Unable to initialize {}", getClass().getName(), e); return null; } }
/** * 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 void configure(AtmosphereConfig config) { String s = config.getInitParameter(ApplicationConfig.MESSAGE_DELIMITER); if (s != null) { wsDelimiter = s; } }
/** * Return the {@link AtmosphereHandler} mapped to the passed servlet-path. * * @param req the {@link AtmosphereResponse} * @return the {@link AtmosphereHandler} mapped to the passed servlet-path. * @throws javax.servlet.ServletException */ protected AtmosphereHandlerWrapper map(AtmosphereRequest req) throws ServletException { String path; if (req.getPathInfo() != null) { path = req.getServletPath() + req.getPathInfo(); } else { path = req.getServletPath(); } if (path.isEmpty()) { path = "/"; } // (1) First, try exact match AtmosphereHandlerWrapper atmosphereHandlerWrapper = map(path); if (atmosphereHandlerWrapper == null) { // (2) Try with a trailing / if (!path.endsWith("/")) { atmosphereHandlerWrapper = map(path + "/"); } // (3) Try wildcard if (atmosphereHandlerWrapper == null) { atmosphereHandlerWrapper = map("/all"); } } if (atmosphereHandlerWrapper == null) { throw new AtmosphereMappingException("No AtmosphereHandler maps request for " + path); } config .getBroadcasterFactory() .add(atmosphereHandlerWrapper.broadcaster, atmosphereHandlerWrapper.broadcaster.getID()); return atmosphereHandlerWrapper; }
protected AtmosphereHandlerWrapper map(String path) { AtmosphereHandlerWrapper atmosphereHandlerWrapper = config.handlers().get(path); if (atmosphereHandlerWrapper == null) { final Map<String, String> m = new HashMap<String, String>(); for (Map.Entry<String, AtmosphereHandlerWrapper> e : config.handlers().entrySet()) { UriTemplate t = new UriTemplate(e.getKey()); logger.trace("Trying to map {} to {}", t, path); if (t.match(path, m)) { atmosphereHandlerWrapper = e.getValue(); logger.trace("Mapped {} to {}", t, e.getValue()); break; } } } return atmosphereHandlerWrapper; }
public void _destroy() { try { removeEventListeners(); if (!isCancelled.get()) { try { getBroadcaster(false).removeAtmosphereResource(this); } catch (IllegalStateException ex) { logger.trace(ex.getMessage(), ex); } if (config.getBroadcasterFactory().getDefault() != null) { config.getBroadcasterFactory().getDefault().removeAllAtmosphereResource(this); } } } catch (Throwable t) { logger.trace("destroyResource", t); } }
@Override public HttpSession session(boolean create) { if (config.isSupportSession() && session == null) { // http://java.net/jira/browse/GLASSFISH-18856 session = req.getSession(create); } return session; }
private static void keepAliveThreads(ThreadPoolExecutor e, AtmosphereConfig config) { int keepAlive = DEFAULT_KEEP_ALIVE; String s = config.getInitParameter(ApplicationConfig.EXECUTORFACTORY_KEEP_ALIVE); if (s != null) { keepAlive = Integer.parseInt(s); } e.setKeepAliveTime(keepAlive, TimeUnit.SECONDS); }
public JBossWebCometSupport(AtmosphereConfig config) { super(config); Object b = config.getInitParameter(ApplicationConfig.TOMCAT_CLOSE_STREAM); closeConnectionOnInputStream = b == null ? true : Boolean.parseBoolean(b.toString()); try { Class.forName(HttpEvent.class.getName()); } catch (Throwable e) { throw new IllegalStateException(unableToDetectComet()); } }
@Override public void configure(AtmosphereConfig config) { Object o = config.properties().get("shared"); if (o != null) { isShared = Boolean.parseBoolean(o.toString()); } if (isShared) { reaper = ExecutorsFactory.getScheduler(config); } else { reaper = Executors.newSingleThreadScheduledExecutor(); } this.config = config; }
@Override public void init(ServletConfig sc) throws ServletException { String maxInactive = sc.getInitParameter(MAX_INACTIVE) != null ? sc.getInitParameter(MAX_INACTIVE) : config.getInitParameter(MAX_INACTIVE); if (maxInactive != null) { trackActiveRequest = true; final long maxInactiveTime = Long.parseLong(maxInactive); if (maxInactiveTime <= 0) return; closedDetector.scheduleAtFixedRate( new Runnable() { public void run() { for (AtmosphereRequest req : aliveRequests.keySet()) { long l = (Long) req.getAttribute(MAX_INACTIVE); if (l > 0 && System.currentTimeMillis() - l > maxInactiveTime) { try { logger.debug( "Close detector disconnecting {}. Current size {}", req, aliveRequests.size()); AtmosphereResourceImpl r = (AtmosphereResourceImpl) aliveRequests.remove(req); cancelled(req, r.getResponse(false)); } catch (Throwable e) { logger.warn("closedDetector", e); } finally { try { req.setAttribute(MAX_INACTIVE, (long) -1); } catch (Throwable t) { logger.trace("closedDetector", t); } } } } } }, 0, 1, TimeUnit.SECONDS); } }
public ChannelBufferPool( final int minIdle, final int writeBufferPoolSize, final long validationInterval, AtmosphereConfig config) { this.writeBufferPoolSize = writeBufferPoolSize; initialize(minIdle); if (writeBufferPoolSize != -1) { ExecutorsFactory.getScheduler(config) .scheduleWithFixedDelay( new Runnable() { @Override public void run() { int size = pool.size(); if (size < minIdle) { int sizeToBeAdded = minIdle - size; for (int i = 0; i < sizeToBeAdded; i++) { pool.add(createObject()); } } else if (size > writeBufferPoolSize) { int sizeToBeRemoved = size - writeBufferPoolSize; for (int i = 0; i < sizeToBeRemoved; i++) { pool.poll(); } } } }, validationInterval, validationInterval, TimeUnit.SECONDS); config.shutdownHook( new AtmosphereConfig.ShutdownHook() { @Override public void shutdown() { pool.clear(); } }); } }
public void configure(AtmosphereConfig config) { this.config = config; String maxInactive = config.getInitParameter(MAX_INACTIVE); if (maxInactive != null) { maxInactiveTime = Long.parseLong(maxInactive); } if (maxInactiveTime > 0) { ExecutorsFactory.getScheduler(config) .scheduleAtFixedRate( new Runnable() { public void run() { idleResources(); } }, 0, 2, TimeUnit.SECONDS); } }
/** {@inheritDoc} */ @Override public void configure(final AtmosphereConfig config) { framework = config.framework(); arsf = AtmosphereResourceSessionFactory.getDefault(); setStompFormat(PropertyClass.STOMP_FORMAT_CLASS.retrieve(StompFormat.class, config)); try { // TODO: user must map AtmosphereServlet to /stomp in web.xml, can we offer a chance to set a // custom location ? framework.addAtmosphereHandler( "/stomp", framework.newClassInstance( AtmosphereHandler.class, AbstractReflectorAtmosphereHandler.Default.class)); interceptors = new ConcurrentHashMap<org.atmosphere.stomp.protocol.Action, StompInterceptor>(); configureInterceptor( config, ConnectInterceptor.class, org.atmosphere.stomp.protocol.Action.CONNECT, org.atmosphere.stomp.protocol.Action.STOMP, org.atmosphere.stomp.protocol.Action.NULL); configureInterceptor( config, SubscribeInterceptor.class, org.atmosphere.stomp.protocol.Action.SUBSCRIBE); configureInterceptor( config, UnsubscribeInterceptor.class, org.atmosphere.stomp.protocol.Action.UNSUBSCRIBE); configureInterceptor( config, SendInterceptor.class, org.atmosphere.stomp.protocol.Action.SEND); final BroadcastFilterLifecycle filter = framework.newClassInstance(BroadcastFilterLifecycle.class, StompBroadcastFilter.class); framework.broadcasterFilters(filter); filter.init(config); } catch (InstantiationException e) { logger.error("", e); } catch (IllegalAccessException e) { logger.error("", e); } }
protected void idleResources() { for (Broadcaster b : config.getBroadcasterFactory().lookupAll()) { for (AtmosphereResource r : b.getAtmosphereResources()) { AtmosphereRequest req = AtmosphereResourceImpl.class.cast(r).getRequest(false); try { if (req.getAttribute(MAX_INACTIVE) == null) return; long l = (Long) req.getAttribute(MAX_INACTIVE); if (l > 0 && System.currentTimeMillis() - l > maxInactiveTime) { req.setAttribute(MAX_INACTIVE, (long) -1); logger.debug("IdleResourceInterceptor disconnecting {}", r); if (!AtmosphereResourceImpl.class.cast(r).isSuspended() || !AtmosphereResourceImpl.class.cast(r).isInScope()) { return; } Future<?> f = (Future<?>) req.getAttribute(HeartbeatInterceptor.HEARTBEAT_FUTURE); if (f != null) f.cancel(false); req.removeAttribute(HeartbeatInterceptor.HEARTBEAT_FUTURE); Object o = req.getAttribute(ASYNCHRONOUS_HOOK); req.setAttribute(ASYNCHRONOUS_HOOK, null); AsynchronousProcessor.AsynchronousProcessorHook h; if (o != null && AsynchronousProcessor.AsynchronousProcessorHook.class.isAssignableFrom( o.getClass())) { h = (AsynchronousProcessor.AsynchronousProcessorHook) o; h.closed(); } } } catch (Throwable e) { logger.warn("IdleResourceInterceptor", e); } } } }
/** * Create an {@link ExecutorService} to be used for dispatching messages, not I/O events. * * @param config the {@link AtmosphereConfig} * @param name a name to use if shared is false. * @return {@link ExecutorService} */ public static ExecutorService getMessageDispatcher( final AtmosphereConfig config, final String name) { final boolean shared = config.framework().isShareExecutorServices(); boolean isExecutorShared = shared ? true : false; if (!shared || config.properties().get("executorService") == null) { int numberOfMessageProcessingThread = DEFAULT_MESSAGE_THREAD; String s = config.getInitParameter( ApplicationConfig.BROADCASTER_MESSAGE_PROCESSING_THREADPOOL_MAXSIZE); if (s != null) { numberOfMessageProcessingThread = Integer.parseInt(s); } if (isExecutorShared && numberOfMessageProcessingThread == 1) { logger.warn( "Not enough numberOfMessageProcessingThread for a shareable thread pool {}, " + "Setting it to a newCachedThreadPool", numberOfMessageProcessingThread); numberOfMessageProcessingThread = -1; } ThreadPoolExecutor messageService; if (numberOfMessageProcessingThread == -1) { messageService = (ThreadPoolExecutor) Executors.newCachedThreadPool( new ThreadFactory() { private final AtomicInteger count = new AtomicInteger(); @Override public Thread newThread(final Runnable runnable) { Thread t = new Thread( runnable, (shared ? "Atmosphere-Shared" : name) + "-DispatchOp-" + count.getAndIncrement()); t.setDaemon(true); return t; } }); } else { messageService = (ThreadPoolExecutor) Executors.newFixedThreadPool( numberOfMessageProcessingThread, new ThreadFactory() { private final AtomicInteger count = new AtomicInteger(); @Override public Thread newThread(final Runnable runnable) { Thread t = new Thread( runnable, (shared ? "Atmosphere-Shared" : name) + "-DispatchOp-" + count.getAndIncrement()); t.setDaemon(true); return t; } }); } keepAliveThreads(messageService, config); if (shared) { config.properties().put("executorService", messageService); } return messageService; } else { return (ExecutorService) config.properties().get("executorService"); } }
@AfterMethod public void unSet() throws Exception { config.destroy(); ExecutorsFactory.reset(config); factory.destroy(); }
@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; }
@Override public AtmosphereResource resume() { if (!isSuspended()) { logger.warn("AtmosphereResource {} not suspend, cannot resume it.", uuid()); return this; } try { if (!isResumed.getAndSet(true) && isInScope.get()) { logger.trace("AtmosphereResource {} is resuming", uuid()); action.type(Action.TYPE.RESUME); // We need it as Jetty doesn't support timeout Broadcaster b = getBroadcaster(false); if (!b.isDestroyed() && b instanceof DefaultBroadcaster) { ((DefaultBroadcaster) b).broadcastOnResume(this); } notifyListeners(); try { if (!b.isDestroyed()) { broadcaster.removeAtmosphereResource(this); } } catch (IllegalStateException ex) { logger.warn("Unable to resume", this); logger.debug(ex.getMessage(), ex); } if (b.getScope() == Broadcaster.SCOPE.REQUEST) { logger.debug("Broadcaster's scope is set to request, destroying it {}", b.getID()); b.destroy(); } // Resuming here means we need to pull away from all other Broadcaster, if they exists. if (config.getBroadcasterFactory() != null) { config.getBroadcasterFactory().removeAllAtmosphereResource(this); } try { req.setAttribute(ApplicationConfig.RESUMED_ON_TIMEOUT, Boolean.FALSE); } catch (Exception ex) { logger.debug("Resume exception: Cannot resume an already resumed/cancelled request", ex); } finally { try { Meteor m = (Meteor) req.getAttribute(METEOR); if (m != null) { m.destroy(); } } catch (Exception ex) { logger.debug( "Meteor resume exception: Cannot resume an already resumed/cancelled request", ex); } } if (req.getAttribute(PRE_SUSPEND) == null) { asyncSupport.action(this); } } else { logger.trace("Already resumed {}", this); return this; } } catch (Throwable t) { logger.trace("Wasn't able to resume a connection {}", this, t); } listeners.clear(); return this; }
/** {@inheritDoc} */ @Override public synchronized AtmosphereResource resume() { // We need to synchronize the method because the resume may occurs at the same time a message is // published // and we will miss that message. The DefaultBroadcaster synchronize on that method before // writing a message. try { if (!isResumed && isInScope) { action.type(Action.TYPE.RESUME); isResumed = true; // We need it as Jetty doesn't support timeout Broadcaster b = getBroadcaster(false); if (!b.isDestroyed() && b instanceof DefaultBroadcaster) { ((DefaultBroadcaster) b).broadcastOnResume(this); } notifyListeners(); try { if (!b.isDestroyed()) { broadcaster.removeAtmosphereResource(this); } } catch (IllegalStateException ex) { logger.warn("Unable to resume", this); logger.debug(ex.getMessage(), ex); } if (b.getScope() == Broadcaster.SCOPE.REQUEST) { logger.debug("Broadcaster's scope is set to request, destroying it {}", b.getID()); b.destroy(); } // Resuming here means we need to pull away from all other Broadcaster, if they exists. if (config.getBroadcasterFactory() != null) { config.getBroadcasterFactory().removeAllAtmosphereResource(this); } try { req.setAttribute(ApplicationConfig.RESUMED_ON_TIMEOUT, Boolean.FALSE); } catch (Exception ex) { logger.debug("Resume exception: Cannot resume an already resumed/cancelled request", ex); } finally { try { Meteor m = (Meteor) req.getAttribute(METEOR); if (m != null) { m.destroy(); } } catch (Exception ex) { logger.debug( "Meteor resume exception: Cannot resume an already resumed/cancelled request", ex); } } if (req.getAttribute(PRE_SUSPEND) == null) { asyncSupport.action(this); } } else { logger.debug("Cannot resume an already resumed/cancelled request {}", this); } } catch (Throwable t) { logger.trace("Wasn't able to resume a connection {}", this, t); } notifyListeners(new AtmosphereResourceEventImpl(this, true, false)); listeners.clear(); return this; }
/** * Parse the atmosphere-handlers element. * * @param document */ private AtmosphereConfig parse(AtmosphereConfig config, Document document) { Element element = document.getDocumentElement(); NodeList atmosphereHandlers = element.getElementsByTagName("atmosphere-handler"); for (int i = 0; i < atmosphereHandlers.getLength(); i++) { AtmosphereHandlerConfig atmoHandler = new AtmosphereHandlerConfig(); Node root = atmosphereHandlers.item(i); // parse Attributes for (int j = 0; j < root.getAttributes().getLength(); j++) { Node attribute = root.getAttributes().item(j); if (attribute.getNodeName().equals("support-session")) { atmoHandler.setSupportSession(attribute.getNodeValue()); } else if (attribute.getNodeName().equals("context-root")) { atmoHandler.setContextRoot(attribute.getNodeValue()); } else if (attribute.getNodeName().equals("class-name")) { atmoHandler.setClassName(attribute.getNodeValue()); } else if (attribute.getNodeName().equals("broadcaster")) { atmoHandler.setBroadcaster(attribute.getNodeValue()); } else if (attribute.getNodeName().equals("broadcasterCache")) { atmoHandler.setBroadcasterCache(attribute.getNodeValue()); } else if (attribute.getNodeName().equals("broadcastFilterClasses")) { String[] values = attribute.getNodeValue().split(","); for (String value : values) { atmoHandler.getBroadcastFilterClasses().add(value); } } else if (attribute.getNodeName().equals("comet-support")) { atmoHandler.setCometSupport(attribute.getNodeValue()); } else if (attribute.getNodeName().equals("interceptorClasses")) { String[] values = attribute.getNodeValue().split(","); for (String value : values) { atmoHandler.getAtmosphereInterceptorClasses().add(value); } } } NodeList list = root.getChildNodes(); for (int j = 0; j < list.getLength(); j++) { Node n = list.item(j); if (n.getNodeName().equals("property")) { String param = n.getAttributes().getNamedItem("name").getNodeValue(); String value = n.getAttributes().getNamedItem("value").getNodeValue(); atmoHandler.getProperties().add(new AtmosphereHandlerProperty(param, value)); } else if (n.getNodeName().equals("applicationConfig")) { String param = null; String value = null; for (int k = 0; k < n.getChildNodes().getLength(); k++) { Node n2 = n.getChildNodes().item(k); if (n2.getNodeName().equals("param-name")) { param = n2.getFirstChild().getNodeValue(); } else if (n2.getNodeName().equals("param-value")) { if (n2 != null) { value = n2.getFirstChild().getNodeValue(); } } } if (param != null) { atmoHandler.getApplicationConfig().add(new ApplicationConfiguration(param, value)); } } else if (n.getNodeName().equals("frameworkConfig")) { String param = null; String value = null; for (int k = 0; k < n.getChildNodes().getLength(); k++) { Node n2 = n.getChildNodes().item(k); if (n2.getNodeName().equals("param-name")) { param = n2.getFirstChild().getNodeValue(); } else if (n2.getNodeName().equals("param-value")) { if (n2 != null) { value = n2.getFirstChild().getNodeValue(); } } } if (param != null) { atmoHandler.getFrameworkConfig().add(new FrameworkConfiguration(param, value)); } } } config.getAtmosphereHandlerConfig().add(atmoHandler); } return config; }
/** * 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(); }
public Tomcat7CometSupport(AtmosphereConfig config) { super(config); Object b = config.getInitParameter(ApplicationConfig.TOMCAT_CLOSE_STREAM); closeConnectionOnInputStream = b == null ? true : Boolean.parseBoolean(b.toString()); }
/** Return the container's name. */ public String getContainerName() { return config.getServletConfig().getServletContext().getServerInfo(); }