1 package org
.argeo
.osgi
.useradmin
;
3 import java
.util
.ArrayList
;
4 import java
.util
.Arrays
;
5 import java
.util
.Collections
;
6 import java
.util
.Dictionary
;
7 import java
.util
.Enumeration
;
8 import java
.util
.Iterator
;
11 import javax
.naming
.NamingEnumeration
;
12 import javax
.naming
.NamingException
;
13 import javax
.naming
.directory
.Attribute
;
14 import javax
.naming
.directory
.Attributes
;
15 import javax
.naming
.directory
.BasicAttribute
;
16 import javax
.naming
.ldap
.LdapName
;
18 import org
.argeo
.osgi
.useradmin
.AbstractUserDirectory
.WorkingCopy
;
20 class LdifUser
implements DirectoryUser
{
21 private final AbstractUserDirectory userAdmin
;
23 private final LdapName dn
;
25 private final boolean frozen
;
26 private Attributes publishedAttributes
;
28 private final AttributeDictionary properties
;
29 private final AttributeDictionary credentials
;
31 LdifUser(AbstractUserDirectory userAdmin
, LdapName dn
, Attributes attributes
) {
32 this(userAdmin
, dn
, attributes
, false);
35 private LdifUser(AbstractUserDirectory userAdmin
, LdapName dn
,
36 Attributes attributes
, boolean frozen
) {
37 this.userAdmin
= userAdmin
;
39 this.publishedAttributes
= attributes
;
40 properties
= new AttributeDictionary(false);
41 credentials
= new AttributeDictionary(true);
46 public String
getName() {
51 public int getType() {
56 public Dictionary
<String
, Object
> getProperties() {
61 public Dictionary
<String
, Object
> getCredentials() {
66 public boolean hasCredential(String key
, Object value
) {
67 Object storedValue
= getCredentials().get(key
);
68 if (storedValue
== null || value
== null)
70 if (!(value
instanceof String
|| value
instanceof byte[]))
72 if (storedValue
instanceof String
&& value
instanceof String
)
73 return storedValue
.equals(value
);
74 if (storedValue
instanceof byte[] && value
instanceof byte[])
75 return Arrays
.equals((byte[]) storedValue
, (byte[]) value
);
80 public LdapName
getDn() {
85 public synchronized Attributes
getAttributes() {
86 return isEditing() ?
getModifiedAttributes() : publishedAttributes
;
89 /** Should only be called from working copy thread. */
90 private synchronized Attributes
getModifiedAttributes() {
91 assert getWc() != null;
92 return getWc().getAttributes(getDn());
95 protected synchronized boolean isEditing() {
96 return getWc() != null && getModifiedAttributes() != null;
99 private synchronized WorkingCopy
getWc() {
100 return userAdmin
.getWorkingCopy();
103 protected synchronized void startEditing() {
105 throw new UserDirectoryException("Cannot edit frozen view");
106 if (getUserAdmin().isReadOnly())
107 throw new UserDirectoryException("User directory is read-only");
108 assert getModifiedAttributes() == null;
109 getWc().startEditing(this);
110 // modifiedAttributes = (Attributes) publishedAttributes.clone();
113 public synchronized void publishAttributes(Attributes modifiedAttributes
) {
114 publishedAttributes
= modifiedAttributes
;
117 // protected synchronized void stopEditing(boolean apply) {
118 // assert getModifiedAttributes() != null;
120 // publishedAttributes = getModifiedAttributes();
121 // // modifiedAttributes = null;
124 public DirectoryUser
getPublished() {
125 return new LdifUser(userAdmin
, dn
, publishedAttributes
, true);
129 public int hashCode() {
130 return dn
.hashCode();
134 public boolean equals(Object obj
) {
137 if (obj
instanceof LdifUser
) {
138 LdifUser that
= (LdifUser
) obj
;
139 return this.dn
.equals(that
.dn
);
145 public String
toString() {
146 return dn
.toString();
149 protected AbstractUserDirectory
getUserAdmin() {
153 private class AttributeDictionary
extends Dictionary
<String
, Object
> {
154 private final List
<String
> effectiveKeys
= new ArrayList
<String
>();
155 private final List
<String
> attrFilter
;
156 private final Boolean includeFilter
;
158 public AttributeDictionary(Boolean includeFilter
) {
159 this.attrFilter
= userAdmin
.getCredentialAttributeIds();
160 this.includeFilter
= includeFilter
;
162 NamingEnumeration
<String
> ids
= getAttributes().getIDs();
163 while (ids
.hasMore()) {
164 String id
= ids
.next();
165 if (includeFilter
&& attrFilter
.contains(id
))
166 effectiveKeys
.add(id
);
167 else if (!includeFilter
&& !attrFilter
.contains(id
))
168 effectiveKeys
.add(id
);
170 } catch (NamingException e
) {
171 throw new UserDirectoryException(
172 "Cannot initialise attribute dictionary", e
);
178 return effectiveKeys
.size();
182 public boolean isEmpty() {
183 return effectiveKeys
.size() == 0;
187 public Enumeration
<String
> keys() {
188 return Collections
.enumeration(effectiveKeys
);
192 public Enumeration
<Object
> elements() {
193 final Iterator
<String
> it
= effectiveKeys
.iterator();
194 return new Enumeration
<Object
>() {
197 public boolean hasMoreElements() {
202 public Object
nextElement() {
203 String key
= it
.next();
205 return getAttributes().get(key
).get();
206 } catch (NamingException e
) {
207 throw new UserDirectoryException(
208 "Cannot get value for key " + key
, e
);
216 public Object
get(Object key
) {
218 Attribute attr
= getAttributes().get(key
.toString());
222 } catch (NamingException e
) {
223 throw new UserDirectoryException(
224 "Cannot get value for attribute " + key
, e
);
229 public Object
put(String key
, Object value
) {
230 userAdmin
.checkEdit();
234 if (!(value
instanceof String
|| value
instanceof byte[]))
235 throw new IllegalArgumentException(
236 "Value must be String or byte[]");
238 if (includeFilter
&& !attrFilter
.contains(key
))
239 throw new IllegalArgumentException("Key " + key
241 else if (!includeFilter
&& attrFilter
.contains(key
))
242 throw new IllegalArgumentException("Key " + key
+ " excluded");
245 Attribute attribute
= getModifiedAttributes().get(
247 attribute
= new BasicAttribute(key
.toString());
248 attribute
.add(value
);
249 Attribute previousAttribute
= getModifiedAttributes().put(
251 if (previousAttribute
!= null)
252 return previousAttribute
.get();
255 } catch (NamingException e
) {
256 throw new UserDirectoryException(
257 "Cannot get value for attribute " + key
, e
);
262 public Object
remove(Object key
) {
263 userAdmin
.checkEdit();
267 if (includeFilter
&& !attrFilter
.contains(key
))
268 throw new IllegalArgumentException("Key " + key
270 else if (!includeFilter
&& attrFilter
.contains(key
))
271 throw new IllegalArgumentException("Key " + key
+ " excluded");
274 Attribute attr
= getModifiedAttributes().remove(key
.toString());
279 } catch (NamingException e
) {
280 throw new UserDirectoryException("Cannot remove attribute "