View Javadoc

1   //========================================================================
2   // Copyright 2009 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.client.ext;
16  
17  import java.util.Map;
18  
19  import org.cometd.Bayeux;
20  import org.cometd.Client;
21  import org.cometd.Extension;
22  import org.cometd.Message;
23  
24  /**
25   * AckExtension
26   * 
27   * This client-side extension enables the client to acknowledge to the server
28   * the messages that the client has received.
29   * For the acknowledgement to work, the server must be configured with the
30   * correspondent server-side ack extension. If both client and server support
31   * the ack extension, then the ack functionality will take place automatically.
32   * By enabling this extension, all messages arriving from the server will arrive
33   * via the long poll, so the comet communication will be slightly chattier.
34   * The fact that all messages will return via long poll means also that the
35   * messages will arrive with total order, which is not guaranteed if messages
36   * can arrive via both long poll and normal response.
37   * Messages are not acknowledged one by one, but instead a group of messages is
38   * acknowledged when long poll returns.
39   * 
40   * @author dyu
41   */
42  
43  public class AckExtension implements Extension
44  {
45      
46      public static final String EXT_FIELD = "ack";
47      
48      private volatile boolean _serverSupportsAcks = false;
49      private volatile int _ackId = -1;
50  
51      public AckExtension()
52      {
53          
54      }
55  
56      public Message send(Client from, Message message)
57      {
58          return message;
59      }
60      
61      public Message rcv(Client from, Message message)
62      {
63          return message;
64      }
65  
66      public Message sendMeta(Client from, Message message)
67      {
68          if(Bayeux.META_HANDSHAKE.equals(message.getChannel()))
69          {
70              message.getExt(true).put(EXT_FIELD, Boolean.TRUE);
71              _ackId = -1;
72          }
73          else if(_serverSupportsAcks && Bayeux.META_CONNECT.equals(message.getChannel()))
74          {
75              message.getExt(true).put(EXT_FIELD, _ackId);
76          }
77          
78          return message;
79      }
80      
81      public Message rcvMeta(Client from, Message message)
82      {
83          if(Bayeux.META_HANDSHAKE.equals(message.getChannel()))
84          {
85              Map<String,Object> ext = message.getExt(false);
86              _serverSupportsAcks = ext!=null && Boolean.TRUE.equals(ext.get(EXT_FIELD));
87          }
88          else if(_serverSupportsAcks && Boolean.TRUE.equals(message.get(Bayeux.SUCCESSFUL_FIELD)) 
89                  && Bayeux.META_CONNECT.equals(message.getChannel()))
90          {
91              Map<String,Object> ext = message.getExt(false);
92              if(ext!=null)
93              {
94                  Object ack = ext.get(EXT_FIELD);
95                  if(ack instanceof Number)
96                      _ackId = ((Number)ack).intValue();
97              }
98          }
99          
100         return message;
101     }
102 
103 }