1 package com.atlassian.user.impl.hibernate;
2
3 import com.atlassian.user.*;
4 import com.atlassian.user.impl.DuplicateEntityException;
5 import com.atlassian.user.impl.RepositoryException;
6 import com.atlassian.user.impl.hibernate.repository.HibernateRepository;
7 import com.atlassian.user.repository.RepositoryIdentifier;
8 import com.atlassian.user.search.page.DefaultPager;
9 import com.atlassian.user.search.page.Pager;
10 import com.atlassian.user.search.page.PagerFactory;
11 import com.atlassian.user.util.Assert;
12 import net.sf.hibernate.HibernateException;
13 import net.sf.hibernate.ObjectDeletedException;
14 import net.sf.hibernate.Query;
15 import net.sf.hibernate.Session;
16 import org.springframework.dao.DataAccessException;
17 import org.springframework.orm.hibernate.HibernateCallback;
18 import org.springframework.orm.hibernate.HibernateTemplate;
19 import org.springframework.orm.hibernate.SessionFactoryUtils;
20 import org.springframework.orm.hibernate.support.HibernateDaoSupport;
21
22 import java.util.*;
23
24
25
26
27 public class HibernateGroupManager extends HibernateDaoSupport implements GroupManager
28 {
29 public static final String GROUPNAME_FIELD = "groupname";
30 public static final String GROUPID_FIELD = "groupid";
31 public static final String ENTITYID_FIELD = "entityid";
32 public static final String EXTERNAL_ENTITY_NAME_FIELD = "externalEntityName";
33
34 private final RepositoryIdentifier identifier;
35 protected final HibernateRepository repository;
36 protected final UserManager userManager;
37 protected final ExternalEntityDAO externalEntityDao;
38
39 private static final boolean USE_EXPERIMENTAL_MAPPINGS = Boolean.getBoolean("com.atlassian.user.experimentalMapping");
40
41 public HibernateGroupManager(RepositoryIdentifier identifier, HibernateRepository repository, UserManager userManager, ExternalEntityDAO externalEntityDao)
42 {
43 this.identifier = identifier;
44 this.repository = repository;
45 this.userManager = userManager;
46 setSessionFactory(repository.getSessionFactory());
47 this.externalEntityDao = externalEntityDao;
48 }
49
50 public Pager<Group> getGroups() throws EntityException
51 {
52 List<Group> result;
53
54 try
55 {
56 result = getGroupsFromHibernate();
57 }
58 catch (DataAccessException e)
59 {
60 throw new RepositoryException(e);
61 }
62
63 if (result == null)
64 return DefaultPager.emptyPager();
65
66 return new DefaultPager<Group>(result);
67 }
68
69 public List<Group> getWritableGroups()
70 {
71 return getGroupsFromHibernate();
72 }
73
74 public Pager<Group> getGroups(User user) throws EntityException
75 {
76 Collection<Group> groups = getAllGroupsForUser(user);
77 return new DefaultPager<Group>(groups);
78 }
79
80 protected Collection<Group> getAllGroupsForUser(User user) throws RepositoryException
81 {
82 Assert.notNull(user, "User must not be null");
83
84 if (isUserExternal(user))
85 return getGroupsForExternalEntity(getCorrespondingExternalEntity(user));
86
87 return getGroupsForLocalUser(user);
88 }
89
90
91
92
93 protected boolean isUserExternal(User user)
94 {
95 return !(user instanceof DefaultHibernateUser);
96 }
97
98 private List<Group> getGroupsForLocalUser(User user) throws RepositoryException
99 {
100 Assert.notNull(user, "User must not be null");
101 Assert.isInstanceOf(DefaultHibernateUser.class, user);
102
103 if (isUserExternal(user))
104 return Collections.emptyList();
105
106 return getLocalUserGroupsFromHibernate((DefaultHibernateUser) user);
107 }
108
109 private List<Group> getGroupsForExternalEntity(final ExternalEntity externalEntity) throws RepositoryException
110 {
111 if (externalEntity == null)
112 throw new IllegalArgumentException("Input (externalEntity) is null.");
113
114 return getExternalUserGroupsFromHibernate(externalEntity);
115 }
116
117
118
119
120 public Pager<String> getMemberNames(Group group) throws EntityException
121 {
122 if (group == null)
123 throw new IllegalArgumentException("Group cannot be null.");
124 if (!isHandledGroup(group))
125 throw new IllegalArgumentException("Group passed to HibernateGroupManager must be of type 'DefaultHibernateGroup'");
126
127
128
129
130
131
132 return PagerFactory.getPager(getExternalMemberNames(group), getLocalMemberNames(group));
133 }
134
135 protected void validateGroup(Group group)
136 {
137 if (group == null)
138 throw new IllegalArgumentException("Input (group) is null.");
139 }
140
141 public Pager<String> getLocalMemberNames(Group group) throws EntityException
142 {
143 validateGroup(group);
144 return new DefaultPager<String>(getLocalMemberNamesFromHibernate((DefaultHibernateGroup) group));
145 }
146
147 public Pager<User> getLocalMembers(Group group) throws RepositoryException
148 {
149 if (group == null)
150 throw new IllegalArgumentException("Input (group) is null.");
151 else if (!isHandledGroup(group))
152 return DefaultPager.emptyPager();
153
154 DefaultHibernateGroup defGroup = (DefaultHibernateGroup) group;
155 return new DefaultPager<User>(new ArrayList<User>(defGroup.getLocalMembers()));
156 }
157
158 private boolean isHandledGroup(Group group)
159 {
160 return (group instanceof DefaultHibernateGroup);
161 }
162
163 public Pager<String> getExternalMemberNames(Group group) throws EntityException
164 {
165 if (group == null)
166 throw new IllegalArgumentException("Input (group) is null.");
167 else if (!isHandledGroup(group))
168 return DefaultPager.emptyPager();
169
170 final DefaultHibernateGroup defGroup = (DefaultHibernateGroup) group;
171
172 return new DefaultPager<String>(getExternalMemberNamesFromHibernate(defGroup));
173 }
174
175 public DefaultHibernateGroup getGroup(Group group) throws EntityException
176 {
177
178 if (group instanceof DefaultHibernateGroup)
179 {
180
181 try
182 {
183 return (DefaultHibernateGroup) getSession().get(DefaultHibernateGroup.class, ((DefaultHibernateGroup) group).getId());
184 }
185 catch (ObjectDeletedException e)
186 {
187 return null;
188 }
189 catch (HibernateException e)
190 {
191 throw new EntityException(e);
192 }
193 }
194 else
195 {
196 return getGroup(group.getName());
197 }
198
199 }
200
201
202 public DefaultHibernateGroup getGroup(final String groupname) throws EntityException
203 {
204 if (groupname == null)
205 throw new IllegalArgumentException("Input (groupname) is null.");
206
207 List result;
208 DefaultHibernateGroup foundGroup = null;
209
210 try
211 {
212 result = getHibernateTemplate().executeFind(new HibernateCallback()
213 {
214 public Object doInHibernate(Session session) throws HibernateException
215 {
216 Query queryObject = session.getNamedQuery("atluser.group_find");
217 SessionFactoryUtils.applyTransactionTimeout(queryObject, getSessionFactory());
218
219 if (groupname != null)
220 queryObject.setParameter(GROUPNAME_FIELD, groupname);
221
222 return queryObject.list();
223 }
224 });
225 }
226 catch (DataAccessException e)
227 {
228 throw new RepositoryException(e);
229 }
230
231 try
232 {
233 foundGroup = (DefaultHibernateGroup) result.get(0);
234 }
235 catch (Exception e)
236 {
237 return foundGroup;
238 }
239
240 return foundGroup;
241 }
242
243 public Group createGroup(String groupname) throws EntityException
244 {
245 if (groupname == null)
246 throw new IllegalArgumentException("Input (groupname) is null.");
247
248 Group group = getGroup(groupname);
249
250 if (group == null)
251 {
252 group = new DefaultHibernateGroup(groupname);
253 getHibernateTemplate().save(group);
254 }
255 else
256 throw new DuplicateEntityException("Group [" + groupname + "] already exists in this repository (" +
257 identifier.getName() + ")");
258
259 return group;
260 }
261
262
263
264
265
266
267
268 public void removeGroup(Group group) throws EntityException
269 {
270 Group groupInSession = getGroupInSession(group);
271
272 DefaultHibernateGroup dGroup = (DefaultHibernateGroup) groupInSession;
273 dGroup.setExternalMembers(null);
274 dGroup.setLocalMembers(null);
275
276 getHibernateTemplate().delete(groupInSession);
277 }
278
279 public void addMembership(Group group, User user) throws EntityException
280 {
281 validateGroupAndUser(group, user);
282
283 DefaultHibernateGroup dGroup = getGroupInSession(group);
284
285 if (isUserExternal(user))
286 {
287 addExternalUserMembership(user, dGroup);
288 }
289 else
290 {
291 addLocalUserMembership(user, dGroup);
292 }
293
294 getHibernateTemplate().saveOrUpdate(dGroup);
295 }
296
297 private void addLocalUserMembership(User user, DefaultHibernateGroup dGroup)
298 {
299 if (USE_EXPERIMENTAL_MAPPINGS)
300 {
301 DefaultHibernateUser huser = (DefaultHibernateUser) user;
302 huser.getGroups().add(dGroup);
303 getHibernateTemplate().saveOrUpdate(user);
304 }
305 else
306 {
307 if (dGroup.getLocalMembers() == null)
308 dGroup.setLocalMembers(new HashSet<User>());
309
310 dGroup.getLocalMembers().add(user);
311 }
312 }
313
314 private void addExternalUserMembership(User user, DefaultHibernateGroup dGroup)
315 throws RepositoryException
316 {
317 if (dGroup.getExternalMembers() == null)
318 dGroup.setExternalMembers(new HashSet<ExternalEntity>());
319
320 dGroup.getExternalMembers().add(getCorrespondingExternalEntity(user));
321 }
322
323 protected ExternalEntity getCorrespondingExternalEntity(final User user) throws RepositoryException
324 {
325 if (user == null)
326 throw new IllegalArgumentException("Input (user) is null.");
327
328 ExternalEntity result = externalEntityDao.getExternalEntity(user.getName());
329
330 if (result == null)
331 return externalEntityDao.createExternalEntity(user.getName());
332 else
333 return result;
334 }
335
336 public boolean hasMembership(Group group, User user) throws EntityException
337 {
338 if (group==null || getGroup(group) == null)
339 return false;
340
341 validateGroupAndUser(group, user);
342
343 final DefaultHibernateGroup defGroup = getGroupInSession(group);
344
345 if (isUserExternal(user))
346 {
347 return hasExternalMembership(defGroup, user);
348 }
349 else
350 {
351 return hasLocalMembership(defGroup, (DefaultHibernateUser) user);
352 }
353 }
354
355 protected void validateGroupAndUser(Group group, User user) throws EntityException
356 {
357 if (group == null)
358 throw new IllegalArgumentException("Can't add membership for null group");
359
360 if (getGroup(group) == null)
361 throw new IllegalArgumentException("Group unknown: [" + group + "] in [" + identifier.getKey() + "]");
362
363 if (user == null)
364 throw new IllegalArgumentException("User unknown: [" + user + "] in [" + identifier.getKey() + "]");
365
366 if (!isHandledGroup(group))
367 throw new IllegalArgumentException("Group is not a Hibernate entity [" + group.getClass().getName());
368 }
369
370 protected boolean hasExternalMembership(final DefaultHibernateGroup defGroup, final User user) throws EntityException
371 {
372 try
373 {
374 return (Boolean)getHibernateTemplate().execute(new HibernateCallback()
375 {
376 public Object doInHibernate(final Session session) throws HibernateException
377 {
378 final Query queryObject = session.getNamedQuery("atluser.externalEntity_hasMembership");
379 SessionFactoryUtils.applyTransactionTimeout(queryObject, getSessionFactory());
380 queryObject.setLong(GROUPID_FIELD, defGroup.getId());
381 queryObject.setString(EXTERNAL_ENTITY_NAME_FIELD, user.getName());
382 Integer count = (Integer)queryObject.uniqueResult();
383 return count != null && count > 0;
384 }
385 });
386 }
387 catch (DataAccessException e)
388 {
389 throw new RepositoryException(e);
390 }
391 }
392
393 protected boolean hasLocalMembership(DefaultHibernateGroup defGroup, DefaultHibernateUser defUser) throws EntityException
394 {
395 Collection usersGroups = getAllGroupsForUser(defUser);
396
397 return (usersGroups != null && usersGroups.contains(defGroup));
398 }
399
400 public void removeMembership(Group group, User user) throws EntityException
401 {
402 validateGroupAndUser(group, user);
403
404 Group groupInSession = getGroupInSession(group);
405
406 DefaultHibernateGroup hibernateGroup = (DefaultHibernateGroup) groupInSession;
407
408 HibernateTemplate hibernateTemplate = getHibernateTemplate();
409 if (isUserExternal(user))
410 {
411 ExternalEntity extUser = getCorrespondingExternalEntity(user);
412
413
414 hibernateGroup.getExternalMembers().remove(extUser);
415
416 }
417 else
418 {
419 if(USE_EXPERIMENTAL_MAPPINGS) {
420 DefaultHibernateUser huser = (DefaultHibernateUser)user;
421 huser.getGroups().remove(groupInSession);
422 hibernateTemplate.saveOrUpdate(huser);
423 }
424
425 else {
426
427 hibernateGroup.getLocalMembers().remove(user);
428 hibernateTemplate.saveOrUpdate(groupInSession);
429 }
430 }
431
432 hibernateTemplate.flush();
433 }
434
435 public boolean isReadOnly(Group group) throws EntityException
436 {
437 return (getGroup(group) == null);
438 }
439
440 public boolean supportsExternalMembership() throws EntityException
441 {
442 return true;
443 }
444
445
446
447
448 public RepositoryIdentifier getIdentifier()
449 {
450 return identifier;
451 }
452
453 public RepositoryIdentifier getRepository(Entity entity) throws EntityException
454 {
455 if (getGroup(entity.getName()) != null)
456 return identifier;
457
458 return null;
459 }
460
461
462
463
464
465 public boolean isCreative()
466 {
467 return true;
468 }
469
470
471
472
473
474 private DefaultHibernateGroup getGroupInSession(Group group)
475 throws EntityException
476 {
477 if (group == null)
478 throw new IllegalArgumentException("Input (group) is null.");
479 else if (!isHandledGroup(group))
480 throw new IllegalArgumentException("Group is not a Hibernate entity [" + group.getClass().getName());
481
482 return getGroup(group);
483 }
484
485 @SuppressWarnings("unchecked")
486 private List<Group> getGroupsFromHibernate()
487 {
488 return getHibernateTemplate().executeFind(new HibernateCallback()
489 {
490 public Object doInHibernate(Session session) throws HibernateException
491 {
492 Query queryObject = session.getNamedQuery("atluser.group_findAll");
493 SessionFactoryUtils.applyTransactionTimeout(queryObject, getSessionFactory());
494 return queryObject.list();
495 }
496 });
497 }
498
499
500 @SuppressWarnings("unchecked")
501 private List<Group> getLocalUserGroupsFromHibernate(final DefaultHibernateUser defUser) throws RepositoryException
502 {
503 try
504 {
505 return getHibernateTemplate().executeFind(new HibernateCallback()
506 {
507 public Object doInHibernate(Session session) throws HibernateException
508 {
509 Query queryObject = session.getNamedQuery("atluser.group_getGroupsForUser");
510 SessionFactoryUtils.applyTransactionTimeout(queryObject, getSessionFactory());
511 queryObject.setLong(ENTITYID_FIELD, defUser.getId());
512
513 return queryObject.list();
514 }
515 });
516 }
517 catch (DataAccessException e)
518 {
519 throw new RepositoryException(e);
520 }
521 }
522
523 @SuppressWarnings("unchecked")
524 private List<Group> getExternalUserGroupsFromHibernate(final ExternalEntity externalEntity) throws RepositoryException
525 {
526 try
527 {
528 return getHibernateTemplate().executeFind(new HibernateCallback()
529 {
530 public Object doInHibernate(Session session) throws HibernateException
531 {
532 Query queryObject = session.getNamedQuery("atluser.group_getGroupsForExternalEntity");
533 SessionFactoryUtils.applyTransactionTimeout(queryObject, getSessionFactory());
534
535 if (externalEntity != null)
536 queryObject.setLong(ENTITYID_FIELD, externalEntity.getId());
537
538 return queryObject.list();
539 }
540 });
541 }
542 catch (DataAccessException e)
543 {
544 throw new RepositoryException(e);
545 }
546 }
547
548 @SuppressWarnings("unchecked")
549 private List<String> getLocalMemberNamesFromHibernate(final DefaultHibernateGroup defGroup) throws RepositoryException
550 {
551 try
552 {
553 return getHibernateTemplate().executeFind(new HibernateCallback()
554 {
555 public Object doInHibernate(Session session) throws HibernateException
556 {
557 Query queryObject = session.getNamedQuery("atluser.group_getLocalMemberNames");
558 SessionFactoryUtils.applyTransactionTimeout(queryObject, getSessionFactory());
559
560 if (defGroup != null)
561 queryObject.setLong(GROUPID_FIELD, defGroup.getId());
562
563 return queryObject.list();
564 }
565 });
566 }
567 catch (DataAccessException e)
568 {
569 throw new RepositoryException(e);
570 }
571 }
572
573 @SuppressWarnings("unchecked")
574 private List<String> getExternalMemberNamesFromHibernate(final DefaultHibernateGroup defGroup)
575 throws RepositoryException
576 {
577 List result;
578 try
579 {
580 result = getHibernateTemplate().executeFind(new HibernateCallback()
581 {
582 public Object doInHibernate(Session session) throws HibernateException
583 {
584 Query queryObject = session.getNamedQuery("atluser.group_getExternalMemberNames");
585 SessionFactoryUtils.applyTransactionTimeout(queryObject, getSessionFactory());
586
587 if (defGroup != null)
588 queryObject.setLong(GROUPID_FIELD, defGroup.getId());
589
590 return queryObject.list();
591 }
592 });
593 }
594 catch (DataAccessException e)
595 {
596 throw new RepositoryException(e);
597 }
598 return result;
599 }
600 }