View Javadoc

1   /*
2      Copyright 2010 Ramon Servadei
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   
8          http://www.apache.org/licenses/LICENSE-2.0
9   
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15   */
16  package mirrormap;
17  
18  import java.io.Serializable;
19  import java.util.logging.Level;
20  import java.util.logging.Logger;
21  
22  import mirrormap.collections.IMapListener;
23  import mirrormap.commands.AddCommand;
24  import mirrormap.commands.ICommand;
25  import mirrormap.commands.RemoveCommand;
26  import mirrormap.commands.UpdateCommand;
27  import mirrormap.nio.IConnectionEndPoint;
28  
29  /**
30   * A listener attached to a {@link MirrorMap} that will send changes in the map
31   * to a single {@link IConnectionEndPoint}.
32   * 
33   * @author Ramon Servadei
34   */
35  class ConnectionEndPointMapListener implements
36      IMapListener<Serializable, Serializable>
37  {
38      private final static Logger LOGGER =
39          Logger.getLogger(ConnectionEndPointMapListener.class.getName());
40  
41      /** The end point to send changes to */
42      private final IConnectionEndPoint connectionEndPoint;
43  
44      /** The name of the {@link MirrorMap} this listener is attached to */
45      private final String mirrorMapName;
46  
47      /**
48       * Construct the listener for a specific {@link MirrorMap} to send changes
49       * from the map to the {@link IConnectionEndPoint}
50       * 
51       * @param connectionEndPoint
52       *            the end point to send map changes to
53       * @param mirrorMapName
54       *            the name of the {@link MirrorMap} this listener is attached to
55       */
56      ConnectionEndPointMapListener(IConnectionEndPoint connectionEndPoint,
57          String mirrorMapName)
58      {
59          super();
60          this.connectionEndPoint = connectionEndPoint;
61          this.mirrorMapName = mirrorMapName;
62      }
63  
64      public void didAdd(Serializable key, Serializable value)
65      {
66          if (isRemoteChange())
67          {
68              return;
69          }
70          final ICommand command = new AddCommand(this.mirrorMapName, key, value);
71          send(command);
72      }
73  
74      public void didRemove(Serializable key, Serializable value)
75      {
76          if (isRemoteChange())
77          {
78              return;
79          }
80          final ICommand command = new RemoveCommand(this.mirrorMapName, key);
81          send(command);
82      }
83  
84      public void didUpdate(Serializable key, Serializable oldValue,
85          Serializable newValue)
86      {
87          if (isRemoteChange())
88          {
89              return;
90          }
91          final ICommand command =
92              new UpdateCommand(this.mirrorMapName, key, newValue);
93          send(command);
94      }
95  
96      public void willAdd(Serializable key, Serializable value)
97      {
98          // noop
99      }
100 
101     public void willRemove(Serializable key)
102     {
103         // noop
104     }
105 
106     public void willUpdate(Serializable key, Serializable currentValue,
107         Serializable newValue)
108     {
109         // noop
110     }
111 
112     @Override
113     public int hashCode()
114     {
115         final int prime = 31;
116         int result = 1;
117         result =
118             prime
119                 * result
120                 + ((connectionEndPoint == null) ? 0
121                     : connectionEndPoint.hashCode());
122         result =
123             prime * result
124                 + ((mirrorMapName == null) ? 0 : mirrorMapName.hashCode());
125         return result;
126     }
127 
128     @Override
129     public boolean equals(Object obj)
130     {
131         if (this == obj)
132             return true;
133         if (obj == null)
134             return false;
135         if (getClass() != obj.getClass())
136             return false;
137         ConnectionEndPointMapListener other =
138             (ConnectionEndPointMapListener) obj;
139         if (mirrorMapName == null)
140         {
141             if (other.mirrorMapName != null)
142                 return false;
143         }
144         else
145             if (!mirrorMapName.equals(other.mirrorMapName))
146                 return false;
147         if (connectionEndPoint == null)
148         {
149             if (other.connectionEndPoint != null)
150                 return false;
151         }
152         else
153             if (!connectionEndPoint.equals(other.connectionEndPoint))
154                 return false;
155         return true;
156     }
157 
158     private void send(final ICommand command)
159     {
160         if (LOGGER.isLoggable(Level.FINEST))
161         {
162             LOGGER.finest("Sending " + command.toString() + " to "
163                 + this.connectionEndPoint);
164         }
165         if (this.connectionEndPoint.isActive())
166         {
167             this.connectionEndPoint.send(command.getBytes());
168         }
169         else
170         {
171             if (LOGGER.isLoggable(Level.INFO))
172             {
173                 LOGGER.info(this.connectionEndPoint
174                     + " is inactive, unregistering from mirror map "
175                     + this.mirrorMapName);
176             }
177             MirrorMap.get(this.mirrorMapName).removeListener(this);
178         }
179     }
180 
181     /**
182      * Checks if the thread is the MirrorMap I/O thread
183      * 
184      * @return <code>true</code> if the current thread is the MirrorMap I/O
185      *         thread
186      */
187     private final boolean isRemoteChange()
188     {
189         return Thread.currentThread().getName().equals(
190             MirrorMap.getClientThreadName());
191     }
192 
193 }