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.services;
007:
008: import javax.naming.InvalidNameException;
009: import javax.naming.Name;
010:
011: import org.apache.commons.logging.Log;
012: import org.apache.commons.logging.LogFactory;
013: import org.jasig.portal.EntityIdentifier;
014: import org.jasig.portal.concurrency.CachingException;
015: import org.jasig.portal.groups.CompositeEntityIdentifier;
016: import org.jasig.portal.groups.CompositeServiceIdentifier;
017: import org.jasig.portal.groups.GroupServiceConfiguration;
018: import org.jasig.portal.groups.GroupsException;
019: import org.jasig.portal.groups.ICompositeGroupService;
020: import org.jasig.portal.groups.ICompositeGroupServiceFactory;
021: import org.jasig.portal.groups.IEntity;
022: import org.jasig.portal.groups.IEntityGroup;
023: import org.jasig.portal.groups.IGroupConstants;
024: import org.jasig.portal.groups.IGroupMember;
025: import org.jasig.portal.groups.IGroupService;
026: import org.jasig.portal.groups.IGroupServiceFactory;
027: import org.jasig.portal.groups.ILockableEntityGroup;
028: import org.jasig.portal.properties.PropertiesManager;
029: import org.jasig.portal.security.IPerson;
030:
031: /**
032: * Bootstrap class for the IGroupService implementation.
033: *
034: * @author Alex Vigdor
035: * @author Dan Ellentuck
036: * @version $Revision: 36429 $
037: */
038:
039: public class GroupService implements IGroupConstants {
040:
041: private static final Log log = LogFactory
042: .getLog(GroupService.class);
043:
044: // Singleton instance of the bootstrap class:
045: private static GroupService instance = null;
046:
047: // Switch for composite/simple service
048: private static boolean composite;
049:
050: // The group service:
051: private IGroupService groupService = null;
052: private ICompositeGroupService compositeGroupService = null;
053:
054: protected static final String GROUP_SERVICE_KEY = "org.jasig.portal.services.GroupService.key_";
055:
056: /** Creates new GroupService */
057: private GroupService() throws GroupsException {
058: super ();
059: initializeCompositeService();
060: }
061:
062: /**
063: * Returns a pre-existing <code>IEntityGroup</code> or null if the
064: * <code>IGroupMember</code> does not exist.
065: * @param key String - the group key.
066: * @return org.jasig.portal.groups.IEntityGroup
067: */
068: public static IEntityGroup findGroup(String key)
069: throws GroupsException {
070: return instance().ifindGroup(key);
071: }
072:
073: /**
074: * Returns a pre-existing <code>ILockableEntityGroup</code> or null if the
075: * group is not found.
076: * @param key String - the group key.
077: * @param lockOwner String - the owner of the lock, typically the user.
078: * @return org.jasig.portal.groups.ILockableEntityGroup
079: */
080: public static ILockableEntityGroup findLockableGroup(String key,
081: String lockOwner) throws GroupsException {
082: return instance().ifindLockableGroup(key, lockOwner);
083: }
084:
085: /**
086: * Receives notice that the UserInstance has been unbound from
087: * the HttpSession. In response, we remove the corresponding group member
088: * from the cache.
089: * @param person org.jasig.portal.security.IPerson
090: */
091: public static void finishedSession(IPerson person) {
092: try {
093: instance().ifinishedSession(person);
094: } catch (GroupsException ge) {
095: log.error("Error upon session finishing for person ["
096: + person + "]", ge);
097: }
098: }
099:
100: /**
101: * Returns the <code>ICompositeGroupService</code> implementation in use.
102: * @return org.jasig.portal.groups.ICompositeGroupService
103: */
104: public static ICompositeGroupService getCompositeGroupService()
105: throws GroupsException {
106: return instance().compositeGroupService;
107: }
108:
109: /**
110: * @return java.lang.String
111: */
112: protected String getDefaultServiceName() throws GroupsException {
113: return (String) getServiceConfiguration().getAttributes().get(
114: "defaultService");
115: }
116:
117: /**
118: * Refers to the PropertiesManager to get the key for the group
119: * associated with 'name' and asks the group store implementation for the corresponding
120: * <code>IEntityGroup</code>.
121: */
122: public static IEntityGroup getDistinguishedGroup(String name)
123: throws GroupsException {
124: return instance().igetDistinguishedGroup(name);
125: }
126:
127: /**
128: * @return java.lang.String
129: */
130: public String getDistinguishedGroupKey(String name) {
131: return PropertiesManager.getProperty(GROUP_SERVICE_KEY + name,
132: "");
133: }
134:
135: /**
136: * Returns an <code>IEntity</code> representing a portal entity. This does
137: * not guarantee that the entity actually exists.
138: * @param key String - the group key.
139: * @param type Class - the Class of the underlying IGroupMember.
140: * @return org.jasig.portal.groups.IEntity
141: */
142: public static IEntity getEntity(String key, Class type)
143: throws GroupsException {
144: return getEntity(key, type, null);
145:
146: }
147:
148: /**
149: * Returns an <code>IEntity</code> representing a portal entity. This does
150: * not guarantee that the entity actually exists.
151: *
152: * @param key
153: * String - the group key.
154: * @param type
155: * Class - the Class of the underlying IGroupMember.
156: * @param service
157: * String - the name of the component service.
158: * @return org.jasig.portal.groups.IEntity
159: */
160: public static IEntity getEntity(String key, Class type,
161: String service) throws GroupsException {
162: return instance().igetEntity(key, type, service);
163: }
164:
165: /**
166: * Returns an <code> IGroupMember </code> representing either a group or a
167: * portal entity. If the parm <code> type </code> is the group type, the
168: * <code> IGroupMember </code> is an <code> IEntityGroup </code> else it is
169: * an <code> IEntity </code> .
170: */
171: public static IGroupMember getGroupMember(String key, Class type)
172: throws GroupsException {
173: return instance().igetGroupMember(key, type);
174: }
175:
176: /**
177: * Returns an <code>IGroupMember</code> representing either a group or a
178: * portal entity, based on the <code>EntityIdentifier</code>, which
179: * refers to the UNDERLYING entity for the <code>IGroupMember</code>.
180: */
181: public static IGroupMember getGroupMember(
182: EntityIdentifier underlyingEntityIdentifier)
183: throws GroupsException {
184: return getGroupMember(underlyingEntityIdentifier.getKey(),
185: underlyingEntityIdentifier.getType());
186: }
187:
188: /**
189: * Returns the <code>IGroupService</code> implementation in use.
190: * @return org.jasig.portal.groups.IGroupService
191: */
192: public static IGroupService getGroupService()
193: throws GroupsException {
194: return instance().groupService;
195: }
196:
197: /**
198: * Refers to the PropertiesManager to get the key for the root group
199: * associated with 'type' and asks the group store implementation for the corresponding
200: * <code>IEntityGroup</code>.
201: */
202: public static IEntityGroup getRootGroup(Class type)
203: throws GroupsException {
204: return instance().igetRootGroup(type);
205: }
206:
207: /**
208: * @return java.lang.String
209: */
210: protected GroupServiceConfiguration getServiceConfiguration()
211: throws GroupsException {
212: try {
213: return GroupServiceConfiguration.getConfiguration();
214: } catch (Exception ex) {
215: throw new GroupsException(
216: "Problem retrieving service configuration", ex);
217: }
218: }
219:
220: /**
221: * Returns a pre-existing <code>IEntityGroup</code> or null if the
222: * <code>IGroupMember</code> does not exist.
223: * @param key String - the group key.
224: * @return org.jasig.portal.groups.IEntityGroup
225: */
226: protected IEntityGroup ifindGroup(String key)
227: throws GroupsException {
228: return compositeGroupService.findGroup(key);
229: }
230:
231: /**
232: * Returns a pre-existing <code>ILockableEntityGroup</code> or null if the
233: * group is not found.
234: * @param key String - the group key.
235: * @param lockOwner String - typically the user.
236: * @return org.jasig.portal.groups.ILockableEntityGroup
237: */
238: protected ILockableEntityGroup ifindLockableGroup(String key,
239: String lockOwner) throws GroupsException {
240: return compositeGroupService.findGroupWithLock(key, lockOwner);
241: }
242:
243: /**
244: * Receives notice that the UserInstance has been unbound from the
245: * HttpSession. In response, we remove the corresponding group member from
246: * the cache. We use the roundabout route of creating a group member and
247: * then getting its EntityIdentifier because we need the EntityIdentifier
248: * for the group member, which is cached, not the EntityIdentifier for the
249: * IPerson, which is not.
250: * @param person org.jasig.portal.security.IPerson
251: */
252: protected void ifinishedSession(IPerson person)
253: throws GroupsException {
254: IGroupMember gm = getGroupMember(person.getEntityIdentifier());
255: try {
256: EntityCachingService.instance().remove(
257: gm.getEntityIdentifier());
258: } catch (CachingException ce) {
259: throw new GroupsException("Problem removing group member "
260: + gm.getKey() + " from cache", ce);
261: }
262: }
263:
264: /**
265: * Refers to the PropertiesManager to get the key for the group
266: * associated with 'name' and asks the group store implementation for the corresponding
267: * <code>IEntityGroup</code>.
268: */
269: protected IEntityGroup igetDistinguishedGroup(String name)
270: throws GroupsException {
271: try {
272: String key = getDistinguishedGroupKey(name);
273: return compositeGroupService.findGroup(key);
274: } catch (Exception ex) {
275: throw new GroupsException(
276: "GroupService.getDistinguishedGroup(): "
277: + "could not find key for: " + name, ex);
278: }
279: }
280:
281: /**
282: * Returns an <code>IEntity</code> representing a pre-existing portal entity.
283: * @param key String - the group key.
284: * @param type Class - the Class of the underlying IGroupMember.
285: * @return org.jasig.portal.groups.IEntity
286: */
287: protected IEntity igetEntity(String key, Class type, String service)
288: throws GroupsException {
289: return compositeGroupService.getEntity(key, type, service);
290: }
291:
292: /**
293: * Returns an <code>IGroupMember</code> representing either a group or a
294: * portal entity. If the parm <code>type</code> is the group type,
295: * the <code>IGroupMember</code> is an <code>IEntityGroup</code> else it is
296: * an <code>IEntity</code>.
297: */
298: protected IGroupMember igetGroupMember(String key, Class type)
299: throws GroupsException {
300: return compositeGroupService.getGroupMember(key, type);
301: }
302:
303: /**
304: * Refers to the PropertiesManager to get the key for the root group
305: * associated with 'type' and asks the group store implementation for the corresponding
306: * <code>IEntityGroup</code>.
307: */
308: protected IEntityGroup igetRootGroup(Class type)
309: throws GroupsException {
310: return igetDistinguishedGroup(type.getName());
311: }
312:
313: /**
314: * Returns a new <code>IEntityGroup</code> for the given Class with an unused
315: * key.
316: * @return org.jasig.portal.groups.IEntityGroup
317: */
318: protected IEntityGroup inewGroup(Class type) throws GroupsException {
319: return inewGroup(type, getDefaultServiceName());
320: }
321:
322: /**
323: * Returns a new <code>IEntityGroup</code> for the given Class with an unused
324: * key.
325: * @return org.jasig.portal.groups.IEntityGroup
326: */
327: protected IEntityGroup inewGroup(Class type, String serviceName)
328: throws GroupsException {
329: try {
330: return compositeGroupService.newGroup(type,
331: parseServiceName(serviceName));
332: } catch (InvalidNameException ine) {
333: throw new GroupsException(
334: "GroupService.inewGroup(): invalid service name",
335: ine);
336: }
337: }
338:
339: /**
340: * @exception org.jasig.portal.groups.GroupsException
341: */
342: private void initialize() throws GroupsException {
343: composite = false;
344: String eMsg = null;
345: String factoryName = PropertiesManager
346: .getProperty("org.jasig.portal.groups.GroupServiceFactory");
347:
348: if (factoryName == null) {
349: eMsg = "GroupService.initialize(): No entry for org.jasig.portal.groups.GroupServiceFactory in portal.properties.";
350: log.error(eMsg);
351: throw new GroupsException(eMsg);
352: }
353:
354: try {
355: IGroupServiceFactory groupServiceFactory = (IGroupServiceFactory) Class
356: .forName(factoryName).newInstance();
357: groupService = groupServiceFactory.newGroupService();
358: } catch (Exception e) {
359: eMsg = "GroupService.initialize(): Problem creating groups service...";
360: log.error(eMsg, e);
361: throw new GroupsException(eMsg, e);
362: }
363: }
364:
365: /**
366: * @exception org.jasig.portal.groups.GroupsException
367: */
368: private void initializeCompositeService() throws GroupsException {
369: composite = true;
370: String eMsg = null;
371: try {
372: GroupServiceConfiguration cfg = getServiceConfiguration();
373: String factoryName = (String) cfg.getAttributes().get(
374: "compositeFactory");
375:
376: if (factoryName == null) {
377: eMsg = "GroupService.initialize(): No entry for CompositeServiceFactory in configuration";
378: log.error(eMsg);
379: throw new GroupsException(eMsg);
380: }
381:
382: ICompositeGroupServiceFactory serviceFactory = (ICompositeGroupServiceFactory) Class
383: .forName(factoryName).newInstance();
384: compositeGroupService = serviceFactory.newGroupService();
385: } catch (Exception e) {
386: eMsg = "GroupService.initialize(): Problem creating groups service... "
387: + e.getMessage();
388: log.error(eMsg, e);
389: throw new GroupsException(eMsg, e);
390: }
391: }
392:
393: public static synchronized GroupService instance()
394: throws GroupsException {
395: if (instance == null) {
396: instance = new GroupService();
397: }
398: return instance;
399: }
400:
401: /**
402: * Answer if the underlying group service is a composite service,
403: * implementing ICompositeGroupService.
404: */
405: public static boolean isComposite() {
406: return composite;
407: }
408:
409: /**
410: * Returns a new <code>IEntityGroup</code> for the given Class with an unused
411: * key.
412: * @return org.jasig.portal.groups.IEntityGroup
413: */
414: public static IEntityGroup newGroup(Class type)
415: throws GroupsException {
416: return instance().inewGroup(type);
417: }
418:
419: /**
420: * Returns a new <code>IEntityGroup</code> for the given Class with an unused
421: * key.
422: * @return org.jasig.portal.groups.IEntityGroup
423: */
424: public static IEntityGroup newGroup(Class type, String serviceName)
425: throws GroupsException {
426: return instance().inewGroup(type, serviceName);
427: }
428:
429: /**
430: * Extracts the final node from the String form of a composite key.
431: * @return String
432: * @exception javax.naming.InvalidNameException
433: */
434: public static String parseLocalKey(String compositeKey)
435: throws InvalidNameException, GroupsException {
436: return new CompositeEntityIdentifier(compositeKey, new Object()
437: .getClass()).getLocalKey();
438: }
439:
440: /**
441: * Converts the String form of a service name into a Name.
442: * @return javax.naming.Name
443: * @exception InvalidNameException
444: * @exception GroupsException
445: */
446: public static Name parseServiceName(String serviceName)
447: throws InvalidNameException, GroupsException {
448: return new CompositeServiceIdentifier(serviceName)
449: .getServiceName();
450: }
451:
452: public static EntityIdentifier[] searchForEntities(String query,
453: int method, Class type) throws GroupsException {
454: return instance().compositeGroupService.searchForEntities(
455: query, method, type);
456: }
457:
458: public static EntityIdentifier[] searchForEntities(String query,
459: int method, Class type, IEntityGroup ancestor)
460: throws GroupsException {
461: return instance().compositeGroupService.searchForEntities(
462: query, method, type, ancestor);
463: }
464:
465: public static EntityIdentifier[] searchForGroups(String query,
466: int method, Class leaftype) throws GroupsException {
467: return instance().compositeGroupService.searchForGroups(query,
468: method, leaftype);
469: }
470:
471: public static EntityIdentifier[] searchForGroups(String query,
472: int method, Class leaftype, IEntityGroup ancestor)
473: throws GroupsException {
474: return instance().compositeGroupService.searchForGroups(query,
475: method, leaftype, ancestor);
476: }
477:
478: public static void startUp() throws GroupsException {
479: instance();
480: }
481: }
|