Transaction recording and rollback support for bind and rebind.
This commit is contained in:
@@ -1,88 +0,0 @@
|
||||
package org.springframework.ldap.support;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.DirContext;
|
||||
|
||||
import org.springframework.ldap.ContextSource;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionException;
|
||||
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
|
||||
import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
public class ContextSourceTransactionManager extends
|
||||
AbstractPlatformTransactionManager {
|
||||
|
||||
private ContextSource contextSource;
|
||||
|
||||
public void setContextSource(ContextSource contextSource) {
|
||||
this.contextSource = contextSource;
|
||||
}
|
||||
|
||||
public ContextSource getContextSource() {
|
||||
return contextSource;
|
||||
}
|
||||
|
||||
protected Object doGetTransaction() throws TransactionException {
|
||||
DirContextHolder contextHolder = (DirContextHolder) TransactionSynchronizationManager
|
||||
.getResource(this.contextSource);
|
||||
ContextSourceTransactionObject txObject = new ContextSourceTransactionObject(
|
||||
contextHolder);
|
||||
return txObject;
|
||||
}
|
||||
|
||||
protected void doBegin(Object transaction, TransactionDefinition definition)
|
||||
throws TransactionException {
|
||||
ContextSourceTransactionObject txObject = (ContextSourceTransactionObject) transaction;
|
||||
|
||||
if (txObject.getContextHolder() == null) {
|
||||
DirContext newCtx = getContextSource().getReadOnlyContext();
|
||||
DirContextHolder contextHolder = new DirContextHolder(newCtx);
|
||||
|
||||
txObject.setContextHolder(contextHolder);
|
||||
TransactionSynchronizationManager.bindResource(getContextSource(),
|
||||
contextHolder);
|
||||
}
|
||||
}
|
||||
|
||||
protected void doCommit(DefaultTransactionStatus status)
|
||||
throws TransactionException {
|
||||
// Nothing much to do here.
|
||||
}
|
||||
|
||||
protected void doRollback(DefaultTransactionStatus status)
|
||||
throws TransactionException {
|
||||
// Perform compensating transaction cleanup using information stored in
|
||||
// ContextHolder.
|
||||
}
|
||||
|
||||
protected void doCleanupAfterCompletion(Object transaction) {
|
||||
ContextSourceTransactionObject txObject = (ContextSourceTransactionObject) transaction;
|
||||
TransactionSynchronizationManager.unbindResource(contextSource);
|
||||
DirContext ctx = txObject.getContextHolder().getCtx();
|
||||
|
||||
try {
|
||||
ctx.close();
|
||||
} catch (NamingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
static class ContextSourceTransactionObject {
|
||||
private DirContextHolder contextHolder;
|
||||
|
||||
public ContextSourceTransactionObject(DirContextHolder contextHolder) {
|
||||
this.contextHolder = contextHolder;
|
||||
}
|
||||
|
||||
public DirContextHolder getContextHolder() {
|
||||
return contextHolder;
|
||||
}
|
||||
|
||||
public void setContextHolder(DirContextHolder contextHolder) {
|
||||
this.contextHolder = contextHolder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package org.springframework.ldap.support;
|
||||
|
||||
import javax.naming.directory.DirContext;
|
||||
|
||||
import org.springframework.transaction.support.ResourceHolderSupport;
|
||||
|
||||
public class DirContextHolder extends ResourceHolderSupport {
|
||||
private DirContext ctx;
|
||||
|
||||
public void setCtx(DirContext ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
public DirContextHolder(DirContext ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
public DirContext getCtx() {
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package org.springframework.ldap.support;
|
||||
|
||||
import javax.naming.directory.DirContext;
|
||||
|
||||
public interface DirContextProxy {
|
||||
DirContext getTargetContext();
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
package org.springframework.ldap.support;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.DirContext;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.ldap.ContextSource;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
public class TransactionAwareContextSourceProxy implements ContextSource {
|
||||
|
||||
private ContextSource target;
|
||||
|
||||
public TransactionAwareContextSourceProxy(ContextSource target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public DirContext getReadOnlyContext() throws DataAccessException {
|
||||
DirContextHolder contextHolder = (DirContextHolder) TransactionSynchronizationManager
|
||||
.getResource(target);
|
||||
DirContext ctx = null;
|
||||
|
||||
if (contextHolder != null) {
|
||||
ctx = contextHolder.getCtx();
|
||||
}
|
||||
|
||||
if (ctx == null) {
|
||||
ctx = target.getReadOnlyContext();
|
||||
if (contextHolder != null) {
|
||||
contextHolder.setCtx(ctx);
|
||||
}
|
||||
}
|
||||
return getTransactionAwareDirContextProxy(ctx, target);
|
||||
}
|
||||
|
||||
private DirContext getTransactionAwareDirContextProxy(DirContext context,
|
||||
ContextSource target) {
|
||||
return (DirContext) Proxy
|
||||
.newProxyInstance(DirContextProxy.class.getClassLoader(),
|
||||
new Class[] { DirContextProxy.class },
|
||||
new TransactionAwareDirContextInvocationHandler(
|
||||
context, target));
|
||||
|
||||
}
|
||||
|
||||
public DirContext getReadWriteContext() throws DataAccessException {
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
}
|
||||
|
||||
static class TransactionAwareDirContextInvocationHandler implements
|
||||
InvocationHandler {
|
||||
private DirContext target;
|
||||
|
||||
private ContextSource contextSource;
|
||||
|
||||
public TransactionAwareDirContextInvocationHandler(DirContext target,
|
||||
ContextSource contextSource) {
|
||||
this.target = target;
|
||||
this.contextSource = contextSource;
|
||||
}
|
||||
|
||||
public Object invoke(Object proxy, Method method, Object[] args)
|
||||
throws Throwable {
|
||||
|
||||
if (method.getName().equals("getTargetContext")) {
|
||||
return target;
|
||||
} else if (method.getName().equals("equals")) {
|
||||
// Only consider equal when proxies are identical.
|
||||
return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE);
|
||||
} else if (method.getName().equals("hashCode")) {
|
||||
// Use hashCode of Connection proxy.
|
||||
return new Integer(hashCode());
|
||||
} else if (method.getName().equals("close")) {
|
||||
doCloseConnection(target, contextSource);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return method.invoke(target, args);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw e.getTargetException();
|
||||
}
|
||||
}
|
||||
|
||||
private void doCloseConnection(DirContext context,
|
||||
ContextSource contextSource) throws NamingException {
|
||||
DirContextHolder transactionContextHolder = (DirContextHolder) TransactionSynchronizationManager
|
||||
.getResource(contextSource);
|
||||
if (transactionContextHolder == null
|
||||
|| transactionContextHolder.getCtx() != context) {
|
||||
// This is not the transactional context or the transaction is
|
||||
// no longer active - we should close it.
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user