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

org.hibernate.cache.infinispan.impl.ClassLoaderAwareCache Maven / Gradle / Ivy

There is a newer version: 5.6.15.Final
Show newest version
package org.hibernate.cache.infinispan.impl;

import java.lang.annotation.Annotation;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.infinispan.AbstractDelegatingAdvancedCache;
import org.infinispan.AdvancedCache;
import org.infinispan.commands.VisitableCommand;
import org.infinispan.context.InvocationContext;
import org.infinispan.interceptors.base.CommandInterceptor;
import org.infinispan.notifications.Listener;
import org.infinispan.notifications.cachelistener.annotation.CacheEntryActivated;
import org.infinispan.notifications.cachelistener.annotation.CacheEntryCreated;
import org.infinispan.notifications.cachelistener.annotation.CacheEntryEvicted;
import org.infinispan.notifications.cachelistener.annotation.CacheEntryInvalidated;
import org.infinispan.notifications.cachelistener.annotation.CacheEntryLoaded;
import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified;
import org.infinispan.notifications.cachelistener.annotation.CacheEntryPassivated;
import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved;
import org.infinispan.notifications.cachelistener.annotation.CacheEntryVisited;
import org.infinispan.notifications.cachelistener.event.Event;
import org.infinispan.stats.Stats;

/**
 * @author Paul Ferraro
 */
public class ClassLoaderAwareCache extends AbstractDelegatingAdvancedCache {
   final WeakReference classLoaderRef;

   public ClassLoaderAwareCache(AdvancedCache cache, ClassLoader classLoader) {
      super(cache);
      this.classLoaderRef = new WeakReference(classLoader);
      cache.removeInterceptor(ClassLoaderAwareCommandInterceptor.class);
      cache.addInterceptor(new ClassLoaderAwareCommandInterceptor(), 0);
   }

   @Override
   public Stats getStats() {
      return this.getAdvancedCache().getStats();
   }

   @Override
   public void stop() {
      super.stop();
      this.classLoaderRef.clear();
   }

   @Override
   public void addListener(Object listener) {
      super.addListener(new ClassLoaderAwareListener(listener, this));
   }

   void setContextClassLoader(final ClassLoader classLoader) {
      PrivilegedAction action = new PrivilegedAction() {
         @Override
         public Void run() {
            Thread.currentThread().setContextClassLoader(classLoader);
            return null;
         }
      };
      AccessController.doPrivileged(action);
   }

   private class ClassLoaderAwareCommandInterceptor extends CommandInterceptor {
      @Override
      protected Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable {
         ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
         ClassLoaderAwareCache.this.setContextClassLoader(ClassLoaderAwareCache.this.classLoaderRef.get());
         try {
            return super.handleDefault(ctx, command);
         }
         finally {
            ClassLoaderAwareCache.this.setContextClassLoader(classLoader);
         }
      }
   }

   static final Map, Event.Type> events = new HashMap, Event.Type>();

   static {
      events.put(CacheEntryActivated.class, Event.Type.CACHE_ENTRY_ACTIVATED);
      events.put(CacheEntryCreated.class, Event.Type.CACHE_ENTRY_CREATED);
      events.put(CacheEntryEvicted.class, Event.Type.CACHE_ENTRY_EVICTED);
      events.put(CacheEntryInvalidated.class, Event.Type.CACHE_ENTRY_INVALIDATED);
      events.put(CacheEntryLoaded.class, Event.Type.CACHE_ENTRY_LOADED);
      events.put(CacheEntryModified.class, Event.Type.CACHE_ENTRY_MODIFIED);
      events.put(CacheEntryPassivated.class, Event.Type.CACHE_ENTRY_PASSIVATED);
      events.put(CacheEntryRemoved.class, Event.Type.CACHE_ENTRY_REMOVED);
      events.put(CacheEntryVisited.class, Event.Type.CACHE_ENTRY_VISITED);
   }

   @Listener
   public static class ClassLoaderAwareListener {
      private final Object listener;
      private final Map> methods = new EnumMap>(Event.Type.class);
      private final ClassLoaderAwareCache cache;

      public ClassLoaderAwareListener(Object listener, ClassLoaderAwareCache cache) {
         this.listener = listener;
         this.cache = cache;
         for (Method method : listener.getClass().getMethods()) {
            for (Map.Entry, Event.Type> entry : events.entrySet()) {
               Class annotation = entry.getKey();
               if (method.isAnnotationPresent(annotation)) {
                  List methods = this.methods.get(entry.getValue());
                  if (methods == null) {
                     methods = new LinkedList();
                     this.methods.put(entry.getValue(), methods);
                  }
                  methods.add(method);
               }
            }
         }
      }

      @CacheEntryActivated
      @CacheEntryCreated
      @CacheEntryEvicted
      @CacheEntryInvalidated
      @CacheEntryLoaded
      @CacheEntryModified
      @CacheEntryPassivated
      @CacheEntryRemoved
      @CacheEntryVisited
      public void event(Event event) throws Throwable {
         List methods = this.methods.get(event.getType());
         if (methods != null) {
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            ClassLoader visible = (ClassLoader) cache.classLoaderRef.get();
            cache.setContextClassLoader(visible);
            try {
               for (Method method : this.methods.get(event.getType())) {
                  try {
                     method.invoke(this.listener, event);
                  }
                  catch (InvocationTargetException e) {
                     throw e.getCause();
                  }
               }
            }
            finally {
               cache.setContextClassLoader(classLoader);
            }
         }
      }

      public int hashCode() {
         return this.listener.hashCode();
      }

      public boolean equals(Object object) {
         if (object == null) return false;
         if (object instanceof ClassLoaderAwareCache.ClassLoaderAwareListener) {
            @SuppressWarnings("unchecked")
            ClassLoaderAwareListener listener = (ClassLoaderAwareListener) object;
            return this.listener.equals(listener.listener);
         }
         return this.listener.equals(object);
      }
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy