// ========================================================================
// Copyright 2006 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================
package org.mortbay.cometd.continuation;
import org.mortbay.cometd.ClientImpl;
import org.mortbay.thread.Timeout;
import org.mortbay.util.ajax.Continuation;
/* ------------------------------------------------------------ */
/**
* Extension of {@link ClientImpl} that uses {@link Continuation}s to
* resume clients waiting for messages. Continuation clients are used for
* remote clients and have removed if they are not accessed within
* an idle timeout (@link {@link ContinuationBayeux#_clientTimer}).
*
* @author gregw
*
*/
public class ContinuationClient extends ClientImpl
{
private long _accessed;
public transient Timeout.Task _timeout;
private ContinuationBayeux _bayeux;
private transient Continuation _continuation;
/* ------------------------------------------------------------ */
protected ContinuationClient(ContinuationBayeux bayeux)
{
super(bayeux);
_bayeux=bayeux;
if (!isLocal())
{
_timeout=new Timeout.Task()
{
@Override
public void expired()
{
remove(true);
}
@Override
public String toString()
{
return "T-"+ContinuationClient.this.toString();
}
};
_bayeux.startTimeout(_timeout,getTimeout());
}
}
/* ------------------------------------------------------------ */
public void setContinuation(Continuation continuation)
{
if (continuation==null)
{
synchronized (this)
{
if (_continuation!=null)
{
if(_continuation.isPending())
_continuation.resume();
}
_continuation=null;
if(_timeout!=null)
_bayeux.startTimeout(_timeout,getTimeout());
}
}
else
{
synchronized (this)
{
if (_continuation!=null)
{
if(_continuation.isPending())
_continuation.resume();
}
_continuation=continuation;
_bayeux.cancelTimeout(_timeout);
}
}
}
/* ------------------------------------------------------------ */
public Continuation getContinuation()
{
return _continuation;
}
/* ------------------------------------------------------------ */
@Override
public void resume()
{
synchronized (this)
{
if (_continuation!=null)
{
_continuation.resume();
}
_continuation=null;
}
}
/* ------------------------------------------------------------ */
@Override
public boolean isLocal()
{
return false;
}
/* ------------------------------------------------------------ */
public void access()
{
synchronized(this)
{
// distribute access time in cluster
_accessed=_bayeux.getNow();
if (_timeout!=null && _timeout.isScheduled())
{
_timeout.reschedule();
}
}
}
/* ------------------------------------------------------------ */
public synchronized long lastAccessed()
{
return _accessed;
}
/* ------------------------------------------------------------ */
/* (non-Javadoc)
* @see org.mortbay.cometd.ClientImpl#remove(boolean)
*/
@Override
public void remove(boolean wasTimeout)
{
synchronized(this)
{
if (!wasTimeout && _timeout!=null)
_bayeux.cancelTimeout(_timeout);
_timeout=null;
super.remove(wasTimeout);
}
}
}