org.atmosphere.cpr.AtmosphereServlet Maven / Gradle / Ivy
/*
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2007-2008 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*
*/
package org.atmosphere.cpr;
import org.apache.catalina.CometEvent;
import org.apache.catalina.CometProcessor;
import org.atmosphere.container.BlockingIOCometSupport;
import org.atmosphere.container.GoogleAppEngineCometSupport;
import org.atmosphere.container.JBossWebCometSupport;
import org.atmosphere.container.TomcatCometSupport;
import org.atmosphere.container.WebLogicCometSupport;
import org.atmosphere.handler.ReflectorServletProcessor;
import org.atmosphere.util.AtmosphereConfigReader;
import org.atmosphere.util.AtmosphereConfigReader.Property;
import org.atmosphere.util.BroadcasterLookup;
import org.atmosphere.util.IntrospectionUtils;
import org.atmosphere.util.LoggerUtils;
import org.atmosphere.util.Version;
import org.jboss.servlet.http.HttpEvent;
import org.jboss.servlet.http.HttpEventServlet;
import weblogic.servlet.http.AbstractAsyncServlet;
import weblogic.servlet.http.RequestResponseKey;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* The {@link AtmosphereServlet} acts as a dispatcher for {@link AtmosphereHandler}
* defined in META-INF/atmosphere.xml, or if atmosphere.xml is missing, all classes
* that implements {@link AtmosphereHandler} will be discovered and mapped using
* the class's name. This {@link Servlet} can be defined inside an application's
* web.xml using the following:
*
<servlet>
<description>AtmosphereServlet</description>
<servlet-name>AtmosphereServlet</servlet-name>
<servlet-class>org.atmosphere.cpr.AtmosphereServlet</servlet-class>
<load-on-startup>0 </load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AtmosphereServlet</servlet-name>
<url-pattern>/Atmosphere </url-pattern>
</servlet-mapping>
*
*
* You can force this Servlet to use native API of the Web Server instead of
* the Servlet 3.0 Async API you are deploying on by adding
*
<init-param>
<param-name>org.atmosphere.useNative</param-name>
<param-value>true</param-value>
</init-param>
*
*
* You can force this Servlet to use one Thread per connection instead of
* native API of the Web Server you are deploying on by adding
*
<init-param>
<param-name>org.atmosphere.useBlocking</param-name>
<param-value>true</param-value>
</init-param>
*
*
* The Atmosphere Framework can also be used as a Servlet Filter ({@link AtmosphereFilter}).
*
* If you are planning to use JSP, Servlet or JSF, you can instead use the
* {@link MeteorServlet}, which allow the use of {@link Meteor} inside those
* components.
*
* @author Jeanfrancois Arcand
*/
public class
AtmosphereServlet extends AbstractAsyncServlet
implements CometProcessor, HttpEventServlet{
// If we detect Servlet 3.0, should we still use the default
// native Comet API.
protected boolean useNativeImplementation = false;
protected boolean useBlockingImplementation = false;
protected boolean useStreamForFlushingComments = false;
public final static String JERSEY_BROADCASTER = "org.atmosphere.jersey.JerseyBroadcaster";
public final static String JERSEY_CONTAINER = "com.sun.jersey.spi.container.servlet.ServletContainer";
public final static String GAE_BROADCASTER = org.atmosphere.util.gae.GAEDefaultBroadcaster.class.getName();
public final static String PROPERTY_SERVLET_MAPPING = "org.atmosphere.jersey.servlet-mapping";
public final static String PROPERTY_BLOCKING_COMETSUPPORT = "org.atmosphere.useBlocking";
public final static String PROPERTY_NATIVE_COMETSUPPORT = "org.atmosphere.useNative";
public final static String PROPERTY_USE_STREAM = "org.atmosphere.useStream";
public final static String BROADCASTER_CLASS = "org.atmosphere.cpr.broadcasterClass";
public final static String PROPERTY_COMET_SUPPORT = "org.atmosphere.cpr.cometSupport";
public final static String PRIMEFACES_SERVLET="org.primefaces.comet.PrimeFacesCometServlet";
public final static String DISABLE_ONSTATE_EVENT = "org.atmosphere.disableOnStateEvent";
public final static String WEB_INF = "/WEB-INF/classes/";
public final static Logger logger = LoggerUtils.getLogger();
protected final ArrayList possibleAtmosphereHandlersCandidate = new ArrayList();
protected final HashMap initParams = new HashMap();
/**
* The list of {@link AtmosphereHandler} and their associated mapping.
*/
protected final Map atmosphereHandlers =
new HashMap();
// The WebServer we are running on.
protected CometSupport cometSupport;
protected AtmosphereConfig config;
protected boolean isFilter = false;
protected String broadcasterClassName = DefaultBroadcaster.class.getName();
protected final AtomicBoolean isCometSupportConfigured = new AtomicBoolean(false);
protected boolean isCometSupportSpecified = false;
protected boolean isBroadcasterSpecified = false;
public final static class AtmosphereHandlerWrapper{
public final AtmosphereHandler atmosphereHandler;
public Broadcaster broadcaster;
public AtmosphereHandlerWrapper(AtmosphereHandler g){
this.atmosphereHandler = g;
}
public AtmosphereHandlerWrapper(AtmosphereHandler g, Broadcaster b){
this.atmosphereHandler = g;
this.broadcaster = b;
}
}
/**
* Return a configured instance of {@link AtmosphereConfig}
* @param supportSession true if session is supported.
*
* @return a configured instance of {@link AtmosphereConfig}
*/
public AtmosphereConfig newAtmosphereConfig(boolean supportSession){
AtmosphereConfig c = new AtmosphereConfig();
c.supportSession = supportSession;
return c;
}
public class AtmosphereConfig{
protected boolean supportSession = true;
protected AtmosphereHandler ah;
private BroadcasterLookup bl = new BroadcasterLookup();
protected Map handlers(){
return AtmosphereServlet.this.atmosphereHandlers;
}
public ServletContext getServletContext(){
return AtmosphereServlet.this.getServletContext();
}
public String getInitParameter(String name){
// First looks locally
String s = initParams.get(name);
if (s != null){
return s;
}
return AtmosphereServlet.this.getInitParameter(name);
}
public Enumeration getInitParameterNames(){
return AtmosphereServlet.this.getInitParameterNames();
}
public ServletConfig getServletConfig(){
return AtmosphereServlet.this.getServletConfig();
}
public String getWebServerName(){
return AtmosphereServlet.this.cometSupport.getContainerName();
}
/**
* Return the {@link AtmosphereHandler} associated with this config.
* @return the {@link AtmosphereHandler} associated with this config.
*/
public AtmosphereHandler getAtmosphereHandler(){
return ah;
}
/**
* Return an instance of a {@link BroadcasterLookup}
* @return an instance of a {@link BroadcasterLookup}
*/
public BroadcasterLookup getBroadcasterLookup(){
return bl;
}
}
/**
* Simple class/struck that hold the current state.
*/
public static class Action{
public enum TYPE {SUSPEND, RESUME, NONE, CANCEL}
public long timeout = -1L;
public TYPE type;
public Action(){
type = TYPE.NONE;
}
public Action(TYPE type){
this.type = type;
}
public Action(TYPE type,long timeout){
this.timeout = timeout;
this.type = type;
}
}
/**
* Create an Atmosphere Servlet.
*/
public AtmosphereServlet(){
if (System.getProperty(PROPERTY_NATIVE_COMETSUPPORT) != null){
useNativeImplementation = Boolean
.parseBoolean(System.getProperty(PROPERTY_NATIVE_COMETSUPPORT));
isCometSupportSpecified = true;
}
if (System.getProperty(PROPERTY_BLOCKING_COMETSUPPORT) != null){
useBlockingImplementation = Boolean
.parseBoolean(System.getProperty(PROPERTY_BLOCKING_COMETSUPPORT));
isCometSupportSpecified = true;
}
if (System.getProperty(DISABLE_ONSTATE_EVENT) != null){
initParams.put(DISABLE_ONSTATE_EVENT,System.getProperty(DISABLE_ONSTATE_EVENT));
}
}
/**
* Create an Atmosphere Servlet.
*/
public AtmosphereServlet(boolean isFilter){
this();
this.isFilter = isFilter;
}
/**
* Add an {@link AtmosphereHandler} serviced by the {@link Servlet}
* This API is exposed to allow embedding an Atmosphere application.
* @param mapping The servlet mapping (servlet path)
* @param h implementation of an {@link AtmosphereHandler}
*/
public void addAtmosphereHandler(String mapping, AtmosphereHandler h) {
if (!mapping.startsWith("/")){
mapping = "/" + mapping;
}
AtmosphereHandlerWrapper w = new AtmosphereHandlerWrapper(h);
atmosphereHandlers.put(mapping,w);
try{
w.broadcaster = (Broadcaster)this.getClass().getClassLoader()
.loadClass(broadcasterClassName).newInstance();
} catch (Throwable t) {
logger.log(Level.WARNING, "Unable to load Broadcaster class: "
+ broadcasterClassName, t);
} finally {
if (w.broadcaster == null){
w.broadcaster = new DefaultBroadcaster();
}
}
}
/**
* Add init-param like if they were defined in web.xml
* @param name The name
* @param value The value
*/
public void addInitParameter(String name, String value){
initParams.put(name,value);
}
/**
* Load the {@link AtmosphereHandler} associated with this AtmosphereServlet.
* @param sc the {@link ServletContext}
*/
@Override
public void init(ServletConfig sc) throws ServletException{
try{
super.init(sc);
config = new AtmosphereConfig();
doInitParams(sc);
detectGoogleAppEngine(sc);
loadConfiguration(sc);
autoDetectContainer();
cometSupport.init(sc);
initAtmosphereServletProcessor(sc);
logger.log(Level.INFO,"Atmosphere Framework "
+ Version.getRawVersion() + " started.");
} catch (Throwable t){
logger.log(Level.SEVERE,"",t);
if (t instanceof ServletException)
throw (ServletException)t;
throw new ServletException(t.getCause());
}
}
/**
* Read init param from web.xml and apply them.
* @param sc
*/
protected void doInitParams(ServletConfig sc){
initParams.put(DISABLE_ONSTATE_EVENT,"false");
String s = sc.getInitParameter(PROPERTY_NATIVE_COMETSUPPORT);
if (s != null){
useNativeImplementation = Boolean.parseBoolean(s);
if (useNativeImplementation) isCometSupportSpecified = true;
}
s = sc.getInitParameter(PROPERTY_BLOCKING_COMETSUPPORT);
if (s != null){
useBlockingImplementation = Boolean.parseBoolean(s);
if (useBlockingImplementation) isCometSupportSpecified = true;
}
s = sc.getInitParameter(PROPERTY_USE_STREAM);
if (s != null){
useStreamForFlushingComments = Boolean.parseBoolean(s);
}
s = sc.getInitParameter(PROPERTY_COMET_SUPPORT);
if (s != null){
cometSupport = new DefaultCometSupportResolver(config).newCometSupport(s);
isCometSupportSpecified = true;
}
s = sc.getInitParameter(BROADCASTER_CLASS);
if (s != null){
broadcasterClassName = s;
isBroadcasterSpecified = true;
}
}
protected void loadConfiguration(ServletConfig sc)throws ServletException{
try{
//TODO -> Add support for WEB-INF/lib/*.jar
URL url = sc.getServletContext().getResource("/WEB-INF/classes/");
URLClassLoader urlC = new URLClassLoader(new URL[] {url},
Thread.currentThread().getContextClassLoader());
loadAtmosphereDotXml(sc.getServletContext().
getResourceAsStream("/META-INF/atmosphere.xml"), urlC);
if (atmosphereHandlers.size() == 0){
logger.warning("Missing META-INF/atmosphere.xml." +
" Will try to autodetect AtmosphereHandler");
autoDetectAtmosphereHandlers(sc.getServletContext(), urlC);
// If we still haven found anything.
if (atmosphereHandlers.size() == 0) {
detectJerseyRuntime(sc);
}
}
} catch (Throwable t){
throw new ServletException(t);
}
}
/**
* Auto-detect Jersey when no atmosphere.xml file are specified.
*
* @param sc {@link ServletConfig}
* @return true if Jersey classes are detected
*/
protected boolean detectJerseyRuntime(ServletConfig sc){
// If Primefaces is detected, never starts Jersey.
try{
Class.forName(PRIMEFACES_SERVLET);
return false;
} catch (Throwable t){
}
try{
Class.forName(JERSEY_CONTAINER);
useStreamForFlushingComments = true;
} catch (Throwable t){
return false;
}
logger.warning("Missing META-INF/atmosphere.xml but found the Jersey runtime. " +
"Starting Jersey");
ReflectorServletProcessor rsp = new ReflectorServletProcessor();
if (!isBroadcasterSpecified) broadcasterClassName = JERSEY_BROADCASTER;
rsp.setServletClassName(JERSEY_CONTAINER);
config.supportSession = false;
initParams.put(DISABLE_ONSTATE_EVENT,"true");
String mapping = sc.getInitParameter(PROPERTY_SERVLET_MAPPING);
if (mapping == null){
mapping = "/*";
}
addAtmosphereHandler(mapping,rsp);
return true;
}
/**
* Auto-Detect Google App Engine.
*/
boolean detectGoogleAppEngine(ServletConfig sc){
if (sc.getServletContext().getServerInfo().startsWith("Google")){
broadcasterClassName = GAE_BROADCASTER;
cometSupport = new GoogleAppEngineCometSupport(config);
return true;
} else {
return false;
}
}
/**
* Initialize {@link AtmosphereServletProcessor}
* @param sc the {@link ServletConfig}
* @throws javax.servlet.ServletException
*/
void initAtmosphereServletProcessor(ServletConfig sc) throws ServletException{
AtmosphereHandler a;
for (Entry h: atmosphereHandlers.entrySet()){
a = h.getValue().atmosphereHandler;
if (a instanceof AtmosphereServletProcessor){
((AtmosphereServletProcessor)a).init(sc);
}
}
}
@Override
public void destroy(){
if (cometSupport instanceof AsynchronousProcessor){
((AsynchronousProcessor)cometSupport).shutdown();
}
AtmosphereHandler a;
for (Entry h: atmosphereHandlers.entrySet()){
a = h.getValue().atmosphereHandler;
if (a instanceof AtmosphereServletProcessor){
((AtmosphereServletProcessor)a).destroy();
}
}
BroadcasterLookup.destroy();
}
/**
* Load AtmosphereHandler defined under META-INF/atmosphere.xml
*/
protected void loadAtmosphereDotXml(InputStream stream, URLClassLoader c)
throws IOException, ServletException{
if (stream == null){
return;
}
AtmosphereConfigReader reader = new AtmosphereConfigReader(stream);
Map atmosphereHandlerNames = reader.getAtmosphereHandlers();
Set> entries = atmosphereHandlerNames.entrySet();
for (Entry entry: entries){
AtmosphereHandler g;
try {
if (!entry.getValue().equals(ReflectorServletProcessor.class.getName())){
g = (AtmosphereHandler) c.loadClass(entry.getValue()).newInstance();
} else {
g = new ReflectorServletProcessor();
}
logger.info("Sucessfully loaded " + g
+ " mapped to context-path " + entry.getKey());
AtmosphereHandlerWrapper wrapper = new AtmosphereHandlerWrapper(g);
atmosphereHandlers.put(entry.getKey(), wrapper);
boolean isJersey = false;
for (Property p: reader.getProperty(entry.getKey())){
if (p.value != null && p.value.indexOf("jersey") != -1){
isJersey = true;
initParams.put(DISABLE_ONSTATE_EVENT,"true");
useStreamForFlushingComments = true;
}
IntrospectionUtils.setProperty(g,p.name,p.value);
}
config.supportSession = !isJersey;
if (!reader.supportSession().equals("")){
config.supportSession = Boolean.valueOf(reader.supportSession());
}
for (Property p: reader.getProperty(entry.getKey())){
IntrospectionUtils.addProperty(g,p.name,p.value);
}
String broadcasterClass = reader.getBroadcasterClass(entry.getKey());
if (broadcasterClass != null){
wrapper.broadcaster = (Broadcaster)
c.loadClass(broadcasterClass).newInstance();
broadcasterClassName = broadcasterClass;
}
if (!isJersey && wrapper.broadcaster == null){
wrapper.broadcaster = (Broadcaster)
c.loadClass(broadcasterClassName).newInstance();
} else if (broadcasterClass == null){
broadcasterClassName = JERSEY_BROADCASTER;
wrapper.broadcaster = (Broadcaster)
c.loadClass(JERSEY_BROADCASTER).newInstance();
}
if (reader.getCometSupportClass() != null){
cometSupport = (CometSupport)
c.loadClass(reader.getCometSupportClass()).newInstance();
}
logger.info("Using " + wrapper.broadcaster.getClass().getName()
+ " with a Thread Pool size of : "
+ BroadcasterConfig.numOfProcessor);
} catch (Throwable t) {
logger.log(Level.WARNING, "Unable to load AtmosphereHandler class: "
+ entry.getValue(), t);
throw new ServletException(t);
}
}
}
/**
* Set the {@link CometSupport} implementation. Make sure you don't set
* an implementation that only works on some Container. See {@link BlockingIOCometSupport}
* for an example.
*
* @param cometSupport
*/
public void setCometSupport(CometSupport cometSupport){
this.cometSupport = cometSupport;
}
/**
* Return the current {@link CometSupport}
* @return
*/
public CometSupport getCometSupport(){
return cometSupport;
}
/**
* Returns an instance of CometSupportResolver {@link CometSupportResolver}
* @return CometSupportResolver
*/
protected CometSupportResolver createCometSupportResolver(){
return new DefaultCometSupportResolver(config);
}
/**
* Auto detect the underlying Servlet Container we are running on.
*/
protected void autoDetectContainer(){
// Was defined in atmosphere.xml
if (getCometSupport() == null){
setCometSupport(createCometSupportResolver().resolve(useNativeImplementation,useBlockingImplementation));
}
logger.info("Atmosphere is using for CometSupport: "
+ getCometSupport().getClass().getName()+ " running under container "
+ cometSupport.getContainerName());
}
/**
* Auto detect instance of {@link AtmosphereHandler} in case META-INF/atmosphere.xml
* is missing.
* @param sc {@link ServletContext}
* @param c {@link URLClassLoader} to load the class.
*/
protected void autoDetectAtmosphereHandlers(ServletContext sc, URLClassLoader c)
throws MalformedURLException, URISyntaxException{
String s = sc.getRealPath(WEB_INF);
// Weblogic bug
if (s == null){
URL u = sc.getResource(WEB_INF);
if (u == null) return;
s = u.getPath();
}
File f = new File(s);
if (f.isDirectory()){
getFiles(f);
for (String className: possibleAtmosphereHandlersCandidate){
try {
className = className.replace('\\','/');
className = className.substring(className.indexOf(WEB_INF)
+ WEB_INF.length(), className.lastIndexOf(".")).replace('/','.');
AtmosphereHandler g = (AtmosphereHandler) c.loadClass(className).newInstance();
logger.info("Sucessfully loaded " + g
+ " mapped to context-path " + g.getClass().getSimpleName());
atmosphereHandlers.put("/" + g.getClass().getSimpleName(),
new AtmosphereHandlerWrapper(g,
(Broadcaster)c.loadClass(broadcasterClassName).newInstance()));
} catch (Throwable t) {
logger.finest(className + " is not a AtmosphereHandler");
}
}
}
logger.info("Atmosphere using Broadcaster " + broadcasterClassName);
}
/**
* Get the list of possible candidate to load as {@link AtmosphereHandler}
* @param f the real path {@link File}
*/
protected void getFiles(File f){
File[] files = f.listFiles();
for (File test: files){
if (test.isDirectory()){
getFiles(test);
} else {
String clazz = test.getAbsolutePath();
if (clazz.endsWith(".class")){
possibleAtmosphereHandlersCandidate.add(clazz);
}
}
}
}
/**
* Delegate the request processing to an instance of {@link CometSupport}
* @param req the {@link HttpServletRequest}
* @param res the {@link HttpServletResponse}
* @throws java.io.IOException
* @throws javax.servlet.ServletException
*/
@Override
public void doHead(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
doPost(req, res);
}
/**
* Delegate the request processing to an instance of {@link CometSupport}
* @param req the {@link HttpServletRequest}
* @param res the {@link HttpServletResponse}
* @throws java.io.IOException
* @throws javax.servlet.ServletException
*/
@Override
public void doOptions(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
doPost(req, res);
}
/**
* Delegate the request processing to an instance of {@link CometSupport}
* @param req the {@link HttpServletRequest}
* @param res the {@link HttpServletResponse}
* @throws java.io.IOException
* @throws javax.servlet.ServletException
*/
@Override
public void doTrace(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
doPost(req, res);
}
/**
* Delegate the request processing to an instance of {@link CometSupport}
* @param req the {@link HttpServletRequest}
* @param res the {@link HttpServletResponse}
* @throws java.io.IOException
* @throws javax.servlet.ServletException
*/
@Override
public void doDelete(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
doPost(req, res);
}
/**
* Delegate the request processing to an instance of {@link CometSupport}
* @param req the {@link HttpServletRequest}
* @param res the {@link HttpServletResponse}
* @throws java.io.IOException
* @throws javax.servlet.ServletException
*/
@Override
public void doPut(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
doPost(req, res);
}
/**
* Delegate the request processing to an instance of {@link CometSupport}
* @param req the {@link HttpServletRequest}
* @param res the {@link HttpServletResponse}
* @throws java.io.IOException
* @throws javax.servlet.ServletException
*/
@Override
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
doPost(req, res);
}
/**
* Delegate the request processing to an instance of {@link CometSupport}
* @param req the {@link HttpServletRequest}
* @param res the {@link HttpServletResponse}
* @throws java.io.IOException
* @throws javax.servlet.ServletException
*/
@Override
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
doCometSupport(req,res);
}
/**
* Invoke the proprietary {@link CometSupport}
*
* @param req
* @param res
* @return
* @throws IOException
* @throws ServletException
*/
protected Action doCometSupport(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
req.setAttribute(BROADCASTER_CLASS, broadcasterClassName);
req.setAttribute(PROPERTY_USE_STREAM, useStreamForFlushingComments);
try{
return cometSupport.service(req, res);
} catch (IllegalStateException ex){
if (ex.getMessage() != null && ex.getMessage().startsWith("Tomcat failed")){
if (!isFilter){
logger.warning(ex.getMessage());
logger.warning("Using the BlockingIOCometSupport.");
}
cometSupport = new BlockingIOCometSupport(config);
service(req,res);
} else {
logger.log(Level.SEVERE,"AtmosphereServlet exception", ex);
throw ex;
}
}
return null;
}
/**
* Hack to support Tomcat AIO like other WebServer. This method is invoked
* by Tomcat when it detect a {@link Servlet} implements the interface
* {@link CometProcessor} without invoking {@link Servlet#service}
*
* @param cometEvent the {@link CometEvent}
* @throws java.io.IOException
* @throws javax.servlet.ServletException
*/
public void event(CometEvent cometEvent) throws IOException, ServletException {
HttpServletRequest req = cometEvent.getHttpServletRequest();
HttpServletResponse res = cometEvent.getHttpServletResponse();
req.setAttribute(TomcatCometSupport.COMET_EVENT, cometEvent);
if (!isCometSupportSpecified && !isCometSupportConfigured.getAndSet(true)){
synchronized(cometSupport){
if (!cometSupport.getClass().equals(TomcatCometSupport.class)){
logger.warning("TomcatCometSupport is enabled, switching to it");
cometSupport = new TomcatCometSupport(config);
}
}
}
doCometSupport(req, res);
}
/**
* Hack to support JBossWeb AIO like other WebServer. This method is invoked
* by Tomcat when it detect a {@link Servlet} implements the interface
* {@link HttpEventServlet} without invoking {@link Servlet#service}
*
* @param httpEvent the {@link CometEvent}
* @throws java.io.IOException
* @throws javax.servlet.ServletException
*/
public void event(HttpEvent httpEvent) throws IOException, ServletException {
HttpServletRequest req = httpEvent.getHttpServletRequest();
HttpServletResponse res = httpEvent.getHttpServletResponse();
req.setAttribute(JBossWebCometSupport.HTTP_EVENT, httpEvent);
if (!isCometSupportSpecified && !isCometSupportConfigured.getAndSet(true)){
synchronized(cometSupport){
if (!cometSupport.getClass().equals(JBossWebCometSupport.class)){
logger.warning("JBossWebCometSupport is enabled, switching to it");
cometSupport = new JBossWebCometSupport(config);
}
}
}
doCometSupport(req, res);
}
/**
* Weblogic specific comet based implementation.
*
* @param rrk
* @return
* @throws java.io.IOException
* @throws javax.servlet.ServletException
*/
protected boolean doRequest(RequestResponseKey rrk) throws IOException, ServletException {
try{
rrk.getRequest().getSession().setAttribute(WebLogicCometSupport.RRK,rrk);
Action action = doCometSupport(rrk.getRequest(), rrk.getResponse());
if (action.type == Action.TYPE.SUSPEND){
if (action.timeout == -1){
rrk.setTimeout(Integer.MAX_VALUE);
} else {
rrk.setTimeout((int)action.timeout);
}
}
return action.type == Action.TYPE.SUSPEND;
} catch (IllegalStateException ex){
logger.log(Level.SEVERE,"AtmosphereServlet.doRequest exception", ex);
throw ex;
}
}
/**
* Weblogic specific comet based implementation.
*
* @param rrk
* @return
* @throws java.io.IOException
* @throws javax.servlet.ServletException
*/
protected void doResponse(RequestResponseKey rrk, Object context)
throws IOException, ServletException {
rrk.getResponse().flushBuffer();
}
/**
* Weblogic specific comet based implementation.
*
* @param rrk
* @return
* @throws java.io.IOException
* @throws javax.servlet.ServletException
*/
protected void doTimeout(RequestResponseKey rrk) throws IOException, ServletException {
((AsynchronousProcessor)cometSupport).timedout(rrk.getRequest(), rrk.getResponse());
}
/**
* Return the default {@link Broadcaster} class name.
* @return the broadcasterClassName
*/
public String getDefaultBroadcasterClassName() {
return broadcasterClassName;
}
/**
* Set the default {@link Broadcaster} class name
* @param broadcasterClassName the broadcasterClassName to set
*/
public void setDefaultBroadcasterClassName(String broadcasterClassName) {
this.broadcasterClassName = broadcasterClassName;
}
/**
* true if Atmosphere uses {@link HttpServletResponse#getOutputStream()}
* by default for write operation.
*
* @return the useStreamForFlushingComments
*/
public boolean isUseStreamForFlushingComments() {
return useStreamForFlushingComments;
}
/**
* Set to true so Atmosphere uses {@link HttpServletResponse#getOutputStream()}
* by default for write operation. Default is false.
*
* @param useStreamForFlushingComments the useStreamForFlushingComments to set
*/
public void setUseStreamForFlushingComments(boolean useStreamForFlushingComments) {
this.useStreamForFlushingComments = useStreamForFlushingComments;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy