Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * 
   * 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 com.sun.enterprise.web.connector.grizzly.comet;
 
 import java.util.Set;
The main object used by CometHandler and Servlet to push information amongs suspended request/response. The CometContext is always available for CometHandler and can be used to java.lang.Object.notify(), or share information with other CometHandler. This is the equivalent of server push as the CometContext will invoke all registered CometHandler (addCometHandler(com.sun.enterprise.web.connector.grizzly.comet.CometHandler)) sequentially or using a thread pool when the setBlockingNotification(boolean) is set to false

A CometContext can be considered as a topic where CometHandler register for information. A CometContext can be shared amongs Servlet of the same application, or globally accros all deployed web applications. Normally, a CometContext is created using a topic's name like:<


 
 CometEngine ce = CometEngine.getEngine();
 CometContext cc = ce.registerContext("MyTopic");
 cc.setBlockingNotification(false); // Use multiple thread to execute the server push
 
 and then inside a Servlet.service method, you just need to call:
 
 cc.addCometListener(myNewCometListener());
 cc.notify("I'm pushing data to all registered CometHandler");
 </core>

As soom as addCometHandler(com.sun.enterprise.web.connector.grizzly.comet.CometHandler) is invoked, Grizzly will automatically suspend the request/response (will not commit the response). A response can be resumed by invoking resumeCometHandler, which will automatically commit the response and remove the associated CometHandler from the CometContext. A CometContext uses a NotificationHandler to invoke, using the calling thread or a Grizzly thread pool, all CometHandler than have been added using the addCometHandler(com.sun.enterprise.web.connector.grizzly.comet.CometHandler). A NotificationHandler can be used to filter or transform the content that will eventually be pushed back to all connected clients. You can also use a NotificationHandler to throttle push like invoking only a subset of the CometHandler, etc.

Attributes can be added/removed the same way HttpServletSession is doing. It is not recommended to use attributes if this CometContext is not shared amongs multiple context path (uses HttpServletSession instead).

Author(s):
Jeanfrancois Arcand
 
public class CometContext<E> {
    
    
Generic error message
    protected final static String INVALID_COMET_HANDLER = "CometHandler cannot be null. " 
            + "This CometHandler was probably resumed and an invalid " 
            +  "reference was made to it.";
    
    
Main logger
    private final static Logger logger = SelectorThread.logger();  
 
     
    
Attributes placeholder.
    private ConcurrentHashMap attributes;
    
    
    
The context path associated with this instance.
    private String topic;
    
    
    
Is the CometContext instance been cancelled.
    protected boolean cancelled = false;
    
    
    
The list of registered CometHandler
    protected ConcurrentHashMap<CometHandler,SelectionKeyhandlers;
    
    
    
The CometSelector used to register java.nio.channels.SelectionKey for upcoming bytes.
    protected CometSelector cometSelector;
    
    
    
The CometContext continuationType. See CometEngine
    protected int continuationType = .;
    
    
    
The default delay expiration before a CometContext's CometHandler are interrupted.
    private long expirationDelay = 30 * 1000;
    
    
    
true if the caller of java.lang.Object.notify() should block when notifying other CometHandler.
    protected boolean blockingNotification = false;

    
    
The default NotificationHandler.
    protected NotificationHandler notificationHandler
    
    
    
SelectionKey that are in the process of being parked.
    private static Queue<SelectionKeyinProgressSelectionKey = null;
     
    
    
Current associated list of CometTask
    protected Queue<CometTaskactiveTasks =
            new ConcurrentQueue<CometTask>("CometContext.activeTasks");
    
