View Javadoc

1   package org.apache.jcs.auxiliary.remote.http.server;
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.io.Serializable;
24  import java.util.Map;
25  import java.util.Set;
26  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.apache.jcs.auxiliary.remote.behavior.IRemoteCacheService;
30  import org.apache.jcs.engine.behavior.ICacheElement;
31  import org.apache.jcs.engine.behavior.ICompositeCacheManager;
32  import org.apache.jcs.engine.control.CompositeCache;
33  import org.apache.jcs.engine.control.CompositeCacheManager;
34  import org.apache.jcs.engine.logging.CacheEvent;
35  import org.apache.jcs.engine.logging.behavior.ICacheEvent;
36  import org.apache.jcs.engine.logging.behavior.ICacheEventLogger;
37  
38  /**
39   * This class contains common methods for remote cache services. Eventually I hope to extract out
40   * much of the RMI server to use this as well. I'm starting with the Http service.
41   */
42  public abstract class AbstractRemoteCacheService
43      implements IRemoteCacheService
44  {
45      /** An optional event logger */
46      private transient ICacheEventLogger cacheEventLogger;
47  
48      /** If there is no event logger, we will return this event for all create calls. */
49      private static final ICacheEvent EMPTY_ICACHE_EVENT = new CacheEvent();
50  
51      /** The central hub */
52      private ICompositeCacheManager cacheManager;
53  
54      /** Name of the event log source. */
55      private String eventLogSourceName = "AbstractRemoteCacheService";
56  
57      /** Number of puts into the cache. */
58      private int puts = 0;
59  
60      /** The interval at which we will log updates. */
61      private final int logInterval = 100;
62  
63      /** log instance */
64      private final static Log log = LogFactory.getLog( AbstractRemoteCacheService.class );
65  
66      /**
67       * Creates the super with the needed items.
68       * <p>
69       * @param cacheManager
70       * @param cacheEventLogger
71       */
72      public AbstractRemoteCacheService( ICompositeCacheManager cacheManager, ICacheEventLogger cacheEventLogger )
73      {
74          this.cacheManager = cacheManager;
75          this.cacheEventLogger = cacheEventLogger;
76      }
77  
78      /**
79       * @param item
80       * @throws IOException
81       */
82      public void update( ICacheElement item )
83          throws IOException
84      {
85          update( item, 0 );
86      }
87  
88      /**
89       * The internal processing is wrapped in event logging calls.
90       * <p>
91       * @param item
92       * @param requesterId
93       * @throws IOException
94       */
95      public void update( ICacheElement item, long requesterId )
96          throws IOException
97      {
98          ICacheEvent cacheEvent = createICacheEvent( item, requesterId, ICacheEventLogger.UPDATE_EVENT );
99          try
100         {
101             logUpdateInfo( item );
102 
103             processUpdate( item, requesterId );
104         }
105         finally
106         {
107             logICacheEvent( cacheEvent );
108         }
109     }
110 
111     /**
112      * The internal processing is wrapped in event logging calls.
113      * <p>
114      * @param item
115      * @param requesterId
116      * @throws IOException
117      */
118     abstract void processUpdate( ICacheElement item, long requesterId )
119         throws IOException;
120 
121     /**
122      * Log some details.
123      * <p>
124      * @param item
125      */
126     private void logUpdateInfo( ICacheElement item )
127     {
128         if ( log.isInfoEnabled() )
129         {
130             // not thread safe, but it doesn't have to be accurate
131             puts++;
132             if ( puts % logInterval == 0 )
133             {
134                 log.info( "puts = " + puts );
135             }
136         }
137 
138         if ( log.isDebugEnabled() )
139         {
140             log.debug( "In update, put [" + item.getKey() + "] in [" + item.getCacheName() + "]" );
141         }
142     }
143 
144     /**
145      * Returns a cache value from the specified remote cache; or null if the cache or key does not
146      * exist.
147      * <p>
148      * @param cacheName
149      * @param key
150      * @return ICacheElement
151      * @throws IOException
152      */
153     public ICacheElement get( String cacheName, Serializable key )
154         throws IOException
155     {
156         return this.get( cacheName, key, 0 );
157     }
158 
159     /**
160      * Returns a cache bean from the specified cache; or null if the key does not exist.
161      * <p>
162      * Adding the requestor id, allows the cache to determine the source of the get.
163      * <p>
164      * The internal processing is wrapped in event logging calls.
165      * <p>
166      * @param cacheName
167      * @param key
168      * @param requesterId
169      * @return ICacheElement
170      * @throws IOException
171      */
172     public ICacheElement get( String cacheName, Serializable key, long requesterId )
173         throws IOException
174     {
175         ICacheElement element = null;
176         ICacheEvent cacheEvent = createICacheEvent( cacheName, key, requesterId, ICacheEventLogger.GET_EVENT );
177         try
178         {
179             element = processGet( cacheName, key, requesterId );
180         }
181         finally
182         {
183             logICacheEvent( cacheEvent );
184         }
185         return element;
186     }
187 
188     /**
189      * Returns a cache bean from the specified cache; or null if the key does not exist.
190      * <p>
191      * Adding the requestor id, allows the cache to determine the source of the get.
192      * <p>
193      * @param cacheName
194      * @param key
195      * @param requesterId
196      * @return ICacheElement
197      * @throws IOException
198      */
199     abstract ICacheElement processGet( String cacheName, Serializable key, long requesterId )
200         throws IOException;
201 
202     /**
203      * Gets all matching items.
204      * <p>
205      * @param cacheName
206      * @param pattern
207      * @return Map of keys and wrapped objects
208      * @throws IOException
209      */
210     public Map<Serializable, ICacheElement> getMatching( String cacheName, String pattern )
211         throws IOException
212     {
213         return getMatching( cacheName, pattern, 0 );
214     }
215 
216     /**
217      * Retrieves all matching keys.
218      * <p>
219      * @param cacheName
220      * @param pattern
221      * @param requesterId
222      * @return Map of keys and wrapped objects
223      * @throws IOException
224      */
225     public Map<Serializable, ICacheElement> getMatching( String cacheName, String pattern, long requesterId )
226         throws IOException
227     {
228         ICacheEvent cacheEvent = createICacheEvent( cacheName, pattern, requesterId,
229                                                     ICacheEventLogger.GETMATCHING_EVENT );
230         try
231         {
232             return processGetMatching( cacheName, pattern, requesterId );
233         }
234         finally
235         {
236             logICacheEvent( cacheEvent );
237         }
238     }
239 
240     /**
241      * Retrieves all matching keys.
242      * <p>
243      * @param cacheName
244      * @param pattern
245      * @param requesterId
246      * @return Map of keys and wrapped objects
247      * @throws IOException
248      */
249     abstract Map<Serializable, ICacheElement> processGetMatching( String cacheName, String pattern, long requesterId )
250         throws IOException;
251 
252     /**
253      * Gets multiple items from the cache based on the given set of keys.
254      * <p>
255      * @param cacheName
256      * @param keys
257      * @return a map of Serializable key to ICacheElement element, or an empty map if there is no
258      *         data in cache for any of these keys
259      * @throws IOException
260      */
261     public Map<Serializable, ICacheElement> getMultiple( String cacheName, Set<Serializable> keys )
262         throws IOException
263     {
264         return this.getMultiple( cacheName, keys, 0 );
265     }
266 
267     /**
268      * Gets multiple items from the cache based on the given set of keys.
269      * <p>
270      * The internal processing is wrapped in event logging calls.
271      * <p>
272      * @param cacheName
273      * @param keys
274      * @param requesterId
275      * @return a map of Serializable key to ICacheElement element, or an empty map if there is no
276      *         data in cache for any of these keys
277      * @throws IOException
278      */
279     public Map<Serializable, ICacheElement> getMultiple( String cacheName, Set<Serializable> keys, long requesterId )
280         throws IOException
281     {
282         ICacheEvent cacheEvent = createICacheEvent( cacheName, (Serializable) keys, requesterId,
283                                                     ICacheEventLogger.GETMULTIPLE_EVENT );
284         try
285         {
286             return processGetMultiple( cacheName, keys, requesterId );
287         }
288         finally
289         {
290             logICacheEvent( cacheEvent );
291         }
292     }
293 
294     /**
295      * Gets multiple items from the cache based on the given set of keys.
296      * <p>
297      * @param cacheName
298      * @param keys
299      * @param requesterId
300      * @return a map of Serializable key to ICacheElement element, or an empty map if there is no
301      *         data in cache for any of these keys
302      * @throws IOException
303      */
304     abstract Map<Serializable, ICacheElement> processGetMultiple( String cacheName, Set<Serializable> keys, long requesterId )
305         throws IOException;
306 
307     /**
308      * Gets the set of keys of objects currently in the group.
309      * <p>
310      * @param cacheName
311      * @param group
312      * @return A Set of group keys
313      */
314     public Set<Serializable> getGroupKeys( String cacheName, String group )
315     {
316         return processGetGroupKeys( cacheName, group );
317     }
318 
319     /**
320      * Gets the set of keys of objects currently in the group.
321      * <p>
322      * @param cacheName
323      * @param groupName
324      * @return Set
325      */
326     public Set<Serializable> processGetGroupKeys( String cacheName, String groupName )
327     {
328         CompositeCache cache = getCacheManager().getCache( cacheName );
329 
330         return cache.getGroupKeys( groupName );
331     }
332 
333     /**
334      * Removes the given key from the specified remote cache. Defaults the listener id to 0.
335      * <p>
336      * @param cacheName
337      * @param key
338      * @throws IOException
339      */
340     public void remove( String cacheName, Serializable key )
341         throws IOException
342     {
343         remove( cacheName, key, 0 );
344     }
345 
346     /**
347      * Remove the key from the cache region and don't tell the source listener about it.
348      * <p>
349      * The internal processing is wrapped in event logging calls.
350      * <p>
351      * @param cacheName
352      * @param key
353      * @param requesterId
354      * @throws IOException
355      */
356     public void remove( String cacheName, Serializable key, long requesterId )
357         throws IOException
358     {
359         ICacheEvent cacheEvent = createICacheEvent( cacheName, key, requesterId, ICacheEventLogger.REMOVE_EVENT );
360         try
361         {
362             processRemove( cacheName, key, requesterId );
363         }
364         finally
365         {
366             logICacheEvent( cacheEvent );
367         }
368     }
369 
370     /**
371      * Remove the key from the cache region and don't tell the source listener about it.
372      * <p>
373      * @param cacheName
374      * @param key
375      * @param requesterId
376      * @throws IOException
377      */
378     abstract void processRemove( String cacheName, Serializable key, long requesterId )
379         throws IOException;
380 
381     /**
382      * Remove all keys from the specified remote cache.
383      * <p>
384      * @param cacheName
385      * @throws IOException
386      */
387     public void removeAll( String cacheName )
388         throws IOException
389     {
390         removeAll( cacheName, 0 );
391     }
392 
393     /**
394      * Remove all keys from the specified remote cache.
395      * <p>
396      * The internal processing is wrapped in event logging calls.
397      * <p>
398      * @param cacheName
399      * @param requesterId
400      * @throws IOException
401      */
402     public void removeAll( String cacheName, long requesterId )
403         throws IOException
404     {
405         ICacheEvent cacheEvent = createICacheEvent( cacheName, "all", requesterId, ICacheEventLogger.REMOVEALL_EVENT );
406         try
407         {
408             processRemoveAll( cacheName, requesterId );
409         }
410         finally
411         {
412             logICacheEvent( cacheEvent );
413         }
414     }
415 
416     /**
417      * Remove all keys from the specified remote cache.
418      * <p>
419      * @param cacheName
420      * @param requesterId
421      * @throws IOException
422      */
423     abstract void processRemoveAll( String cacheName, long requesterId )
424         throws IOException;
425 
426     /**
427      * Frees the specified remote cache.
428      * <p>
429      * @param cacheName
430      * @throws IOException
431      */
432     public void dispose( String cacheName )
433         throws IOException
434     {
435         dispose( cacheName, 0 );
436     }
437 
438     /**
439      * Frees the specified remote cache.
440      * <p>
441      * @param cacheName
442      * @param requesterId
443      * @throws IOException
444      */
445     public void dispose( String cacheName, long requesterId )
446         throws IOException
447     {
448         ICacheEvent cacheEvent = createICacheEvent( cacheName, "none", requesterId, ICacheEventLogger.DISPOSE_EVENT );
449         try
450         {
451             processDispose( cacheName, requesterId );
452         }
453         finally
454         {
455             logICacheEvent( cacheEvent );
456         }
457     }
458 
459     /**
460      * @param cacheName
461      * @param requesterId
462      * @throws IOException
463      */
464     abstract void processDispose( String cacheName, long requesterId )
465         throws IOException;
466 
467     /**
468      * Gets the stats attribute of the RemoteCacheServer object.
469      * <p>
470      * @return The stats value
471      * @throws IOException
472      */
473     public String getStats()
474         throws IOException
475     {
476         return cacheManager.getStats();
477     }
478 
479     /**
480      * Logs an event if an event logger is configured.
481      * <p>
482      * @param item
483      * @param requesterId
484      * @param eventName
485      * @return ICacheEvent
486      */
487     protected ICacheEvent createICacheEvent( ICacheElement item, long requesterId, String eventName )
488     {
489         if ( cacheEventLogger == null )
490         {
491             return EMPTY_ICACHE_EVENT;
492         }
493         String ipAddress = getExtraInfoForRequesterId( requesterId );
494         return cacheEventLogger.createICacheEvent( getEventLogSourceName(), item.getCacheName(), eventName, ipAddress,
495                                                    item );
496     }
497 
498     /**
499      * Logs an event if an event logger is configured.
500      * <p>
501      * @param cacheName
502      * @param key
503      * @param requesterId
504      * @param eventName
505      * @return ICacheEvent
506      */
507     protected ICacheEvent createICacheEvent( String cacheName, Serializable key, long requesterId, String eventName )
508     {
509         if ( cacheEventLogger == null )
510         {
511             return EMPTY_ICACHE_EVENT;
512         }
513         String ipAddress = getExtraInfoForRequesterId( requesterId );
514         return cacheEventLogger.createICacheEvent( getEventLogSourceName(), cacheName, eventName, ipAddress, key );
515     }
516 
517     /**
518      * Logs an event if an event logger is configured.
519      * <p>
520      * @param source
521      * @param eventName
522      * @param optionalDetails
523      */
524     protected void logApplicationEvent( String source, String eventName, String optionalDetails )
525     {
526         if ( cacheEventLogger != null )
527         {
528             cacheEventLogger.logApplicationEvent( source, eventName, optionalDetails );
529         }
530     }
531 
532     /**
533      * Logs an event if an event logger is configured.
534      * <p>
535      * @param cacheEvent
536      */
537     protected void logICacheEvent( ICacheEvent cacheEvent )
538     {
539         if ( cacheEventLogger != null )
540         {
541             cacheEventLogger.logICacheEvent( cacheEvent );
542         }
543     }
544 
545     /**
546      * Ip address for the client, if one is stored.
547      * <p>
548      * Protected for testing.
549      * <p>
550      * @param requesterId
551      * @return String
552      */
553     protected abstract String getExtraInfoForRequesterId( long requesterId );
554 
555     /**
556      * Allows it to be injected.
557      * <p>
558      * @param cacheEventLogger
559      */
560     public void setCacheEventLogger( ICacheEventLogger cacheEventLogger )
561     {
562         this.cacheEventLogger = cacheEventLogger;
563     }
564 
565     /**
566      * @param cacheManager the cacheManager to set
567      */
568     protected void setCacheManager( CompositeCacheManager cacheManager )
569     {
570         this.cacheManager = cacheManager;
571     }
572 
573     /**
574      * @return the cacheManager
575      */
576     protected ICompositeCacheManager getCacheManager()
577     {
578         return cacheManager;
579     }
580 
581     /**
582      * @param eventLogSourceName the eventLogSourceName to set
583      */
584     protected void setEventLogSourceName( String eventLogSourceName )
585     {
586         this.eventLogSourceName = eventLogSourceName;
587     }
588 
589     /**
590      * @return the eventLogSourceName
591      */
592     protected String getEventLogSourceName()
593     {
594         return eventLogSourceName;
595     }
596 }