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  
24  import java.util.HashMap;
25  import java.util.HashSet;
26  import java.util.Iterator;
27  import java.util.Map;
28  import java.util.Set;
29  
30  import org.apache.jcs.engine.behavior.ICacheObserver;
31  import org.apache.jcs.engine.behavior.ICacheListener;
32  
33  import org.apache.commons.logging.Log;
34  import org.apache.commons.logging.LogFactory;
35  
36  /***
37   * Intercepts the requests to the underlying ICacheObserver object so that the
38   * listeners can be recorded locally for remote connection recovery purposes.
39   * (Durable subscription like those in JMS is not implemented at this stage for
40   * it can be too expensive on the runtime.)
41   *
42   */
43  public class CacheWatchRepairable
44      implements ICacheObserver
45  {
46      private final static Log log = LogFactory.getLog( CacheWatchRepairable.class );
47  
48      // the underlying ICacheObserver.
49      private ICacheObserver cacheWatch;
50  
51      private Map cacheMap = new HashMap();
52  
53      /***
54       * Replaces the underlying cache watch service and reattached all existing
55       * listeners to the new cache watch.
56       * <p>
57       * @param cacheWatch
58       *            The new cacheWatch value
59       */
60      public void setCacheWatch( ICacheObserver cacheWatch )
61      {
62          this.cacheWatch = cacheWatch;
63          synchronized ( cacheMap )
64          {
65              for ( Iterator itr = cacheMap.entrySet().iterator(); itr.hasNext(); )
66              {
67                  Map.Entry entry = (Map.Entry) itr.next();
68                  String cacheName = (String) entry.getKey();
69                  Set listenerSet = (Set) entry.getValue();
70                  for ( Iterator itr2 = listenerSet.iterator(); itr2.hasNext(); )
71                  {
72                      try
73                      {
74                          cacheWatch.addCacheListener( cacheName, (ICacheListener) itr2.next() );
75                      }
76                      catch ( IOException ex )
77                      {
78                          log.error( "Problem adding listener.", ex );
79                      }
80                  }
81              }
82          }
83      }
84  
85      /***
86       * Adds a feature to the CacheListener attribute of the CacheWatchRepairable
87       * object
88       * <p>
89       * @param cacheName
90       *            The feature to be added to the CacheListener attribute
91       * @param obj
92       *            The feature to be added to the CacheListener attribute
93       * @throws IOException
94       */
95      public void addCacheListener( String cacheName, ICacheListener obj )
96          throws IOException
97      {
98          // Record the added cache listener locally, regardless of whether the
99          // remote add-listener
100         // 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                 cacheMap.put( cacheName, listenerSet );
108             }
109             listenerSet.add( obj );
110         }
111         cacheWatch.addCacheListener( cacheName, obj );
112     }
113 
114     /***
115      * Adds a feature to the CacheListener attribute of the CacheWatchRepairable
116      * object
117      * <p>
118      * @param obj
119      *            The feature to be added to the CacheListener attribute
120      * @throws IOException
121      */
122     public void addCacheListener( ICacheListener obj )
123         throws IOException
124     {
125         // Record the added cache listener locally, regardless of whether the
126         // remote add-listener
127         // operation succeeds or fails.
128         synchronized ( cacheMap )
129         {
130             for ( Iterator itr = cacheMap.values().iterator(); itr.hasNext(); )
131             {
132                 Set listenerSet = (Set) itr.next();
133                 listenerSet.add( obj );
134             }
135         }
136         cacheWatch.addCacheListener( obj );
137     }
138 
139     /***
140      * Tell the server to release us.
141      * <p>
142      * @param cacheName
143      * @param obj
144      * @throws IOException
145      */
146     public void removeCacheListener( String cacheName, ICacheListener obj )
147         throws IOException
148     {
149         if ( log.isInfoEnabled() )
150         {
151             log.info( "removeCacheListener, cacheName [" + cacheName + "]" );
152         }
153         // Record the removal locally, regardless of whether the remote
154         // remove-listener
155         // operation succeeds or fails.
156         synchronized ( cacheMap )
157         {
158             Set listenerSet = (Set) cacheMap.get( cacheName );
159             if ( listenerSet != null )
160             {
161                 listenerSet.remove( obj );
162             }
163         }
164         cacheWatch.removeCacheListener( cacheName, obj );
165     }
166 
167     /***
168      * @param obj
169      * @throws IOException
170      */
171     public void removeCacheListener( ICacheListener obj )
172         throws IOException
173     {
174         if ( log.isInfoEnabled() )
175         {
176             log.info( "removeCacheListener, ICacheListener [" + obj + "]" );
177         }
178 
179         // Record the removal locally, regardless of whether the remote
180         // remove-listener operation succeeds or fails.
181         synchronized ( cacheMap )
182         {
183             for ( Iterator itr = cacheMap.values().iterator(); itr.hasNext(); )
184             {
185                 Set listenerSet = (Set) itr.next();
186                 if ( log.isDebugEnabled() )
187                 {
188                     log.debug( "Before removing [" + obj + "] the listenerSet = " + listenerSet );
189                 }
190                 listenerSet.remove( obj );
191             }
192         }
193         cacheWatch.removeCacheListener( obj );
194     }
195 }