Transaction recording and rollback support for bind and rebind.

This commit is contained in:
Mattias Arthursson
2006-12-26 14:27:45 +00:00
parent a658f81bdd
commit 7904af3492
4 changed files with 0 additions and 218 deletions

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}

View File

@@ -1,7 +0,0 @@
package org.springframework.ldap.support;
import javax.naming.directory.DirContext;
public interface DirContextProxy {
DirContext getTargetContext();
}

View File

@@ -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();
}
}
}
}