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

io.mongock.driver.api.lock.guard.proxy.LockGuardProxyFactory Maven / Gradle / Ivy

The newest version!
package io.mongock.driver.api.lock.guard.proxy;

import io.changock.migration.api.annotations.NonLockGuarded;
import io.mongock.driver.api.lock.LockManager;
import io.mongock.utils.Constants;
import io.mongock.utils.JdkUtil;
import javassist.util.proxy.ProxyFactory;
import org.objenesis.ObjenesisStd;

import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

public class LockGuardProxyFactory {

  private static final Set DEFAULT_NON_GUARDED_METHODS = new HashSet<>(
      Collections.singletonList("finalize")
  );

  static {
    ProxyFactory.nameGenerator = new ProxyFactory.UniqueName() {
      private final String sep = Constants.PROXY_MONGOCK_PREFIX + Integer.toHexString(this.hashCode() & 0xfff) + "_";
      private int counter = 0;

      @Override
      public String get(String classname) {
        return classname + sep + Integer.toHexString(counter++);
      }
    };
  }

  private final LockManager lockManager;
  private final Collection notProxiedPackagePrefixes;
  private final Set nonGuardedMethods;
  private final boolean lockGuardEnabled;

  public LockGuardProxyFactory(LockManager lockManager, boolean lockGuardEnabled) {
    this(lockManager, Collections.emptyList(), DEFAULT_NON_GUARDED_METHODS, lockGuardEnabled);
  }

  public LockGuardProxyFactory(LockManager lockManager, Collection notProxiedPackagePrefixes, boolean lockGuardEnabled) {
    this(lockManager, notProxiedPackagePrefixes, DEFAULT_NON_GUARDED_METHODS, lockGuardEnabled);
  }

  public LockGuardProxyFactory(LockManager lockManager, Collection notProxiedPackagePrefixes, Set nonGuardedMethods, boolean lockGuardEnabled) {
    this.lockManager = lockManager;
    this.notProxiedPackagePrefixes = notProxiedPackagePrefixes;
    this.nonGuardedMethods = nonGuardedMethods;
    this.lockGuardEnabled = lockGuardEnabled;
  }

  @SuppressWarnings("unchecked")
  public  T getProxy(T targetObject, Class interfaceType) {
    return (T) getRawProxy(targetObject, interfaceType);
  }

  @SuppressWarnings("unchecked")
  public Object getRawProxy(Object targetObject, Class interfaceType) {
    return shouldBeLockGuardProxied(targetObject, interfaceType) ? createProxy(targetObject, interfaceType) : targetObject;
  }

  //TODO add here check
  private boolean shouldBeLockGuardProxied(Object targetObject, Class interfaceType) {

    return targetObject != null
        && lockGuardEnabled
        && !Modifier.isFinal(interfaceType.getModifiers())
        && isPackageProxiable(interfaceType.getPackage().getName())
        && !interfaceType.isAnnotationPresent(NonLockGuarded.class)
        && !targetObject.getClass().isAnnotationPresent(NonLockGuarded.class)
        && !JdkUtil.isInternalJdkClass(targetObject.getClass())
        && !JdkUtil.isInternalJdkClass(interfaceType);
  }

  private boolean isPackageProxiable(String packageName) {
    return notProxiedPackagePrefixes.stream().noneMatch(packageName::startsWith);
  }

  private Object createProxy(Object impl, Class type) {

    ProxyFactory proxyFactory = new ProxyFactory();
    if (type.isInterface()) {
      proxyFactory.setInterfaces(new Class[]{type});
    } else {
      proxyFactory.setSuperclass(type);
    }

    Object proxyInstance = new ObjenesisStd()
        .getInstantiatorOf(proxyFactory.createClass())
        .newInstance();

    ((javassist.util.proxy.Proxy) proxyInstance).setHandler(new LockGuardMethodHandler<>(impl, lockManager, this, nonGuardedMethods));
    return proxyInstance;
  }

  public static boolean isProxy(Object obj) {
    return isProxyClass(obj.getClass());
  }

  public static boolean isProxyClass(Class c) {
    return Proxy.isProxyClass(c) || ProxyFactory.isProxyClass(c);
  }

  public static void checkProxy(Object obj) {
    if(!isProxyClass(obj.getClass())) {
      throw new RuntimeException("Is not proxy");
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy