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(DefaultHibernateGroup defGroup, User user) throws EntityException
371 {
372 ExternalEntity entity = getCorrespondingExternalEntity(user);
373
374 return defGroup.getExternalMembers().contains(entity);
375 }
376
377 protected boolean hasLocalMembership(DefaultHibernateGroup defGroup, DefaultHibernateUser defUser) throws EntityException
378 {
379 Collection usersGroups = getAllGroupsForUser(defUser);
380
381 return (usersGroups != null && usersGroups.contains(defGroup));
382 }
383
384 public void removeMembership(Group group, User user) throws EntityException
385 {
386 validateGroupAndUser(group, user);
387
388 Group groupInSession = getGroupInSession(group);
389
390 DefaultHibernateGroup hibernateGroup = (DefaultHibernateGroup) groupInSession;
391
392 HibernateTemplate hibernateTemplate = getHibernateTemplate();
393 if (isUserExternal(user))
394 {
395 ExternalEntity extUser = getCorrespondingExternalEntity(user);
396
397
398 hibernateGroup.getExternalMembers().remove(extUser);
399
400 }
401 else
402 {
403 if(USE_EXPERIMENTAL_MAPPINGS) {
404 DefaultHibernateUser huser = (DefaultHibernateUser)user;
405 huser.getGroups().remove(groupInSession);
406 hibernateTemplate.saveOrUpdate(huser);
407 }
408
409 else {
410
411 hibernateGroup.getLocalMembers().remove(user);
412 hibernateTemplate.saveOrUpdate(groupInSession);
413 }
414 }
415
416 hibernateTemplate.flush();
417 }
418
419 public boolean isReadOnly(Group group) throws EntityException
420 {
421 return (getGroup(group) == null);
422 }
423
424 public boolean supportsExternalMembership() throws EntityException
425 {
426 return true;
427 }
428
429
430
431
432 public RepositoryIdentifier getIdentifier()
433 {
434 return identifier;
435 }
436
437 public RepositoryIdentifier getRepository(Entity entity) throws EntityException
438 {
439 if (getGroup(entity.getName()) != null)
440 return identifier;
441
442 return null;
443 }
444
445
446
447
448
449 public boolean isCreative()
450 {
451 return true;
452 }
453
454
455
456
457
458 private DefaultHibernateGroup getGroupInSession(Group group)
459 throws EntityException
460 {
461 if (group == null)
462 throw new IllegalArgumentException("Input (group) is null.");
463 else if (!isHandledGroup(group))
464 throw new IllegalArgumentException("Group is not a Hibernate entity [" + group.getClass().getName());
465
466 return getGroup(group);
467 }
468
469 @SuppressWarnings("unchecked")
470 private List<Group> getGroupsFromHibernate()
471 {
472 return getHibernateTemplate().executeFind(new HibernateCallback()
473 {
474 public Object doInHibernate(Session session) throws HibernateException
475 {
476 Query queryObject = session.getNamedQuery("atluser.group_findAll");
477 SessionFactoryUtils.applyTransactionTimeout(queryObject, getSessionFactory());
478 return queryObject.list();
479 }
480 });
481 }
482
483
484 @SuppressWarnings("unchecked")
485 private List<Group> getLocalUserGroupsFromHibernate(final DefaultHibernateUser defUser) throws RepositoryException
486 {
487 try
488 {
489 return getHibernateTemplate().executeFind(new HibernateCallback()
490 {
491 public Object doInHibernate(Session session) throws HibernateException
492 {
493 Query queryObject = session.getNamedQuery("atluser.group_getGroupsForUser");
494 SessionFactoryUtils.applyTransactionTimeout(queryObject, getSessionFactory());
495 queryObject.setLong(ENTITYID_FIELD, defUser.getId());
496
497 return queryObject.list();
498 }
499 });
500 }
501 catch (DataAccessException e)
502 {
503 throw new RepositoryException(e);
504 }
505 }
506
507 @SuppressWarnings("unchecked")
508 private List<Group> getExternalUserGroupsFromHibernate(final ExternalEntity externalEntity) throws RepositoryException
509 {
510 try
511 {
512 return getHibernateTemplate().executeFind(new HibernateCallback()
513 {
514 public Object doInHibernate(Session session) throws HibernateException
515 {
516 Query queryObject = session.getNamedQuery("atluser.group_getGroupsForExternalEntity");
517 SessionFactoryUtils.applyTransactionTimeout(queryObject, getSessionFactory());
518
519 if (externalEntity != null)
520 queryObject.setLong(ENTITYID_FIELD, externalEntity.getId());
521
522 return queryObject.list();
523 }
524 });
525 }
526 catch (DataAccessException e)
527 {
528 throw new RepositoryException(e);
529 }
530 }
531
532 @SuppressWarnings("unchecked")
533 private List<String> getLocalMemberNamesFromHibernate(final DefaultHibernateGroup defGroup) throws RepositoryException
534 {
535 try
536 {
537 return getHibernateTemplate().executeFind(new HibernateCallback()
538 {
539 public Object doInHibernate(Session session) throws HibernateException
540 {
541 Query queryObject = session.getNamedQuery("atluser.group_getLocalMemberNames");
542 SessionFactoryUtils.applyTransactionTimeout(queryObject, getSessionFactory());
543
544 if (defGroup != null)
545 queryObject.setLong(GROUPID_FIELD, defGroup.getId());
546
547 return queryObject.list();
548 }
549 });
550 }
551 catch (DataAccessException e)
552 {
553 throw new RepositoryException(e);
554 }
555 }
556
557 @SuppressWarnings("unchecked")
558 private List<String> getExternalMemberNamesFromHibernate(final DefaultHibernateGroup defGroup)
559 throws RepositoryException
560 {
561 List result;
562 try
563 {
564 result = getHibernateTemplate().executeFind(new HibernateCallback()
565 {
566 public Object doInHibernate(Session session) throws HibernateException
567 {
568 Query queryObject = session.getNamedQuery("atluser.group_getExternalMemberNames");
569 SessionFactoryUtils.applyTransactionTimeout(queryObject, getSessionFactory());
570
571 if (defGroup != null)
572 queryObject.setLong(GROUPID_FIELD, defGroup.getId());
573
574 return queryObject.list();
575 }
576 });
577 }
578 catch (DataAccessException e)
579 {
580 throw new RepositoryException(e);
581 }
582 return result;
583 }
584 }