1 // ========================================================================
2 // Copyright 2006 Mort Bay Consulting Pty. Ltd.
3 // ------------------------------------------------------------------------
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 // ========================================================================
14
15 package org.mortbay.cometd;
16
17 import javax.servlet.ServletRequest;
18
19 import org.mortbay.cometd.ClientImpl;
20 import org.mortbay.thread.Timeout;
21
22 /* ------------------------------------------------------------ */
23 /**
24 * Extension of {@link ClientImpl} that uses {@link Continuation}s to
25 * resume clients waiting for messages. Continuation clients are used for
26 * remote clients and have removed if they are not accessed within
27 * an idle timeout (@link {@link SuspendingBayeux#_clientTimer}).
28 *
29 * @author gregw
30 *
31 */
32 public class SuspendingClient extends ClientImpl
33 {
34 private long _accessed;
35 public transient Timeout.Task _timeout;
36 private SuspendingBayeux _bayeux;
37 private transient ServletRequest _pollRequest;
38
39 /* ------------------------------------------------------------ */
40 protected SuspendingClient(SuspendingBayeux bayeux)
41 {
42 super(bayeux);
43 _bayeux=bayeux;
44
45 if (!isLocal())
46 {
47 _timeout=new Timeout.Task()
48 {
49 public void expired()
50 {
51 remove(true);
52 }
53 public String toString()
54 {
55 return "T-"+SuspendingClient.this.toString();
56 }
57 };
58 _bayeux.startTimeout(_timeout,getTimeout());
59 }
60 }
61
62
63 /* ------------------------------------------------------------ */
64 public void setPollRequest(ServletRequest request)
65 {
66 Timeout.Task task=null;
67
68 if (request==null)
69 {
70 synchronized (this)
71 {
72 if (_pollRequest!=null)
73 {
74 if(_pollRequest.isSuspended())
75 _pollRequest.resume();
76 }
77 _pollRequest=null;
78 task=_timeout;
79 }
80
81 if (task!=null)
82 _bayeux.startTimeout(task,getTimeout());
83 }
84 else
85 {
86 synchronized (this)
87 {
88 if (_pollRequest!=null)
89 {
90 if(_pollRequest.isSuspended())
91 _pollRequest.resume();
92 }
93 _pollRequest=request;
94 task=_timeout;
95 }
96
97 if (task!=null)
98 _bayeux.cancelTimeout(task);
99 }
100 }
101
102 /* ------------------------------------------------------------ */
103 public ServletRequest getPollRequest()
104 {
105 return _pollRequest;
106 }
107
108 /* ------------------------------------------------------------ */
109 public void resume()
110 {
111 Timeout.Task task=null;
112 synchronized (this)
113 {
114 if (_pollRequest!=null)
115 {
116 _pollRequest.getServletResponse().disable();
117 _pollRequest.resume();
118 task=_timeout;
119 }
120 _pollRequest=null;
121 }
122
123 if (task!=null)
124 _bayeux.startTimeout(task,getTimeout());
125 }
126
127 /* ------------------------------------------------------------ */
128 public boolean isLocal()
129 {
130 return false;
131 }
132
133 /* ------------------------------------------------------------ */
134 public void access()
135 {
136 Timeout.Task task=null;
137 synchronized(this)
138 {
139 // distribute access time in cluster
140 _accessed=_bayeux.getNow();
141 if (_timeout!=null && _timeout.isScheduled())
142 task=_timeout;
143 }
144
145 if (task!=null)
146 _bayeux.startTimeout(task,getTimeout());
147 }
148
149
150 /* ------------------------------------------------------------ */
151 public synchronized long lastAccessed()
152 {
153 return _accessed;
154 }
155
156 /* ------------------------------------------------------------ */
157 /* (non-Javadoc)
158 * @see org.mortbay.cometd.ClientImpl#remove(boolean)
159 */
160 public void remove(boolean wasTimeout)
161 {
162 Timeout.Task task=null;
163 synchronized(this)
164 {
165 if (!wasTimeout)
166 task=_timeout;
167 _timeout=null;
168 super.remove(wasTimeout);
169 }
170
171 if (task!=null)
172 _bayeux.cancelTimeout(task);
173
174 }
175
176 }