001    /*
002      GRANITE DATA SERVICES
003      Copyright (C) 2011 GRANITE DATA SERVICES S.A.S.
004    
005      This file is part of Granite Data Services.
006    
007      Granite Data Services is free software; you can redistribute it and/or modify
008      it under the terms of the GNU Library General Public License as published by
009      the Free Software Foundation; either version 2 of the License, or (at your
010      option) any later version.
011    
012      Granite Data Services is distributed in the hope that it will be useful, but
013      WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014      FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015      for more details.
016    
017      You should have received a copy of the GNU Library General Public License
018      along with this library; if not, see <http://www.gnu.org/licenses/>.
019    */
020    
021    package org.granite.gravity.jetty8;
022    
023    import org.eclipse.jetty.continuation.Continuation;
024    import org.granite.gravity.AbstractChannel;
025    import org.granite.gravity.AsyncHttpContext;
026    import org.granite.gravity.Gravity;
027    import org.granite.gravity.GravityConfig;
028    import org.granite.gravity.MessageReceivingException;
029    import org.granite.logging.Logger;
030    
031    import flex.messaging.messages.AsyncMessage;
032    
033    /**
034     * @author William DRAI
035     */
036    public class ContinuationChannel extends AbstractChannel {
037    
038        private static final Logger log = Logger.getLogger(ContinuationChannel.class);
039    
040        private Continuation continuation = null;
041    
042        public ContinuationChannel(Gravity gravity, String id, ContinuationChannelFactory factory, String clientType) {
043            super(gravity, id, factory, clientType);
044        }
045    
046        public void setContinuation(Continuation continuation) {
047            log.debug("Setting continuation %s for client: %s", continuation, getId());
048            try {
049                if (this.continuation != null && this.continuation.isSuspended()) {
050                    log.debug("Resuming previous continuation %s for client: %s", this.continuation, getId());
051                    this.continuation.resume();
052                }
053            }
054            finally {
055                this.continuation = continuation;
056            }
057        }
058        
059        public void close() {
060            this.continuation = null;
061    //      try {
062    //            if (this.continuation != null)
063    //                this.continuation.
064    //        }
065    //      finally {
066    //            this.continuation = null;
067    //      }
068        }
069        
070    
071        public void resume() {
072            log.debug("Resuming pending continuation %s for client: %s", continuation, getId());
073            try {
074                if (this.continuation != null && this.continuation.isSuspended())
075                    this.continuation.resume();
076            }
077            finally {
078                this.continuation = null;
079            }
080        }
081        
082        @Override
083            public void receive(AsyncMessage message) throws MessageReceivingException {
084                    if (message == null)
085                            throw new NullPointerException("message cannot be null");
086    
087                    GravityConfig gravityConfig = gravity.getGravityConfig();
088                    
089                    receivedQueueLock.lock();
090                    try {
091                            if (receivedQueue.size() + 1 > gravityConfig.getMaxMessagesQueuedPerChannel())
092                                    throw new MessageReceivingException(message, "Could not queue message (channel's queue is full) for channel: " + this);
093                            
094                            receivedQueue.add(message);
095                    }
096                    finally {
097                            receivedQueueLock.unlock();
098                    }
099                    
100                    synchronized (this) {
101                            resume();
102                    }
103            }
104    
105            @Override
106            protected boolean hasAsyncHttpContext() {
107                    return false;
108            }
109    
110            @Override
111            protected void releaseAsyncHttpContext(AsyncHttpContext context) {
112            }
113    
114            @Override
115            protected AsyncHttpContext acquireAsyncHttpContext() {
116            return null;
117        }
118    
119        public boolean isLocal() {
120            return true;
121        }
122    
123            @Override
124            public void destroy() {
125                    try {
126                            super.destroy();
127                    }
128                    finally {
129                            synchronized (this) {
130                                    close();
131                            }
132                    }
133            }
134    }