1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.james.jcr;
21
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Iterator;
25
26 import javax.jcr.Credentials;
27 import javax.jcr.Node;
28 import javax.jcr.NodeIterator;
29 import javax.jcr.PathNotFoundException;
30 import javax.jcr.Repository;
31 import javax.jcr.RepositoryException;
32 import javax.jcr.Session;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.apache.james.api.user.User;
37 import org.apache.james.api.user.UsersRepository;
38
39
40 public class JCRUsersRepository extends AbstractJCRRepository implements UsersRepository {
41
42
43 private static final String PASSWD_PROPERTY = "passwd";
44
45 private static final String USERNAME_PROPERTY = "username";
46
47 private static final Log LOGGER = LogFactory.getLog(JCRMailRepository.class);
48
49
50
51
52 public JCRUsersRepository() {
53 super(LOGGER);
54 this.path = "users";
55 }
56
57
58
59
60
61
62
63
64
65
66
67 public JCRUsersRepository(Repository repository, Credentials credentials, String workspace, String path, Log logger) {
68 super(repository, credentials, workspace, path, logger);
69 }
70
71
72
73
74
75 public JCRUsersRepository(Repository repository) {
76 super(repository, LOGGER);
77 this.path = "users";
78 }
79
80
81
82
83
84
85
86
87
88
89
90
91
92 public boolean addUser(User user) {
93 throw new UnsupportedOperationException("Unsupported by JCR");
94 }
95
96
97
98
99
100
101
102
103
104
105
106 public void addUser(String name, Object attributes) {
107 if (attributes instanceof String) {
108 addUser(name, (String) attributes);
109 } else {
110 throw new IllegalArgumentException("Expected password string");
111 }
112 }
113
114
115
116
117
118
119
120
121
122
123 public boolean addUser(String username, String password) {
124
125 try {
126 final Session session = login();
127 try {
128 final String name = toSafeName(username);
129 final String path = this.path + "/" + name;
130 final Node rootNode = session.getRootNode();
131 try {
132 rootNode.getNode(path);
133 logger.info("User already exists");
134 return false;
135 } catch (PathNotFoundException e) {
136
137 }
138 Node parent;
139 try {
140 parent = rootNode.getNode(this.path);
141 } catch (PathNotFoundException e) {
142
143
144 parent = rootNode.addNode(this.path);
145 }
146
147 Node node = parent.addNode(name);
148 node.setProperty(USERNAME_PROPERTY, username);
149 final String hashedPassword;
150 if (password == null)
151 {
152
153 hashedPassword = "";
154 }
155 else
156 {
157 hashedPassword = JCRUser.hashPassword(username, password);
158 }
159 node.setProperty(PASSWD_PROPERTY, hashedPassword);
160 session.save();
161 return true;
162 } finally {
163 session.logout();
164 }
165
166 } catch (RepositoryException e) {
167 if (logger.isInfoEnabled()) {
168 logger.info("Failed to add user: " + username, e);
169 }
170 }
171
172 return false;
173 }
174
175
176
177
178
179
180
181
182
183
184 public User getUserByName(String username) {
185 User user;
186 try {
187 final Session session = login();
188 try {
189 final String name = toSafeName(username);
190 final String path = this.path + "/" + name;
191 final Node rootNode = session.getRootNode();
192
193 try {
194 final Node node = rootNode.getNode(path);
195 user = new JCRUser(node.getProperty(USERNAME_PROPERTY).getString(),
196 node.getProperty(PASSWD_PROPERTY).getString());
197 } catch (PathNotFoundException e) {
198
199 user = null;
200 }
201 } finally {
202 session.logout();
203 }
204
205 } catch (RepositoryException e) {
206 if (logger.isInfoEnabled()) {
207 logger.info("Failed to add user: " + username, e);
208 }
209 user = null;
210 }
211 return user;
212 }
213
214
215
216
217
218
219
220
221
222
223
224
225 public User getUserByNameCaseInsensitive(String name) {
226 throw new UnsupportedOperationException();
227 }
228
229
230
231
232
233
234
235
236 public String getRealName(String name) {
237 return null;
238 }
239
240
241
242
243
244
245
246 public boolean updateUser(final User user) {
247 if (user != null && user instanceof JCRUser)
248 {
249 final JCRUser jcrUser = (JCRUser) user;
250 final String userName = jcrUser.getUserName();
251 try {
252 final Session session = login();
253 try {
254 final String name = toSafeName(userName);
255 final String path = this.path + "/" + name;
256 final Node rootNode = session.getRootNode();
257
258 try {
259 final String hashedSaltedPassword = jcrUser.getHashedSaltedPassword();
260 rootNode.getNode(path).setProperty(PASSWD_PROPERTY, hashedSaltedPassword);
261 session.save();
262 return true;
263 } catch (PathNotFoundException e) {
264
265 logger.debug("User not found");
266 }
267 } finally {
268 session.logout();
269 }
270
271 } catch (RepositoryException e) {
272 if (logger.isInfoEnabled()) {
273 logger.info("Failed to add user: " + userName, e);
274 }
275 }
276 }
277 return false;
278 }
279
280
281
282
283
284
285 public void removeUser(String username) {
286 try {
287 final Session session = login();
288 try {
289 final String name = toSafeName(username);
290 final String path = this.path + "/" + name;
291 try {
292 session.getRootNode().getNode(path).remove();
293 session.save();
294 } catch (PathNotFoundException e) {
295
296 }
297 } finally {
298 session.logout();
299 }
300
301 } catch (RepositoryException e) {
302 if (logger.isInfoEnabled()) {
303 logger.info("Failed to add user: " + username, e);
304 }
305 }
306 }
307
308
309
310
311
312
313
314 public boolean contains(String name) {
315 try {
316 final Session session = login();
317 try {
318 final Node rootNode = session.getRootNode();
319 final String path = this.path + "/" + toSafeName(name);
320 rootNode.getNode(path);
321 return true;
322 } finally {
323 session.logout();
324 }
325
326 } catch (RepositoryException e) {
327 if (logger.isDebugEnabled()) {
328 logger.debug("User not found: " + name, e);
329 }
330 }
331
332 return false;
333 }
334
335
336
337
338
339
340
341
342
343
344
345 public boolean containsCaseInsensitive(String name) {
346 throw new UnsupportedOperationException();
347 }
348
349
350
351
352
353
354
355
356
357
358
359
360 public boolean test(String username, String password) {
361 try {
362 final Session session = login();
363 try {
364 final String name = toSafeName(username);
365 final String path = this.path + "/" + name;
366 final Node rootNode = session.getRootNode();
367
368 try {
369 final Node node = rootNode.getNode(path);
370 final String current = node.getProperty(PASSWD_PROPERTY).getString();
371 if (current == null || current == "")
372 {
373 return password == null || password == "";
374 }
375 final String hashPassword = JCRUser.hashPassword(username, password);
376 return current.equals(hashPassword);
377 } catch (PathNotFoundException e) {
378
379 logger.debug("User not found");
380 return false;
381 }
382 } finally {
383 session.logout();
384 }
385
386 } catch (RepositoryException e) {
387 if (logger.isInfoEnabled()) {
388 logger.info("Failed to add user: " + username, e);
389 }
390 return false;
391 }
392
393 }
394
395
396
397
398
399
400 public int countUsers() {
401 try {
402 final Session session = login();
403 try {
404 final Node rootNode = session.getRootNode();
405 try {
406 final Node node = rootNode.getNode(path);
407
408
409 NodeIterator it = node.getNodes();
410 return (int) it.getSize();
411 } catch (PathNotFoundException e) {
412 return 0;
413 }
414 } finally {
415 session.logout();
416 }
417 } catch (RepositoryException e) {
418 if (logger.isInfoEnabled()) {
419 logger.info("Failed to count user", e);
420 }
421 return 0;
422 }
423 }
424
425
426
427
428
429
430 public Iterator list() {
431 final Collection userNames = new ArrayList();
432 try {
433 final Session session = login();
434 try {
435 final Node rootNode = session.getRootNode();
436 try {
437 final Node baseNode = rootNode.getNode(path);
438
439 final NodeIterator it = baseNode.getNodes();
440 while(it.hasNext()) {
441 final Node node = it.nextNode();
442 try {
443 final String userName = node.getProperty(USERNAME_PROPERTY).getString();
444 userNames.add(userName);
445 } catch (PathNotFoundException e) {
446 logger.info("Node missing user name. Ignoring.");
447 }
448 }
449 } catch (PathNotFoundException e) {
450 logger.info("Path not found. Forgotten to setup the repository?");
451 }
452 } finally {
453 session.logout();
454 }
455 } catch (RepositoryException e) {
456 if (logger.isInfoEnabled()) {
457 logger.info("Failed to count user", e);
458 }
459 }
460 return userNames.iterator();
461 }
462 }