X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.security.core%2Fsrc%2Forg%2Fargeo%2Fosgi%2Fuseradmin%2FAbstractUserDirectory.java;h=58eb41ca377f0d3254825960ef75a8ec9bebcc18;hb=a0cb2f599e0f63b29c7e7a3f0dffde69726241bf;hp=884e4ce09ff0ccd1e550f01fe3c402dadae12608;hpb=268e023a9de5db2549431a4415e584ac68a4f98b;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java index 884e4ce09..58eb41ca3 100644 --- a/org.argeo.security.core/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java +++ b/org.argeo.security.core/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java @@ -12,10 +12,10 @@ import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.Dictionary; -import java.util.HashMap; +import java.util.Enumeration; +import java.util.Hashtable; import java.util.Iterator; import java.util.List; -import java.util.Map; import javax.naming.InvalidNameException; import javax.naming.directory.Attributes; @@ -26,8 +26,6 @@ import javax.naming.ldap.Rdn; import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.transaction.TransactionManager; -import javax.transaction.xa.XAException; -import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; import org.apache.commons.logging.Log; @@ -45,13 +43,13 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { private final static Log log = LogFactory .getLog(AbstractUserDirectory.class); - private Dictionary properties; - private String baseDn = "dc=example,dc=com"; - private String userObjectClass; - private String groupObjectClass; + private final Hashtable properties; + private final String baseDn; + private final String userObjectClass; + private final String groupObjectClass; - private boolean isReadOnly; - private URI uri; + private final boolean readOnly; + private final URI uri; private UserAdmin externalRoles; private List indexedUserProperties = Arrays.asList(new String[] { @@ -62,12 +60,15 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { .asList(new String[] { LdifName.userpassword.name() }); private TransactionManager transactionManager; - private ThreadLocal workingCopy = new ThreadLocal(); + private ThreadLocal workingCopy = new ThreadLocal(); private Xid editingTransactionXid = null; - AbstractUserDirectory(Dictionary properties) { - // TODO make a copy? - this.properties = properties; + AbstractUserDirectory(Dictionary props) { + properties = new Hashtable(); + for (Enumeration keys = props.keys(); keys.hasMoreElements();) { + String key = keys.nextElement(); + properties.put(key, props.get(key)); + } String uriStr = UserAdminConf.uri.getValue(properties); if (uriStr == null) @@ -76,20 +77,21 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { try { uri = new URI(uriStr); } catch (URISyntaxException e) { - throw new UserDirectoryException("Badly formatted URI", e); + throw new UserDirectoryException("Badly formatted URI " + + uriStr, e); } baseDn = UserAdminConf.baseDn.getValue(properties).toString(); - String isReadOnly = UserAdminConf.readOnly.getValue(properties); - if (isReadOnly == null) - this.isReadOnly = readOnlyDefault(uri); - else - this.isReadOnly = new Boolean(isReadOnly); + String readOnlyStr = UserAdminConf.readOnly.getValue(properties); + if (readOnlyStr == null) { + readOnly = readOnlyDefault(uri); + properties.put(UserAdminConf.readOnly.property(), + Boolean.toString(readOnly)); + } else + readOnly = new Boolean(readOnlyStr); - this.userObjectClass = UserAdminConf.userObjectClass - .getValue(properties); - this.groupObjectClass = UserAdminConf.groupObjectClass - .getValue(properties); + userObjectClass = UserAdminConf.userObjectClass.getValue(properties); + groupObjectClass = UserAdminConf.groupObjectClass.getValue(properties); } /** Returns the groups this user is a direct member of. */ @@ -115,11 +117,11 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { return workingCopy.get() != null; } - protected WorkingCopy getWorkingCopy() { - WorkingCopy wc = workingCopy.get(); + protected UserDirectoryWorkingCopy getWorkingCopy() { + UserDirectoryWorkingCopy wc = workingCopy.get(); if (wc == null) return null; - if (wc.xid == null) { + if (wc.getXid() == null) { workingCopy.set(null); return null; } @@ -137,7 +139,7 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { throw new UserDirectoryException( "A transaction needs to be active in order to edit"); if (editingTransactionXid == null) { - WorkingCopy wc = new WorkingCopy(); + UserDirectoryWorkingCopy wc = new UserDirectoryWorkingCopy(this); try { transaction.enlistResource(wc); editingTransactionXid = wc.getXid(); @@ -186,7 +188,7 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { } protected DirectoryUser doGetRole(LdapName dn) { - WorkingCopy wc = getWorkingCopy(); + UserDirectoryWorkingCopy wc = getWorkingCopy(); DirectoryUser user = daoGetRole(dn); if (wc != null) { if (user == null && wc.getNewUsers().containsKey(dn)) @@ -200,7 +202,7 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { @SuppressWarnings("unchecked") @Override public Role[] getRoles(String filter) throws InvalidSyntaxException { - WorkingCopy wc = getWorkingCopy(); + UserDirectoryWorkingCopy wc = getWorkingCopy(); Filter f = filter != null ? FrameworkUtil.createFilter(filter) : null; List res = doGetRoles(f); if (wc != null) { @@ -243,6 +245,9 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { } if (collectedUsers.size() == 1) return collectedUsers.get(0); + else if (collectedUsers.size() > 1) + log.warn(collectedUsers.size() + " users for " + + (key != null ? key + "=" : "") + value); return null; } @@ -268,7 +273,7 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { @Override public Role createRole(String name, int type) { checkEdit(); - WorkingCopy wc = getWorkingCopy(); + UserDirectoryWorkingCopy wc = getWorkingCopy(); LdapName dn = toDn(name); if ((daoHasRole(dn) && !wc.getDeletedUsers().containsKey(dn)) || wc.getNewUsers().containsKey(dn)) @@ -317,7 +322,7 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { @Override public boolean removeRole(String name) { checkEdit(); - WorkingCopy wc = getWorkingCopy(); + UserDirectoryWorkingCopy wc = getWorkingCopy(); LdapName dn = toDn(name); boolean actuallyDeleted; if (daoHasRole(dn) || wc.getNewUsers().containsKey(dn)) { @@ -336,16 +341,20 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { } // TRANSACTION - protected void prepare(WorkingCopy wc) { + protected void prepare(UserDirectoryWorkingCopy wc) { } - protected void commit(WorkingCopy wc) { + protected void commit(UserDirectoryWorkingCopy wc) { } - protected void rollback(WorkingCopy wc) { + protected void rollback(UserDirectoryWorkingCopy wc) { + + } + void clearEditingTransactionXid() { + editingTransactionXid = null; } // UTILITIES @@ -371,10 +380,6 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { return uri; } - protected void setUri(URI uri) { - this.uri = uri; - } - protected List getIndexedUserProperties() { return indexedUserProperties; } @@ -383,22 +388,21 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { this.indexedUserProperties = indexedUserProperties; } - protected void setReadOnly(boolean isReadOnly) { - this.isReadOnly = isReadOnly; - } - private static boolean readOnlyDefault(URI uri) { if (uri == null) return true; if (uri.getScheme().equals("file")) { File file = new File(uri); - return !file.canWrite(); + if (file.exists()) + return !file.canWrite(); + else + return !file.getParentFile().canWrite(); } return true; } public boolean isReadOnly() { - return isReadOnly; + return readOnly; } UserAdmin getExternalRoles() { @@ -429,156 +433,4 @@ abstract class AbstractUserDirectory implements UserAdmin, UserDirectory { this.transactionManager = transactionManager; } - // - // XA RESOURCE - // - protected class WorkingCopy implements XAResource { - private Xid xid; - private int transactionTimeout = 0; - - private Map newUsers = new HashMap(); - private Map modifiedUsers = new HashMap(); - private Map deletedUsers = new HashMap(); - - @Override - public void start(Xid xid, int flags) throws XAException { - if (editingTransactionXid != null) - throw new UserDirectoryException("Transaction " - + editingTransactionXid + " already editing"); - this.xid = xid; - } - - @Override - public void end(Xid xid, int flags) throws XAException { - checkXid(xid); - - // clean collections - newUsers.clear(); - newUsers = null; - modifiedUsers.clear(); - modifiedUsers = null; - deletedUsers.clear(); - deletedUsers = null; - - // clean IDs - this.xid = null; - editingTransactionXid = null; - } - - @Override - public int prepare(Xid xid) throws XAException { - checkXid(xid); - if (noModifications()) - return XA_RDONLY; - try { - AbstractUserDirectory.this.prepare(this); - } catch (Exception e) { - log.error("Cannot prepare " + xid, e); - throw new XAException(XAException.XA_RBOTHER); - } - return XA_OK; - } - - @Override - public void commit(Xid xid, boolean onePhase) throws XAException { - checkXid(xid); - if (noModifications()) - return; - try { - if (onePhase) - AbstractUserDirectory.this.prepare(this); - AbstractUserDirectory.this.commit(this); - } catch (Exception e) { - log.error("Cannot commit " + xid, e); - throw new XAException(XAException.XA_RBOTHER); - } - } - - @Override - public void rollback(Xid xid) throws XAException { - checkXid(xid); - try { - AbstractUserDirectory.this.rollback(this); - } catch (Exception e) { - log.error("Cannot rollback " + xid, e); - throw new XAException(XAException.XA_HEURMIX); - } - } - - @Override - public void forget(Xid xid) throws XAException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isSameRM(XAResource xares) throws XAException { - return xares == this; - } - - @Override - public Xid[] recover(int flag) throws XAException { - throw new UnsupportedOperationException(); - } - - @Override - public int getTransactionTimeout() throws XAException { - return transactionTimeout; - } - - @Override - public boolean setTransactionTimeout(int seconds) throws XAException { - transactionTimeout = seconds; - return true; - } - - private Xid getXid() { - return xid; - } - - private void checkXid(Xid xid) throws XAException { - if (this.xid == null) - throw new XAException(XAException.XAER_OUTSIDE); - if (!this.xid.equals(xid)) - throw new XAException(XAException.XAER_NOTA); - } - - @Override - protected void finalize() throws Throwable { - if (editingTransactionXid != null) - log.warn("Editing transaction still referenced but no working copy " - + editingTransactionXid); - editingTransactionXid = null; - } - - public boolean noModifications() { - return newUsers.size() == 0 && modifiedUsers.size() == 0 - && deletedUsers.size() == 0; - } - - public Attributes getAttributes(LdapName dn) { - if (modifiedUsers.containsKey(dn)) - return modifiedUsers.get(dn); - return null; - } - - public void startEditing(DirectoryUser user) { - LdapName dn = user.getDn(); - if (modifiedUsers.containsKey(dn)) - throw new UserDirectoryException("Already editing " + dn); - modifiedUsers.put(dn, (Attributes) user.getAttributes().clone()); - } - - public Map getNewUsers() { - return newUsers; - } - - public Map getDeletedUsers() { - return deletedUsers; - } - - public Map getModifiedUsers() { - return modifiedUsers; - } - - } }