View Javadoc

    1   package org.mortbay.cometd;
    2
    3   import java.nio.ByteBuffer;
    4   import java.util.Collections;
    5   import java.util.HashMap;
    6   import java.util.Iterator;
    7   import java.util.Map;
    8   import java.util.Set;
    9   import java.util.concurrent.atomic.AtomicInteger;
    10
    11  import org.cometd.Bayeux;
    12  import org.cometd.Message;
    13  import org.mortbay.util.ajax.JSON;
    14
    15  public class MessageImpl extends HashMap<String,Object> implements Message, org.mortbay.util.ajax.JSON.Generator
    16  {
    17      Message _associated;
    18      ByteBuffer _buffer;
    19      String _channel;
    20      String _clientId;
    21      Object _data;
    22      Object _ext;
    23      String _id;
    24      String _json;
    25      boolean _lazy=false;
    26      final MessagePool _pool;
    27      AtomicInteger _refs=new AtomicInteger();
    28
    29      /* ------------------------------------------------------------ */
    30      public MessageImpl()
    31      {
    32          super(8);
    33          _pool=null;
    34      }
    35
    36      /* ------------------------------------------------------------ */
    37      public MessageImpl(MessagePool bayeux)
    38      {
    39          super(8);
    40          _pool=bayeux;
    41      }
    42
    43      /* ------------------------------------------------------------ */
    44      public void addJSON(StringBuffer buffer)
    45      {
    46          buffer.append(getJSON());
    47      }
    48
    49      /* ------------------------------------------------------------ */
    50      /*
    51       * (non-Javadoc)
    52       *
    53       * @see java.util.HashMap#clear()
    54       */
    55      @Override
    56      public void clear()
    57      {
    58          setAssociated(null);
    59          _buffer=null;
    60          _channel=null;
    61          _clientId=null;
    62          _data=null;
    63          _ext=null;
    64          _id=null;
    65          _json=null;
    66          _lazy=false;
    67          _ext=null; // TODO recycle
    68          _refs.set(0);
    69
    70          Iterator<Map.Entry<String,Object>> iterator=super.entrySet().iterator();
    71          while(iterator.hasNext())
    72          {
    73              Map.Entry<String,Object> entry=iterator.next();
    74              String key=entry.getKey();
    75              if (Bayeux.CHANNEL_FIELD.equals(key))
    76                  entry.setValue(null);
    77              else if (Bayeux.ID_FIELD.equals(key))
    78                  entry.setValue(null);
    79              else if (Bayeux.TIMESTAMP_FIELD.equals(key))
    80                  entry.setValue(null);
    81              else if (Bayeux.DATA_FIELD.equals(key))
    82                  entry.setValue(null);
    83              else if (Bayeux.EXT_FIELD.equals(key))
    84                  entry.setValue(null);
    85              else
    86                  iterator.remove();
    87          }
    88          super.clear();
    89      }
    90
    91      /* ------------------------------------------------------------ */
    92      public Object clone()
    93      {
    94          MessageImpl msg=new MessageImpl();
    95          msg.putAll(this);
    96          msg._channel=_channel;
    97          msg._clientId=_clientId;
    98          msg._id=_id;
    99          return msg;
    100     }
    101
    102     /* ------------------------------------------------------------ */
    103     public void decRef()
    104     {
    105         int r=_refs.decrementAndGet();
    106         if (r == 0 && _pool != null)
    107         {
    108             setAssociated(null);
    109             _pool.recycleMessage(this);
    110         }
    111         else if (r < 0)
    112             throw new IllegalStateException();
    113     }
    114
    115     /* ------------------------------------------------------------ */
    116     /*
    117      * (non-Javadoc)
    118      *
    119      * @see java.util.HashMap#entrySet()
    120      */
    121     @Override
    122     public Set<java.util.Map.Entry<String,Object>> entrySet()
    123     {
    124         return Collections.unmodifiableSet(super.entrySet());
    125     }
    126
    127     /* ------------------------------------------------------------ */
    128     public Message getAssociated()
    129     {
    130         return _associated;
    131     }
    132
    133     /* ------------------------------------------------------------ */
    134     public ByteBuffer getBuffer()
    135     {
    136         return _buffer;
    137     }
    138
    139     /* ------------------------------------------------------------ */
    140     public String getChannel()
    141     {
    142         return _channel;
    143     }
    144
    145     /* ------------------------------------------------------------ */
    146     public String getClientId()
    147     {
    148         if (_clientId == null)
    149             _clientId=(String)get(Bayeux.CLIENT_FIELD);
    150         return _clientId;
    151     }
    152
    153     /* ------------------------------------------------------------ */
    154     public Object getData()
    155     {
    156         return _data;
    157     }
    158
    159     /* ------------------------------------------------------------ */
    160     public Map<String,Object> getExt(boolean create)
    161     {
    162         Object ext=_ext == null?get(Bayeux.EXT_FIELD):_ext;
    163         if (ext instanceof Map)
    164             return (Map<String,Object>)ext;
    165         if (ext instanceof JSON.Literal)
    166         {
    167             JSON json=_pool == null?JSON.getDefault():_pool.getMsgJSON();
    168             _ext=ext=json.fromJSON(ext.toString());
    169             super.put(Bayeux.EXT_FIELD,ext);
    170             return (Map<String,Object>)ext;
    171         }
    172
    173         if (!create)
    174             return null;
    175
    176         _ext=ext=new HashMap<String,Object>();
    177         super.put(Bayeux.EXT_FIELD,ext);
    178         return (Map<String,Object>)ext;
    179
    180     }
    181
    182     /* ------------------------------------------------------------ */
    183     public String getId()
    184     {
    185         return _id;
    186     }
    187
    188     /* ------------------------------------------------------------ */
    189     public String getJSON()
    190     {
    191         if (_json == null)
    192         {
    193             JSON json=_pool == null?JSON.getDefault():_pool.getMsgJSON();
    194             StringBuffer buf=new StringBuffer(json.getStringBufferSize());
    195             synchronized(buf)
    196             {
    197                 json.appendMap(buf,this);
    198                 _json=buf.toString();
    199             }
    200         }
    201         return _json;
    202     }
    203
    204     /* ------------------------------------------------------------ */
    205     public int getRefs()
    206     {
    207         return _refs.get();
    208     }
    209
    210     /* ------------------------------------------------------------ */
    211     public void incRef()
    212     {
    213         _refs.incrementAndGet();
    214     }
    215
    216     /* ------------------------------------------------------------ */
    217     /**
    218      * Lazy messages are queued but do not wake up waiting clients.
    219      *
    220      * @return true if message is lazy
    221      */
    222     public boolean isLazy()
    223     {
    224         return _lazy;
    225     }
    226
    227     /* ------------------------------------------------------------ */
    228     public boolean isSuccessful()
    229     {
    230         Boolean bool=(Boolean)get(Bayeux.SUCCESSFUL_FIELD);
    231         return bool != null && bool.booleanValue();
    232     }
    233
    234     /* ------------------------------------------------------------ */
    235     /*
    236      * (non-Javadoc)
    237      *
    238      * @see java.util.HashMap#keySet()
    239      */
    240     @Override
    241     public Set<String> keySet()
    242     {
    243         return Collections.unmodifiableSet(super.keySet());
    244     }
    245
    246     /* ------------------------------------------------------------ */
    247     /*
    248      * (non-Javadoc)
    249      *
    250      * @see java.util.HashMap#put(java.lang.Object, java.lang.Object)
    251      */
    252     @Override
    253     public Object put(String key, Object value)
    254     {
    255         _json=null;
    256         _buffer=null;
    257         if (Bayeux.CHANNEL_FIELD.equals(key))
    258             _channel=(String)value;
    259         else if (Bayeux.ID_FIELD.equals(key))
    260             _id=value.toString();
    261         else if (Bayeux.CLIENT_FIELD.equals(key))
    262             _clientId=(String)value;
    263         else if (Bayeux.DATA_FIELD.equals(key))
    264             _data=value;
    265         else if (Bayeux.EXT_FIELD.equals(key))
    266             _ext=value;
    267         return super.put(key,value);
    268     }
    269
    270     /* ------------------------------------------------------------ */
    271     /*
    272      * (non-Javadoc)
    273      *
    274      * @see java.util.HashMap#putAll(java.util.Map)
    275      */
    276     @Override
    277     public void putAll(Map<? extends String,? extends Object> m)
    278     {
    279         _json=null;
    280         _buffer=null;
    281         super.putAll(m);
    282         _channel=(String)get(Bayeux.CHANNEL_FIELD);
    283         Object id=get(Bayeux.ID_FIELD);
    284         _id=id == null?null:id.toString();
    285         _data=get(Bayeux.DATA_FIELD);
    286     }
    287
    288     /* ------------------------------------------------------------ */
    289     /*
    290      * (non-Javadoc)
    291      *
    292      * @see java.util.HashMap#remove(java.lang.Object)
    293      */
    294     @Override
    295     public Object remove(Object key)
    296     {
    297         _json=null;
    298         _buffer=null;
    299         if (Bayeux.CHANNEL_FIELD.equals(key))
    300             _channel=null;
    301         else if (Bayeux.ID_FIELD.equals(key))
    302             _id=null;
    303         else if (Bayeux.DATA_FIELD.equals(key))
    304             _data=null;
    305         else if (Bayeux.EXT_FIELD.equals(key))
    306             _ext=null;
    307         return super.remove(key);
    308     }
    309
    310     /* ------------------------------------------------------------ */
    311     public void setAssociated(Message associated)
    312     {
    313         if (_associated != associated)
    314         {
    315             if (_associated != null)
    316                 ((MessageImpl)_associated).decRef();
    317             _associated=associated;
    318             if (_associated != null)
    319                 ((MessageImpl)_associated).incRef();
    320         }
    321     }
    322
    323     /* ------------------------------------------------------------ */
    324     /**
    325      * @param buffer
    326      *            A cached buffer containing HTTP response headers and message
    327      *            content, to be reused when sending one message to multiple
    328      *            clients
    329      */
    330     public void setBuffer(ByteBuffer buffer)
    331     {
    332         _buffer=buffer;
    333     }
    334
    335     /* ------------------------------------------------------------ */
    336     /**
    337      * Lazy messages are queued but do not wake up waiting clients.
    338      *
    339      * @param lazy
    340      *            true if message is lazy
    341      */
    342     public void setLazy(boolean lazy)
    343     {
    344         _lazy=lazy;
    345     }
    346
    347     /* ------------------------------------------------------------ */
    348     public String toString()
    349     {
    350         return getJSON();
    351     }
    352 }