001: /* Copyright 2001, 2002 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal.groups;
007:
008: import java.util.ArrayList;
009: import java.util.Collection;
010: import java.util.Iterator;
011:
012: import org.jasig.portal.EntityIdentifier;
013: import org.jasig.portal.concurrency.CachingException;
014: import org.jasig.portal.concurrency.IEntityLock;
015: import org.jasig.portal.concurrency.LockingException;
016: import org.jasig.portal.groups.local.EntitySearcherImpl;
017: import org.jasig.portal.groups.local.ITypedEntitySearcher;
018: import org.jasig.portal.groups.local.searchers.RDBMChannelDefSearcher;
019: import org.jasig.portal.groups.local.searchers.RDBMPersonSearcher;
020: import org.jasig.portal.properties.PropertiesManager;
021: import org.jasig.portal.services.EntityCachingService;
022: import org.jasig.portal.services.EntityLockService;
023: import org.apache.commons.logging.Log;
024: import org.apache.commons.logging.LogFactory;
025:
026: /**
027: * Reference group service.
028: *
029: * @author Dan Ellentuck
030: * @version $Revision: 36683 $
031: * @deprecated Use instead an {@link ICompositeGroupService}
032: * implementation.
033: */
034: public class ReferenceGroupService implements ILockableGroupService {
035: private static final Log log = LogFactory
036: .getLog(ReferenceGroupService.class);
037:
038: /**
039: * Default value for cacheInUse.
040: * This value will be used when the corresponding property cannot be loaded.
041: */
042: private static final boolean DEFAULT_USE_CACHE = false;
043:
044: // Singleton instance:
045: protected static IGroupService singleton = null;
046:
047: // Factories for IGroupMembers:
048: protected IEntityStore entityFactory = null;
049: protected IEntityGroupStore groupFactory = null;
050:
051: // Entity searcher
052: protected IEntitySearcher entitySearcher = null;
053:
054: // Are group members cached? See portal.properties.
055: private boolean cacheInUse;
056:
057: /**
058: * ReferenceGroupsService constructor.
059: */
060: private ReferenceGroupService() throws GroupsException {
061: super ();
062: initialize();
063: }
064:
065: /**
066: *
067: */
068: protected void addGroupToCache(IEntityGroup group)
069: throws CachingException {
070: EntityCachingService.instance().add(group);
071: }
072:
073: /**
074: * Answers if <code>IGroupMembers</code> are being cached.
075: */
076: protected boolean cacheInUse() {
077: return cacheInUse;
078: }
079:
080: /**
081: * Removes the <code>IEntityGroup</code> from the cache and the store.
082: * @param group IEntityGroup
083: */
084: public void deleteGroup(IEntityGroup group) throws GroupsException {
085: if (cacheInUse()) {
086: try {
087: removeGroupFromCache(group);
088: } catch (CachingException ce) {
089: throw new GroupsException("Problem deleting group "
090: + group.getKey(), ce);
091: }
092: }
093: getGroupStore().delete(group);
094: }
095:
096: /**
097: * Removes the <code>ILockableEntityGroup</code> from the cache and the store.
098: * @param group ILockableEntityGroup
099: */
100: public void deleteGroup(ILockableEntityGroup group)
101: throws GroupsException {
102: try {
103: if (group.getLock().isValid()) {
104: deleteGroup((IEntityGroup) group);
105: group.getLock().release();
106: } else {
107: throw new GroupsException("Could not delete group "
108: + group.getKey() + " has invalid lock.");
109: }
110: } catch (LockingException le) {
111: throw new GroupsException("Could not delete group "
112: + group.getKey(), le);
113: }
114: }
115:
116: /**
117: * Returns and caches the containing groups for the <code>IGroupMember</code>
118: * @param gm IGroupMember
119: */
120: public Iterator findContainingGroups(IGroupMember gm)
121: throws GroupsException {
122: Collection groups = new ArrayList(10);
123: IEntityGroup group = null;
124: for (Iterator it = getGroupStore().findContainingGroups(gm); it
125: .hasNext();) {
126: group = (IEntityGroup) it.next();
127: groups.add(group);
128: if (cacheInUse()) {
129: try {
130: if (getGroupFromCache(group.getEntityIdentifier()
131: .getKey()) == null) {
132: addGroupToCache(group);
133: }
134: } catch (CachingException ce) {
135: throw new GroupsException(
136: "Problem finding containing groups", ce);
137: }
138: }
139: }
140: return groups.iterator();
141: }
142:
143: /**
144: * Returns a pre-existing <code>IEntityGroup</code> or null if it
145: * does not exist.
146: */
147: public IEntityGroup findGroup(String key) throws GroupsException {
148: return (cacheInUse()) ? findGroupWithCache(key) : groupFactory
149: .find(key);
150: }
151:
152: /**
153: * Returns a pre-existing <code>IEntityGroup</code> or null if it
154: * does not exist.
155: */
156: protected IEntityGroup findGroupWithCache(String key)
157: throws GroupsException {
158: try {
159: IEntityGroup group = getGroupFromCache(key);
160: if (group == null) {
161: group = groupFactory.find(key);
162: if (group != null) {
163: addGroupToCache(group);
164: }
165: }
166: return group;
167: } catch (CachingException ce) {
168: throw new GroupsException(
169: "Problem retrieving group " + key, ce);
170: }
171: }
172:
173: /**
174: * Returns a pre-existing <code>ILockableEntityGroup</code> or null if the
175: * group is not found.
176: */
177: public ILockableEntityGroup findGroupWithLock(String key,
178: String owner) throws GroupsException {
179: return findGroupWithLock(key, owner, 0);
180: }
181:
182: /**
183: * Returns a pre-existing <code>ILockableEntityGroup</code> or null if the
184: * group is not found.
185: */
186: public ILockableEntityGroup findGroupWithLock(String key,
187: String owner, int secs) throws GroupsException {
188: Class groupType = org.jasig.portal.EntityTypes.GROUP_ENTITY_TYPE;
189: try {
190: IEntityLock lock = (secs == 0) ? EntityLockService
191: .instance().newWriteLock(groupType, key, owner)
192: : EntityLockService.instance().newWriteLock(
193: groupType, key, owner, secs);
194:
195: ILockableEntityGroup group = groupFactory.findLockable(key);
196: if (group == null) {
197: lock.release();
198: } else {
199: group.setLock(lock);
200: }
201:
202: return group;
203: } catch (LockingException le) {
204: throw new GroupsException("Problem getting lock for group "
205: + key, le);
206: }
207:
208: }
209:
210: /**
211: * Returns and caches the member groups for the <code>IEntityGroup</code>
212: * @param eg IEntityGroup
213: */
214: public Iterator findMemberGroups(IEntityGroup eg)
215: throws GroupsException {
216: Collection groups = new ArrayList(10);
217: IEntityGroup group = null;
218: for (Iterator it = getGroupStore().findMemberGroups(eg); it
219: .hasNext();) {
220: group = (IEntityGroup) it.next();
221: groups.add(group);
222: if (cacheInUse()) {
223: try {
224: if (getGroupFromCache(group.getEntityIdentifier()
225: .getKey()) == null) {
226: addGroupToCache(group);
227: }
228: } catch (CachingException ce) {
229: throw new GroupsException(
230: "Problem finding member groups", ce);
231: }
232: }
233: }
234: return groups.iterator();
235: }
236:
237: /**
238: * Refers to the PropertiesManager to get the key for the group
239: * associated with 'name' and asks the group store implementation for the corresponding
240: * <code>IEntityGroup</code>.
241: */
242: public IEntityGroup getDistinguishedGroup(String name)
243: throws GroupsException {
244:
245: String key = PropertiesManager.getProperty(
246: "org.jasig.portal.groups.ReferenceGroupService.key_"
247: + name, null);
248: if (key != null) {
249: return findGroup(key);
250: } else {
251: throw new GroupsException(
252: "ReferenceGroupService.getDistinguishedGroup(): no key found to match requested name ["
253: + name + "]");
254: }
255: }
256:
257: /**
258: * Returns an <code>IEntity</code> representing a portal entity. This does
259: * not guarantee that the entity actually exists.
260: */
261: public IEntity getEntity(String key, Class type)
262: throws GroupsException {
263: return entityFactory.newInstance(key, type);
264: }
265:
266: /**
267: * Returns a cached <code>IEntityGroup</code> or null if it has not been cached.
268: */
269: protected IEntityGroup getGroupFromCache(String key)
270: throws CachingException {
271: return (IEntityGroup) EntityCachingService.instance().get(
272: org.jasig.portal.EntityTypes.GROUP_ENTITY_TYPE, key);
273: }
274:
275: /**
276: * Returns an <code>IGroupMember</code> representing either a group or a
277: * portal entity, based on the <code>EntityIdentifier</code>, which
278: * refers to the UNDERLYING entity for the <code>IGroupMember</code>.
279: */
280: public IGroupMember getGroupMember(
281: EntityIdentifier underlyingEntityIdentifier)
282: throws GroupsException {
283: return getGroupMember(underlyingEntityIdentifier.getKey(),
284: underlyingEntityIdentifier.getType());
285: }
286:
287: /**
288: * Returns an <code>IGroupMember</code> representing either a group or a
289: * portal entity. If the parm <code>type</code> is the group type,
290: * the <code>IGroupMember</code> is an <code>IEntityGroup</code> else it is
291: * an <code>IEntity</code>.
292: */
293: public IGroupMember getGroupMember(String key, Class type)
294: throws GroupsException {
295: IGroupMember gm = null;
296: if (type == org.jasig.portal.EntityTypes.GROUP_ENTITY_TYPE)
297: gm = findGroup(key);
298: else
299: gm = getEntity(key, type);
300: return gm;
301: }
302:
303: /**
304: * Returns the implementation of <code>IEntityGroupStore</code> whose class name
305: * was retrieved by the PropertiesManager (see initialize()).
306: */
307: public IEntityGroupStore getGroupStore() throws GroupsException {
308: return groupFactory;
309: }
310:
311: /**
312: * Refers to the PropertiesManager to get the key for the root group
313: * associated with 'type' and asks the group store implementation for the corresponding
314: * <code>IEntityGroup</code>.
315: */
316: public IEntityGroup getRootGroup(Class type) throws GroupsException {
317: return getDistinguishedGroup(type.getName());
318: }
319:
320: /**
321: * @exception org.jasig.portal.groups.GroupsException
322: */
323: private void initialize() throws GroupsException {
324: String eMsg = null;
325: entityFactory = new RDBMEntityStore();
326:
327: String groupFactoryName = PropertiesManager
328: .getProperty(
329: "org.jasig.portal.groups.EntityGroupFactory.implementation",
330: null);
331:
332: if (groupFactoryName == null) {
333: eMsg = "ReferenceGroupService.initialize(): EntityGroupStoreImpl not specified in portal.properties";
334: log.error(eMsg);
335: throw new GroupsException(eMsg);
336: }
337:
338: try {
339: groupFactory = (IEntityGroupStore) Class.forName(
340: groupFactoryName).newInstance();
341: } catch (Exception e) {
342: eMsg = "ReferenceGroupService.initialize(): Failed to instantiate "
343: + groupFactoryName;
344: log.error(eMsg);
345: throw new GroupsException(eMsg, e);
346: }
347:
348: cacheInUse = PropertiesManager.getPropertyAsBoolean(
349: "org.jasig.portal.groups.IEntityGroupService.useCache",
350: DEFAULT_USE_CACHE);
351:
352: ITypedEntitySearcher[] tes = new ITypedEntitySearcher[2];
353: tes[0] = new RDBMChannelDefSearcher();
354: tes[1] = new RDBMPersonSearcher();
355: entitySearcher = new EntitySearcherImpl(tes);
356: }
357:
358: /**
359: * Returns a new <code>IEntityGroup</code> for the given Class with an unused
360: * key.
361: */
362: public IEntityGroup newGroup(Class type) throws GroupsException {
363: try {
364: IEntityGroup group = groupFactory.newInstance(type);
365: addGroupToCache(group);
366: return group;
367: } catch (CachingException e) {
368: throw new GroupsException(e);
369: }
370: }
371:
372: /**
373: *
374: */
375: protected void removeGroupFromCache(IEntityGroup group)
376: throws CachingException {
377: EntityCachingService.instance().remove(
378: group.getEntityIdentifier());
379: }
380:
381: /**
382: * @return org.jasig.portal.groups.IGroupService
383: * @exception org.jasig.portal.groups.GroupsException
384: */
385: public static synchronized IGroupService singleton()
386: throws GroupsException {
387: if (singleton == null) {
388: singleton = new ReferenceGroupService();
389: }
390: return singleton;
391: }
392:
393: /**
394: * Updates the cache and the store with the new <code>IEntityGroup</code>.
395: * @param group IEntityGroup
396: */
397: public void updateGroup(IEntityGroup group) throws GroupsException {
398: if (cacheInUse()) {
399: try {
400: updateGroupInCache(group);
401: } catch (CachingException ce) {
402: throw new GroupsException("Problem updating group "
403: + group.getKey(), ce);
404: }
405: }
406: getGroupStore().update(group);
407: }
408:
409: /**
410: * Updates the <code>ILockableEntityGroup</code> in the cache and the store.
411: * @param group ILockableEntityGroup
412: */
413: public void updateGroup(ILockableEntityGroup group)
414: throws GroupsException {
415: updateGroup(group, false);
416: }
417:
418: /**
419: * Updates the <code>ILockableEntityGroup</code> in the store and removes
420: * it from the cache.
421: * @param group ILockableEntityGroup
422: */
423: public void updateGroup(ILockableEntityGroup group,
424: boolean renewLock) throws GroupsException {
425: try {
426: if (!group.getLock().isValid()) {
427: throw new GroupsException("Could not update group "
428: + group.getKey() + " has invalid lock.");
429: }
430:
431: if (!renewLock) {
432: updateGroup((IEntityGroup) group);
433: group.getLock().release();
434: } else {
435: getGroupStore().update(group);
436: if (cacheInUse) {
437: removeGroupFromCache(group);
438: }
439: group.getLock().renew();
440: }
441: } catch (LockingException le) {
442: throw new GroupsException("Problem updating group "
443: + group.getKey(), le);
444: } catch (CachingException ce) {
445: throw new GroupsException("Problem updating group "
446: + group.getKey(), ce);
447: }
448: }
449:
450: /**
451: *
452: */
453: protected void updateGroupInCache(IEntityGroup group)
454: throws CachingException {
455: EntityCachingService.instance().update(group);
456: }
457:
458: /**
459: * Updates the cache and the store with the updated <code>IEntityGroup</code>.
460: * @param group IEntityGroup
461: */
462: public void updateGroupMembers(IEntityGroup group)
463: throws GroupsException {
464: if (cacheInUse()) {
465: try {
466: EntityCachingService.instance().update(group);
467: } catch (CachingException ce) {
468: throw new GroupsException(
469: "Problem updating members for group "
470: + group.getKey(), ce);
471: }
472: }
473: getGroupStore().updateMembers(group);
474: }
475:
476: /**
477: * Updates the <code>ILockableEntityGroup</code> in the cache and the store.
478: * @param group ILockableEntityGroup
479: */
480: public void updateGroupMembers(ILockableEntityGroup group)
481: throws GroupsException {
482: updateGroupMembers(group, false);
483: }
484:
485: /**
486: * Updates the <code>ILockableEntityGroup</code> in the store and removes
487: * it from the cache.
488: * @param group ILockableEntityGroup
489: */
490: public void updateGroupMembers(ILockableEntityGroup group,
491: boolean renewLock) throws GroupsException {
492: try {
493: if (!group.getLock().isValid()) {
494: throw new GroupsException("Could not update group "
495: + group.getKey() + " has invalid lock.");
496: }
497:
498: if (!renewLock) {
499: updateGroupMembers((IEntityGroup) group);
500: group.getLock().release();
501: } else {
502: getGroupStore().updateMembers(group);
503: if (cacheInUse) {
504: removeGroupFromCache(group);
505: }
506: group.getLock().renew();
507: }
508: } catch (LockingException le) {
509: throw new GroupsException("Problem updating group "
510: + group.getKey(), le);
511: } catch (CachingException ce) {
512: throw new GroupsException("Problem updating group "
513: + group.getKey(), ce);
514: }
515: }
516:
517: public EntityIdentifier[] searchForGroups(String query, int method,
518: Class leaftype) throws GroupsException {
519: return removeDuplicates(groupFactory.searchForGroups(query,
520: method, leaftype));
521: }
522:
523: public EntityIdentifier[] searchForGroups(String query, int method,
524: Class leaftype, IEntityGroup ancestor)
525: throws GroupsException {
526: return filterEntities(searchForGroups(query, method, leaftype),
527: ancestor);
528: }
529:
530: public EntityIdentifier[] searchForEntities(String query,
531: int method, Class type) throws GroupsException {
532: return removeDuplicates(entitySearcher.searchForEntities(query,
533: method, type));
534: }
535:
536: public EntityIdentifier[] searchForEntities(String query,
537: int method, Class type, IEntityGroup ancestor)
538: throws GroupsException {
539: return filterEntities(searchForEntities(query, method, type),
540: ancestor);
541: }
542:
543: private EntityIdentifier[] filterEntities(
544: EntityIdentifier[] entities, IEntityGroup ancestor)
545: throws GroupsException {
546: ArrayList ar = new ArrayList(entities.length);
547: for (int i = 0; i < entities.length; i++) {
548: IGroupMember gm = this .getGroupMember(entities[i]);
549: if (ancestor.deepContains(gm)) {
550: ar.add(entities[i]);
551: }
552: }
553: return (EntityIdentifier[]) ar.toArray(new EntityIdentifier[0]);
554: }
555:
556: private EntityIdentifier[] removeDuplicates(
557: EntityIdentifier[] entities) {
558: ArrayList ar = new ArrayList(entities.length);
559: for (int i = 0; i < entities.length; i++) {
560: if (!ar.contains(entities[i])) {
561: ar.add(entities[i]);
562: }
563: }
564: return (EntityIdentifier[]) ar.toArray(new EntityIdentifier[0]);
565: }
566: }
|