All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.infinispan.jcache.JCacheNotifier Maven / Gradle / Ivy

There is a newer version: 9.1.7.Final
Show newest version
package org.infinispan.jcache;

import org.infinispan.AdvancedCache;
import org.infinispan.commons.util.CollectionFactory;
import org.infinispan.jcache.logging.Log;
import org.infinispan.util.logging.LogFactory;

import javax.cache.Cache;
import javax.cache.configuration.CacheEntryListenerConfiguration;
import javax.cache.configuration.Factory;
import javax.cache.event.CacheEntryCreatedListener;
import javax.cache.event.CacheEntryEvent;
import javax.cache.event.CacheEntryEventFilter;
import javax.cache.event.CacheEntryExpiredListener;
import javax.cache.event.CacheEntryListener;
import javax.cache.event.CacheEntryRemovedListener;
import javax.cache.event.CacheEntryUpdatedListener;
import javax.cache.event.EventType;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * JCache notifications dispatcher.
 *
 * TODO: Deal with asynchronous listeners...
 *
 * @author Galder Zamarreño
 * @since 5.3
 */
public class JCacheNotifier {

   private static final Log log =
         LogFactory.getLog(JCacheNotifier.class, Log.class);

   private static final boolean isTrace = log.isTraceEnabled();

   // Traversals are a not more common than mutations when it comes to
   // keeping track of registered listeners, so use copy-on-write lists.

   private final List> createdListeners =
         new CopyOnWriteArrayList>();

   private final List> updatedListeners =
         new CopyOnWriteArrayList>();

   private final List> removedListeners =
         new CopyOnWriteArrayList>();

   private final List> expiredListeners =
         new CopyOnWriteArrayList>();

   private final ConcurrentMap, CacheEntryListenerConfiguration> listenerCfgs =
         CollectionFactory.makeConcurrentMap();

   private JCacheListenerAdapter listenerAdapter;

   public void addListener(CacheEntryListenerConfiguration reg,
         Cache jcache, JCacheNotifier notifier, AdvancedCache cache) {
      boolean addListenerAdapter = listenerCfgs.isEmpty();
      addListener(reg, false);

      if (addListenerAdapter) {
         listenerAdapter = new JCacheListenerAdapter(jcache, notifier);
         cache.addListener(listenerAdapter);
      }
   }

   public void removeListener(CacheEntryListenerConfiguration reg,
         AdvancedCache cache) {
      removeListener(reg);

      if (listenerCfgs.isEmpty())
         cache.removeListener(listenerAdapter);
   }

   public void notifyEntryCreated(Cache cache, K key, V value) {
      if (!createdListeners.isEmpty()) {
         List> events =
               createEvent(cache, key, value, EventType.CREATED);
         for (CacheEntryCreatedListener listener : createdListeners)
            listener.onCreated(getEntryIterable(events, listenerCfgs.get(listener)));
      }
   }

   public void notifyEntryUpdated(Cache cache, K key, V value) {
      if (!updatedListeners.isEmpty()) {
         List> events =
               createEvent(cache, key, value, EventType.UPDATED);
         for (CacheEntryUpdatedListener listener : updatedListeners)
            listener.onUpdated(getEntryIterable(events, listenerCfgs.get(listener)));
      }
   }

   public void notifyEntryRemoved(Cache cache, K key, V value) {
      if (!removedListeners.isEmpty()) {
         List> events =
               createEvent(cache, key, value, EventType.REMOVED);
         for (CacheEntryRemovedListener listener : removedListeners) {
            listener.onRemoved(getEntryIterable(events, listenerCfgs.get(listener)));
         }
      }
   }

   public void notifyEntryExpired(Cache cache, K key, V value) {
      if (!expiredListeners.isEmpty()) {
         List> events =
               createEvent(cache, key, value, EventType.EXPIRED);
         for (CacheEntryExpiredListener listener : expiredListeners) {
            listener.onExpired(getEntryIterable(events, listenerCfgs.get(listener)));
         }
      }
   }

   private Iterable> getEntryIterable(
         List> events,
         CacheEntryListenerConfiguration listenerCfg) {
      Factory> factory = listenerCfg.getCacheEntryEventFilterFactory();
      if (factory != null) {
         CacheEntryEventFilter filter = factory.create();
         return filter == null  ? events
               : new JCacheEventFilteringIterable(events, filter);
      }

      return events;
   }

   @SuppressWarnings("unchecked")
   private boolean addListener(CacheEntryListenerConfiguration listenerCfg, boolean addIfAbsent) {
      boolean added = false;
      CacheEntryListener listener =
            listenerCfg.getCacheEntryListenerFactory().create();
      if (listener instanceof CacheEntryCreatedListener)
         added = !containsListener(addIfAbsent, listener, createdListeners)
               && createdListeners.add((CacheEntryCreatedListener) listener);

      if (listener instanceof CacheEntryUpdatedListener)
         added = !containsListener(addIfAbsent, listener, updatedListeners)
               && updatedListeners.add((CacheEntryUpdatedListener) listener);

      if (listener instanceof CacheEntryRemovedListener)
         added = !containsListener(addIfAbsent, listener, removedListeners)
               && removedListeners.add((CacheEntryRemovedListener) listener);

      if (listener instanceof CacheEntryExpiredListener)
         added = !containsListener(addIfAbsent, listener, expiredListeners)
               && expiredListeners.add((CacheEntryExpiredListener) listener);

      if (added)
         listenerCfgs.put(listener, listenerCfg);

      return added;
   }

   private boolean containsListener(boolean addIfAbsent,
         CacheEntryListener listenerToAdd,
         List> listeners) {
      // If add only if no listener present, check the listeners collection
      if (addIfAbsent) {
         for (CacheEntryListener listener : listeners) {
            if (listener.equals(listenerToAdd))
               return true;
         }
      }

      return false;
   }

   @SuppressWarnings("unchecked")
   private void removeListener(CacheEntryListenerConfiguration listenerCfg) {
      for (Map.Entry, CacheEntryListenerConfiguration> entry : listenerCfgs.entrySet()) {
         CacheEntryListenerConfiguration cfg = entry.getValue();
         if (cfg.equals(listenerCfg)) {
            CacheEntryListener listener = entry.getKey();
            if (listener instanceof CacheEntryCreatedListener)
               createdListeners.remove(listener);

            if (listener instanceof CacheEntryUpdatedListener)
               updatedListeners.remove(listener);

            if (listener instanceof CacheEntryRemovedListener)
               removedListeners.remove(listener);

            if (listener instanceof CacheEntryExpiredListener)
               expiredListeners.remove(listener);
         }
      }
   }


   private List> createEvent(
         Cache cache, K key, V value, EventType eventType) {
      List> events =
            Collections.>singletonList(
                  new RICacheEntryEvent(cache, key, value, eventType));
      if (isTrace) log.tracef("Received event: %s", events);
      return events;
   }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy