View Javadoc
1   package org.argeo.cms.e4.users;
2   
3   import java.util.ArrayList;
4   import java.util.Collections;
5   import java.util.HashMap;
6   import java.util.Hashtable;
7   import java.util.LinkedHashMap;
8   import java.util.List;
9   import java.util.Map;
10  
11  import javax.transaction.Status;
12  import javax.transaction.UserTransaction;
13  
14  import org.argeo.api.NodeConstants;
15  import org.argeo.cms.CmsException;
16  import org.argeo.osgi.useradmin.UserAdminConf;
17  import org.argeo.osgi.useradmin.UserDirectory;
18  import org.osgi.service.useradmin.UserAdmin;
19  import org.osgi.service.useradmin.UserAdminEvent;
20  import org.osgi.service.useradmin.UserAdminListener;
21  
22  /** Centralise interaction with the UserAdmin in this bundle */
23  public class UserAdminWrapper {
24  
25  	private UserAdmin userAdmin;
26  	// private ServiceReference<UserAdmin> userAdminServiceReference;
27  //	private Set<String> uris;
28  	private Map<UserDirectory, Hashtable<String, String>> userDirectories = Collections
29  			.synchronizedMap(new LinkedHashMap<>());
30  	private UserTransaction userTransaction;
31  
32  	// First effort to simplify UX while managing users and groups
33  	public final static boolean COMMIT_ON_SAVE = true;
34  
35  	// Registered listeners
36  	List<UserAdminListener> listeners = new ArrayList<UserAdminListener>();
37  
38  	/**
39  	 * Starts a transaction if necessary. Should always been called together with
40  	 * {@link UserAdminWrapper#commitOrNotifyTransactionStateChange()} once the
41  	 * security model changes have been performed.
42  	 */
43  	public UserTransaction beginTransactionIfNeeded() {
44  		try {
45  			// UserTransaction userTransaction = getUserTransaction();
46  			if (userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION) {
47  				userTransaction.begin();
48  				// UiAdminUtils.notifyTransactionStateChange(userTransaction);
49  			}
50  			return userTransaction;
51  		} catch (Exception e) {
52  			throw new CmsException("Unable to begin transaction", e);
53  		}
54  	}
55  
56  	/**
57  	 * Depending on the current application configuration, it will either commit the
58  	 * current transaction or throw a notification that the transaction state has
59  	 * changed (In the later case, it must be called from the UI thread).
60  	 */
61  	public void commitOrNotifyTransactionStateChange() {
62  		try {
63  			// UserTransaction userTransaction = getUserTransaction();
64  			if (userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION)
65  				return;
66  
67  			if (UserAdminWrapper.COMMIT_ON_SAVE)
68  				userTransaction.commit();
69  			else
70  				UiAdminUtils.notifyTransactionStateChange(userTransaction);
71  		} catch (Exception e) {
72  			throw new CmsException("Unable to clean transaction", e);
73  		}
74  	}
75  
76  	// TODO implement safer mechanism
77  	public void addListener(UserAdminListener userAdminListener) {
78  		if (!listeners.contains(userAdminListener))
79  			listeners.add(userAdminListener);
80  	}
81  
82  	public void removeListener(UserAdminListener userAdminListener) {
83  		if (listeners.contains(userAdminListener))
84  			listeners.remove(userAdminListener);
85  	}
86  
87  	public void notifyListeners(UserAdminEvent event) {
88  		for (UserAdminListener listener : listeners)
89  			listener.roleChanged(event);
90  	}
91  
92  	public Map<String, String> getKnownBaseDns(boolean onlyWritable) {
93  		Map<String, String> dns = new HashMap<String, String>();
94  		for (UserDirectory userDirectory : userDirectories.keySet()) {
95  			Boolean readOnly = userDirectory.isReadOnly();
96  			String baseDn = userDirectory.getBaseDn().toString();
97  
98  			if (onlyWritable && readOnly)
99  				continue;
100 			if (baseDn.equalsIgnoreCase(NodeConstants.ROLES_BASEDN))
101 				continue;
102 			if (baseDn.equalsIgnoreCase(NodeConstants.TOKENS_BASEDN))
103 				continue;
104 			dns.put(baseDn, UserAdminConf.propertiesAsUri(userDirectories.get(userDirectory)).toString());
105 
106 		}
107 //		for (String uri : uris) {
108 //			if (!uri.startsWith("/"))
109 //				continue;
110 //			Dictionary<String, ?> props = UserAdminConf.uriAsProperties(uri);
111 //			String readOnly = UserAdminConf.readOnly.getValue(props);
112 //			String baseDn = UserAdminConf.baseDn.getValue(props);
113 //
114 //			if (onlyWritable && "true".equals(readOnly))
115 //				continue;
116 //			if (baseDn.equalsIgnoreCase(NodeConstants.ROLES_BASEDN))
117 //				continue;
118 //			if (baseDn.equalsIgnoreCase(NodeConstants.TOKENS_BASEDN))
119 //				continue;
120 //			dns.put(baseDn, uri);
121 //		}
122 		return dns;
123 	}
124 
125 	public UserAdmin getUserAdmin() {
126 		return userAdmin;
127 	}
128 
129 	public UserTransaction getUserTransaction() {
130 		return userTransaction;
131 	}
132 
133 	/* DEPENDENCY INJECTION */
134 	public void setUserAdmin(UserAdmin userAdmin, Map<String, String> properties) {
135 		this.userAdmin = userAdmin;
136 //		this.uris = Collections.unmodifiableSortedSet(new TreeSet<>(properties.keySet()));
137 	}
138 
139 	public void setUserTransaction(UserTransaction userTransaction) {
140 		this.userTransaction = userTransaction;
141 	}
142 
143 	public void addUserDirectory(UserDirectory userDirectory, Map<String, String> properties) {
144 		userDirectories.put(userDirectory, new Hashtable<>(properties));
145 	}
146 
147 	public void removeUserDirectory(UserDirectory userDirectory, Map<String, String> properties) {
148 		userDirectories.remove(userDirectory);
149 	}
150 
151 	// public void setUserAdminServiceReference(
152 	// ServiceReference<UserAdmin> userAdminServiceReference) {
153 	// this.userAdminServiceReference = userAdminServiceReference;
154 	// }
155 }