001/** 002 * GRANITE DATA SERVICES 003 * Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S. 004 * 005 * This file is part of the Granite Data Services Platform. 006 * 007 * Granite Data Services is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * Granite Data Services is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 015 * General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this library; if not, write to the Free Software 019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 020 * USA, or see <http://www.gnu.org/licenses/>. 021 */ 022package org.granite.gravity.jetty; 023 024import org.granite.gravity.AbstractChannel; 025import org.granite.gravity.AsyncHttpContext; 026import org.granite.gravity.Gravity; 027import org.granite.gravity.GravityConfig; 028import org.granite.gravity.MessageReceivingException; 029import org.granite.logging.Logger; 030import org.mortbay.util.ajax.Continuation; 031 032import flex.messaging.messages.AsyncMessage; 033 034/** 035 * @author William DRAI 036 */ 037public class ContinuationChannel extends AbstractChannel { 038 039 private static final Logger log = Logger.getLogger(ContinuationChannel.class); 040 041 private Continuation continuation = null; 042 043 public ContinuationChannel(Gravity gravity, String id, ContinuationChannelFactory factory, String clientType) { 044 super(gravity, id, factory, clientType); 045 } 046 047 public void setContinuation(Continuation continuation) { 048 log.debug("Setting continuation %s for client: %s", continuation, getId()); 049 try { 050 if (this.continuation != null && this.continuation.isPending()) { 051 log.debug("Resuming previous continuation %s for client: %s", this.continuation, getId()); 052 this.continuation.resume(); 053 } 054 } 055 finally { 056 this.continuation = continuation; 057 } 058 } 059 060 public void close() { 061 try { 062 if (this.continuation != null) 063 this.continuation.reset(); 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.isPending()) 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}