Fields Summary |
---|
public static final int | BEFORE_REQUEST_PROCESSINGThe token used to support BEFORE_REQUEST_PROCESSING polling. |
public static final int | AFTER_SERVLET_PROCESSINGThe token used to support AFTER_SERVLET_PROCESSING polling. |
public static final int | AFTER_RESPONSE_PROCESSINGThe token used to support BEFORE_RESPONSE_PROCESSING polling. |
private static final Logger | loggerMain logger |
private com.sun.enterprise.web.connector.grizzly.Pipeline | pipelineThe Pipeline used to execute CometTask |
private static CometEngine | cometEngineThe single instance of this class. |
private ConcurrentHashMap | activeContextsThe current active CometContext keyed by context path. |
private ConcurrentLinkedQueue | cometTasksCache of CometTask instance |
private ConcurrentLinkedQueue | cometContextsCache of CometContext instance. |
private CometSelector | cometSelectorThe CometSelector used to poll requests. |
private static String | notificationHandlerClassNameThe default class to use when deciding which NotificationHandler
to use. The default is DefaultNotificationHandler. |
private ConcurrentHashMap | threadsIdTemporary repository that associate a Thread ID with a Key.
NOTE: A ThreadLocal might be more efficient. |
private ConcurrentHashMap | updatedCometContextsStore modified CometContext. |
Methods Summary |
---|
protected java.nio.channels.SelectionKey | activateContinuation(java.lang.Long threadId, CometContext cometContext, boolean continueExecution)Tell the CometEngine to activate Grizzly ARP on that CometContext.
This method is called when CometContext.addCometHandler() is
invoked.
if (!continueExecution){
updatedCometContexts.put(threadId,cometContext);
}
return threadsId.remove(threadId);
|
private void | executeServlet(int continuationType, com.sun.enterprise.web.connector.grizzly.async.AsyncProcessorTask apt)Bring the cometContext path target (most probably a Servlet) to the processing
stage we need for Comet request processing.
switch (continuationType){
case BEFORE_REQUEST_PROCESSING:
apt.setStage(AsyncTask.PRE_EXECUTE);
break;
case AFTER_SERVLET_PROCESSING:
apt.getProcessorTask().invokeAdapter();
return;
case AFTER_RESPONSE_PROCESSING:
apt.setStage(AsyncTask.POST_EXECUTE);
break;
default:
throw new IllegalStateException("Invalid state");
}
try{
apt.doTask();
} catch (IOException ex){
logger.log(Level.SEVERE,"executeServlet",ex);
}
|
private void | finalizeContext(CometContext cometContext)Cleanup the CometContext
Iterator<String> iterator = activeContexts.keySet().iterator();
String contextPath;
while(iterator.hasNext()){
contextPath = iterator.next();
if ( activeContexts.get(contextPath).equals(cometContext) ){
activeContexts.remove(contextPath);
break;
}
}
ConcurrentLinkedQueue<AsyncProcessorTask> asyncTasks =
cometContext.getAsyncProcessorTask();
for (AsyncProcessorTask apt: asyncTasks){
flushResponse(apt);
}
cometContext.recycle();
cometContexts.offer(cometContext);
|
private void | flushResponse(com.sun.enterprise.web.connector.grizzly.async.AsyncProcessorTask apt)Complete the asynchronous request.
apt.setStage(AsyncTask.POST_EXECUTE);
try{
apt.doTask();
} catch (IllegalStateException ex){
if (logger.isLoggable(Level.FINEST)){
logger.log(Level.FINEST,"flushResponse failed",ex);
}
} catch (IOException ex) {
logger.log(Level.SEVERE,"flushResponse failed",ex);
}
|
public CometContext | getCometContext(java.lang.String contextPath)Return the CometContext associated with the cometContext path.
XXX: This is not secure as a you can get a CometContext associated
with another cometContext path. But this allow interesting application...
MUST BE REVISTED.
return activeContexts.get(contextPath);
|
protected CometTask | getCometTask(CometContext cometContext, java.nio.channels.SelectionKey key)Return a clean and configured CometTask
CometTask cometTask = cometTasks.poll();
if (cometTask == null){
cometTask = new CometTask();
}
cometTask.setCometContext(cometContext);
cometTask.setSelectionKey(key);
cometTask.setCometSelector(cometSelector);
cometTask.setPipeline(pipeline);
return cometTask;
|
public static final synchronized com.sun.enterprise.web.connector.grizzly.comet.CometEngine | getEngine()Return a singleton of this Class.
if (cometEngine == null) {
cometEngine = new CometEngine();
}
return cometEngine;
|
public static java.lang.String | getNotificationHandlerClassName()
return notificationHandlerClassName;
|
protected boolean | handle(com.sun.enterprise.web.connector.grizzly.async.AsyncProcessorTask apt)Handle an interrupted(or polled) request by matching the current context
path with the registered one.
If required, the bring the target component (Servlet) to the proper
execution stage and then notify the CometHandler
if (pipeline == null){
pipeline = apt.getPipeline();
}
String contextPath = apt.getProcessorTask().getRequestURI();
CometContext cometContext = null;
if (contextPath != null){
cometContext = activeContexts.get(contextPath);
if (cometContext != null){
NotificationHandler notificationHandler =
cometContext.getNotificationHandler();
if (notificationHandler != null && (notificationHandler
instanceof DefaultNotificationHandler)){
((DefaultNotificationHandler)notificationHandler)
.setPipeline(pipeline);
}
}
}
/*
* If the cometContext is null, it means the context has never
* been registered. The registration might happens during the
* Servlet.service() execution so we need to keep a reference
* to the current thread so we can later retrieve the associated
* SelectionKey. The SelectionKey is required in order to park the
* request.
*/
boolean activateContinuation = true;
SelectionKey key = apt.getProcessorTask().getSelectionKey();
threadsId.put(Thread.currentThread().getId(),key);
int continuationType = (cometContext == null)?
AFTER_SERVLET_PROCESSING:cometContext.continuationType;
/*
* Execute the Servlet.service method. CometEngine.register() or
* CometContext.addCometHandler() might be invoked during the
* execution.
*/
executeServlet(continuationType,apt);
/*
* Will return a CometContext instance if and only if the
* Servlet.service() have invoked CometContext.addCometHandler().
* If the returned CometContext is null, it means we need to
* execute a synchronous request.
*/
cometContext = updatedCometContexts.remove(Thread.currentThread().getId());
CometTask cometTask = null;
if (cometContext == null){
activateContinuation = false;
} else {
cometTask = getCometTask(cometContext,key);
cometTask.setSelectorThread(
apt.getProcessorTask().getSelectorThread());
}
boolean parkRequest = true;
if (activateContinuation) {
// Disable keep-alive
key.attach(null);
cometContext.addAsyncProcessorTask(apt);
cometContext.initialize(key);
cometTask.setExpirationDelay(cometContext.getExpirationDelay());
cometTask.setSelectorThread(apt.getSelectorThread());
cometSelector.registerKey(key,cometTask);
} else {
parkRequest = false;
if (cometTask != null){
cometTask.recycle();
cometTasks.offer(cometTask);
}
}
return parkRequest;
|
protected void | interrupt(java.nio.channels.SelectionKey key)The CometSelector is expiring idle SelectionKey ,
hence we need to resume the current request.
CometTask cometTask = (CometTask)key.attachment();
key.attach(null);
if (cometTask == null)
throw new IllegalStateException("cometTask cannot be null");
SelectionKey akey = cometTask.getSelectionKey();
try{
if (!akey.isValid()) return;
CometContext cometContext = cometTask.getCometContext();
Iterator<AsyncProcessorTask> iterator =
cometContext.getAsyncProcessorTask().iterator();
AsyncHandler ah = null;
while (iterator.hasNext()){
AsyncProcessorTask apt = iterator.next();
ah = apt.getAsyncExecutor().getAsyncHandler();
if (apt.getProcessorTask().getSelectionKey() == akey){
iterator.remove();
ah.removeFromInterruptedQueue(apt);
flushResponse(apt);
if (akey != null){
akey.attach(null);
}
break;
}
}
} finally {
cometTask.recycle();
cometTasks.offer(cometTask);
}
|
private static NotificationHandler | loadNotificationHandlerInstance(java.lang.String className)Util to load classes using reflection.
Class clazz = null;
try{
clazz = Class.forName(className,true,
Thread.currentThread().getContextClassLoader());
return (NotificationHandler)clazz.newInstance();
} catch (Throwable t) {
logger.log(Level.WARNING,"Invalid NotificationHandler: ",t);
}
return new DefaultNotificationHandler();
|
public static final java.util.logging.Logger | logger()Return the current logger.
return logger;
|
public CometContext | register(java.lang.String contextPath)Register a context path with this CometEngine . The
CometContext returned will be of type
AFTER_SERVLET_PROCESSING, which means the request target (most probably
a Servlet) will be executed first and then polled.
return register(contextPath,AFTER_SERVLET_PROCESSING);
|
public CometContext | register(java.lang.String contextPath, int type)Register a context path with this CometEngine . The
CometContext returned will be of type
type .
CometContext cometContext = activeContexts.get(contextPath);
if (cometContext == null){
cometContext = cometContexts.poll();
if (cometContext == null){
cometContext = new CometContext(contextPath,type);
cometContext.setCometSelector(cometSelector);
NotificationHandler notificationHandler
= loadNotificationHandlerInstance
(notificationHandlerClassName);
cometContext.setNotificationHandler(notificationHandler);
if (notificationHandler != null && (notificationHandler
instanceof DefaultNotificationHandler)){
((DefaultNotificationHandler)notificationHandler)
.setPipeline(pipeline);
}
}
activeContexts.put(contextPath,cometContext);
}
return cometContext;
|
protected void | resume(java.nio.channels.SelectionKey key, CometContext cometContext)Resume the long polling request by unblocking the current
SelectionKey
Iterator<AsyncProcessorTask> iterator =
cometContext.getAsyncProcessorTask().iterator();
while (iterator.hasNext()){
AsyncProcessorTask apt = iterator.next();
if (apt.getProcessorTask().getSelectionKey() == key){
iterator.remove();
apt.getAsyncExecutor().getAsyncHandler()
.removeFromInterruptedQueue(apt);
flushResponse(apt);
break;
}
}
|
public static void | setNotificationHandlerClassName(java.lang.String aNotificationHandlerClassName)
notificationHandlerClassName = aNotificationHandlerClassName;
|
public CometContext | unregister(java.lang.String contextPath)Unregister the CometHandler to the list of the
CometContext .
CometContext cometContext = activeContexts.get(contextPath);
try{
cometContext.notify(cometContext,CometEvent.TERMINATE);
} catch (IOException ex){
logger.log(Level.WARNING,"unregister",ex);
}
finalizeContext(cometContext);
return activeContexts.remove(contextPath);
|