package org.springframework.versions.interceptors; import internal.org.springframework.versions.AuthenticationFacade; import internal.org.springframework.versions.LockingService; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.springframework.data.util.ReflectionUtils; import org.springframework.util.Assert; import org.springframework.versions.LockOwnerException; import org.springframework.versions.LockParticipant; import javax.persistence.Id; import java.lang.reflect.Field; import static java.lang.String.format; public class PessimisticLockingInterceptor implements MethodInterceptor { private LockingService locker; private AuthenticationFacade auth; private static final ReflectionUtils.AnnotationFieldFilter ID_FILTER = new ReflectionUtils.AnnotationFieldFilter(Id.class); private static final ReflectionUtils.AnnotationFieldFilter DATA_ID_FILTER = new ReflectionUtils.AnnotationFieldFilter(org.springframework.data.annotation.Id.class); public PessimisticLockingInterceptor(LockingService locker, AuthenticationFacade auth) { Assert.notNull(locker, "locker cannot be null"); Assert.notNull(auth, "auth cannot be null"); this.locker = locker; this.auth = auth; } @Override public Object invoke(MethodInvocation invocation) throws Throwable { LockParticipant participant = invocation.getMethod().getAnnotation(LockParticipant.class); if (participant != null) { return invokeWithIntecept(invocation); } return invocation.proceed(); } private Object invokeWithIntecept(MethodInvocation invocation) throws Throwable { Object entity = invocation.getArguments()[0]; Field idField = ReflectionUtils.findField(entity.getClass(), ID_FILTER); if (idField == null) { idField = ReflectionUtils.findField(entity.getClass(), DATA_ID_FILTER); } if (idField == null) { return invocation.proceed(); } org.springframework.util.ReflectionUtils.makeAccessible(idField); Object id = org.springframework.util.ReflectionUtils.getField(idField, entity); if (locker.lockOwner(id) == null || locker.isLockOwner(id, auth.getAuthentication())) { return invocation.proceed(); } else { throw new LockOwnerException("Not lock owner"); } } }