View Javadoc

1   package org.apache.jcs.engine;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.IOException;
23  import java.util.HashMap;
24  import java.util.HashSet;
25  import java.util.Iterator;
26  import java.util.Map;
27  import java.util.Set;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.apache.jcs.engine.behavior.ICacheListener;
32  import org.apache.jcs.engine.behavior.ICacheObserver;
33  
34  /***
35   * Intercepts the requests to the underlying ICacheObserver object so that the listeners can be
36   * recorded locally for remote connection recovery purposes. (Durable subscription like those in JMS
37   * is not implemented at this stage for it can be too expensive.)
38   */
39  public class CacheWatchRepairable
40      implements ICacheObserver
41  {
42      /*** The logger */
43      private final static Log log = LogFactory.getLog( CacheWatchRepairable.class );
44  
45      /*** the underlying ICacheObserver. */
46      private ICacheObserver cacheWatch;
47  
48      /*** Map of cache regions. */
49      private Map cacheMap = new HashMap();
50  
51      /***
52       * Replaces the underlying cache watch service and reattached all existing listeners to the new
53       * cache watch.
54       * <p>
55       * @param cacheWatch The new cacheWatch value
56       */
57      public void setCacheWatch( ICacheObserver cacheWatch )
58      {
59          this.cacheWatch = cacheWatch;
60          synchronized ( cacheMap )
61          {
62              for ( Iterator itr = cacheMap.entrySet().iterator(); itr.hasNext(); )
63              {
64                  Map.Entry entry = (Map.Entry) itr.next();
65                  String cacheName = (String) entry.getKey();
66                  Set listenerSet = (Set) entry.getValue();
67                  for ( Iterator itr2 = listenerSet.iterator(); itr2.hasNext(); )
68                  {
69                      ICacheListener listener = (ICacheListener) itr2.next();
70                      try
71                      {
72                          if ( log.isInfoEnabled() )
73                          {
74                              log.info( "Adding listener to cache watch. ICacheListener = " + listener
75                                  + " | ICacheObserver = " + cacheWatch );
76                          }
77                          cacheWatch.addCacheListener( cacheName, listener );
78                      }
79                      catch ( IOException ex )
80                      {
81                          log.error( "Problem adding listener. ICacheListener = " + listener + " | ICacheObserver = "
82                              + cacheWatch, ex );
83                      }
84                  }
85              }
86          }
87      }
88  
89      /***
90       * Adds a feature to the CacheListener attribute of the CacheWatchRepairable object
91       * <p>
92       * @param cacheName The feature to be added to the CacheListener attribute
93       * @param obj The feature to be added to the CacheListener attribute
94       * @throws IOException
95       */
96      public void addCacheListener( String cacheName, ICacheListener obj )
97          throws IOException
98      {
99          // Record the added cache listener locally, regardless of whether the
100         // remote add-listener operation succeeds or fails.
101         synchronized ( cacheMap )
102         {
103             Set listenerSet = (Set) cacheMap.get( cacheName );
104             if ( listenerSet == null )
105             {
106                 listenerSet = new HashSet();
107                 
108                 cacheMap.put( cacheName, listenerSet );
109             }
110             listenerSet.add( obj );
111         }
112         if ( log.isInfoEnabled() )
113         {
114             log.info( "Adding listener to cache watch. ICacheListener = " + obj
115                 + " | ICacheObserver = " + cacheWatch + " | cacheName = " + cacheName );
116         }
117         cacheWatch.addCacheListener( cacheName, obj );
118     }
119 
120     /***
121      * Adds a feature to the CacheListener attribute of the CacheWatchRepairable object
122      * <p>
123      * @param obj The feature to be added to the CacheListener attribute
124      * @throws IOException
125      */
126     public void addCacheListener( ICacheListener obj )
127         throws IOException
128     {
129         // Record the added cache listener locally, regardless of whether the
130         // remote add-listener operation succeeds or fails.
131         synchronized ( cacheMap )
132         {
133             for ( Iterator itr = cacheMap.values().iterator(); itr.hasNext(); )
134             {
135                 Set listenerSet = (Set) itr.next();
136                 listenerSet.add( obj );
137             }
138         }
139         if ( log.isInfoEnabled() )
140         {
141             log.info( "Adding listener to cache watch. ICacheListener = " + obj
142                 + " | ICacheObserver = " + cacheWatch );
143         }        
144         cacheWatch.addCacheListener( obj );
145     }
146 
147     /***
148      * Tell the server to release us.
149      * <p>
150      * @param cacheName
151      * @param obj
152      * @throws IOException
153      */
154     public void removeCacheListener( String cacheName, ICacheListener obj )
155         throws IOException
156     {
157         if ( log.isInfoEnabled() )
158         {
159             log.info( "removeCacheListener, cacheName [" + cacheName + "]" );
160         }
161         // Record the removal locally, regardless of whether the remote
162         // remove-listener operation succeeds or fails.
163         synchronized ( cacheMap )
164         {
165             Set listenerSet = (Set) cacheMap.get( cacheName );
166             if ( listenerSet != null )
167             {
168                 listenerSet.remove( obj );
169             }
170         }
171         cacheWatch.removeCacheListener( cacheName, obj );
172     }
173 
174     /***
175      * @param obj
176      * @throws IOException
177      */
178     public void removeCacheListener( ICacheListener obj )
179         throws IOException
180     {
181         if ( log.isInfoEnabled() )
182         {
183             log.info( "removeCacheListener, ICacheListener [" + obj + "]" );
184         }
185 
186         // Record the removal locally, regardless of whether the remote
187         // remove-listener operation succeeds or fails.
188         synchronized ( cacheMap )
189         {
190             for ( Iterator itr = cacheMap.values().iterator(); itr.hasNext(); )
191             {
192                 Set listenerSet = (Set) itr.next();
193                 if ( log.isDebugEnabled() )
194                 {
195                     log.debug( "Before removing [" + obj + "] the listenerSet = " + listenerSet );
196                 }
197                 listenerSet.remove( obj );
198             }
199         }
200         cacheWatch.removeCacheListener( obj );
201     }
202 }