+++ /dev/null
-package org.argeo.cms.util.useradmin;
-
-import java.security.AccessController;
-import java.util.List;
-import java.util.Set;
-
-import javax.naming.InvalidNameException;
-import javax.naming.ldap.LdapName;
-import javax.naming.ldap.Rdn;
-import javax.security.auth.Subject;
-import javax.security.auth.x500.X500Principal;
-
-import org.argeo.ArgeoException;
-import org.argeo.cms.CmsException;
-import org.argeo.cms.CmsView;
-import org.argeo.cms.auth.AuthConstants;
-import org.argeo.cms.auth.CurrentUser;
-import org.argeo.cms.util.CmsUtils;
-import org.argeo.eclipse.ui.EclipseUiUtils;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.osgi.useradmin.LdifName;
-import org.osgi.service.useradmin.Group;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
-import org.osgi.service.useradmin.UserAdmin;
-
-/** Centralise common patterns to manage roles with a user admin */
-public class UserAdminUtils {
-
- /** Retrieves a {@link Role} given a LDAP name */
- public final static Role getRole(UserAdmin userAdmin, LdapName dn) {
- Role role = userAdmin.getRole(dn.toString());
- return role;
- }
-
- /** Retrieves the unique local username given a {@link User}. */
- public final static String getUsername(User user) {
- String username = null;
- if (user instanceof Group)
- username = getProperty(user, LdifName.cn.name());
- else
- username = getProperty(user, LdifName.uid.name());
- return username;
- }
-
- /**
- * Easily retrieves one of the {@link Role}'s property or an empty String if
- * the requested property is not defined
- */
- public final static String getProperty(Role role, String key) {
- Object obj = role.getProperties().get(key);
- if (obj != null)
- return (String) obj;
- else
- return "";
- }
-
- // CENTRALIZE SOME METHODS UNTIL API IS STABLE
- /** Simply checks if current user is registered */
- public static boolean isRegistered() {
- return !CurrentUser.isAnonymous();
- }
-
- /** Simply checks if current user as a home */
- public static boolean hasHome() {
- return isRegistered();
- }
-
- // SELF HELPERS
- /** Simply retrieves the current logged-in user display name. */
- public static User getCurrentUser(UserAdmin userAdmin) {
- return (User) getRole(userAdmin, getCurrentUserLdapName());
- }
-
- /** Simply retrieves the current logged-in user display name. */
- public static String getCurrentUserDisplayName(UserAdmin userAdmin) {
- String username = getCurrentUsername();
- return getUserDisplayName(userAdmin, username);
- }
-
- /** Simply retrieves the current logged-in user display name. */
- public static String getCurrentUserMail(UserAdmin userAdmin) {
- String username = getCurrentUsername();
- return getUserMail(userAdmin, username);
- }
-
- /** Returns the local name of the current connected user */
- public final static String getUsername(UserAdmin userAdmin) {
- LdapName dn = getCurrentUserLdapName();
- return getUsername((User) getRole(userAdmin, dn));
- }
-
- /** Returns true if the current user is in the specified role */
- public static boolean isUserInRole(String role) {
- Set<String> roles = CurrentUser.roles();
- return roles.contains(role);
- }
-
- /** Simply checks if current user is the same as the passed one */
- public static boolean isCurrentUser(User user) {
- String userName = getProperty(user, LdifName.dn.name());
- try {
- LdapName selfUserName = getCurrentUserLdapName();
- LdapName userLdapName = new LdapName(userName);
- if (userLdapName.equals(selfUserName))
- return true;
- else
- return false;
- } catch (InvalidNameException e) {
- throw new ArgeoException("User " + user + " has an unvalid dn: "
- + userName, e);
- }
- }
-
- public final static LdapName getCurrentUserLdapName() {
- String name = getCurrentUsername();
- return getLdapName(name);
- }
-
- /** Simply retrieves username for current user, generally a LDAP dn */
- public static String getCurrentUsername() {
- Subject subject = currentSubject();
- String name = subject.getPrincipals(X500Principal.class).iterator()
- .next().toString();
- return name;
- }
-
- /**
- * Fork of the {@link CurrentUser#currentSubject} method that is private.
- * TODO Enhance and factorize
- */
- private static Subject currentSubject() {
- CmsView cmsView = CmsUtils.getCmsView();
- if (cmsView != null)
- return cmsView.getSubject();
- Subject subject = Subject.getSubject(AccessController.getContext());
- if (subject != null)
- return subject;
- throw new CmsException("Cannot find related subject");
- }
-
- // HOME MANAGEMENT
- /**
- * Simply retrieves the *relative* path to the current user home node from
- * the base home node
- */
- public static String getCurrentUserHomeRelPath() {
- return getHomeRelPath(getCurrentUsername());
- }
-
- /**
- * Simply retrieves the *relative* path to the home node of a user given its
- * userName
- */
- public static String getHomeRelPath(String userName) {
- String id = getUserUid(userName);
- String currHomePath = JcrUtils.firstCharsToPath(id, 2) + "/" + id;
- return currHomePath;
- }
-
- // HELPERS TO RETRIEVE REMARKABLE PROPERTIES
- /** Simply retrieves the user uid from his dn with no useradmin */
- public static String getUserUid(String dn) {
- LdapName ldapName = getLdapName(dn);
- Rdn last = ldapName.getRdn(ldapName.size() - 1);
- if (last.getType().toLowerCase().equals(LdifName.uid.name())
- || last.getType().toLowerCase().equals(LdifName.cn.name()))
- return (String) last.getValue();
- else
- throw new ArgeoException("Cannot retrieve user uid, "
- + "non valid dn: " + dn);
- }
-
- /**
- * Returns the local username if no user with this dn is found or if the
- * found user has no defined display name
- */
- public static String getUserDisplayName(UserAdmin userAdmin, String dn) {
- Role user = getRole(userAdmin, getLdapName(dn));
- if (user == null)
- return getUserUid(dn);
- String displayName = getProperty(user, LdifName.displayName.name());
- if (EclipseUiUtils.isEmpty(displayName))
- displayName = getProperty(user, LdifName.cn.name());
- if (EclipseUiUtils.isEmpty(displayName))
- return getUserUid(dn);
- else
- return displayName;
- }
-
- /**
- * Returns null if no user with this dn is found or if the found user has no
- * defined mail
- */
- public static String getUserMail(UserAdmin userAdmin, String dn) {
- Role user = getRole(userAdmin, getLdapName(dn));
- if (user == null)
- return null;
- else
- return getProperty(user, LdifName.mail.name());
- }
-
- // VARIOUS UI HELPERS
- public final static String buildDefaultCn(String firstName, String lastName) {
- return (firstName.trim() + " " + lastName.trim() + " ").trim();
- }
-
- /** Simply retrieves a display name of the relevant domain */
- public final static String getDomainName(User user) {
- String dn = user.getName();
- if (dn.endsWith(AuthConstants.ROLES_BASEDN))
- return "System roles";
- try {
- LdapName name = new LdapName(dn);
- List<Rdn> rdns = name.getRdns();
- String dname = null;
- int i = 0;
- loop: while (i < rdns.size()) {
- Rdn currrRdn = rdns.get(i);
- if (!LdifName.dc.name().equals(currrRdn.getType()))
- break loop;
- else {
- String currVal = (String) currrRdn.getValue();
- dname = dname == null ? currVal : currVal + "." + dname;
- }
- i++;
- }
- return dname;
- } catch (InvalidNameException e) {
- throw new ArgeoException("Unable to get domain name for " + dn, e);
- }
- }
-
- // Local Helpers
- /** Simply retrieves a LDAP name from a dn with no exception */
- public static LdapName getLdapName(String dn) {
- try {
- return new LdapName(dn);
- } catch (InvalidNameException e) {
- throw new ArgeoException("Cannot parse LDAP name " + dn, e);
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-package org.argeo.cms.util.useradmin;
-
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.transaction.Status;
-import javax.transaction.UserTransaction;
-
-import org.argeo.ArgeoException;
-import org.argeo.cms.auth.AuthConstants;
-import org.argeo.osgi.useradmin.UserAdminConf;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.useradmin.UserAdmin;
-import org.osgi.service.useradmin.UserAdminEvent;
-import org.osgi.service.useradmin.UserAdminListener;
-
-/**
- * Base useradmin wrapper. Implementing application might extends to add
- * business specific behaviour
- */
-public class UserAdminWrapper {
- // private Log log = LogFactory.getLog(UserAdminWrapper.class);
-
- private UserAdmin userAdmin;
- private ServiceReference<UserAdmin> userAdminServiceReference;
- private UserTransaction userTransaction;
-
- /* USER ADMIN LISTENER MANAGEMENT */
- List<UserAdminListener> listeners = new ArrayList<UserAdminListener>();
-
- // TODO implement safer mechanism
- public void addListener(UserAdminListener userAdminListener) {
- if (!listeners.contains(userAdminListener))
- listeners.add(userAdminListener);
- }
-
- /**
- * Starts a transaction if none already exists and notify the userAdmin
- * listeners.Must be called from the UI Thread.
- */
- public UserTransaction beginTransactionIfNeeded() {
- try {
- if (userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION) {
- userTransaction.begin();
- }
- return userTransaction;
- } catch (Exception e) {
- throw new ArgeoException("Unable to begin transaction", e);
- }
- }
-
- // Expose this?
- public void removeListener(UserAdminListener userAdminListener) {
- if (listeners.contains(userAdminListener))
- listeners.remove(userAdminListener);
- }
-
- public void notifyListeners(UserAdminEvent event) {
- for (UserAdminListener listener : listeners)
- listener.roleChanged(event);
- }
-
- public Map<String, String> getKnownBaseDns(boolean onlyWritable) {
- Map<String, String> dns = new HashMap<String, String>();
- for (String uri : userAdminServiceReference.getPropertyKeys()) {
- if (!uri.startsWith("/"))
- continue;
- Dictionary<String, ?> props = UserAdminConf.uriAsProperties(uri);
- String readOnly = UserAdminConf.readOnly.getValue(props);
- String baseDn = UserAdminConf.baseDn.getValue(props);
-
- if (onlyWritable && "true".equals(readOnly))
- continue;
- if (baseDn.equalsIgnoreCase(AuthConstants.ROLES_BASEDN))
- continue;
- dns.put(baseDn, uri);
- }
- return dns;
- }
-
- public UserAdmin getUserAdmin() {
- return userAdmin;
- }
-
- public UserTransaction getUserTransaction() {
- return userTransaction;
- }
-
- /* DEPENDENCY INJECTION */
- public void setUserAdmin(UserAdmin userAdmin) {
- this.userAdmin = userAdmin;
- }
-
- public void setUserTransaction(UserTransaction userTransaction) {
- this.userTransaction = userTransaction;
- }
-
- public void setUserAdminServiceReference(
- ServiceReference<UserAdmin> userAdminServiceReference) {
- this.userAdminServiceReference = userAdminServiceReference;
- }
-}
\ No newline at end of file
--- /dev/null
+package org.argeo.osgi.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;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+class SimpleTransaction implements Transaction, Status {
+ private final static Log log = LogFactory.getLog(SimpleTransaction.class);
+
+ 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;
+ log.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;
+ log.error("Cannot prepare " + xaRes + " for " + xid, e);
+ }
+ }
+ if (status == STATUS_MARKED_ROLLBACK) {
+ rollback();
+ throw new RollbackException();
+ }
+
+ // complete
+ status = STATUS_COMMITTED;
+ if (log.isDebugEnabled())
+ log.debug("COMMITTED " + xid);
+ 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) {
+ log.error("Cannot rollback " + xaRes + " for " + xid, e);
+ }
+ }
+
+ // complete
+ status = STATUS_ROLLEDBACK;
+ if (log.isDebugEnabled())
+ log.debug("ROLLEDBACK " + xid);
+ 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) {
+ log.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) {
+ log.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) {
+ log.error("Cannot end " + xaRes, e);
+ }
+ xaResources.clear();
+ }
+
+ @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.osgi.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;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class SimpleTransactionManager implements TransactionManager, UserTransaction {
+ private final static Log log = LogFactory.getLog(SimpleTransactionManager.class);
+
+ 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);
+ if (log.isDebugEnabled())
+ log.debug("STARTED " + transaction.getXid());
+ }
+
+ @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 RuntimeException("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 RuntimeException("Cannot get status", e);
+ }
+ }
+
+ @Override
+ public boolean getRollbackOnly() {
+ try {
+ return getStatus() == Status.STATUS_MARKED_ROLLBACK;
+ } catch (SystemException e) {
+ throw new RuntimeException("Cannot get status", e);
+ }
+ }
+
+ @Override
+ public void setRollbackOnly() {
+ try {
+ getCurrent().setRollbackOnly();
+ } catch (Exception e) {
+ throw new RuntimeException("Cannot set rollback only", e);
+ }
+ }
+
+ }
+}
--- /dev/null
+package org.argeo.osgi.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);
+ // }
+}