<groupId>org.argeo.tp.javax</groupId>
<artifactId>javax.enterprise.cdi-api</artifactId>
</dependency>
+
+ <!-- JTA is still indirectly required by Jackrabbit -->
<dependency>
<groupId>org.argeo.tp.javax</groupId>
<artifactId>javax.transaction-api</artifactId>
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="User Admin Wrapper">
<implementation class="org.argeo.cms.e4.users.UserAdminWrapper"/>
- <reference bind="setUserTransaction" cardinality="1..1" interface="javax.transaction.UserTransaction" name="UserTransaction" policy="static"/>
+ <reference bind="setUserTransaction" cardinality="1..1" interface="org.argeo.osgi.transaction.WorkTransaction" name="UserTransaction" policy="static"/>
<reference bind="setUserAdmin" cardinality="1..1" interface="org.osgi.service.useradmin.UserAdmin" name="UserAdmin" policy="static"/>
<service>
<provide interface="org.argeo.cms.e4.users.UserAdminWrapper"/>
import javax.inject.Inject;
import javax.naming.InvalidNameException;
import javax.naming.ldap.LdapName;
-import javax.transaction.UserTransaction;
import org.argeo.api.security.CryptoKeyring;
import org.argeo.cms.CmsException;
import org.argeo.cms.auth.CurrentUser;
import org.argeo.cms.ui.dialogs.CmsMessageDialog;
import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
+import org.argeo.osgi.transaction.WorkTransaction;
import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.jface.dialogs.Dialog;
@Inject
private UserAdmin userAdmin;
@Inject
- private UserTransaction userTransaction;
+ private WorkTransaction userTransaction;
@Inject
@Optional
private CryptoKeyring keyring = null;
import javax.jcr.Session;
import javax.naming.InvalidNameException;
import javax.naming.ldap.LdapName;
-import javax.transaction.UserTransaction;
import org.argeo.api.NodeConstants;
import org.argeo.api.NodeInstance;
import org.argeo.eclipse.ui.parts.LdifUsersTable;
import org.argeo.jcr.JcrUtils;
import org.argeo.naming.LdapAttrs;
+import org.argeo.osgi.transaction.WorkTransaction;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ToolBarManager;
userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_CHANGED, myGroup));
} else if (role.getType() == Role.USER) {
// TODO check if the group is already member of this group
- UserTransaction transaction = userAdminWrapper.beginTransactionIfNeeded();
+ WorkTransaction transaction = userAdminWrapper.beginTransactionIfNeeded();
User user = (User) role;
myGroup.addMember(user);
if (UserAdminWrapper.COMMIT_ON_SAVE)
package org.argeo.cms.e4.users;
-import javax.transaction.UserTransaction;
+import org.argeo.osgi.transaction.WorkTransaction;
/** First effort to centralize back end methods used by the user admin UI */
public class UiAdminUtils {
*/
/** Easily notify the ActiveWindow that the transaction had a state change */
public final static void notifyTransactionStateChange(
- UserTransaction userTransaction) {
+ WorkTransaction userTransaction) {
// try {
// IWorkbenchWindow aww = PlatformUI.getWorkbench()
// .getActiveWorkbenchWindow();
import java.util.List;
import java.util.Map;
-import javax.transaction.Status;
-import javax.transaction.UserTransaction;
-
import org.argeo.api.NodeConstants;
import org.argeo.cms.CmsException;
+import org.argeo.osgi.transaction.WorkTransaction;
import org.argeo.osgi.useradmin.UserAdminConf;
import org.argeo.osgi.useradmin.UserDirectory;
import org.osgi.service.useradmin.UserAdmin;
// private Set<String> uris;
private Map<UserDirectory, Hashtable<String, String>> userDirectories = Collections
.synchronizedMap(new LinkedHashMap<>());
- private UserTransaction userTransaction;
+ private WorkTransaction userTransaction;
// First effort to simplify UX while managing users and groups
public final static boolean COMMIT_ON_SAVE = true;
* {@link UserAdminWrapper#commitOrNotifyTransactionStateChange()} once the
* security model changes have been performed.
*/
- public UserTransaction beginTransactionIfNeeded() {
+ public WorkTransaction beginTransactionIfNeeded() {
try {
// UserTransaction userTransaction = getUserTransaction();
- if (userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION) {
+ if (userTransaction.isNoTransactionStatus()) {
userTransaction.begin();
// UiAdminUtils.notifyTransactionStateChange(userTransaction);
}
public void commitOrNotifyTransactionStateChange() {
try {
// UserTransaction userTransaction = getUserTransaction();
- if (userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION)
+ if (userTransaction.isNoTransactionStatus())
return;
if (UserAdminWrapper.COMMIT_ON_SAVE)
return userAdmin;
}
- public UserTransaction getUserTransaction() {
+ public WorkTransaction getUserTransaction() {
return userTransaction;
}
// this.uris = Collections.unmodifiableSortedSet(new TreeSet<>(properties.keySet()));
}
- public void setUserTransaction(UserTransaction userTransaction) {
+ public void setUserTransaction(WorkTransaction userTransaction) {
this.userTransaction = userTransaction;
}
import java.util.List;
import java.util.Map;
-import javax.transaction.SystemException;
-import javax.transaction.UserTransaction;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.argeo.api.NodeConstants;
import org.argeo.eclipse.ui.parts.LdifUsersTable;
import org.argeo.naming.LdapAttrs;
import org.argeo.naming.LdapObjs;
+import org.argeo.osgi.transaction.WorkTransaction;
import org.eclipse.jface.dialogs.IPageChangeProvider;
import org.eclipse.jface.dialogs.IPageChangedListener;
import org.eclipse.jface.dialogs.MessageDialog;
public boolean performFinish() {
if (!canFinish())
return false;
- UserTransaction ut = userAdminWrapper.getUserTransaction();
- try {
- if (ut.getStatus() != javax.transaction.Status.STATUS_NO_TRANSACTION
- && !MessageDialog.openConfirm(getShell(), "Existing Transaction",
- "A user transaction is already existing, " + "are you sure you want to proceed ?"))
- return false;
- } catch (SystemException e) {
- throw new CmsException("Cannot get user transaction state " + "before user batch update", e);
- }
+ WorkTransaction ut = userAdminWrapper.getUserTransaction();
+ if (!ut.isNoTransactionStatus() && !MessageDialog.openConfirm(getShell(), "Existing Transaction",
+ "A user transaction is already existing, " + "are you sure you want to proceed ?"))
+ return false;
// We cannot use jobs, user modifications are still meant to be done in
// the UIThread
} catch (Exception e) {
throw new CmsException("Cannot perform batch update on users", e);
} finally {
- UserTransaction ut = userAdminWrapper.getUserTransaction();
- try {
- if (ut.getStatus() != javax.transaction.Status.STATUS_NO_TRANSACTION)
- ut.rollback();
- } catch (IllegalStateException | SecurityException | SystemException e) {
- log.error("Unable to rollback session in 'finally', " + "the system might be in a dirty state");
- e.printStackTrace();
- }
+ WorkTransaction ut = userAdminWrapper.getUserTransaction();
+ if (!ut.isNoTransactionStatus())
+ ut.rollback();
}
}
}
} catch (Exception e) {
throw new CmsException("Cannot perform batch update on users", e);
} finally {
- UserTransaction ut = userAdminWrapper.getUserTransaction();
- try {
- if (ut.getStatus() != javax.transaction.Status.STATUS_NO_TRANSACTION)
- ut.rollback();
- } catch (IllegalStateException | SecurityException | SystemException e) {
- log.error("Unable to rollback session in finally block, the system might be in a dirty state");
- e.printStackTrace();
- }
+ WorkTransaction ut = userAdminWrapper.getUserTransaction();
+ if (!ut.isNoTransactionStatus())
+ ut.rollback();
}
}
}
}
/**
- * Displays a list of users with a check box to be able to choose some of
- * them
+ * Displays a list of users with a check box to be able to choose some of them
*/
private class ChooseUsersWizardPage extends WizardPage implements IPageChangedListener {
private static final long serialVersionUID = 7651807402211214274L;
public void testWriteReadCsv() throws Exception {
// session().setNamespacePrefix("argeo", ArgeoNames.ARGEO_NAMESPACE);
- InputStreamReader reader = new InputStreamReader(getClass().getResourceAsStream("/org/argeo/api/ldap.cnd"));
+ InputStreamReader reader = new InputStreamReader(getClass().getResourceAsStream("/org/argeo/cms/jcr/ldap.cnd"));
CndImporter.registerNodeTypes(reader, session());
reader.close();
- reader = new InputStreamReader(getClass().getResourceAsStream("/org/argeo/cms/argeo.cnd"));
+ reader = new InputStreamReader(getClass().getResourceAsStream("/org/argeo/cms/jcr/argeo.cnd"));
CndImporter.registerNodeTypes(reader, session());
reader.close();
// reader = new InputStreamReader(getClass().getResourceAsStream("/org/argeo/cms/cms.cnd"));
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
-import javax.transaction.UserTransaction;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.argeo.jcr.Jcr;
import org.argeo.jcr.JcrUtils;
import org.argeo.naming.Distinguished;
+import org.argeo.osgi.transaction.WorkTransaction;
import org.osgi.service.useradmin.Group;
import org.osgi.service.useradmin.Role;
import org.osgi.service.useradmin.UserAdmin;
private Repository repository;
// private UserAdminService userAdminService;
private UserAdmin userAdmin;
- private UserTransaction userTransaction;
+ private WorkTransaction userTransaction;
public void init() {
makeSureRolesExists(getRequiredRoles());
// this.userAdminService = userAdminService;
// }
- protected UserTransaction getUserTransaction() {
+ protected WorkTransaction getUserTransaction() {
return userTransaction;
}
this.userAdmin = userAdmin;
}
- public void setUserTransaction(UserTransaction userTransaction) {
+ public void setUserTransaction(WorkTransaction userTransaction) {
this.userTransaction = userTransaction;
}
import javax.naming.InvalidNameException;
import javax.naming.ldap.LdapName;
-import javax.transaction.UserTransaction;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.argeo.osgi.transaction.WorkTransaction;
import org.osgi.service.useradmin.Role;
import org.osgi.service.useradmin.UserAdmin;
private String role;
private List<String> roles = new ArrayList<String>();
private UserAdmin userAdmin;
- private UserTransaction userTransaction;
+ private WorkTransaction userTransaction;
@Override
public void run() {
this.userAdmin = userAdminService;
}
- public void setUserTransaction(UserTransaction userTransaction) {
+ public void setUserTransaction(WorkTransaction userTransaction) {
this.userTransaction = userTransaction;
}
<provide interface="org.argeo.cms.CmsUserManager"/>
</service>
<reference bind="setUserAdmin" cardinality="1..1" interface="org.osgi.service.useradmin.UserAdmin" name="UserAdmin" policy="static"/>
- <reference bind="setUserTransaction" cardinality="1..1" interface="javax.transaction.UserTransaction" name="UserTransaction" policy="static"/>
+ <reference bind="setUserTransaction" cardinality="1..1" interface="org.argeo.osgi.transaction.WorkTransaction" name="UserTransaction" policy="static"/>
<reference bind="addUserDirectory" cardinality="0..n" interface="org.argeo.osgi.useradmin.UserDirectory" name="UserDirectory" policy="static" unbind="removeUserDirectory"/>
-</scr:component>
\ No newline at end of file
+</scr:component>
import java.util.Set;
import javax.security.auth.Subject;
-import javax.transaction.UserTransaction;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.useradmin.Role;
import org.osgi.service.useradmin.User;
-import org.osgi.service.useradmin.UserAdmin;
/**
* Provide method interfaces to manage user concepts without accessing directly
// User createUserFromPerson(Node person);
- @Deprecated
- public UserAdmin getUserAdmin();
-
- @Deprecated
- public UserTransaction getUserTransaction();
+// @Deprecated
+// public UserAdmin getUserAdmin();
+//
+// @Deprecated
+// public UserTransaction getUserTransaction();
}
\ No newline at end of file
import javax.naming.InvalidNameException;
import javax.naming.ldap.LdapName;
import javax.security.auth.Subject;
-import javax.transaction.Status;
-import javax.transaction.UserTransaction;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.argeo.naming.LdapAttrs;
import org.argeo.naming.NamingUtils;
import org.argeo.naming.SharedSecret;
+import org.argeo.osgi.transaction.WorkTransaction;
import org.argeo.osgi.useradmin.TokenUtils;
import org.argeo.osgi.useradmin.UserAdminConf;
import org.argeo.osgi.useradmin.UserDirectory;
private UserAdmin userAdmin;
// private Map<String, String> serviceProperties;
- private UserTransaction userTransaction;
+ private WorkTransaction userTransaction;
private Map<UserDirectory, Hashtable<String, String>> userDirectories = Collections
.synchronizedMap(new LinkedHashMap<>());
return tokenStr;
} catch (Exception e1) {
try {
- if (userTransaction.getStatus() != Status.STATUS_NO_TRANSACTION)
+ if (!userTransaction.isNoTransactionStatus())
userTransaction.rollback();
} catch (Exception e2) {
if (log.isTraceEnabled())
log.debug("Token " + token + " expired.");
} catch (Exception e1) {
try {
- if (userTransaction.getStatus() != Status.STATUS_NO_TRANSACTION)
+ if (!userTransaction.isNoTransactionStatus())
userTransaction.rollback();
} catch (Exception e2) {
if (log.isTraceEnabled())
userTransaction.commit();
} catch (Exception e1) {
try {
- if (userTransaction.getStatus() != Status.STATUS_NO_TRANSACTION)
+ if (!userTransaction.isNoTransactionStatus())
userTransaction.rollback();
} catch (Exception e2) {
if (log.isTraceEnabled())
return userAdmin;
}
- public UserTransaction getUserTransaction() {
- return userTransaction;
- }
+// public UserTransaction getUserTransaction() {
+// return userTransaction;
+// }
/* DEPENDENCY INJECTION */
public void setUserAdmin(UserAdmin userAdmin) {
// this.serviceProperties = serviceProperties;
}
- public void setUserTransaction(UserTransaction userTransaction) {
+ public void setUserTransaction(WorkTransaction userTransaction) {
this.userTransaction = userTransaction;
}
-
+
public void addUserDirectory(UserDirectory userDirectory, Map<String, String> properties) {
userDirectories.put(userDirectory, new Hashtable<>(properties));
}
import java.net.URL;
import java.util.Dictionary;
-import javax.transaction.UserTransaction;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.argeo.api.NodeConstants;
import org.argeo.api.NodeDeployment;
import org.argeo.api.NodeState;
+import org.argeo.osgi.transaction.WorkTransaction;
import org.argeo.osgi.useradmin.UserAdminConf;
import org.eclipse.equinox.http.jetty.JettyConfigurator;
import org.osgi.framework.BundleContext;
private Long availableSince;
-
// Readiness
private boolean nodeAvailable = false;
private boolean userAdminAvailable = false;
// httpSt.open();
KernelUtils.asyncOpen(httpSt);
-
ServiceTracker<?, ?> userAdminSt = new ServiceTracker<UserAdmin, UserAdmin>(bc, UserAdmin.class, null) {
@Override
public UserAdmin addingService(ServiceReference<UserAdmin> reference) {
} catch (Exception e) {
throw new IllegalStateException("Cannot analyse clean state", e);
}
- deployConfig = new DeployConfig(configurationAdmin, isClean);
+ deployConfig = new DeployConfig(configurationAdmin, isClean);
Activator.registerService(NodeDeployment.class, CmsDeployment.this, null);
// JcrInitUtils.addToDeployment(CmsDeployment.this);
httpExpected = deployConfig.getProps(KernelConstants.JETTY_FACTORY_PID, "default") != null;
private void addStandardSystemRoles(UserAdmin userAdmin) {
// we assume UserTransaction is already available (TODO make it more robust)
- UserTransaction userTransaction = bc.getService(bc.getServiceReference(UserTransaction.class));
+ WorkTransaction userTransaction = bc.getService(bc.getServiceReference(WorkTransaction.class));
try {
userTransaction.begin();
Role adminRole = userAdmin.getRole(NodeConstants.ROLE_ADMIN);
// if (nodeHttp != null)
// nodeHttp.destroy();
-
try {
JettyConfigurator.stopServer(KernelConstants.DEFAULT_JETTY_SERVER);
} catch (Exception e) {
}
}
-
@Override
public synchronized Long getAvailableSince() {
return availableSince;
return availableSince != null;
}
-
}
import java.util.List;
import java.util.Locale;
-import javax.transaction.TransactionManager;
-import javax.transaction.UserTransaction;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.argeo.api.NodeConstants;
import org.argeo.api.NodeState;
import org.argeo.cms.LocaleUtils;
-import org.argeo.transaction.simple.SimpleTransactionManager;
+import org.argeo.osgi.transaction.SimpleTransactionManager;
+import org.argeo.osgi.transaction.WorkControl;
+import org.argeo.osgi.transaction.WorkTransaction;
import org.argeo.util.LangUtils;
import org.osgi.framework.Constants;
import org.osgi.service.cm.ManagedServiceFactory;
private void initSimpleTransactionManager() {
SimpleTransactionManager transactionManager = new SimpleTransactionManager();
- Activator.registerService(TransactionManager.class, transactionManager, null);
- Activator.registerService(UserTransaction.class, transactionManager, null);
+ Activator.registerService(WorkControl.class, transactionManager, null);
+ Activator.registerService(WorkTransaction.class, transactionManager, null);
+// Activator.registerService(TransactionManager.class, transactionManager, null);
+// Activator.registerService(UserTransaction.class, transactionManager, null);
// TODO TransactionSynchronizationRegistry
}
import javax.security.auth.kerberos.KerberosPrincipal;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
-import javax.transaction.TransactionManager;
import org.apache.commons.httpclient.auth.AuthPolicy;
import org.apache.commons.httpclient.auth.CredentialsProvider;
import org.argeo.cms.internal.http.client.HttpCredentialProvider;
import org.argeo.cms.internal.http.client.SpnegoAuthScheme;
import org.argeo.naming.DnsBrowser;
+import org.argeo.osgi.transaction.WorkControl;
import org.argeo.osgi.useradmin.AbstractUserDirectory;
import org.argeo.osgi.useradmin.AggregatingUserAdmin;
import org.argeo.osgi.useradmin.LdapUserAdmin;
// private ServiceRegistration<UserAdmin> userAdminReg;
// JTA
- private final ServiceTracker<TransactionManager, TransactionManager> tmTracker;
+ private final ServiceTracker<WorkControl, WorkControl> tmTracker;
// private final String cacheName = UserDirectory.class.getName();
// GSS API
super(systemRolesBaseDn, tokensBaseDn);
BundleContext bc = Activator.getBundleContext();
if (bc != null) {
- tmTracker = new ServiceTracker<>(bc, TransactionManager.class, null);
+ tmTracker = new ServiceTracker<>(bc, WorkControl.class, null);
tmTracker.open();
} else {
tmTracker = null;
protected void postAdd(AbstractUserDirectory userDirectory) {
// JTA
- TransactionManager tm = tmTracker != null ? tmTracker.getService() : null;
+ WorkControl tm = tmTracker != null ? tmTracker.getService() : null;
if (tm == null)
throw new IllegalStateException("A JTA transaction manager must be available.");
- userDirectory.setTransactionManager(tm);
+ userDirectory.setTransactionControl(tm);
// if (tmTracker.getService() instanceof BitronixTransactionManager)
// EhCacheXAResourceProducer.registerXAResource(cacheName, userDirectory.getXaResource());
import java.util.Hashtable;
import java.util.List;
-import javax.transaction.TransactionManager;
-
import org.argeo.naming.LdapAttrs;
-import org.argeo.transaction.simple.SimpleTransactionManager;
+import org.argeo.osgi.transaction.SimpleTransactionManager;
import org.osgi.service.useradmin.Authorization;
import org.osgi.service.useradmin.Group;
import org.osgi.service.useradmin.Role;
final static int TM_BITRONIX = 1;
private int tmType = TM_SIMPLE;
- private TransactionManager tm;
+ private SimpleTransactionManager tm;
private URI uri;
private AbstractUserDirectory userAdmin;
private Path tempDir;
}
}
- private AbstractUserDirectory initUserAdmin(URI uri, TransactionManager tm) {
+ private AbstractUserDirectory initUserAdmin(URI uri, SimpleTransactionManager tm) {
Dictionary<String, Object> props = new Hashtable<>();
props.put(UserAdminConf.uri.name(), uri.toString());
props.put(UserAdminConf.baseDn.name(), BASE_DN);
// JTA
// if (TM_BITRONIX == tmType)
// EhCacheXAResourceProducer.registerXAResource(UserDirectory.class.getName(), userAdmin.getXaResource());
- userAdmin.setTransactionManager(tm);
+ userAdmin.setTransactionControl(tm);
return userAdmin;
}
--- /dev/null
+package org.argeo.osgi.transaction;
+
+/** JTA transaction status. */
+public class JtaStatusAdapter implements TransactionStatusAdapter<Integer> {
+ private static final Integer STATUS_ACTIVE = 0;
+ private static final Integer STATUS_COMMITTED = 3;
+ private static final Integer STATUS_COMMITTING = 8;
+ private static final Integer STATUS_MARKED_ROLLBACK = 1;
+ private static final Integer STATUS_NO_TRANSACTION = 6;
+ private static final Integer STATUS_PREPARED = 2;
+ private static final Integer STATUS_PREPARING = 7;
+ private static final Integer STATUS_ROLLEDBACK = 4;
+ private static final Integer STATUS_ROLLING_BACK = 9;
+// private static final Integer STATUS_UNKNOWN = 5;
+
+ @Override
+ public Integer getActiveStatus() {
+ return STATUS_ACTIVE;
+ }
+
+ @Override
+ public Integer getPreparingStatus() {
+ return STATUS_PREPARING;
+ }
+
+ @Override
+ public Integer getMarkedRollbackStatus() {
+ return STATUS_MARKED_ROLLBACK;
+ }
+
+ @Override
+ public Integer getPreparedStatus() {
+ return STATUS_PREPARED;
+ }
+
+ @Override
+ public Integer getCommittingStatus() {
+ return STATUS_COMMITTING;
+ }
+
+ @Override
+ public Integer getCommittedStatus() {
+ return STATUS_COMMITTED;
+ }
+
+ @Override
+ public Integer getRollingBackStatus() {
+ return STATUS_ROLLING_BACK;
+ }
+
+ @Override
+ public Integer getRolledBackStatus() {
+ return STATUS_ROLLEDBACK;
+ }
+
+ @Override
+ public Integer getNoTransactionStatus() {
+ return STATUS_NO_TRANSACTION;
+ }
+
+}
--- /dev/null
+package org.argeo.osgi.transaction;
+
+/** Internal unchecked rollback exception. */
+class SimpleRollbackException extends RuntimeException {
+ private static final long serialVersionUID = 8055601819719780566L;
+
+ public SimpleRollbackException() {
+ super();
+ }
+
+ public SimpleRollbackException(Throwable cause) {
+ super(cause);
+ }
+
+}
--- /dev/null
+package org.argeo.osgi.transaction;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+/** Simple implementation of an XA transaction. */
+class SimpleTransaction<T>
+//implements Transaction, Status
+{
+ private final Xid xid;
+ private T status;
+ private final List<XAResource> xaResources = new ArrayList<XAResource>();
+
+ private final SimpleTransactionManager transactionManager;
+ private TransactionStatusAdapter<T> tsa;
+
+ public SimpleTransaction(SimpleTransactionManager transactionManager, TransactionStatusAdapter<T> tsa) {
+ this.tsa = tsa;
+ this.status = tsa.getActiveStatus();
+ this.xid = new UuidXid();
+ this.transactionManager = transactionManager;
+ }
+
+ public synchronized void commit()
+// throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
+// SecurityException, IllegalStateException, SystemException
+ {
+ status = tsa.getPreparingStatus();
+ for (XAResource xaRes : xaResources) {
+ if (status.equals(tsa.getMarkedRollbackStatus()))
+ break;
+ try {
+ xaRes.prepare(xid);
+ } catch (XAException e) {
+ status = tsa.getMarkedRollbackStatus();
+ error("Cannot prepare " + xaRes + " for " + xid, e);
+ }
+ }
+ if (status.equals(tsa.getMarkedRollbackStatus())) {
+ rollback();
+ throw new SimpleRollbackException();
+ }
+ status = tsa.getPreparedStatus();
+
+ status = tsa.getCommittingStatus();
+ for (XAResource xaRes : xaResources) {
+ if (status.equals(tsa.getMarkedRollbackStatus()))
+ break;
+ try {
+ xaRes.commit(xid, false);
+ } catch (XAException e) {
+ status = tsa.getMarkedRollbackStatus();
+ error("Cannot prepare " + xaRes + " for " + xid, e);
+ }
+ }
+ if (status.equals(tsa.getMarkedRollbackStatus())) {
+ rollback();
+ throw new SimpleRollbackException();
+ }
+
+ // complete
+ status = tsa.getCommittedStatus();
+ clearResources(XAResource.TMSUCCESS);
+ transactionManager.unregister(xid);
+ }
+
+ public synchronized void rollback()
+// throws IllegalStateException, SystemException
+ {
+ status = tsa.getRollingBackStatus();
+ for (XAResource xaRes : xaResources) {
+ try {
+ xaRes.rollback(xid);
+ } catch (XAException e) {
+ error("Cannot rollback " + xaRes + " for " + xid, e);
+ }
+ }
+
+ // complete
+ status = tsa.getRolledBackStatus();
+ clearResources(XAResource.TMFAIL);
+ transactionManager.unregister(xid);
+ }
+
+ public synchronized boolean enlistResource(XAResource xaRes)
+// throws RollbackException, IllegalStateException, SystemException
+ {
+ if (xaResources.add(xaRes)) {
+ try {
+ xaRes.start(getXid(), XAResource.TMNOFLAGS);
+ return true;
+ } catch (XAException e) {
+ error("Cannot enlist " + xaRes, e);
+ return false;
+ }
+ } else
+ return false;
+ }
+
+ public synchronized boolean delistResource(XAResource xaRes, int flag)
+// throws IllegalStateException, SystemException
+ {
+ if (xaResources.remove(xaRes)) {
+ try {
+ xaRes.end(getXid(), flag);
+ } catch (XAException e) {
+ error("Cannot delist " + xaRes, e);
+ return false;
+ }
+ return true;
+ } else
+ return false;
+ }
+
+ protected void clearResources(int flag) {
+ for (XAResource xaRes : xaResources)
+ try {
+ xaRes.end(getXid(), flag);
+ } catch (XAException e) {
+ error("Cannot end " + xaRes, e);
+ }
+ xaResources.clear();
+ }
+
+ protected void error(Object obj, Exception e) {
+ System.err.println(obj);
+ e.printStackTrace();
+ }
+
+ public synchronized T getStatus()
+// throws SystemException
+ {
+ return status;
+ }
+
+// public void registerSynchronization(Synchronization sync)
+// throws RollbackException, IllegalStateException, SystemException {
+// throw new UnsupportedOperationException();
+// }
+
+ public void setRollbackOnly()
+// throws IllegalStateException, SystemException
+ {
+ status = tsa.getMarkedRollbackStatus();
+ }
+
+ @Override
+ public int hashCode() {
+ return xid.hashCode();
+ }
+
+ Xid getXid() {
+ return xid;
+ }
+
+}
--- /dev/null
+package org.argeo.osgi.transaction;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+/**
+ * Simple implementation of an XA transaction manager.
+ */
+public class SimpleTransactionManager
+// implements TransactionManager, UserTransaction
+ implements WorkControl, WorkTransaction {
+ private ThreadLocal<SimpleTransaction<Integer>> current = new ThreadLocal<SimpleTransaction<Integer>>();
+
+ private Map<Xid, SimpleTransaction<Integer>> knownTransactions = Collections
+ .synchronizedMap(new HashMap<Xid, SimpleTransaction<Integer>>());
+ private TransactionStatusAdapter<Integer> tsa = new JtaStatusAdapter();
+// private SyncRegistry syncRegistry = new SyncRegistry();
+
+ /*
+ * WORK IMPLEMENTATION
+ */
+ @Override
+ public <T> T required(Callable<T> work) {
+ T res;
+ begin();
+ try {
+ res = work.call();
+ commit();
+ } catch (Exception e) {
+ rollback();
+ throw new SimpleRollbackException(e);
+ }
+ return res;
+ }
+
+ @Override
+ public WorkContext getWorkContext() {
+ return new WorkContext() {
+
+ @Override
+ public void registerXAResource(XAResource resource, String recoveryId) {
+ getTransaction().enlistResource(resource);
+ }
+ };
+ }
+
+ /*
+ * WORK TRANSACTION IMPLEMENTATION
+ */
+
+ @Override
+ public boolean isNoTransactionStatus() {
+ return tsa.getNoTransactionStatus().equals(getStatus());
+ }
+
+ /*
+ * JTA IMPLEMENTATION
+ */
+
+ public void begin()
+// throws NotSupportedException, SystemException
+ {
+ if (getCurrent() != null)
+ throw new UnsupportedOperationException("Nested transactions are not supported");
+ SimpleTransaction<Integer> transaction = new SimpleTransaction<Integer>(this, tsa);
+ knownTransactions.put(transaction.getXid(), transaction);
+ current.set(transaction);
+ }
+
+ public void commit()
+// throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
+// SecurityException, IllegalStateException, SystemException
+ {
+ if (getCurrent() == null)
+ throw new IllegalStateException("No transaction registered with the current thread.");
+ getCurrent().commit();
+ }
+
+ public int getStatus()
+// throws SystemException
+ {
+ if (getCurrent() == null)
+ return tsa.getNoTransactionStatus();
+ return getTransaction().getStatus();
+ }
+
+ public SimpleTransaction<Integer> getTransaction()
+// throws SystemException
+ {
+ return getCurrent();
+ }
+
+ protected SimpleTransaction<Integer> getCurrent()
+// throws SystemException
+ {
+ SimpleTransaction<Integer> transaction = current.get();
+ if (transaction == null)
+ return null;
+ Integer status = transaction.getStatus();
+ if (status.equals(tsa.getCommittedStatus()) || status.equals(tsa.getRolledBackStatus())) {
+ current.remove();
+ return null;
+ }
+ return transaction;
+ }
+
+ void unregister(Xid xid) {
+ knownTransactions.remove(xid);
+ }
+
+ public void resume(SimpleTransaction<Integer> tobj)
+// throws InvalidTransactionException, IllegalStateException, SystemException
+ {
+ if (getCurrent() != null)
+ throw new IllegalStateException("Transaction " + current.get() + " already registered");
+ current.set(tobj);
+ }
+
+ public void rollback()
+// throws IllegalStateException, SecurityException, SystemException
+ {
+ if (getCurrent() == null)
+ throw new IllegalStateException("No transaction registered with the current thread.");
+ getCurrent().rollback();
+ }
+
+ public void setRollbackOnly()
+// throws IllegalStateException, SystemException
+ {
+ if (getCurrent() == null)
+ throw new IllegalStateException("No transaction registered with the current thread.");
+ getCurrent().setRollbackOnly();
+ }
+
+ public void setTransactionTimeout(int seconds)
+// throws SystemException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public SimpleTransaction<Integer> suspend()
+// throws SystemException
+ {
+ SimpleTransaction<Integer> transaction = getCurrent();
+ current.remove();
+ return transaction;
+ }
+
+// public TransactionSynchronizationRegistry getTsr() {
+// return syncRegistry;
+// }
+//
+// private class SyncRegistry implements TransactionSynchronizationRegistry {
+// @Override
+// public Object getTransactionKey() {
+// try {
+// SimpleTransaction transaction = getCurrent();
+// if (transaction == null)
+// return null;
+// return getCurrent().getXid();
+// } catch (SystemException e) {
+// throw new IllegalStateException("Cannot get transaction key", e);
+// }
+// }
+//
+// @Override
+// public void putResource(Object key, Object value) {
+// throw new UnsupportedOperationException();
+// }
+//
+// @Override
+// public Object getResource(Object key) {
+// throw new UnsupportedOperationException();
+// }
+//
+// @Override
+// public void registerInterposedSynchronization(Synchronization sync) {
+// throw new UnsupportedOperationException();
+// }
+//
+// @Override
+// public int getTransactionStatus() {
+// try {
+// return getStatus();
+// } catch (SystemException e) {
+// throw new IllegalStateException("Cannot get status", e);
+// }
+// }
+//
+// @Override
+// public boolean getRollbackOnly() {
+// try {
+// return getStatus() == Status.STATUS_MARKED_ROLLBACK;
+// } catch (SystemException e) {
+// throw new IllegalStateException("Cannot get status", e);
+// }
+// }
+//
+// @Override
+// public void setRollbackOnly() {
+// try {
+// getCurrent().setRollbackOnly();
+// } catch (Exception e) {
+// throw new IllegalStateException("Cannot set rollback only", e);
+// }
+// }
+//
+// }
+}
--- /dev/null
+package org.argeo.osgi.transaction;
+
+/** Abstract the various approaches to represent transaction status. */
+public interface TransactionStatusAdapter<T> {
+ T getActiveStatus();
+
+ T getPreparingStatus();
+
+ T getMarkedRollbackStatus();
+
+ T getPreparedStatus();
+
+ T getCommittingStatus();
+
+ T getCommittedStatus();
+
+ T getRollingBackStatus();
+
+ T getRolledBackStatus();
+
+ T getNoTransactionStatus();
+}
--- /dev/null
+package org.argeo.osgi.transaction;
+
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.UUID;
+
+import javax.transaction.xa.Xid;
+
+/**
+ * Implementation of {@link Xid} based on {@link UUID}, using max significant
+ * bits as global transaction id, and least significant bits as branch
+ * qualifier.
+ */
+public class UuidXid implements Xid, Serializable {
+ private static final long serialVersionUID = -5380531989917886819L;
+ public final static int FORMAT = (int) serialVersionUID;
+
+ private final static int BYTES_PER_LONG = Long.SIZE / Byte.SIZE;
+
+ private final int format;
+ private final byte[] globalTransactionId;
+ private final byte[] branchQualifier;
+ private final String uuid;
+ private final int hashCode;
+
+ public UuidXid() {
+ this(UUID.randomUUID());
+ }
+
+ public UuidXid(UUID uuid) {
+ this.format = FORMAT;
+ this.globalTransactionId = uuidToBytes(uuid.getMostSignificantBits());
+ this.branchQualifier = uuidToBytes(uuid.getLeastSignificantBits());
+ this.uuid = uuid.toString();
+ this.hashCode = uuid.hashCode();
+ }
+
+ public UuidXid(Xid xid) {
+ this(xid.getFormatId(), xid.getGlobalTransactionId(), xid
+ .getBranchQualifier());
+ }
+
+ private UuidXid(int format, byte[] globalTransactionId,
+ byte[] branchQualifier) {
+ this.format = format;
+ this.globalTransactionId = globalTransactionId;
+ this.branchQualifier = branchQualifier;
+ this.uuid = bytesToUUID(globalTransactionId, branchQualifier)
+ .toString();
+ this.hashCode = uuid.hashCode();
+ }
+
+ @Override
+ public int getFormatId() {
+ return format;
+ }
+
+ @Override
+ public byte[] getGlobalTransactionId() {
+ return Arrays.copyOf(globalTransactionId, globalTransactionId.length);
+ }
+
+ @Override
+ public byte[] getBranchQualifier() {
+ return Arrays.copyOf(branchQualifier, branchQualifier.length);
+ }
+
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj instanceof UuidXid) {
+ UuidXid that = (UuidXid) obj;
+ return Arrays.equals(globalTransactionId, that.globalTransactionId)
+ && Arrays.equals(branchQualifier, that.branchQualifier);
+ }
+ if (obj instanceof Xid) {
+ Xid that = (Xid) obj;
+ return Arrays.equals(globalTransactionId,
+ that.getGlobalTransactionId())
+ && Arrays
+ .equals(branchQualifier, that.getBranchQualifier());
+ }
+ return uuid.equals(obj.toString());
+ }
+
+ @Override
+ protected Object clone() throws CloneNotSupportedException {
+ return new UuidXid(format, globalTransactionId, branchQualifier);
+ }
+
+ @Override
+ public String toString() {
+ return uuid;
+ }
+
+ public UUID asUuid() {
+ return bytesToUUID(globalTransactionId, branchQualifier);
+ }
+
+ public static byte[] uuidToBytes(long bits) {
+ ByteBuffer buffer = ByteBuffer.allocate(BYTES_PER_LONG);
+ buffer.putLong(0, bits);
+ return buffer.array();
+ }
+
+ public static UUID bytesToUUID(byte[] most, byte[] least) {
+ if (most.length < BYTES_PER_LONG)
+ most = Arrays.copyOf(most, BYTES_PER_LONG);
+ if (least.length < BYTES_PER_LONG)
+ least = Arrays.copyOf(least, BYTES_PER_LONG);
+ ByteBuffer buffer = ByteBuffer.allocate(2 * BYTES_PER_LONG);
+ buffer.put(most, 0, BYTES_PER_LONG);
+ buffer.put(least, 0, BYTES_PER_LONG);
+ buffer.flip();
+ return new UUID(buffer.getLong(), buffer.getLong());
+ }
+
+ // public static void main(String[] args) {
+ // UUID uuid = UUID.randomUUID();
+ // System.out.println(uuid);
+ // uuid = bytesToUUID(uuidToBytes(uuid.getMostSignificantBits()),
+ // uuidToBytes(uuid.getLeastSignificantBits()));
+ // System.out.println(uuid);
+ // }
+}
--- /dev/null
+package org.argeo.osgi.transaction;
+
+import javax.transaction.xa.XAResource;
+
+/**
+ * A minimalistic interface similar to OSGi transaction context in order to
+ * register XA resources.
+ */
+public interface WorkContext {
+ void registerXAResource(XAResource resource, String recoveryId);
+}
--- /dev/null
+package org.argeo.osgi.transaction;
+
+import java.util.concurrent.Callable;
+
+/**
+ * A minimalistic interface inspired by OSGi transaction control in order to
+ * commit units of work externally.
+ */
+public interface WorkControl {
+ <T> T required(Callable<T> work);
+
+ void setRollbackOnly();
+
+ WorkContext getWorkContext();
+}
--- /dev/null
+package org.argeo.osgi.transaction;
+
+/**
+ * A minimalistic interface inspired by JTA user transaction in order to commit
+ * units of work externally.
+ */
+public interface WorkTransaction {
+ void begin();
+
+ void commit();
+
+ void rollback();
+
+ boolean isNoTransactionStatus();
+}
--- /dev/null
+/** Minimalistic and partial XA transaction manager implementation. */
+package org.argeo.osgi.transaction;
\ No newline at end of file
import javax.naming.directory.BasicAttributes;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
-import javax.transaction.SystemException;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
import org.argeo.naming.LdapAttrs;
+import org.argeo.osgi.transaction.WorkControl;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
private List<String> credentialAttributeIds = Arrays
.asList(new String[] { LdapAttrs.userPassword.name(), LdapAttrs.authPassword.name() });
- // JTA
- private TransactionManager transactionManager;
+ // Transaction
+// private TransactionManager transactionManager;
+ private WorkControl transactionControl;
private WcXaResource xaResource = new WcXaResource(this);
AbstractUserDirectory(URI uriArg, Dictionary<String, ?> props, boolean scoped) {
}
protected void checkEdit() {
- Transaction transaction;
- try {
- transaction = transactionManager.getTransaction();
- } catch (SystemException e) {
- throw new UserDirectoryException("Cannot get transaction", e);
- }
- if (transaction == null)
- throw new UserDirectoryException("A transaction needs to be active in order to edit");
+// Transaction transaction;
+// try {
+// transaction = transactionManager.getTransaction();
+// } catch (SystemException e) {
+// throw new UserDirectoryException("Cannot get transaction", e);
+// }
+// if (transaction == null)
+// throw new UserDirectoryException("A transaction needs to be active in order to edit");
if (xaResource.wc() == null) {
try {
- transaction.enlistResource(xaResource);
+// transaction.enlistResource(xaResource);
+ transactionControl.getWorkContext().registerXAResource(xaResource, null);
} catch (Exception e) {
throw new UserDirectoryException("Cannot enlist " + xaResource, e);
}
this.externalRoles = externalRoles;
}
- public void setTransactionManager(TransactionManager transactionManager) {
- this.transactionManager = transactionManager;
+// public void setTransactionManager(TransactionManager transactionManager) {
+// this.transactionManager = transactionManager;
+// }
+
+ public void setTransactionControl(WorkControl transactionControl) {
+ this.transactionControl = transactionControl;
}
public WcXaResource getXaResource() {
+++ /dev/null
-package org.argeo.transaction.simple;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.transaction.HeuristicMixedException;
-import javax.transaction.HeuristicRollbackException;
-import javax.transaction.RollbackException;
-import javax.transaction.Status;
-import javax.transaction.Synchronization;
-import javax.transaction.SystemException;
-import javax.transaction.Transaction;
-import javax.transaction.xa.XAException;
-import javax.transaction.xa.XAResource;
-import javax.transaction.xa.Xid;
-
-/** Simple implementation of an XA {@link Transaction}. */
-class SimpleTransaction implements Transaction, Status {
- private final Xid xid;
- private int status = Status.STATUS_ACTIVE;
- private final List<XAResource> xaResources = new ArrayList<XAResource>();
-
- private final SimpleTransactionManager transactionManager;
-
- public SimpleTransaction(SimpleTransactionManager transactionManager) {
- this.xid = new UuidXid();
- this.transactionManager = transactionManager;
- }
-
- @Override
- public synchronized void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
- SecurityException, IllegalStateException, SystemException {
- status = STATUS_PREPARING;
- for (XAResource xaRes : xaResources) {
- if (status == STATUS_MARKED_ROLLBACK)
- break;
- try {
- xaRes.prepare(xid);
- } catch (XAException e) {
- status = STATUS_MARKED_ROLLBACK;
- error("Cannot prepare " + xaRes + " for " + xid, e);
- }
- }
- if (status == STATUS_MARKED_ROLLBACK) {
- rollback();
- throw new RollbackException();
- }
- status = STATUS_PREPARED;
-
- status = STATUS_COMMITTING;
- for (XAResource xaRes : xaResources) {
- if (status == STATUS_MARKED_ROLLBACK)
- break;
- try {
- xaRes.commit(xid, false);
- } catch (XAException e) {
- status = STATUS_MARKED_ROLLBACK;
- error("Cannot prepare " + xaRes + " for " + xid, e);
- }
- }
- if (status == STATUS_MARKED_ROLLBACK) {
- rollback();
- throw new RollbackException();
- }
-
- // complete
- status = STATUS_COMMITTED;
- clearResources(XAResource.TMSUCCESS);
- transactionManager.unregister(xid);
- }
-
- @Override
- public synchronized void rollback() throws IllegalStateException, SystemException {
- status = STATUS_ROLLING_BACK;
- for (XAResource xaRes : xaResources) {
- try {
- xaRes.rollback(xid);
- } catch (XAException e) {
- error("Cannot rollback " + xaRes + " for " + xid, e);
- }
- }
-
- // complete
- status = STATUS_ROLLEDBACK;
- clearResources(XAResource.TMFAIL);
- transactionManager.unregister(xid);
- }
-
- @Override
- public synchronized boolean enlistResource(XAResource xaRes)
- throws RollbackException, IllegalStateException, SystemException {
- if (xaResources.add(xaRes)) {
- try {
- xaRes.start(getXid(), XAResource.TMNOFLAGS);
- return true;
- } catch (XAException e) {
- error("Cannot enlist " + xaRes, e);
- return false;
- }
- } else
- return false;
- }
-
- @Override
- public synchronized boolean delistResource(XAResource xaRes, int flag)
- throws IllegalStateException, SystemException {
- if (xaResources.remove(xaRes)) {
- try {
- xaRes.end(getXid(), flag);
- } catch (XAException e) {
- error("Cannot delist " + xaRes, e);
- return false;
- }
- return true;
- } else
- return false;
- }
-
- protected void clearResources(int flag) {
- for (XAResource xaRes : xaResources)
- try {
- xaRes.end(getXid(), flag);
- } catch (XAException e) {
- error("Cannot end " + xaRes, e);
- }
- xaResources.clear();
- }
-
- protected void error(Object obj, Exception e) {
- System.err.println(obj);
- e.printStackTrace();
- }
-
- @Override
- public synchronized int getStatus() throws SystemException {
- return status;
- }
-
- @Override
- public void registerSynchronization(Synchronization sync)
- throws RollbackException, IllegalStateException, SystemException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setRollbackOnly() throws IllegalStateException, SystemException {
- status = STATUS_MARKED_ROLLBACK;
- }
-
- @Override
- public int hashCode() {
- return xid.hashCode();
- }
-
- Xid getXid() {
- return xid;
- }
-
-}
+++ /dev/null
-package org.argeo.transaction.simple;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.transaction.HeuristicMixedException;
-import javax.transaction.HeuristicRollbackException;
-import javax.transaction.InvalidTransactionException;
-import javax.transaction.NotSupportedException;
-import javax.transaction.RollbackException;
-import javax.transaction.Status;
-import javax.transaction.Synchronization;
-import javax.transaction.SystemException;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-import javax.transaction.TransactionSynchronizationRegistry;
-import javax.transaction.UserTransaction;
-import javax.transaction.xa.Xid;
-
-/**
- * Simple implementation of an XA {@link TransactionManager} and
- * {@link UserTransaction}.
- */
-public class SimpleTransactionManager implements TransactionManager, UserTransaction {
- private ThreadLocal<SimpleTransaction> current = new ThreadLocal<SimpleTransaction>();
-
- private Map<Xid, SimpleTransaction> knownTransactions = Collections
- .synchronizedMap(new HashMap<Xid, SimpleTransaction>());
- private SyncRegistry syncRegistry = new SyncRegistry();
-
- @Override
- public void begin() throws NotSupportedException, SystemException {
- if (getCurrent() != null)
- throw new NotSupportedException("Nested transactions are not supported");
- SimpleTransaction transaction = new SimpleTransaction(this);
- knownTransactions.put(transaction.getXid(), transaction);
- current.set(transaction);
- }
-
- @Override
- public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
- SecurityException, IllegalStateException, SystemException {
- if (getCurrent() == null)
- throw new IllegalStateException("No transaction registered with the current thread.");
- getCurrent().commit();
- }
-
- @Override
- public int getStatus() throws SystemException {
- if (getCurrent() == null)
- return Status.STATUS_NO_TRANSACTION;
- return getTransaction().getStatus();
- }
-
- @Override
- public Transaction getTransaction() throws SystemException {
- return getCurrent();
- }
-
- protected SimpleTransaction getCurrent() throws SystemException {
- SimpleTransaction transaction = current.get();
- if (transaction == null)
- return null;
- int status = transaction.getStatus();
- if (Status.STATUS_COMMITTED == status || Status.STATUS_ROLLEDBACK == status) {
- current.remove();
- return null;
- }
- return transaction;
- }
-
- void unregister(Xid xid) {
- knownTransactions.remove(xid);
- }
-
- @Override
- public void resume(Transaction tobj) throws InvalidTransactionException, IllegalStateException, SystemException {
- if (getCurrent() != null)
- throw new IllegalStateException("Transaction " + current.get() + " already registered");
- current.set((SimpleTransaction) tobj);
- }
-
- @Override
- public void rollback() throws IllegalStateException, SecurityException, SystemException {
- if (getCurrent() == null)
- throw new IllegalStateException("No transaction registered with the current thread.");
- getCurrent().rollback();
- }
-
- @Override
- public void setRollbackOnly() throws IllegalStateException, SystemException {
- if (getCurrent() == null)
- throw new IllegalStateException("No transaction registered with the current thread.");
- getCurrent().setRollbackOnly();
- }
-
- @Override
- public void setTransactionTimeout(int seconds) throws SystemException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Transaction suspend() throws SystemException {
- Transaction transaction = getCurrent();
- current.remove();
- return transaction;
- }
-
- public TransactionSynchronizationRegistry getTsr() {
- return syncRegistry;
- }
-
- private class SyncRegistry implements TransactionSynchronizationRegistry {
- @Override
- public Object getTransactionKey() {
- try {
- SimpleTransaction transaction = getCurrent();
- if (transaction == null)
- return null;
- return getCurrent().getXid();
- } catch (SystemException e) {
- throw new IllegalStateException("Cannot get transaction key", e);
- }
- }
-
- @Override
- public void putResource(Object key, Object value) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Object getResource(Object key) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void registerInterposedSynchronization(Synchronization sync) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getTransactionStatus() {
- try {
- return getStatus();
- } catch (SystemException e) {
- throw new IllegalStateException("Cannot get status", e);
- }
- }
-
- @Override
- public boolean getRollbackOnly() {
- try {
- return getStatus() == Status.STATUS_MARKED_ROLLBACK;
- } catch (SystemException e) {
- throw new IllegalStateException("Cannot get status", e);
- }
- }
-
- @Override
- public void setRollbackOnly() {
- try {
- getCurrent().setRollbackOnly();
- } catch (Exception e) {
- throw new IllegalStateException("Cannot set rollback only", e);
- }
- }
-
- }
-}
+++ /dev/null
-package org.argeo.transaction.simple;
-
-import java.io.Serializable;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import java.util.UUID;
-
-import javax.transaction.xa.Xid;
-
-/**
- * Implementation of {@link Xid} based on {@link UUID}, using max significant
- * bits as global transaction id, and least significant bits as branch
- * qualifier.
- */
-public class UuidXid implements Xid, Serializable {
- private static final long serialVersionUID = -5380531989917886819L;
- public final static int FORMAT = (int) serialVersionUID;
-
- private final static int BYTES_PER_LONG = Long.SIZE / Byte.SIZE;
-
- private final int format;
- private final byte[] globalTransactionId;
- private final byte[] branchQualifier;
- private final String uuid;
- private final int hashCode;
-
- public UuidXid() {
- this(UUID.randomUUID());
- }
-
- public UuidXid(UUID uuid) {
- this.format = FORMAT;
- this.globalTransactionId = uuidToBytes(uuid.getMostSignificantBits());
- this.branchQualifier = uuidToBytes(uuid.getLeastSignificantBits());
- this.uuid = uuid.toString();
- this.hashCode = uuid.hashCode();
- }
-
- public UuidXid(Xid xid) {
- this(xid.getFormatId(), xid.getGlobalTransactionId(), xid
- .getBranchQualifier());
- }
-
- private UuidXid(int format, byte[] globalTransactionId,
- byte[] branchQualifier) {
- this.format = format;
- this.globalTransactionId = globalTransactionId;
- this.branchQualifier = branchQualifier;
- this.uuid = bytesToUUID(globalTransactionId, branchQualifier)
- .toString();
- this.hashCode = uuid.hashCode();
- }
-
- @Override
- public int getFormatId() {
- return format;
- }
-
- @Override
- public byte[] getGlobalTransactionId() {
- return Arrays.copyOf(globalTransactionId, globalTransactionId.length);
- }
-
- @Override
- public byte[] getBranchQualifier() {
- return Arrays.copyOf(branchQualifier, branchQualifier.length);
- }
-
- @Override
- public int hashCode() {
- return hashCode;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj instanceof UuidXid) {
- UuidXid that = (UuidXid) obj;
- return Arrays.equals(globalTransactionId, that.globalTransactionId)
- && Arrays.equals(branchQualifier, that.branchQualifier);
- }
- if (obj instanceof Xid) {
- Xid that = (Xid) obj;
- return Arrays.equals(globalTransactionId,
- that.getGlobalTransactionId())
- && Arrays
- .equals(branchQualifier, that.getBranchQualifier());
- }
- return uuid.equals(obj.toString());
- }
-
- @Override
- protected Object clone() throws CloneNotSupportedException {
- return new UuidXid(format, globalTransactionId, branchQualifier);
- }
-
- @Override
- public String toString() {
- return uuid;
- }
-
- public UUID asUuid() {
- return bytesToUUID(globalTransactionId, branchQualifier);
- }
-
- public static byte[] uuidToBytes(long bits) {
- ByteBuffer buffer = ByteBuffer.allocate(BYTES_PER_LONG);
- buffer.putLong(0, bits);
- return buffer.array();
- }
-
- public static UUID bytesToUUID(byte[] most, byte[] least) {
- if (most.length < BYTES_PER_LONG)
- most = Arrays.copyOf(most, BYTES_PER_LONG);
- if (least.length < BYTES_PER_LONG)
- least = Arrays.copyOf(least, BYTES_PER_LONG);
- ByteBuffer buffer = ByteBuffer.allocate(2 * BYTES_PER_LONG);
- buffer.put(most, 0, BYTES_PER_LONG);
- buffer.put(least, 0, BYTES_PER_LONG);
- buffer.flip();
- return new UUID(buffer.getLong(), buffer.getLong());
- }
-
- // public static void main(String[] args) {
- // UUID uuid = UUID.randomUUID();
- // System.out.println(uuid);
- // uuid = bytesToUUID(uuidToBytes(uuid.getMostSignificantBits()),
- // uuidToBytes(uuid.getLeastSignificantBits()));
- // System.out.println(uuid);
- // }
-}
+++ /dev/null
-/** Minimalistic and partial XA transaction manager implementation. */
-package org.argeo.transaction.simple;
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.argeo.maven</groupId>
<modules>
<!-- Base -->
<module>org.argeo.enterprise</module>
-<!-- <module>org.argeo.jcr</module> -->
+ <!-- <module>org.argeo.jcr</module> -->
<module>org.argeo.osgi.boot</module>
<module>org.argeo.core</module>
<!-- Eclipse -->
<module>org.argeo.eclipse.ui.rap</module>
<!-- CMS -->
<module>org.argeo.api</module>
-<!-- <module>org.argeo.maintenance</module> -->
+ <!-- <module>org.argeo.maintenance</module> -->
<module>org.argeo.cms</module>
<module>org.argeo.cms.jcr</module>
<module>org.argeo.cms.ui.theme</module>
<groupId>org.argeo.tp.misc</groupId>
<artifactId>slf4j.osgi</artifactId>
</exclusion>
+ <!-- Make sure JTA is not used anymore -->
+ <exclusion>
+ <groupId>org.argeo.tp.javax</groupId>
+ <artifactId>javax.transaction-api</artifactId>
+ </exclusion>
</exclusions>
</dependency>
</dependencies>