    // ---------------------------------------------------------------------- //
    
    
    
Create a new instance

Parameters:
topic the context path
type when the Comet processing will happen (see CometEngine).
    public CometContext(String topicint continuationType) {
        this. = topic;
        this. = continuationType;
         = new ConcurrentHashMap();
         = new ConcurrentQueue<SelectionKey>("CometContext.inProgressSelectionKey");
    }

    
    
Get the context path associated with this instance.

Deprecated:
- use getTopic.
Returns:
topic the context path associated with this instance
    public String getContextPath(){
        return getTopic();
    }
    
    
Get the topic representing this instance with this instance. This is the value to uses when invoking CometEngine.getCometContext(java.lang.String)

Returns:
topic the topic associated with this instance
    public String getTopic(){
        return ;
    }
    
    
    
Add an attibute.

Parameters:
key the key
value the value
    public void addAttribute(Object keyObject value){
        .put(key,value);
    }

    
    
Retrive an attribute.

Parameters:
key the key
Returns:
Object the value.
    public Object getAttribute(Object key){
        return .get(key);
    }    
    
    
    
Remove an attribute.

Parameters:
key the key
Returns:
Object the value
    public Object removeAttribute(Object key){
        return .remove(key);
    }  
    
    
    
Add a CometHandler. Client of this method might make sure the CometHandler is removed when the CometHandler.onInterrupt is invoked.

Parameters:
handler a new CometHandler
completeExecution Add the Comethandler but don't block waiting for event.
Returns:
The java.lang.Object.hashCode() value.
    public synchronized int addCometHandler(CometHandler handlerboolean completeExecution){
        Long threadId = Thread.currentThread().getId();
        SelectionKey key = CometEngine.getEngine().
                activateContinuation(threadId,this,completeExecution);
        if (key == null){
            throw new 
               IllegalStateException("Make sure you have enabled Comet or" +
               " make sure the Thread invoking that method " +
               "is the same a the request Thread.");
        }
        
        if (handler == null){
            throw new 
               IllegalStateException();
        }
        if (!completeExecution){
            .putIfAbsent(handler,key);
        } else {
            .putIfAbsent(handler,new SelectionKey() {
                public void cancel() {
                }
                public SelectableChannel channel() {
                    throw new IllegalStateException();
                }
                public int interestOps() {
                    throw new IllegalStateException();
                }
                public SelectionKey interestOps(int ops) {
                    throw new IllegalStateException();
                }
                public boolean isValid() {
                    return true;
                }
                public int readyOps() {
                    throw new IllegalStateException();
                }
                public Selector selector() {
                    throw new IllegalStateException();
                }
            });
        }
        return handler.hashCode();
    }
    
    
    
Add a CometHandler. Client on this method might make sure the CometHandler is removed when the CometHandler.onInterrupt is invoked.

Parameters:
handler a new CometHandler
    public int addCometHandler(CometHandler handler){
        return addCometHandler(handler,false);
    }
    
    
    
Retrive a CometHandler using its hashKey;
    public CometHandler getCometHandler(int hashCode){
        for (CometHandler handler:.keySet()){
            if (handler.hashCode() == hashCode )
               return handler;
        }
        return null;
    }   
    
    
    
Retrive a CometHandler using its SelectionKey. The java.nio.channels.SelectionKey is not exposed to the Comet API, hence this method must be protected.
    protected CometHandler getCometHandler(SelectionKey key){
        for (Entry<CometHandler,SelectionKeyentry:.entrySet()){
            if (entry.getValue() == key )
               return entry.getKey();
        }
        return null;
    }
    
    
    
Notify all CometHandler. The attachment can be null. The type will determine which code>CometHandler} method will be invoked:

 CometEvent.INTERRUPT -> CometHandler.onInterrupt(com.sun.enterprise.web.connector.grizzly.comet.CometEvent)
 CometEvent.NOTIFY -> CometHandler.onEvent(com.sun.enterprise.web.connector.grizzly.comet.CometEvent)
 CometEvent.INITIALIZE -> CometHandler.onInitialize(com.sun.enterprise.web.connector.grizzly.comet.CometEvent)
 CometEvent.TERMINATE -> CometHandler.onTerminate(com.sun.enterprise.web.connector.grizzly.comet.CometEvent)
 CometEvent.READ -> CometHandler.onEvent(com.sun.enterprise.web.connector.grizzly.comet.CometEvent)
 CometEvent.WRITE -> 

