package me.brandonc.security.totp.core;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.NamedThreadLocal;

/**
 * make one thread use one connection in the same time
 */
@Aspect
public class ConnectionManagementAspect {

	private final Logger logger = LoggerFactory.getLogger(ConnectionManagementAspect.class);

	ThreadLocal<Object> localConnection = new NamedThreadLocal<Object>("localConnection");
	ThreadLocal<Integer> localEntrend = new NamedThreadLocal<Integer>("localEntrend") {
		@Override
		protected Integer initialValue() {
			return 0;
		}
	};

	@Pointcut("within(me.brandonc.security.totp.repository.*)")
	public void inRepository() {
	}

	@SuppressAjWarnings("adviceDidNotMatch")
	@Around("call(* redis.clients.util.Pool.getResource()) && inRepository()")
	public Object getResource(ProceedingJoinPoint pjp) {
		Object connection = localConnection.get();
		if (connection == null) {
			logger.trace("create resource");
			try {
				connection = pjp.proceed();
				localConnection.set(connection);

			} catch (Throwable e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			logger.trace("use cached resource");
		}

		localEntrend.set(localEntrend.get().intValue() + 1);
		return connection;
	}

	@SuppressAjWarnings("adviceDidNotMatch")
	@Around("call(* redis.clients.util.Pool.returnResource(..)) && args(resource) && inRepository()")
	public void releaseResource(ProceedingJoinPoint pjp, Object resource) {

		int entrend = localEntrend.get().intValue();
		if (--entrend == 0) {
			try {
				logger.trace("remove cached resource");
				pjp.proceed(new Object[] { resource });
				localConnection.set(null);
				localEntrend.set(0);
			} catch (Throwable e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			localEntrend.set(entrend);
		}
	}
}

@@ -325,58 +325,8 @@
 ory;
-%0Aimport org.springframework.core.NamedThreadLocal;
 %0A%0A/*
@@ -527,18 +527,38 @@
 class);%0A
-%0A
 %09
+private static final 
 ThreadLo
@@ -587,29 +587,24 @@
 ction = new 
-Named
 ThreadLocal%3C
@@ -615,29 +615,33 @@
 ct%3E(
-%22localConnection%22);%0A%09
+);%0A%09private static final 
 Thre
@@ -680,13 +680,8 @@
 new 
-Named
 Thre
@@ -701,22 +701,8 @@
 er%3E(
-%22localEntrend%22
 ) %7B%0A
@@ -1389,27 +1389,16 @@
 nd.get()
-.intValue()
  + 1);%0A%09
@@ -1674,27 +1674,29 @@
 et()
-.intValue()
+;%0A%09%09entrend--
 ;%0A%09%09if (
 --en
@@ -1691,18 +1691,16 @@
 ;%0A%09%09if (
---
 entrend 

improve threadlocal usage