Parameters:
attachment An object shared amongst CometHandler.
type The type of notification.
key The SelectionKey associated with the CometHandler.
Link:
CometHandler#onEvent} }
    protected void invokeCometHandler(CometEvent eventint eventTypeSelectionKey key
            throws IOException{
        CometHandler cometHandler = getCometHandler(key);
        if (cometHandler == null){
            throw new IllegalStateException();
        }
        event.setCometContext(this);  
        cometHandler.onEvent(event);
    }    
    
    
Remove a CometHandler. If the continuation (connection) associated with this CometHandler no longer have CometHandler associated to it, it will be resumed.
    public void removeCometHandler(CometHandler handler){
        removeCometHandler(handler,true);
    }

    
    
Remove a CometHandler. If the continuation (connection) associated with this CometHandler no longer have CometHandler associated to it, it will be resumed.

Returns:
true if the operation succeeded.
    public boolean removeCometHandler0(CometHandler handler){
        return removeCometHandler(handler,true);
    }
     
    
    
Remove a CometHandler. If the continuation (connection) associated with this CometHandler no longer have CometHandler associated to it, it will be resumed.

Parameters:
handler The CometHandler to remove.
resume True is the connection can be resumed if no CometHandler are associated with the underlying SelectionKey.
Returns:
true if the operation succeeded.
    public boolean removeCometHandler(CometHandler handler,boolean resume){        
        SelectionKey key = .remove(handler);
        if (key == nullreturn false;
              
        if (resume && !.containsValue(key)){
            CometEngine.getEngine().resume(key);
        }
        return true;
    }
    
    
    
Remove a CometHandler based on its hashcode. Return true if the operation was sucessfull.

Parameters:
hashCode The hashcode of the CometHandler to remove.
Returns:
true if the operation succeeded.
    public synchronized boolean removeCometHandler(int hashCode){
        Iterator<CometHandleriterator = .keySet().iterator();
        CometHandler cometHandler = null;
        while (iterator.hasNext()){
            cometHandler = iterator.next();
            if (cometHandler.hashCode() == hashCode){
                SelectionKey key = .get(cometHandler);
                if (key == null){
                    .warning("CometHandler already been removed or invalid.");
                    return false;
                }   
                if (.contains(key)){
                    .warning("Cannot resume an in progress connection.");
                    return false;
                }                  
                iterator.remove();
                return true;
            }
        }
        return false;
    }

    
    
Resume the Comet request and remove it from the active CometHandler list. Once resumed, a CometHandler should never manipulate the HttpServletRequest or HttpServletResponse as those are recycled. If you cache them for later reuse by another thread there is a possibility to introduce corrupted responses next time a request is made.

Parameters:
handler The CometHandler to resume.
    public void resumeCometHandler(CometHandler handler){
        resumeCometHandler0(handler);
    }

    
    
Resume the Comet request and remove it from the active CometHandler list. Once resumed, a CometHandler should never manipulate the HttpServletRequest or HttpServletResponse as those are recycled. If you cache them for later reuse by another thread there is a possibility to introduce corrupted responses next time a request is made.

Parameters:
handler The CometHandler to resume.
Returns:
true if the operation succeeded.
    public boolean resumeCometHandler0(CometHandler handler){
        return resumeCometHandler(handler,true);
    }
    
    
    
Resume the Comet request.

Parameters:
handler The CometHandler associated with the current continuation.
remove true if the CometHandler needs to be removed.
Returns:
true if the operation succeeded.
    protected boolean resumeCometHandler(CometHandler handlerboolean remove){
        SelectionKey key = .get(handler);
        if (key == null){
            .warning("CometHandler already been resumed or invalid.");
            return false;
        }   
        
        if (.contains(key)){
            .warning("Cannot resume an in progress connection.");
            return false;            
        }        
                 
        if (remove){
            boolean ok = removeCometHandler(handler,false);
            if (!okreturn false;
        }     
        // Retrieve the CometSelector key.
        SelectionKey cometKey = .cometKeyFor(key.channel());
        if (cometKey != null){
            CometTask task = (CometTask)cometKey.attachment();
            if (task != null){
                .remove(task);
            }
            cometKey.attach(null);
            cometKey.cancel();
        }     
        CometEngine.getEngine().resume(key);
        return true;
    }
    
    
    
Return true if this CometHandler is still active, e.g. there is still a continuation associated with it.

Returns:
true if active, false if not.
    public synchronized boolean isActive(CometHandler cometHandler){
        if (cometHandler == null){
            return false;
        }
        SelectionKey key = .get(cometHandler);
        return (key != null && !.contains(key));
    }
    
    
    
Notify all CometHandler. The attachment can be null. All CometHandler.onEvent() will be invoked.

Parameters:
attachment An object shared amongst CometHandler.
    public void notify(final E attachmentthrows IOException{
        notify(attachment.);
    }
    
    
    
Notify a single CometHandler. The attachment can be null. The type will determine which code>CometHandler} method will be invoked:

 CometEvent.INTERRUPT -> CometHandler.onInterrupt(com.sun.enterprise.web.connector.grizzly.comet.CometEvent)
 CometEvent.NOTIFY -> CometHandler.onEvent(com.sun.enterprise.web.connector.grizzly.comet.CometEvent)
 CometEvent.INITIALIZE -> CometHandler.onInitialize(com.sun.enterprise.web.connector.grizzly.comet.CometEvent)
 CometEvent.TERMINATE -> CometHandler.onTerminate(com.sun.enterprise.web.connector.grizzly.comet.CometEvent)
 CometEvent.READ -> CometHandler.onEvent(com.sun.enterprise.web.connector.grizzly.comet.CometEvent)
 

Parameters:
attachment An object shared amongst CometHandler.
type The type of notification.
cometHandlerID Notify a single CometHandler.
    public void notify(final E attachment,final int eventType,final int cometHandlerID
            throws IOException{   
        CometHandler cometHandler = getCometHandler(cometHandlerID);
  
        if (cometHandler == null){
            throw new IllegalStateException();
        }
        CometEvent event = new CometEvent<E>();
        event.setType(eventType);
        event.attach(attachment);
        event.setCometContext(CometContext.this);
        
        .notify(event,cometHandler);
        if (event.getType() == . 
            || event.getType() == .) {
            resumeCometHandler0(cometHandler);
        } else {
            if ( < .)
                resetSuspendIdleTimeout();
        }
    }
    

    
    
Initialize the newly added CometHandler.

Parameters:
attachment An object shared amongst CometHandler.
type The type of notification.
key The SelectionKey representing the CometHandler.
      
     protected void initialize(SelectionKey keythrows IOException {
        CometEvent event = new CometEvent<E>();
        event.setType(.);
        event.setCometContext(this);
        
        for (Entry<CometHandler,SelectionKeyentry:.entrySet()){
            SelectionKey ak = entry.getValue();
            if(ak != null && ak.equals(key)){
                entry.getKey().onInitialize(event);
                break;
            }
        }
    }
     
      
    
Notify all CometHandler. The attachment can be null. The type will determine which code>CometHandler} method will be invoked:

 CometEvent.INTERRUPT -> CometHandler.onInterrupt(com.sun.enterprise.web.connector.grizzly.comet.CometEvent)
 CometEvent.NOTIFY -> CometHandler.onEvent(com.sun.enterprise.web.connector.grizzly.comet.CometEvent)
 CometEvent.INITIALIZE -> CometHandler.onInitialize(com.sun.enterprise.web.connector.grizzly.comet.CometEvent)
 CometEvent.TERMINATE -> CometHandler.onTerminate(com.sun.enterprise.web.connector.grizzly.comet.CometEvent)
 CometEvent.READ -> CometHandler.onEvent(com.sun.enterprise.web.connector.grizzly.comet.CometEvent)
 

Parameters:
attachment An object shared amongst CometHandler.
type The type of notification.
   
    public void notify(final E attachment,final int eventTypethrows IOException{
        // XXX Use a pool of CometEvent instance.
        CometEvent event = new CometEvent<E>();
        event.setType(eventType);
        event.attach(attachment);
        event.setCometContext(CometContext.this);
        Iterator<CometHandleriterator = .keySet().iterator();
        .notify(event,iterator);
        if (event.getType() == . 
            || event.getType() == .) {
            while(iterator.hasNext()){
                resumeCometHandler0(iterator.next());
            }
        } else {
            if ( < .){
                resetSuspendIdleTimeout();
            }
        } 
    }

    
    
Reset the current timestamp on a suspended connection.
    protected synchronized void resetSuspendIdleTimeout(){
        CometTask cometTask;       
        Iterator<CometTaskit = .iterator();
        while(it.hasNext()){
            cometTask = it.next();           
            cometTask.setExpireTime(System.currentTimeMillis());
        }  
    }    
    
    
    
Register for asynchronous read. If your client supports http pipelining, invoking this method might result in a state where your CometHandler is invoked with a CometRead that will read the next http request. In that case, it is strongly recommended to not use that method unless your CometHandler can handle the http request.

Oaram:
handler The CometHandler that will be invoked.
    public boolean registerAsyncRead(CometHandler handler){
        SelectionKey key = null;
        if (handler != null) {
            key = .get(handler);
        }
        if (handler == null || key == null) { 
            throw new 
               IllegalStateException();            
        }
        // Retrieve the CometSelector key.
        SelectionKey cometKey = .cometKeyFor(key.channel());
        if (cometKey != null){
            cometKey.interestOps(cometKey.interestOps() | .); 
            if (cometKey.attachment() != null){
                ((CometTask)cometKey.attachment()).setAsyncReadSupported(true);
            }
            return true;
        } else {
            return false;
        }  
    }
    
    
    
Register for asynchronous write.
    public boolean registerAsyncWrite(CometHandler handler){
        SelectionKey key = null;
        if (handler != null) {
            key = .get(handler);
        }
        if (handler == null || key == null) { 
            throw new 
               IllegalStateException();            
        }
        // Retrieve the CometSelector key.
        SelectionKey cometKey = .cometKeyFor(key.channel());
        if (cometKey != null){
            cometKey.interestOps(cometKey.interestOps() | .); 
            return true;
        } else {
            return false;
        }           
    }
    
    
    
Recycle this object.
    protected void recycle(){
        .clear();
        .clear();
         = false;
        .clear();
    }    

    
    
Is this instance beeing cancelled by the CometSelector

Returns:
boolean cancelled or not.
    protected boolean isCancelled() {
        return ;
    }

    
    
Cancel this object or "uncancel".

Parameters:
cancelled true or false.
    protected void setCancelled(boolean cancelled) {
        this. = cancelled;
    }

    
    
Set the CometSelector associated with this instance.

Parameters:
CometSelector the CometSelector associated with this instance.
   
    protected void setCometSelector(CometSelector cometSelector) {
        this. = cometSelector;
    }
    
    
    
Helper.
    @Override
    public String toString(){
        return ;
    }

    
    
Return the long delay before a request is resumed.

Returns:
long the long delay before a request is resumed.
    public long getExpirationDelay() {
        return ;
    }

    
    
Set the long delay before a request is resumed.

Parameters:
long the long delay before a request is resumed.
    
    public void setExpirationDelay(long expirationDelay) {
        this. = expirationDelay;
    }   

    
    
    protected void interrupt(CometTask task){
        CometEvent event = new CometEvent<E>();
        event.setType(.);
        event.attach(null);
        event.setCometContext(this);
        
        for (Entry<CometHandler,SelectionKeyentry:.entrySet()){
            if (entry.getValue().equals(task.getSelectionKey())){
                try{
                    .remove(entry.getKey());
                    entry.getKey().onInterrupt(event);
                } catch (IOException ex){
                    .log(.,"Exception: ",ex);
                }
                break;
            }
        }  
        .remove(task);
    }
    
    
    
Return the current list of active CometHandler return the current list of active CometHandler
    public Set<CometHandlergetCometHandlers(){
        return .keySet();
    }
    
    
    
    
Add a CometTask to the active list.

Parameters:
cometTask
    protected void addActiveCometTask(CometTask cometTask) {
        .offer(cometTask);
    }
    
    
    
Return true if the invoker of java.lang.Object.notify() should block when notifying Comet Handlers.
    public boolean isBlockingNotification() {
        return ;
    }

    
    
Set to true if the invoker of java.lang.Object.notify() should block when notifying Comet Handlers.
    public void setBlockingNotification(boolean blockingNotification) {
        this. = blockingNotification;
    }

    
    
Set the current NotificationHandler

Parameters:
notificationHandler
    public void setNotificationHandler(NotificationHandler notificationHandler){
        this. = notificationHandler;
    }
    

    
Return the associated NotificationHandler

Returns:
        return ;
    }

    
    
Add a java.nio.channels.SelectionKey to the list of current operations.

Parameters:
key
    protected static void addInProgressSelectionKey(SelectionKey key){
        .add(key);
    }

    
    
Remove a java.nio.channels.SelectionKey to the list of current operations.

Parameters:
key
Returns:
    protected static boolean removeInProgressSelectionKey(SelectionKey key){
        return .remove(key);
    }
}
    
New to GrepCode? Check out our FAQ X