0001: /**********************************************************************************
0002: * $URL: https://source.sakaiproject.org/svn/user/tags/sakai_2-4-1/user-impl/impl/src/java/org/sakaiproject/user/impl/BaseUserDirectoryService.java $
0003: * $Id: BaseUserDirectoryService.java 15514 2006-10-03 00:15:10Z ggolden@umich.edu $
0004: ***********************************************************************************
0005: *
0006: * Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation.
0007: *
0008: * Licensed under the Educational Community License, Version 1.0 (the "License");
0009: * you may not use this file except in compliance with the License.
0010: * You may obtain a copy of the License at
0011: *
0012: * http://www.opensource.org/licenses/ecl1.php
0013: *
0014: * Unless required by applicable law or agreed to in writing, software
0015: * distributed under the License is distributed on an "AS IS" BASIS,
0016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017: * See the License for the specific language governing permissions and
0018: * limitations under the License.
0019: *
0020: **********************************************************************************/package org.sakaiproject.user.impl;
0021:
0022: import java.util.ArrayList;
0023: import java.util.Collection;
0024: import java.util.Iterator;
0025: import java.util.List;
0026: import java.util.Map;
0027: import java.util.Set;
0028: import java.util.Stack;
0029: import java.util.Vector;
0030:
0031: import org.apache.commons.logging.Log;
0032: import org.apache.commons.logging.LogFactory;
0033: import org.sakaiproject.authz.api.AuthzGroupService;
0034: import org.sakaiproject.authz.api.AuthzPermissionException;
0035: import org.sakaiproject.authz.api.FunctionManager;
0036: import org.sakaiproject.authz.api.GroupNotDefinedException;
0037: import org.sakaiproject.authz.api.SecurityService;
0038: import org.sakaiproject.component.api.ServerConfigurationService;
0039: import org.sakaiproject.component.cover.ComponentManager;
0040: import org.sakaiproject.entity.api.Edit;
0041: import org.sakaiproject.entity.api.Entity;
0042: import org.sakaiproject.entity.api.EntityManager;
0043: import org.sakaiproject.entity.api.HttpAccess;
0044: import org.sakaiproject.entity.api.Reference;
0045: import org.sakaiproject.entity.api.ResourceProperties;
0046: import org.sakaiproject.entity.api.ResourcePropertiesEdit;
0047: import org.sakaiproject.event.api.EventTrackingService;
0048: import org.sakaiproject.id.api.IdManager;
0049: import org.sakaiproject.memory.api.Cache;
0050: import org.sakaiproject.memory.api.MemoryService;
0051: import org.sakaiproject.thread_local.api.ThreadLocalManager;
0052: import org.sakaiproject.time.api.Time;
0053: import org.sakaiproject.time.api.TimeService;
0054: import org.sakaiproject.tool.api.SessionBindingEvent;
0055: import org.sakaiproject.tool.api.SessionBindingListener;
0056: import org.sakaiproject.tool.api.SessionManager;
0057: import org.sakaiproject.user.api.DisplayAdvisorUDP;
0058: import org.sakaiproject.user.api.User;
0059: import org.sakaiproject.user.api.UserAlreadyDefinedException;
0060: import org.sakaiproject.user.api.UserDirectoryProvider;
0061: import org.sakaiproject.user.api.UserDirectoryService;
0062: import org.sakaiproject.user.api.UserEdit;
0063: import org.sakaiproject.user.api.UserFactory;
0064: import org.sakaiproject.user.api.UserIdInvalidException;
0065: import org.sakaiproject.user.api.UserLockedException;
0066: import org.sakaiproject.user.api.UserNotDefinedException;
0067: import org.sakaiproject.user.api.UserPermissionException;
0068: import org.sakaiproject.user.api.UsersShareEmailUDP;
0069: import org.sakaiproject.util.BaseResourceProperties;
0070: import org.sakaiproject.util.BaseResourcePropertiesEdit;
0071: import org.sakaiproject.util.StorageUser;
0072: import org.sakaiproject.util.StringUtil;
0073: import org.sakaiproject.util.Validator;
0074: import org.w3c.dom.Document;
0075: import org.w3c.dom.Element;
0076: import org.w3c.dom.Node;
0077: import org.w3c.dom.NodeList;
0078:
0079: /**
0080: * <p>
0081: * BaseUserDirectoryService is a Sakai user directory services implementation.
0082: * </p>
0083: * <p>
0084: * User records can be kept locally, in Sakai, externally, by a UserDirectoryProvider, or a mixture of both.
0085: * </p>
0086: * <p>
0087: * Each User that ever goes through Sakai is allocated a Sakai unique UUID. Even if we don't keep the User record in Sakai, we keep a map of this id to the external eid.
0088: * </p>
0089: */
0090: public abstract class BaseUserDirectoryService implements
0091: UserDirectoryService, StorageUser, UserFactory {
0092: /** Our log (commons). */
0093: private static Log M_log = LogFactory
0094: .getLog(BaseUserDirectoryService.class);
0095:
0096: /** Storage manager for this service. */
0097: protected Storage m_storage = null;
0098:
0099: /** The initial portion of a relative access point URL. */
0100: protected String m_relativeAccessPoint = null;
0101:
0102: /** An anon. user. */
0103: protected User m_anon = null;
0104:
0105: /** A user directory provider. */
0106: protected UserDirectoryProvider m_provider = null;
0107:
0108: /** Key for current service caching of current user */
0109: protected final String M_curUserKey = getClass().getName()
0110: + ".currentUser";
0111:
0112: /** A cache of calls to the service and the results. */
0113: protected Cache m_callCache = null;
0114:
0115: /**********************************************************************************************************************************************************************************************************************************************************
0116: * Abstractions, etc.
0117: *********************************************************************************************************************************************************************************************************************************************************/
0118:
0119: /**
0120: * Construct storage for this service.
0121: */
0122: protected abstract Storage newStorage();
0123:
0124: /**
0125: * Access the partial URL that forms the root of resource URLs.
0126: *
0127: * @param relative
0128: * if true, form within the access path only (i.e. starting with /content)
0129: * @return the partial URL that forms the root of resource URLs.
0130: */
0131: protected String getAccessPoint(boolean relative) {
0132: return (relative ? "" : serverConfigurationService()
0133: .getAccessUrl())
0134: + m_relativeAccessPoint;
0135: }
0136:
0137: /**
0138: * Access the internal reference which can be used to access the resource from within the system.
0139: *
0140: * @param id
0141: * The user id string.
0142: * @return The the internal reference which can be used to access the resource from within the system.
0143: */
0144: public String userReference(String id) {
0145: // clean up the id
0146: id = cleanId(id);
0147:
0148: return getAccessPoint(true) + Entity.SEPARATOR
0149: + ((id == null) ? "" : id);
0150: }
0151:
0152: /**
0153: * Access the user id extracted from a user reference.
0154: *
0155: * @param ref
0156: * The user reference string.
0157: * @return The the user id extracted from a user reference.
0158: */
0159: protected String userId(String ref) {
0160: String start = getAccessPoint(true) + Entity.SEPARATOR;
0161: int i = ref.indexOf(start);
0162: if (i == -1)
0163: return ref;
0164: String id = ref.substring(i + start.length());
0165: return id;
0166: }
0167:
0168: /**
0169: * Check security permission.
0170: *
0171: * @param lock
0172: * The lock id string.
0173: * @param resource
0174: * The resource reference string, or null if no resource is involved.
0175: * @return true if allowd, false if not
0176: */
0177: protected boolean unlockCheck(String lock, String resource) {
0178: if (!securityService().unlock(lock, resource)) {
0179: return false;
0180: }
0181:
0182: return true;
0183: }
0184:
0185: /**
0186: * Check security permission.
0187: *
0188: * @param lock
0189: * A list of lock strings to consider.
0190: * @param resource
0191: * The resource reference string, or null if no resource is involved.
0192: * @return true if any of these locks are allowed, false if not
0193: */
0194: protected boolean unlockCheck(List locks, String resource) {
0195: Iterator locksIterator = locks.iterator();
0196:
0197: while (locksIterator.hasNext()) {
0198:
0199: if (securityService().unlock((String) locksIterator.next(),
0200: resource))
0201: return true;
0202:
0203: }
0204:
0205: return false;
0206: }
0207:
0208: /**
0209: * Check security permission.
0210: *
0211: * @param lock1
0212: * The lock id string.
0213: * @param lock2
0214: * The lock id string.
0215: * @param resource
0216: * The resource reference string, or null if no resource is involved.
0217: * @return true if either allowed, false if not
0218: */
0219: protected boolean unlockCheck2(String lock1, String lock2,
0220: String resource) {
0221: if (!securityService().unlock(lock1, resource)) {
0222: if (!securityService().unlock(lock2, resource)) {
0223: return false;
0224: }
0225: }
0226:
0227: return true;
0228: }
0229:
0230: /**
0231: * Check security permission.
0232: *
0233: * @param lock
0234: * The lock id string.
0235: * @param resource
0236: * The resource reference string, or null if no resource is involved.
0237: * @exception UserPermissionException
0238: * Thrown if the user does not have access
0239: * @return The lock id string that succeeded
0240: */
0241: protected String unlock(String lock, String resource)
0242: throws UserPermissionException {
0243:
0244: if (!unlockCheck(lock, resource)) {
0245: throw new UserPermissionException(sessionManager()
0246: .getCurrentSessionUserId(), lock, resource);
0247: }
0248:
0249: return lock;
0250: }
0251:
0252: /**
0253: * Check security permission.
0254: *
0255: * @param lock1
0256: * The lock id string.
0257: * @param lock2
0258: * The lock id string.
0259: * @param resource
0260: * The resource reference string, or null if no resource is involved.
0261: * @exception UserPermissionException
0262: * Thrown if the user does not have access to either.
0263: */
0264: protected void unlock2(String lock1, String lock2, String resource)
0265: throws UserPermissionException {
0266: if (!unlockCheck2(lock1, lock2, resource)) {
0267: throw new UserPermissionException(sessionManager()
0268: .getCurrentSessionUserId(), lock1 + "/" + lock2,
0269: resource);
0270: }
0271: }
0272:
0273: /**
0274: * Check security permission.
0275: *
0276: *
0277: * @param locks
0278: * The list of lock strings.
0279: * @param resource
0280: * The resource reference string, or null if no resource is involved.
0281: * @exception UserPermissionException
0282: * Thrown if the user does not have access to either.
0283: * @return A list of the lock strings that the user has access to.
0284: */
0285:
0286: protected List unlock(List locks, String resource)
0287: throws UserPermissionException {
0288: List locksSucceeded = new ArrayList();
0289: String locksFailed = "";
0290:
0291: Iterator locksIterator = locks.iterator();
0292:
0293: while (locksIterator.hasNext()) {
0294:
0295: String lock = (String) locksIterator.next();
0296:
0297: if (unlockCheck(lock, resource)) {
0298: locksSucceeded.add(lock);
0299:
0300: } else {
0301:
0302: locksFailed += lock + " ";
0303: }
0304:
0305: }
0306:
0307: if (locksSucceeded.size() < 1) {
0308: throw new UserPermissionException(sessionManager()
0309: .getCurrentSessionUserId(), locksFailed, resource);
0310: }
0311:
0312: return locksSucceeded;
0313: }
0314:
0315: /**
0316: * Make sure we have a good uuid for a user record. If id is specified, use that. Otherwise get one from the provider or allocate a uuid.
0317: *
0318: * @param id
0319: * The proposed id.
0320: * @param eid
0321: * The proposed eid.
0322: * @return The id to use as the User's uuid.
0323: */
0324: protected String assureUuid(String id, String eid) {
0325: // if we are not using separate id and eid, return the eid
0326: if (!m_separateIdEid)
0327: return eid;
0328:
0329: if (id != null)
0330: return id;
0331:
0332: // TODO: let the provider have a chance to set this? -ggolden
0333:
0334: // allocate a uuid
0335: id = idManager().createUuid();
0336:
0337: return id;
0338: }
0339:
0340: /**********************************************************************************************************************************************************************************************************************************************************
0341: * Configuration
0342: *********************************************************************************************************************************************************************************************************************************************************/
0343:
0344: /**
0345: * Configuration: set the user directory provider helper service.
0346: *
0347: * @param provider
0348: * the user directory provider helper service.
0349: */
0350: public void setProvider(UserDirectoryProvider provider) {
0351: m_provider = provider;
0352: }
0353:
0354: /** The # seconds to cache gets. 0 disables the cache. */
0355: protected int m_cacheSeconds = 0;
0356:
0357: /**
0358: * Set the # minutes to cache a get.
0359: *
0360: * @param time
0361: * The # minutes to cache a get (as an integer string).
0362: */
0363: public void setCacheMinutes(String time) {
0364: m_cacheSeconds = Integer.parseInt(time) * 60;
0365: }
0366:
0367: /** The # seconds to cache gets. 0 disables the cache. */
0368: protected int m_cacheCleanerSeconds = 0;
0369:
0370: /**
0371: * Set the # minutes between cache cleanings.
0372: *
0373: * @param time
0374: * The # minutes between cache cleanings. (as an integer string).
0375: */
0376: public void setCacheCleanerMinutes(String time) {
0377: m_cacheCleanerSeconds = Integer.parseInt(time) * 60;
0378: }
0379:
0380: /** Configuration: case sensitive user eid. */
0381: protected boolean m_caseSensitiveEid = false;
0382:
0383: /**
0384: * Configuration: case sensitive user eid
0385: *
0386: * @param value
0387: * The case sensitive user eid.
0388: */
0389: public void setCaseSensitiveId(String value) {
0390: m_caseSensitiveEid = new Boolean(value).booleanValue();
0391: }
0392:
0393: /** Configuration: use a different id and eid for each record (otherwise make them the same value). */
0394: protected boolean m_separateIdEid = false;
0395:
0396: /**
0397: * Configuration: to use a separate value for id and eid for each user record, or not.
0398: *
0399: * @param value
0400: * The separateIdEid setting.
0401: */
0402: public void setSeparateIdEid(String value) {
0403: m_separateIdEid = new Boolean(value).booleanValue();
0404: }
0405:
0406: /**********************************************************************************************************************************************************************************************************************************************************
0407: * Dependencies
0408: *********************************************************************************************************************************************************************************************************************************************************/
0409:
0410: /**
0411: * @return the ServerConfigurationService collaborator.
0412: */
0413: protected abstract ServerConfigurationService serverConfigurationService();
0414:
0415: /**
0416: * @return the EntityManager collaborator.
0417: */
0418: protected abstract EntityManager entityManager();
0419:
0420: /**
0421: * @return the SecurityService collaborator.
0422: */
0423: protected abstract SecurityService securityService();
0424:
0425: /**
0426: * @return the FunctionManager collaborator.
0427: */
0428: protected abstract FunctionManager functionManager();
0429:
0430: /**
0431: * @return the SessionManager collaborator.
0432: */
0433: protected abstract SessionManager sessionManager();
0434:
0435: /**
0436: * @return the MemoryService collaborator.
0437: */
0438: protected abstract MemoryService memoryService();
0439:
0440: /**
0441: * @return the EventTrackingService collaborator.
0442: */
0443: protected abstract EventTrackingService eventTrackingService();
0444:
0445: /**
0446: * @return the ThreadLocalManager collaborator.
0447: */
0448: protected abstract ThreadLocalManager threadLocalManager();
0449:
0450: /**
0451: * @return the AuthzGroupService collaborator.
0452: */
0453: protected abstract AuthzGroupService authzGroupService();
0454:
0455: /**
0456: * @return the TimeService collaborator.
0457: */
0458: protected abstract TimeService timeService();
0459:
0460: /**
0461: * @return the IdManager collaborator.
0462: */
0463: protected abstract IdManager idManager();
0464:
0465: /**********************************************************************************************************************************************************************************************************************************************************
0466: * Init and Destroy
0467: *********************************************************************************************************************************************************************************************************************************************************/
0468:
0469: /**
0470: * Final initialization, once all dependencies are set.
0471: */
0472: public void init() {
0473: try {
0474: m_relativeAccessPoint = REFERENCE_ROOT;
0475:
0476: // construct storage and read
0477: m_storage = newStorage();
0478: m_storage.open();
0479:
0480: // make an anon. user
0481: m_anon = new BaseUserEdit("");
0482:
0483: // <= 0 indicates no caching desired
0484: if ((m_cacheSeconds > 0) && (m_cacheCleanerSeconds > 0)) {
0485: // build a synchronized map for the call cache, automatiaclly checking for expiration every 15 mins, expire on user events, too.
0486: m_callCache = memoryService().newHardCache(
0487: m_cacheCleanerSeconds, userReference(""));
0488: }
0489:
0490: // register as an entity producer
0491: entityManager()
0492: .registerEntityProducer(this , REFERENCE_ROOT);
0493:
0494: // register functions
0495: functionManager().registerFunction(SECURE_ADD_USER);
0496: functionManager().registerFunction(SECURE_REMOVE_USER);
0497: functionManager().registerFunction(SECURE_UPDATE_USER_OWN);
0498: functionManager().registerFunction(
0499: SECURE_UPDATE_USER_OWN_NAME);
0500: functionManager().registerFunction(
0501: SECURE_UPDATE_USER_OWN_EMAIL);
0502: functionManager().registerFunction(
0503: SECURE_UPDATE_USER_OWN_PASSWORD);
0504: functionManager().registerFunction(
0505: SECURE_UPDATE_USER_OWN_TYPE);
0506: functionManager().registerFunction(SECURE_UPDATE_USER_ANY);
0507:
0508: // if no provider was set, see if we can find one
0509: if (m_provider == null) {
0510: m_provider = (UserDirectoryProvider) ComponentManager
0511: .get(UserDirectoryProvider.class.getName());
0512: }
0513:
0514: M_log.info("init(): provider: "
0515: + ((m_provider == null) ? "none" : m_provider
0516: .getClass().getName())
0517: + " - caching minutes: " + m_cacheSeconds / 60
0518: + " - cache cleaner minutes: "
0519: + m_cacheCleanerSeconds / 60 + " separateIdEid: "
0520: + m_separateIdEid);
0521: } catch (Throwable t) {
0522: M_log.warn("init(): ", t);
0523: }
0524: }
0525:
0526: /**
0527: * Returns to uninitialized state. You can use this method to release resources thet your Service allocated when Turbine shuts down.
0528: */
0529: public void destroy() {
0530: m_storage.close();
0531: m_storage = null;
0532: m_provider = null;
0533: m_anon = null;
0534:
0535: M_log.info("destroy()");
0536: }
0537:
0538: /**********************************************************************************************************************************************************************************************************************************************************
0539: * UserDirectoryService implementation
0540: *********************************************************************************************************************************************************************************************************************************************************/
0541:
0542: /**
0543: * {@inheritDoc}
0544: */
0545: public String getUserEid(String id) throws UserNotDefinedException {
0546: id = cleanId(id);
0547:
0548: // first, check our map
0549: String eid = m_storage.checkMapForEid(id);
0550: if (eid != null)
0551: return eid;
0552:
0553: throw new UserNotDefinedException(id);
0554: }
0555:
0556: /**
0557: * {@inheritDoc}
0558: */
0559: public String getUserId(String eid) throws UserNotDefinedException {
0560: eid = cleanEid(eid);
0561:
0562: // first, check our map
0563: String id = m_storage.checkMapForId(eid);
0564: if (id != null)
0565: return id;
0566:
0567: // if we don't have an id yet for this eid, and there's a provider that recognizes this eid, allocate an id
0568: if (m_provider != null) {
0569: // allocate the id to use if this succeeds
0570: id = assureUuid(null, eid);
0571:
0572: // make a new edit to hold the provider's info, hoping it will be filled in
0573: BaseUserEdit user = new BaseUserEdit((String) null);
0574: user.m_id = id;
0575: user.m_eid = eid;
0576:
0577: // check with the provider
0578: if (m_provider.getUser(user)) {
0579: // record the id -> eid mapping (could possibly fail if somehow this eid was mapped since our test above)
0580: m_storage.putMap(user.getId(), user.getEid());
0581:
0582: return user.getId();
0583: }
0584: }
0585:
0586: // not found
0587: throw new UserNotDefinedException(eid);
0588: }
0589:
0590: /**
0591: * @inheritDoc
0592: */
0593: public User getUser(String id) throws UserNotDefinedException {
0594: // clean up the id
0595: id = cleanId(id);
0596:
0597: if (id == null)
0598: throw new UserNotDefinedException("null");
0599:
0600: // see if we've done this already in this thread
0601: String ref = userReference(id);
0602: UserEdit user = (UserEdit) threadLocalManager().get(ref);
0603:
0604: // if not
0605: if (user == null) {
0606: // check the cache
0607: if ((m_callCache != null) && (m_callCache.containsKey(ref))) {
0608: user = (UserEdit) m_callCache.get(ref);
0609: }
0610:
0611: else {
0612: // find our user record, and use it if we have it
0613: user = m_storage.getById(id);
0614:
0615: // let the provider provide if needed
0616: if ((user == null) && (m_provider != null)) {
0617: // we need the eid for the provider - if we can't find an eid, we throw UserNotDefinedException
0618: String eid = getUserEid(id);
0619:
0620: // make a new edit to hold the provider's info, hoping it will be filled in
0621: user = new BaseUserEdit((String) null);
0622: ((BaseUserEdit) user).m_id = id;
0623: ((BaseUserEdit) user).m_eid = eid;
0624:
0625: if (!m_provider.getUser(user)) {
0626: // it was not provided for, so clear back to null
0627: user = null;
0628: }
0629: }
0630:
0631: // if found, save it for later use in this thread
0632: if (user != null) {
0633: threadLocalManager().set(ref, user);
0634:
0635: // cache
0636: if (m_callCache != null)
0637: m_callCache.put(ref, user, m_cacheSeconds);
0638: }
0639: }
0640: }
0641:
0642: // if not found
0643: if (user == null) {
0644: throw new UserNotDefinedException(id);
0645: }
0646:
0647: return user;
0648: }
0649:
0650: /**
0651: * @inheritDoc
0652: */
0653: public User getUserByEid(String eid) throws UserNotDefinedException {
0654: User rv = null;
0655:
0656: // clean up the eid
0657: eid = cleanEid(eid);
0658: if (eid == null)
0659: throw new UserNotDefinedException("null");
0660:
0661: // find the user id mapped to this eid and get that record (internally or by provider)
0662: String id = getUserId(eid);
0663:
0664: // now we can get by id
0665: rv = getUser(id);
0666:
0667: return rv;
0668: }
0669:
0670: /**
0671: * @inheritDoc
0672: */
0673: public List getUsers(Collection ids) {
0674: // User objects to return
0675: List rv = new Vector();
0676:
0677: // a list of User (edits) setup to check with the provider
0678: Collection fromProvider = new Vector();
0679:
0680: // for each requested id
0681: for (Iterator i = ids.iterator(); i.hasNext();) {
0682: String id = (String) i.next();
0683:
0684: // clean up the id
0685: id = cleanId(id);
0686:
0687: // skip nulls
0688: if (id == null)
0689: continue;
0690:
0691: // see if we've done this already in this thread
0692: String ref = userReference(id);
0693: UserEdit user = (UserEdit) threadLocalManager().get(ref);
0694:
0695: // if not
0696: if (user == null) {
0697: // check the cache
0698: if ((m_callCache != null)
0699: && (m_callCache.containsKey(ref))) {
0700: user = (UserEdit) m_callCache.get(ref);
0701: }
0702:
0703: else {
0704: // find our user record
0705: user = m_storage.getById(id);
0706:
0707: // if we didn't find it locally, collect a list of externals to get
0708: if ((user == null) && (m_provider != null)) {
0709: try {
0710: // get the eid for this user so we can ask the provider
0711: String eid = getUserEid(id);
0712:
0713: // make a new edit to hold the provider's info; the provider will either fill this in, if known, or remove it from the collection
0714: BaseUserEdit providerUser = new BaseUserEdit(
0715: (String) null);
0716: providerUser.m_id = id;
0717: providerUser.m_eid = eid;
0718: fromProvider.add(providerUser);
0719: } catch (UserNotDefinedException e) {
0720: // this user is not internally defined, and we can't find an eid for it, so we skip it
0721: M_log
0722: .warn("getUsers: cannot find eid for user id: "
0723: + id);
0724: }
0725: }
0726:
0727: // if found, save it for later use in this thread
0728: if (user != null) {
0729: // cache
0730: threadLocalManager().set(ref, user);
0731: if (m_callCache != null)
0732: m_callCache.put(ref, user, m_cacheSeconds);
0733: }
0734: }
0735: }
0736:
0737: // if we found a user for this id, add it to the return
0738: if (user != null) {
0739: rv.add(user);
0740: }
0741: }
0742:
0743: // check the provider, all at once
0744: if ((m_provider != null) && (!fromProvider.isEmpty())) {
0745: m_provider.getUsers(fromProvider);
0746:
0747: // for each User in the collection that was filled in (and not removed) by the provider, cache and return it
0748: for (Iterator i = fromProvider.iterator(); i.hasNext();) {
0749: User user = (User) i.next();
0750:
0751: // cache, thread and call cache
0752: String ref = user.getReference();
0753: threadLocalManager().set(ref, user);
0754: if (m_callCache != null)
0755: m_callCache.put(ref, user, m_cacheSeconds);
0756:
0757: // add to return
0758: rv.add(user);
0759: }
0760: }
0761:
0762: return rv;
0763: }
0764:
0765: /**
0766: * @inheritDoc
0767: */
0768: public User getCurrentUser() {
0769: String id = sessionManager().getCurrentSessionUserId();
0770:
0771: // check current service caching - discard if the session user is different
0772: User rv = (User) threadLocalManager().get(M_curUserKey);
0773: if ((rv != null) && (rv.getId().equals(id)))
0774: return rv;
0775:
0776: try {
0777: rv = getUser(id);
0778: } catch (UserNotDefinedException e) {
0779: rv = getAnonymousUser();
0780: }
0781:
0782: // cache in the current service
0783: threadLocalManager().set(M_curUserKey, rv);
0784:
0785: return rv;
0786: }
0787:
0788: /**
0789: * @inheritDoc
0790: */
0791: public boolean allowUpdateUser(String id) {
0792: // clean up the id
0793: id = cleanId(id);
0794: if (id == null)
0795: return false;
0796:
0797: // is this the user's own?
0798: if (id.equals(sessionManager().getCurrentSessionUserId())) {
0799: ArrayList locks = new ArrayList();
0800: locks.add(SECURE_UPDATE_USER_OWN);
0801: locks.add(SECURE_UPDATE_USER_ANY);
0802: locks.add(SECURE_UPDATE_USER_OWN_NAME);
0803: locks.add(SECURE_UPDATE_USER_OWN_EMAIL);
0804: locks.add(SECURE_UPDATE_USER_OWN_PASSWORD);
0805: locks.add(SECURE_UPDATE_USER_OWN_TYPE);
0806:
0807: // own or any
0808: return unlockCheck(locks, userReference(id));
0809: }
0810:
0811: else {
0812: // just any
0813: return unlockCheck(SECURE_UPDATE_USER_ANY,
0814: userReference(id));
0815: }
0816: }
0817:
0818: /**
0819: * @inheritDoc
0820: */
0821: public boolean allowUpdateUserName(String id) {
0822: // clean up the id
0823: id = cleanId(id);
0824: if (id == null)
0825: return false;
0826:
0827: // is this the user's own?
0828: if (id.equals(sessionManager().getCurrentSessionUserId())) {
0829: ArrayList locks = new ArrayList();
0830: locks.add(SECURE_UPDATE_USER_OWN);
0831: locks.add(SECURE_UPDATE_USER_ANY);
0832: locks.add(SECURE_UPDATE_USER_OWN_NAME);
0833:
0834: // own or any
0835: return unlockCheck(locks, userReference(id));
0836: }
0837:
0838: else {
0839: // just any
0840: return unlockCheck(SECURE_UPDATE_USER_ANY,
0841: userReference(id));
0842: }
0843:
0844: }
0845:
0846: /**
0847: * @inheritDoc
0848: */
0849: public boolean allowUpdateUserEmail(String id) {
0850: // clean up the id
0851: id = cleanId(id);
0852: if (id == null)
0853: return false;
0854:
0855: // is this the user's own?
0856: if (id.equals(sessionManager().getCurrentSessionUserId())) {
0857: ArrayList locks = new ArrayList();
0858: locks.add(SECURE_UPDATE_USER_OWN);
0859: locks.add(SECURE_UPDATE_USER_ANY);
0860: locks.add(SECURE_UPDATE_USER_OWN_EMAIL);
0861:
0862: // own or any
0863: return unlockCheck(locks, userReference(id));
0864: }
0865:
0866: else {
0867: // just any
0868: return unlockCheck(SECURE_UPDATE_USER_ANY,
0869: userReference(id));
0870: }
0871:
0872: }
0873:
0874: /**
0875: * @inheritDoc
0876: */
0877: public boolean allowUpdateUserPassword(String id) {
0878: // clean up the id
0879: id = cleanId(id);
0880: if (id == null)
0881: return false;
0882:
0883: // is this the user's own?
0884: if (id.equals(sessionManager().getCurrentSessionUserId())) {
0885: ArrayList locks = new ArrayList();
0886: locks.add(SECURE_UPDATE_USER_OWN);
0887: locks.add(SECURE_UPDATE_USER_ANY);
0888: locks.add(SECURE_UPDATE_USER_OWN_PASSWORD);
0889:
0890: // own or any
0891: return unlockCheck(locks, userReference(id));
0892: }
0893:
0894: else {
0895: // just any
0896: return unlockCheck(SECURE_UPDATE_USER_ANY,
0897: userReference(id));
0898: }
0899:
0900: }
0901:
0902: /**
0903: * @inheritDoc
0904: */
0905: public boolean allowUpdateUserType(String id) {
0906: // clean up the id
0907: id = cleanId(id);
0908: if (id == null)
0909: return false;
0910:
0911: // is this the user's own?
0912: if (id.equals(sessionManager().getCurrentSessionUserId())) {
0913: ArrayList locks = new ArrayList();
0914: locks.add(SECURE_UPDATE_USER_OWN);
0915: locks.add(SECURE_UPDATE_USER_ANY);
0916: locks.add(SECURE_UPDATE_USER_OWN_TYPE);
0917:
0918: // own or any
0919: return unlockCheck(locks, userReference(id));
0920: }
0921:
0922: else {
0923: // just any
0924: return unlockCheck(SECURE_UPDATE_USER_ANY,
0925: userReference(id));
0926: }
0927:
0928: }
0929:
0930: /**
0931: * @inheritDoc
0932: */
0933: public UserEdit editUser(String id) throws UserNotDefinedException,
0934: UserPermissionException, UserLockedException {
0935:
0936: // clean up the id
0937: id = cleanId(id);
0938:
0939: if (id == null)
0940: throw new UserNotDefinedException("null");
0941:
0942: // is this the user's own?
0943: List locksSucceeded = new ArrayList();
0944: String function = null;
0945: if (id.equals(sessionManager().getCurrentSessionUserId())) {
0946: // own or any
0947: List locks = new ArrayList();
0948: locks.add(SECURE_UPDATE_USER_OWN);
0949: locks.add(SECURE_UPDATE_USER_OWN_NAME);
0950: locks.add(SECURE_UPDATE_USER_OWN_EMAIL);
0951: locks.add(SECURE_UPDATE_USER_OWN_PASSWORD);
0952: locks.add(SECURE_UPDATE_USER_OWN_TYPE);
0953: locks.add(SECURE_UPDATE_USER_ANY);
0954:
0955: locksSucceeded = unlock(locks, userReference(id));
0956: function = SECURE_UPDATE_USER_OWN;
0957: } else {
0958: // just any
0959: locksSucceeded.add(unlock(SECURE_UPDATE_USER_ANY,
0960: userReference(id)));
0961: function = SECURE_UPDATE_USER_ANY;
0962: }
0963:
0964: // check for existance
0965: if (!m_storage.check(id)) {
0966: throw new UserNotDefinedException(id);
0967: }
0968:
0969: // ignore the cache - get the user with a lock from the info store
0970: UserEdit user = m_storage.edit(id);
0971: if (user == null)
0972: throw new UserLockedException(id);
0973:
0974: if (!locksSucceeded.contains(SECURE_UPDATE_USER_ANY)
0975: && !locksSucceeded.contains(SECURE_UPDATE_USER_OWN)) {
0976:
0977: // current session does not have permission to edit all properties for this user
0978: // lock the properties the user does not have access to edit
0979:
0980: if (!locksSucceeded.contains(SECURE_UPDATE_USER_OWN_NAME)) {
0981: user.restrictEditFirstName();
0982: user.restrictEditLastName();
0983: }
0984:
0985: if (!locksSucceeded.contains(SECURE_UPDATE_USER_OWN_EMAIL)) {
0986: user.restrictEditEmail();
0987: }
0988:
0989: if (!locksSucceeded
0990: .contains(SECURE_UPDATE_USER_OWN_PASSWORD)) {
0991: user.restrictEditPassword();
0992: }
0993:
0994: if (!locksSucceeded.contains(SECURE_UPDATE_USER_OWN_TYPE)) {
0995: user.restrictEditType();
0996: }
0997:
0998: }
0999:
1000: ((BaseUserEdit) user).setEvent(function);
1001:
1002: return user;
1003: }
1004:
1005: /**
1006: * @inheritDoc
1007: */
1008: public void commitEdit(UserEdit user)
1009: throws UserAlreadyDefinedException {
1010: // check for closed edit
1011: if (!user.isActiveEdit()) {
1012: try {
1013: throw new Exception();
1014: } catch (Exception e) {
1015: M_log.warn("commitEdit(): closed UserEdit", e);
1016: }
1017: return;
1018: }
1019:
1020: // update the properties
1021: addLiveUpdateProperties((BaseUserEdit) user);
1022:
1023: // complete the edit
1024: if (!m_storage.commit(user)) {
1025: m_storage.cancel(user);
1026: ((BaseUserEdit) user).closeEdit();
1027: throw new UserAlreadyDefinedException(user.getEid());
1028: }
1029:
1030: // track it
1031: eventTrackingService().post(
1032: eventTrackingService().newEvent(
1033: ((BaseUserEdit) user).getEvent(),
1034: user.getReference(), true));
1035:
1036: // close the edit object
1037: ((BaseUserEdit) user).closeEdit();
1038: }
1039:
1040: /**
1041: * @inheritDoc
1042: */
1043: public void cancelEdit(UserEdit user) {
1044: // check for closed edit
1045: if (!user.isActiveEdit()) {
1046: try {
1047: throw new Exception();
1048: } catch (Exception e) {
1049: M_log.warn("cancelEdit(): closed UserEdit", e);
1050: }
1051: return;
1052: }
1053:
1054: // release the edit lock
1055: m_storage.cancel(user);
1056:
1057: // close the edit object
1058: ((BaseUserEdit) user).closeEdit();
1059: }
1060:
1061: /**
1062: * @inheritDoc
1063: */
1064: public List getUsers() {
1065: List users = m_storage.getAll();
1066: return users;
1067: }
1068:
1069: /**
1070: * @inheritDoc
1071: */
1072: public List getUsers(int first, int last) {
1073: List all = m_storage.getAll(first, last);
1074:
1075: return all;
1076: }
1077:
1078: /**
1079: * @inheritDoc
1080: */
1081: public int countUsers() {
1082: return m_storage.count();
1083: }
1084:
1085: /**
1086: * @inheritDoc
1087: */
1088: public List searchUsers(String criteria, int first, int last) {
1089: return m_storage.search(criteria, first, last);
1090: }
1091:
1092: /**
1093: * @inheritDoc
1094: */
1095: public int countSearchUsers(String criteria) {
1096: return m_storage.countSearch(criteria);
1097: }
1098:
1099: /**
1100: * @inheritDoc
1101: */
1102: public Collection findUsersByEmail(String email) {
1103: // check internal users
1104: Collection users = m_storage.findUsersByEmail(email);
1105:
1106: // add in provider users
1107: if (m_provider != null) {
1108: // support UDP that has multiple users per email
1109: if (m_provider instanceof UsersShareEmailUDP) {
1110: Collection udpUsers = ((UsersShareEmailUDP) m_provider)
1111: .findUsersByEmail(email, this );
1112: if (udpUsers != null) {
1113: for (Iterator i = udpUsers.iterator(); i.hasNext();) {
1114: BaseUserEdit u = (BaseUserEdit) i.next();
1115:
1116: // find the user id mapped to this eid and get that record (internally or by provider)
1117: try {
1118: // lookup and set the id for this user from the eid set by the provider
1119: u.setId(getUserId(u.getEid()));
1120: users.add((u));
1121: } catch (UserNotDefinedException e) {
1122: M_log
1123: .warn("findUserByEmail: user returnd by provider not recognized by provider: eid: "
1124: + u.getEid());
1125: }
1126: }
1127: }
1128: }
1129:
1130: // check for one
1131: else {
1132: // make a new edit to hold the provider's info
1133: BaseUserEdit edit = new BaseUserEdit((String) null);
1134: if (m_provider.findUserByEmail(edit, email)) {
1135: // find the user id mapped to this eid and get that record (internally or by provider)
1136: try {
1137: // lookup and set the id for this user from the eid set by the provider
1138: edit.setId(getUserId(edit.getEid()));
1139: users.add((edit));
1140: } catch (UserNotDefinedException e) {
1141: M_log
1142: .warn("findUserByEmail: user returnd by provider not recognized by provider: eid: "
1143: + edit.getEid());
1144: }
1145: }
1146: }
1147: }
1148:
1149: return users;
1150: }
1151:
1152: /**
1153: * @inheritDoc
1154: */
1155: public User getAnonymousUser() {
1156: return m_anon;
1157: }
1158:
1159: /**
1160: * @inheritDoc
1161: */
1162: public boolean allowAddUser() {
1163: return unlockCheck(SECURE_ADD_USER, userReference(""));
1164: }
1165:
1166: /**
1167: * @inheritDoc
1168: */
1169: public UserEdit addUser(String id, String eid)
1170: throws UserIdInvalidException, UserAlreadyDefinedException,
1171: UserPermissionException {
1172: // clean the ids
1173: id = cleanId(id);
1174: eid = cleanEid(eid);
1175:
1176: // make sure we have an id
1177: id = assureUuid(id, eid);
1178:
1179: // check security (throws if not permitted)
1180: unlock(SECURE_ADD_USER, userReference(id));
1181:
1182: // reserve a user with this id from the info store - if it's in use, this will return null
1183: UserEdit user = m_storage.put(id, eid);
1184: if (user == null) {
1185: throw new UserAlreadyDefinedException(id + " -" + eid);
1186: }
1187:
1188: ((BaseUserEdit) user).setEvent(SECURE_ADD_USER);
1189:
1190: return user;
1191: }
1192:
1193: /**
1194: * @inheritDoc
1195: */
1196: public User addUser(String id, String eid, String firstName,
1197: String lastName, String email, String pw, String type,
1198: ResourceProperties properties)
1199: throws UserIdInvalidException, UserAlreadyDefinedException,
1200: UserPermissionException {
1201: // get it added
1202: UserEdit edit = addUser(id, eid);
1203:
1204: // fill in the fields
1205: edit.setLastName(lastName);
1206: edit.setFirstName(firstName);
1207: edit.setEmail(email);
1208: edit.setPassword(pw);
1209: edit.setType(type);
1210:
1211: ResourcePropertiesEdit props = edit.getPropertiesEdit();
1212: if (properties != null) {
1213: props.addAll(properties);
1214: }
1215:
1216: // no live props!
1217:
1218: // get it committed - no further security check
1219: if (!m_storage.commit(edit)) {
1220: m_storage.cancel(edit);
1221: ((BaseUserEdit) edit).closeEdit();
1222: throw new UserAlreadyDefinedException(edit.getEid());
1223: }
1224:
1225: // track it
1226: eventTrackingService().post(
1227: eventTrackingService().newEvent(
1228: ((BaseUserEdit) edit).getEvent(),
1229: edit.getReference(), true));
1230:
1231: // close the edit object
1232: ((BaseUserEdit) edit).closeEdit();
1233:
1234: return edit;
1235: }
1236:
1237: /**
1238: * @inheritDoc
1239: */
1240: public UserEdit mergeUser(Element el)
1241: throws UserIdInvalidException, UserAlreadyDefinedException,
1242: UserPermissionException {
1243: // construct from the XML
1244: User userFromXml = new BaseUserEdit(el);
1245:
1246: // check for a valid eid
1247: Validator.checkResourceId(userFromXml.getEid());
1248:
1249: // check security (throws if not permitted)
1250: unlock(SECURE_ADD_USER, userFromXml.getReference());
1251:
1252: // reserve a user with this id from the info store - if it's in use, this will return null
1253: UserEdit user = m_storage.put(userFromXml.getId(), userFromXml
1254: .getEid());
1255: if (user == null) {
1256: throw new UserAlreadyDefinedException(userFromXml.getId()
1257: + " - " + userFromXml.getEid());
1258: }
1259:
1260: // transfer from the XML read user object to the UserEdit
1261: ((BaseUserEdit) user).set(userFromXml);
1262:
1263: ((BaseUserEdit) user).setEvent(SECURE_ADD_USER);
1264:
1265: return user;
1266: }
1267:
1268: /**
1269: * @inheritDoc
1270: */
1271: public boolean allowRemoveUser(String id) {
1272: // clean up the id
1273: id = cleanId(id);
1274: if (id == null)
1275: return false;
1276:
1277: return unlockCheck(SECURE_REMOVE_USER, userReference(id));
1278: }
1279:
1280: /**
1281: * @inheritDoc
1282: */
1283: public void removeUser(UserEdit user)
1284: throws UserPermissionException {
1285: // check for closed edit
1286: if (!user.isActiveEdit()) {
1287: try {
1288: throw new Exception();
1289: } catch (Exception e) {
1290: M_log.warn("removeUser(): closed UserEdit", e);
1291: }
1292: return;
1293: }
1294:
1295: // check security (throws if not permitted)
1296: unlock(SECURE_REMOVE_USER, user.getReference());
1297:
1298: // complete the edit
1299: m_storage.remove(user);
1300:
1301: // track it
1302: eventTrackingService().post(
1303: eventTrackingService().newEvent(SECURE_REMOVE_USER,
1304: user.getReference(), true));
1305:
1306: // close the edit object
1307: ((BaseUserEdit) user).closeEdit();
1308:
1309: // remove any realm defined for this resource
1310: try {
1311: authzGroupService().removeAuthzGroup(
1312: authzGroupService().getAuthzGroup(
1313: user.getReference()));
1314: } catch (AuthzPermissionException e) {
1315: M_log.warn("removeUser: removing realm for : "
1316: + user.getReference() + " : " + e);
1317: } catch (GroupNotDefinedException ignore) {
1318: }
1319: }
1320:
1321: /**
1322: * {@inheritDoc}
1323: */
1324: public User authenticate(String eid, String password) {
1325: // clean up the eid
1326: eid = cleanEid(eid);
1327: if (eid == null)
1328: return null;
1329:
1330: boolean authenticated = false;
1331: boolean newlyCreatedUser = false;
1332: boolean authenticatedFromProvider = false;
1333:
1334: // do we have a record for this user?
1335: UserEdit user = null;
1336:
1337: try {
1338: user = (UserEdit) getUserByEid(eid);
1339: } catch (UserNotDefinedException e) {
1340: // no internal record defined, we go on...
1341: }
1342:
1343: if (user == null) {
1344: if (m_provider != null && m_provider.createUserRecord(eid)) {
1345: try {
1346: user = addUser(null, eid);
1347: newlyCreatedUser = true;
1348: } catch (UserIdInvalidException e) {
1349: M_log.debug("authenticate(): eid invalid: " + eid);
1350: return null;
1351: } catch (UserAlreadyDefinedException e) {
1352: M_log.debug("authenticate(): eid used: " + eid);
1353: return null;
1354: } catch (UserPermissionException e) {
1355: M_log
1356: .debug("authenticate(): PermissionException for adding user "
1357: + eid);
1358: return null;
1359: }
1360: }
1361: }
1362:
1363: if (m_provider != null
1364: && m_provider.authenticateWithProviderFirst(eid)) {
1365: // 1. check provider
1366: authenticated = m_provider.authenticateUser(eid, user,
1367: password);
1368: if (authenticated)
1369: authenticatedFromProvider = true;
1370:
1371: if (!authenticated && user != null) {
1372: // 2. check our user record, if any, if not yet authenticated
1373: authenticated = user.checkPassword(password);
1374: }
1375: } else {
1376: // 1. check our user record, if any, if not yet authenticated
1377: if (user != null) {
1378: authenticated = user.checkPassword(password);
1379: }
1380:
1381: // 2. check our provider, if any, if not yet authenticated
1382: if (!authenticated && m_provider != null) {
1383: authenticated = m_provider.authenticateUser(eid, user,
1384: password);
1385: if (authenticated)
1386: authenticatedFromProvider = true;
1387: }
1388: }
1389:
1390: // if we have an active user edit, deal with it
1391: if (newlyCreatedUser) {
1392: // save if we succeeded with the authentication
1393: if (authenticated) {
1394: try {
1395: commitEdit(user);
1396: } catch (UserAlreadyDefinedException e) {
1397: M_log
1398: .warn("authenticate: exception saving newly created local user record: "
1399: + e.toString());
1400: }
1401: }
1402:
1403: // cancel if not
1404: else {
1405: cancelEdit(user);
1406: }
1407: }
1408:
1409: // if not newly created, but we authenticated from the provider (thus have a provider), have a user record already, and the provider wants us to save after, do so
1410: else if ((user != null) && authenticated
1411: && authenticatedFromProvider
1412: && m_provider.updateUserAfterAuthentication()) {
1413: // get an edit for this id, and move in the possibly changed by the provider values
1414: BaseUserEdit edit = (BaseUserEdit) m_storage.edit(user
1415: .getId());
1416: if (edit != null) {
1417: edit.setAll(user);
1418: edit.setEvent(SECURE_UPDATE_USER_ANY);
1419:
1420: if (!m_storage.commit(edit)) {
1421: m_storage.cancel(edit);
1422: edit.closeEdit();
1423: M_log
1424: .warn("authenticate: exception provider modified user record: id: "
1425: + edit.getId()
1426: + " eid: "
1427: + edit.getEid());
1428: } else {
1429: eventTrackingService().post(
1430: eventTrackingService().newEvent(
1431: edit.getEvent(),
1432: user.getReference(), true));
1433: }
1434: }
1435: }
1436:
1437: // if authenticated, get the user record to return - we might already have it
1438: User rv = null;
1439: if (authenticated) {
1440: rv = user;
1441: if (rv == null) {
1442: // get a user record - if we don't have a mapping for this eid yet, getUserByEid will make one for us
1443: try {
1444: rv = getUserByEid(eid);
1445: } catch (UserNotDefinedException e) {
1446: // we might have authenticated by provider, but don't have proper
1447: // user "existance" (i.e. provider existance or internal user records) to let the user in -ggolden
1448: M_log
1449: .info("authenticate(): attempt by unknown user id: "
1450: + eid);
1451: } catch (Throwable e) {
1452: // we might have authenticated by provider, but don't have proper
1453: // user "existance" (i.e. provider existance or internal user records) to let the user in -ggolden
1454: M_log
1455: .warn("authenticate(): could not getUser() after auth: "
1456: + eid + " : " + e);
1457: }
1458: }
1459:
1460: // cache the user (if we didn't go through the getUserByEid() above, which would have cached it
1461: else {
1462: if (m_callCache != null)
1463: m_callCache.put(userReference(rv.getId()), rv,
1464: m_cacheSeconds);
1465: }
1466: }
1467:
1468: return rv;
1469: }
1470:
1471: /**
1472: * @inheritDoc
1473: */
1474: public void destroyAuthentication() {
1475: // let the provider know
1476: if (m_provider != null) {
1477: m_provider.destroyAuthentication();
1478: }
1479: }
1480:
1481: /**
1482: * Create the live properties for the user.
1483: */
1484: protected void addLiveProperties(BaseUserEdit edit) {
1485: String current = sessionManager().getCurrentSessionUserId();
1486:
1487: edit.m_createdUserId = current;
1488: edit.m_lastModifiedUserId = current;
1489:
1490: Time now = timeService().newTime();
1491: edit.m_createdTime = now;
1492: edit.m_lastModifiedTime = (Time) now.clone();
1493: }
1494:
1495: /**
1496: * Update the live properties for a user for when modified.
1497: */
1498: protected void addLiveUpdateProperties(BaseUserEdit edit) {
1499: String current = sessionManager().getCurrentSessionUserId();
1500:
1501: edit.m_lastModifiedUserId = current;
1502: edit.m_lastModifiedTime = timeService().newTime();
1503: }
1504:
1505: /**
1506: * Adjust the id - trim it to null. Note: eid case insensitive option does NOT apply to id.
1507: *
1508: * @param id
1509: * The id to clean up.
1510: * @return A cleaned up id.
1511: */
1512: protected String cleanId(String id) {
1513: // if we are not doing separate id and eid, use the eid rules
1514: if (!m_separateIdEid)
1515: return cleanEid(id);
1516:
1517: return StringUtil.trimToNull(id);
1518: }
1519:
1520: /**
1521: * Adjust the eid - trim it to null, and lower case IF we are case insensitive.
1522: *
1523: * @param eid
1524: * The eid to clean up.
1525: * @return A cleaned up eid.
1526: */
1527: protected String cleanEid(String eid) {
1528: if (!m_caseSensitiveEid) {
1529: return StringUtil.trimToNullLower(eid);
1530: }
1531:
1532: return StringUtil.trimToNull(eid);
1533: }
1534:
1535: /**********************************************************************************************************************************************************************************************************************************************************
1536: * EntityProducer implementation
1537: *********************************************************************************************************************************************************************************************************************************************************/
1538:
1539: /**
1540: * @inheritDoc
1541: */
1542: public String getLabel() {
1543: return "user";
1544: }
1545:
1546: /**
1547: * @inheritDoc
1548: */
1549: public boolean willArchiveMerge() {
1550: return false;
1551: }
1552:
1553: /**
1554: * @inheritDoc
1555: */
1556: public HttpAccess getHttpAccess() {
1557: return null;
1558: }
1559:
1560: /**
1561: * @inheritDoc
1562: */
1563: public boolean parseEntityReference(String reference, Reference ref) {
1564: // for user access
1565: if (reference.startsWith(REFERENCE_ROOT)) {
1566: String id = null;
1567:
1568: // we will get null, service, userId
1569: String[] parts = StringUtil.split(reference,
1570: Entity.SEPARATOR);
1571:
1572: if (parts.length > 2) {
1573: id = parts[2];
1574: }
1575:
1576: ref.set(APPLICATION_ID, null, id, null, null);
1577:
1578: return true;
1579: }
1580:
1581: return false;
1582: }
1583:
1584: /**
1585: * @inheritDoc
1586: */
1587: public String getEntityDescription(Reference ref) {
1588: // double check that it's mine
1589: if (APPLICATION_ID != ref.getType())
1590: return null;
1591:
1592: String rv = "User: " + ref.getReference();
1593:
1594: try {
1595: User user = getUser(ref.getId());
1596: rv = "User: " + user.getDisplayName();
1597: } catch (UserNotDefinedException e) {
1598: } catch (NullPointerException e) {
1599: }
1600:
1601: return rv;
1602: }
1603:
1604: /**
1605: * @inheritDoc
1606: */
1607: public ResourceProperties getEntityResourceProperties(Reference ref) {
1608: return null;
1609: }
1610:
1611: /**
1612: * @inheritDoc
1613: */
1614: public Entity getEntity(Reference ref) {
1615: return null;
1616: }
1617:
1618: /**
1619: * @inheritDoc
1620: */
1621: public Collection getEntityAuthzGroups(Reference ref, String userId) {
1622: // double check that it's mine
1623: if (APPLICATION_ID != ref.getType())
1624: return null;
1625:
1626: Collection rv = new Vector();
1627:
1628: // for user access: user and template realms
1629: try {
1630: rv.add(userReference(ref.getId()));
1631:
1632: ref.addUserTemplateAuthzGroup(rv, userId);
1633: } catch (NullPointerException e) {
1634: M_log.warn("getEntityRealms(): " + e);
1635: }
1636:
1637: return rv;
1638: }
1639:
1640: /**
1641: * @inheritDoc
1642: */
1643: public String getEntityUrl(Reference ref) {
1644: return null;
1645: }
1646:
1647: /**
1648: * @inheritDoc
1649: */
1650: public String archive(String siteId, Document doc, Stack stack,
1651: String archivePath, List attachments) {
1652: return "";
1653: }
1654:
1655: /**
1656: * @inheritDoc
1657: */
1658: public String merge(String siteId, Element root,
1659: String archivePath, String fromSiteId, Map attachmentNames,
1660: Map userIdTrans, Set userListAllowImport) {
1661: return "";
1662: }
1663:
1664: /**********************************************************************************************************************************************************************************************************************************************************
1665: * UserFactory implementation
1666: *********************************************************************************************************************************************************************************************************************************************************/
1667:
1668: /**
1669: * @inheritDoc
1670: */
1671: public UserEdit newUser() {
1672: return new BaseUserEdit((String) null);
1673: }
1674:
1675: /**********************************************************************************************************************************************************************************************************************************************************
1676: * UserEdit implementation
1677: *********************************************************************************************************************************************************************************************************************************************************/
1678:
1679: /**
1680: * <p>
1681: * BaseUserEdit is an implementation of the UserEdit object.
1682: * </p>
1683: */
1684: public class BaseUserEdit implements UserEdit,
1685: SessionBindingListener {
1686: /** The event code for this edit. */
1687: protected String m_event = null;
1688:
1689: /** Active flag. */
1690: protected boolean m_active = false;
1691:
1692: /** The user id. */
1693: protected String m_id = null;
1694:
1695: /** The user eid. */
1696: protected String m_eid = null;
1697:
1698: /** The user first name. */
1699: protected String m_firstName = null;
1700:
1701: /** The user last name. */
1702: protected String m_lastName = null;
1703:
1704: /** The user email address. */
1705: protected String m_email = null;
1706:
1707: /** The user password. */
1708: protected String m_pw = null;
1709:
1710: /** The properties. */
1711: protected ResourcePropertiesEdit m_properties = null;
1712:
1713: /** The user type. */
1714: protected String m_type = null;
1715:
1716: /** The created user id. */
1717: protected String m_createdUserId = null;
1718:
1719: /** The last modified user id. */
1720: protected String m_lastModifiedUserId = null;
1721:
1722: /** The time created. */
1723: protected Time m_createdTime = null;
1724:
1725: /** The time last modified. */
1726: protected Time m_lastModifiedTime = null;
1727:
1728: /** If editing the first name is restricted **/
1729: protected boolean m_restrictedFirstName = false;
1730:
1731: /** If editing the last name is restricted **/
1732: protected boolean m_restrictedLastName = false;
1733:
1734: /** If editing the email is restricted **/
1735: protected boolean m_restrictedEmail = false;
1736:
1737: /** If editing the password is restricted **/
1738: protected boolean m_restrictedPassword = false;
1739:
1740: /** If editing the type is restricted **/
1741: protected boolean m_restrictedType = false;
1742:
1743: /**
1744: * Construct.
1745: *
1746: * @param id
1747: * The user id.
1748: */
1749: public BaseUserEdit(String id) {
1750: m_id = id;
1751:
1752: // setup for properties
1753: ResourcePropertiesEdit props = new BaseResourcePropertiesEdit();
1754: m_properties = props;
1755:
1756: // if the id is not null (a new user, rather than a reconstruction)
1757: // and not the anon (id == "") user,
1758: // add the automatic (live) properties
1759: if ((m_id != null) && (m_id.length() > 0))
1760: addLiveProperties(this );
1761: }
1762:
1763: /**
1764: * Construct from another User object.
1765: *
1766: * @param user
1767: * The user object to use for values.
1768: */
1769: public BaseUserEdit(User user) {
1770: setAll(user);
1771: }
1772:
1773: /**
1774: * Construct from information in XML.
1775: *
1776: * @param el
1777: * The XML DOM Element definining the user.
1778: */
1779: public BaseUserEdit(Element el) {
1780: // setup for properties
1781: m_properties = new BaseResourcePropertiesEdit();
1782:
1783: m_id = cleanId(el.getAttribute("id"));
1784: m_eid = cleanEid(el.getAttribute("eid"));
1785: m_firstName = StringUtil.trimToNull(el
1786: .getAttribute("first-name"));
1787: m_lastName = StringUtil.trimToNull(el
1788: .getAttribute("last-name"));
1789: setEmail(StringUtil.trimToNull(el.getAttribute("email")));
1790: m_pw = el.getAttribute("pw");
1791: m_type = StringUtil.trimToNull(el.getAttribute("type"));
1792: m_createdUserId = StringUtil.trimToNull(el
1793: .getAttribute("created-id"));
1794: m_lastModifiedUserId = StringUtil.trimToNull(el
1795: .getAttribute("modified-id"));
1796:
1797: String time = StringUtil.trimToNull(el
1798: .getAttribute("created-time"));
1799: if (time != null) {
1800: m_createdTime = timeService().newTimeGmt(time);
1801: }
1802:
1803: time = StringUtil.trimToNull(el
1804: .getAttribute("modified-time"));
1805: if (time != null) {
1806: m_lastModifiedTime = timeService().newTimeGmt(time);
1807: }
1808:
1809: // the children (roles, properties)
1810: NodeList children = el.getChildNodes();
1811: final int length = children.getLength();
1812: for (int i = 0; i < length; i++) {
1813: Node child = children.item(i);
1814: if (child.getNodeType() != Node.ELEMENT_NODE)
1815: continue;
1816: Element element = (Element) child;
1817:
1818: // look for properties
1819: if (element.getTagName().equals("properties")) {
1820: // re-create properties
1821: m_properties = new BaseResourcePropertiesEdit(
1822: element);
1823:
1824: // pull out some properties into fields to convert old (pre 1.38) versions
1825: if (m_createdUserId == null) {
1826: m_createdUserId = m_properties
1827: .getProperty("CHEF:creator");
1828: }
1829: if (m_lastModifiedUserId == null) {
1830: m_lastModifiedUserId = m_properties
1831: .getProperty("CHEF:modifiedby");
1832: }
1833: if (m_createdTime == null) {
1834: try {
1835: m_createdTime = m_properties
1836: .getTimeProperty("DAV:creationdate");
1837: } catch (Exception ignore) {
1838: }
1839: }
1840: if (m_lastModifiedTime == null) {
1841: try {
1842: m_lastModifiedTime = m_properties
1843: .getTimeProperty("DAV:getlastmodified");
1844: } catch (Exception ignore) {
1845: }
1846: }
1847: m_properties.removeProperty("CHEF:creator");
1848: m_properties.removeProperty("CHEF:modifiedby");
1849: m_properties.removeProperty("DAV:creationdate");
1850: m_properties.removeProperty("DAV:getlastmodified");
1851: }
1852: }
1853: }
1854:
1855: /**
1856: * ReConstruct.
1857: *
1858: * @param id
1859: * The id.
1860: * @param eid
1861: * The eid.
1862: * @param email
1863: * The email.
1864: * @param firstName
1865: * The first name.
1866: * @param lastName
1867: * The last name.
1868: * @param type
1869: * The type.
1870: * @param pw
1871: * The password.
1872: * @param createdBy
1873: * The createdBy property.
1874: * @param createdOn
1875: * The createdOn property.
1876: * @param modifiedBy
1877: * The modified by property.
1878: * @param modifiedOn
1879: * The modified on property.
1880: */
1881: public BaseUserEdit(String id, String eid, String email,
1882: String firstName, String lastName, String type,
1883: String pw, String createdBy, Time createdOn,
1884: String modifiedBy, Time modifiedOn) {
1885: m_id = id;
1886: m_eid = eid;
1887: m_firstName = firstName;
1888: m_lastName = lastName;
1889: m_type = type;
1890: setEmail(email);
1891: m_pw = pw;
1892: m_createdUserId = createdBy;
1893: m_lastModifiedUserId = modifiedBy;
1894: m_createdTime = createdOn;
1895: m_lastModifiedTime = modifiedOn;
1896:
1897: // setup for properties, but mark them lazy since we have not yet established them from data
1898: BaseResourcePropertiesEdit props = new BaseResourcePropertiesEdit();
1899: props.setLazy(true);
1900: m_properties = props;
1901: }
1902:
1903: /**
1904: * Take all values from this object.
1905: *
1906: * @param user
1907: * The user object to take values from.
1908: */
1909: protected void setAll(User user) {
1910: m_id = user.getId();
1911: m_eid = user.getEid();
1912: m_firstName = user.getFirstName();
1913: m_lastName = user.getLastName();
1914: m_type = user.getType();
1915: setEmail(user.getEmail());
1916: m_pw = ((BaseUserEdit) user).m_pw;
1917: m_createdUserId = ((BaseUserEdit) user).m_createdUserId;
1918: m_lastModifiedUserId = ((BaseUserEdit) user).m_lastModifiedUserId;
1919: if (((BaseUserEdit) user).m_createdTime != null)
1920: m_createdTime = (Time) ((BaseUserEdit) user).m_createdTime
1921: .clone();
1922: if (((BaseUserEdit) user).m_lastModifiedTime != null)
1923: m_lastModifiedTime = (Time) ((BaseUserEdit) user).m_lastModifiedTime
1924: .clone();
1925:
1926: m_properties = new BaseResourcePropertiesEdit();
1927: m_properties.addAll(user.getProperties());
1928: ((BaseResourcePropertiesEdit) m_properties)
1929: .setLazy(((BaseResourceProperties) user
1930: .getProperties()).isLazy());
1931: }
1932:
1933: /**
1934: * @inheritDoc
1935: */
1936: public Element toXml(Document doc, Stack stack) {
1937: Element user = doc.createElement("user");
1938:
1939: if (stack.isEmpty()) {
1940: doc.appendChild(user);
1941: } else {
1942: ((Element) stack.peek()).appendChild(user);
1943: }
1944:
1945: stack.push(user);
1946:
1947: user.setAttribute("id", getId());
1948: user.setAttribute("eid", getEid());
1949: if (m_firstName != null)
1950: user.setAttribute("first-name", m_firstName);
1951: if (m_lastName != null)
1952: user.setAttribute("last-name", m_lastName);
1953: if (m_type != null)
1954: user.setAttribute("type", m_type);
1955: user.setAttribute("email", getEmail());
1956: user.setAttribute("pw", m_pw);
1957: user.setAttribute("created-id", m_createdUserId);
1958: user.setAttribute("modified-id", m_lastModifiedUserId);
1959: user.setAttribute("created-time", m_createdTime.toString());
1960: user.setAttribute("modified-time", m_lastModifiedTime
1961: .toString());
1962:
1963: // properties
1964: getProperties().toXml(doc, stack);
1965:
1966: stack.pop();
1967:
1968: return user;
1969: }
1970:
1971: /**
1972: * @inheritDoc
1973: */
1974: public String getId() {
1975: if (m_id == null)
1976: return "";
1977: return m_id;
1978: }
1979:
1980: /**
1981: * @inheritDoc
1982: */
1983: public String getEid() {
1984: if (m_eid == null)
1985: return "";
1986: return m_eid;
1987: }
1988:
1989: /**
1990: * @inheritDoc
1991: */
1992: public String getUrl() {
1993: return getAccessPoint(false) + m_id;
1994: }
1995:
1996: /**
1997: * @inheritDoc
1998: */
1999: public String getReference() {
2000: return userReference(m_id);
2001: }
2002:
2003: /**
2004: * @inheritDoc
2005: */
2006: public String getReference(String rootProperty) {
2007: return getReference();
2008: }
2009:
2010: /**
2011: * @inheritDoc
2012: */
2013: public String getUrl(String rootProperty) {
2014: return getUrl();
2015: }
2016:
2017: /**
2018: * @inheritDoc
2019: */
2020: public ResourceProperties getProperties() {
2021: // if lazy, resolve
2022: if (((BaseResourceProperties) m_properties).isLazy()) {
2023: ((BaseResourcePropertiesEdit) m_properties)
2024: .setLazy(false);
2025: m_storage.readProperties(this , m_properties);
2026: }
2027:
2028: return m_properties;
2029: }
2030:
2031: /**
2032: * @inheritDoc
2033: */
2034: public User getCreatedBy() {
2035: try {
2036: return getUser(m_createdUserId);
2037: } catch (Exception e) {
2038: return getAnonymousUser();
2039: }
2040: }
2041:
2042: /**
2043: * @inheritDoc
2044: */
2045: public User getModifiedBy() {
2046: try {
2047: return getUser(m_lastModifiedUserId);
2048: } catch (Exception e) {
2049: return getAnonymousUser();
2050: }
2051: }
2052:
2053: /**
2054: * @inheritDoc
2055: */
2056: public Time getCreatedTime() {
2057: return m_createdTime;
2058: }
2059:
2060: /**
2061: * @inheritDoc
2062: */
2063: public Time getModifiedTime() {
2064: return m_lastModifiedTime;
2065: }
2066:
2067: /**
2068: * @inheritDoc
2069: */
2070: public String getDisplayName() {
2071: String rv = null;
2072:
2073: // let the provider handle it, if we have that sort of provider, and it wants to handle this
2074: if ((m_provider != null)
2075: && (m_provider instanceof DisplayAdvisorUDP)) {
2076: rv = ((DisplayAdvisorUDP) m_provider)
2077: .getDisplayName(this );
2078: }
2079:
2080: if (rv == null) {
2081: // or do it this way
2082: StringBuffer buf = new StringBuffer(128);
2083: if (m_firstName != null)
2084: buf.append(m_firstName);
2085: if (m_lastName != null) {
2086: buf.append(" ");
2087: buf.append(m_lastName);
2088: }
2089:
2090: if (buf.length() == 0) {
2091: rv = getEid();
2092: }
2093:
2094: else {
2095: rv = buf.toString();
2096: }
2097: }
2098:
2099: return rv;
2100: }
2101:
2102: /**
2103: * @inheritDoc
2104: */
2105: public String getDisplayId() {
2106: String rv = null;
2107:
2108: // let the provider handle it, if we have that sort of provider, and it wants to handle this
2109: if ((m_provider != null)
2110: && (m_provider instanceof DisplayAdvisorUDP)) {
2111: rv = ((DisplayAdvisorUDP) m_provider)
2112: .getDisplayId(this );
2113: }
2114:
2115: // use eid if not
2116: if (rv == null) {
2117: rv = getEid();
2118: }
2119:
2120: return rv;
2121: }
2122:
2123: /**
2124: * @inheritDoc
2125: */
2126: public String getFirstName() {
2127: if (m_firstName == null)
2128: return "";
2129: return m_firstName;
2130: }
2131:
2132: /**
2133: * @inheritDoc
2134: */
2135: public String getLastName() {
2136: if (m_lastName == null)
2137: return "";
2138: return m_lastName;
2139: }
2140:
2141: /**
2142: * @inheritDoc
2143: */
2144: public String getSortName() {
2145: StringBuffer buf = new StringBuffer(128);
2146: if (m_lastName != null)
2147: buf.append(m_lastName);
2148: if (m_firstName != null) {
2149: buf.append(", ");
2150: buf.append(m_firstName);
2151: }
2152:
2153: if (buf.length() == 0)
2154: return getEid();
2155:
2156: return buf.toString();
2157: }
2158:
2159: /**
2160: * @inheritDoc
2161: */
2162: public String getEmail() {
2163: if (m_email == null)
2164: return "";
2165: return m_email;
2166: }
2167:
2168: /**
2169: * @inheritDoc
2170: */
2171: public String getType() {
2172: return m_type;
2173: }
2174:
2175: /**
2176: * @inheritDoc
2177: */
2178: public boolean checkPassword(String pw) {
2179: pw = StringUtil.trimToNull(pw);
2180:
2181: // if we have no password, or none is given, we fail
2182: if ((m_pw == null) || (pw == null))
2183: return false;
2184:
2185: // if we have a truncated (i.e. pre SAK-5922) password, deal with it
2186: if (m_pw.length() == 20) {
2187: // encode this password truncated
2188: String encoded = OneWayHash.encode(pw, true);
2189:
2190: if (m_pw.equals(encoded))
2191: return true;
2192: }
2193:
2194: // otherwise deal with the full encoding
2195: else {
2196: // encode this password
2197: String encoded = OneWayHash.encode(pw, false);
2198:
2199: if (m_pw.equals(encoded))
2200: return true;
2201: }
2202:
2203: return false;
2204: }
2205:
2206: /**
2207: * @inheritDoc
2208: */
2209: public boolean equals(Object obj) {
2210: if (!(obj instanceof User))
2211: return false;
2212: return ((User) obj).getId().equals(getId());
2213: }
2214:
2215: /**
2216: * @inheritDoc
2217: */
2218: public int hashCode() {
2219: return getId().hashCode();
2220: }
2221:
2222: /**
2223: * @inheritDoc
2224: */
2225: public int compareTo(Object obj) {
2226: if (!(obj instanceof User))
2227: throw new ClassCastException();
2228:
2229: // if the object are the same, say so
2230: if (obj == this )
2231: return 0;
2232:
2233: // start the compare by comparing their sort names
2234: int compare = getSortName().compareTo(
2235: ((User) obj).getSortName());
2236:
2237: // if these are the same
2238: if (compare == 0) {
2239: // sort based on (unique) eid
2240: compare = getEid().compareTo(((User) obj).getEid());
2241: }
2242:
2243: return compare;
2244: }
2245:
2246: /**
2247: * Clean up.
2248: */
2249: protected void finalize() {
2250: // catch the case where an edit was made but never resolved
2251: if (m_active) {
2252: cancelEdit(this );
2253: }
2254: }
2255:
2256: /**
2257: * @inheritDoc
2258: */
2259: public void setId(String id) {
2260: // set once only!
2261: if (m_id == null) {
2262: m_id = id;
2263: }
2264: }
2265:
2266: /**
2267: * @inheritDoc
2268: */
2269: public void setEid(String eid) {
2270: m_eid = eid;
2271: }
2272:
2273: /**
2274: * @inheritDoc
2275: */
2276: public void setFirstName(String name) {
2277: if (!m_restrictedFirstName) {
2278: m_firstName = name;
2279: }
2280: }
2281:
2282: /**
2283: * @inheritDoc
2284: */
2285: public void setLastName(String name) {
2286: if (!m_restrictedLastName) {
2287: m_lastName = name;
2288: }
2289: }
2290:
2291: /**
2292: * @inheritDoc
2293: */
2294: public void setEmail(String email) {
2295: if (!m_restrictedEmail) {
2296: m_email = email;
2297: }
2298: }
2299:
2300: /**
2301: * @inheritDoc
2302: */
2303: public void setPassword(String pw) {
2304:
2305: if (!m_restrictedPassword) {
2306:
2307: // to clear it
2308: if (pw == null) {
2309: m_pw = null;
2310: }
2311:
2312: // else encode the new one
2313: else {
2314: // encode this password
2315: String encoded = OneWayHash.encode(pw, false);
2316: m_pw = encoded;
2317: }
2318: }
2319: }
2320:
2321: /**
2322: * @inheritDoc
2323: */
2324: public void setType(String type) {
2325: if (!m_restrictedType) {
2326:
2327: m_type = type;
2328:
2329: }
2330: }
2331:
2332: public void restrictEditFirstName() {
2333:
2334: m_restrictedFirstName = true;
2335:
2336: }
2337:
2338: public void restrictEditLastName() {
2339:
2340: m_restrictedLastName = true;
2341:
2342: }
2343:
2344: public void restrictEditEmail() {
2345:
2346: m_restrictedEmail = true;
2347:
2348: }
2349:
2350: public void restrictEditPassword() {
2351:
2352: m_restrictedPassword = true;
2353:
2354: }
2355:
2356: public void restrictEditType() {
2357:
2358: m_restrictedType = true;
2359:
2360: }
2361:
2362: /**
2363: * Take all values from this object.
2364: *
2365: * @param user
2366: * The user object to take values from.
2367: */
2368: protected void set(User user) {
2369: setAll(user);
2370: }
2371:
2372: /**
2373: * Access the event code for this edit.
2374: *
2375: * @return The event code for this edit.
2376: */
2377: protected String getEvent() {
2378: return m_event;
2379: }
2380:
2381: /**
2382: * Set the event code for this edit.
2383: *
2384: * @param event
2385: * The event code for this edit.
2386: */
2387: protected void setEvent(String event) {
2388: m_event = event;
2389: }
2390:
2391: /**
2392: * @inheritDoc
2393: */
2394: public ResourcePropertiesEdit getPropertiesEdit() {
2395: // if lazy, resolve
2396: if (((BaseResourceProperties) m_properties).isLazy()) {
2397: ((BaseResourcePropertiesEdit) m_properties)
2398: .setLazy(false);
2399: m_storage.readProperties(this , m_properties);
2400: }
2401:
2402: return m_properties;
2403: }
2404:
2405: /**
2406: * Enable editing.
2407: */
2408: protected void activate() {
2409: m_active = true;
2410: }
2411:
2412: /**
2413: * @inheritDoc
2414: */
2415: public boolean isActiveEdit() {
2416: return m_active;
2417: }
2418:
2419: /**
2420: * Close the edit object - it cannot be used after this.
2421: */
2422: protected void closeEdit() {
2423: m_active = false;
2424: }
2425:
2426: /**
2427: * Check this User object to see if it is selected by the criteria.
2428: *
2429: * @param criteria
2430: * The critera.
2431: * @return True if the User object is selected by the criteria, false if not.
2432: */
2433: protected boolean selectedBy(String criteria) {
2434: if (StringUtil.containsIgnoreCase(getSortName(), criteria)
2435: || StringUtil.containsIgnoreCase(getDisplayName(),
2436: criteria)
2437: || StringUtil
2438: .containsIgnoreCase(getEid(), criteria)
2439: || StringUtil.containsIgnoreCase(getEmail(),
2440: criteria)) {
2441: return true;
2442: }
2443:
2444: return false;
2445: }
2446:
2447: /******************************************************************************************************************************************************************************************************************************************************
2448: * SessionBindingListener implementation
2449: *****************************************************************************************************************************************************************************************************************************************************/
2450:
2451: /**
2452: * @inheritDoc
2453: */
2454: public void valueBound(SessionBindingEvent event) {
2455: }
2456:
2457: /**
2458: * @inheritDoc
2459: */
2460: public void valueUnbound(SessionBindingEvent event) {
2461: if (M_log.isDebugEnabled())
2462: M_log.debug("valueUnbound()");
2463:
2464: // catch the case where an edit was made but never resolved
2465: if (m_active) {
2466: cancelEdit(this );
2467: }
2468: }
2469: }
2470:
2471: /**********************************************************************************************************************************************************************************************************************************************************
2472: * Storage
2473: *********************************************************************************************************************************************************************************************************************************************************/
2474:
2475: protected interface Storage {
2476: /**
2477: * Open.
2478: */
2479: public void open();
2480:
2481: /**
2482: * Close.
2483: */
2484: public void close();
2485:
2486: /**
2487: * Check if a user by this id exists.
2488: *
2489: * @param id
2490: * The user id.
2491: * @return true if a user by this id exists, false if not.
2492: */
2493: public boolean check(String id);
2494:
2495: /**
2496: * Get the user with this id, or null if not found.
2497: *
2498: * @param id
2499: * The user id.
2500: * @return The user with this id, or null if not found.
2501: */
2502: public UserEdit getById(String id);
2503:
2504: /**
2505: * Get the user with this eid, or null if not found.
2506: *
2507: * @param eid
2508: * The user eid.
2509: * @return The user with this eid, or null if not found.
2510: */
2511: public UserEdit getByEid(String eid);
2512:
2513: /**
2514: * Get the users with this email, or return empty if none found.
2515: *
2516: * @param id
2517: * The user email.
2518: * @return The Collection (User) of users with this email, or an empty collection if none found.
2519: */
2520: public Collection findUsersByEmail(String email);
2521:
2522: /**
2523: * Get all users.
2524: *
2525: * @return The List (UserEdit) of all users.
2526: */
2527: public List getAll();
2528:
2529: /**
2530: * Get all the users in record range.
2531: *
2532: * @param first
2533: * The first record position to return.
2534: * @param last
2535: * The last record position to return.
2536: * @return The List (BaseUserEdit) of all users.
2537: */
2538: public List getAll(int first, int last);
2539:
2540: /**
2541: * Count all the users.
2542: *
2543: * @return The count of all users.
2544: */
2545: public int count();
2546:
2547: /**
2548: * Search for users with id or email, first or last name matching criteria, in range.
2549: *
2550: * @param criteria
2551: * The search criteria.
2552: * @param first
2553: * The first record position to return.
2554: * @param last
2555: * The last record position to return.
2556: * @return The List (BaseUserEdit) of all alias.
2557: */
2558: public List search(String criteria, int first, int last);
2559:
2560: /**
2561: * Count all the users with id or email, first or last name matching criteria.
2562: *
2563: * @param criteria
2564: * The search criteria.
2565: * @return The count of all aliases with id or target matching criteria.
2566: */
2567: public int countSearch(String criteria);
2568:
2569: /**
2570: * Add a new user with this id and eid.
2571: *
2572: * @param id
2573: * The user id.
2574: * @param eid
2575: * The user eid.
2576: * @return The locked User object with this id and eid, or null if the id is in use.
2577: */
2578: public UserEdit put(String id, String eid);
2579:
2580: /**
2581: * Get a lock on the user with this id, or null if a lock cannot be gotten.
2582: *
2583: * @param id
2584: * The user id.
2585: * @return The locked User with this id, or null if this records cannot be locked.
2586: */
2587: public UserEdit edit(String id);
2588:
2589: /**
2590: * Commit the changes and release the lock.
2591: *
2592: * @param user
2593: * The user to commit.
2594: * @return true if successful, false if not (eid may not be unique).
2595: */
2596: public boolean commit(UserEdit user);
2597:
2598: /**
2599: * Cancel the changes and release the lock.
2600: *
2601: * @param user
2602: * The user to commit.
2603: */
2604: public void cancel(UserEdit user);
2605:
2606: /**
2607: * Remove this user.
2608: *
2609: * @param user
2610: * The user to remove.
2611: */
2612: public void remove(UserEdit user);
2613:
2614: /**
2615: * Read properties from storage into the edit's properties.
2616: *
2617: * @param edit
2618: * The user to read properties for.
2619: */
2620: public void readProperties(UserEdit edit,
2621: ResourcePropertiesEdit props);
2622:
2623: /**
2624: * Create a mapping between the id and eid.
2625: *
2626: * @param id
2627: * The user id.
2628: * @param eid
2629: * The user eid.
2630: * @return true if successful, false if not (id or eid might be in use).
2631: */
2632: public boolean putMap(String id, String eid);
2633:
2634: /**
2635: * Check the id -> eid mapping: lookup this id and return the eid if found
2636: *
2637: * @param id
2638: * The user id to lookup.
2639: * @return The eid mapped to this id, or null if none.
2640: */
2641: public String checkMapForEid(String id);
2642:
2643: /**
2644: * Check the id -> eid mapping: lookup this eid and return the id if found
2645: *
2646: * @param eid
2647: * The user eid to lookup.
2648: * @return The id mapped to this eid, or null if none.
2649: */
2650: public String checkMapForId(String eid);
2651: }
2652:
2653: /**********************************************************************************************************************************************************************************************************************************************************
2654: * StorageUser implementation (no container)
2655: *********************************************************************************************************************************************************************************************************************************************************/
2656:
2657: /**
2658: * @inheritDoc
2659: */
2660: public Entity newContainer(String ref) {
2661: return null;
2662: }
2663:
2664: /**
2665: * @inheritDoc
2666: */
2667: public Entity newContainer(Element element) {
2668: return null;
2669: }
2670:
2671: /**
2672: * @inheritDoc
2673: */
2674: public Entity newContainer(Entity other) {
2675: return null;
2676: }
2677:
2678: /**
2679: * @inheritDoc
2680: */
2681: public Entity newResource(Entity container, String id,
2682: Object[] others) {
2683: return new BaseUserEdit(id);
2684: }
2685:
2686: /**
2687: * @inheritDoc
2688: */
2689: public Entity newResource(Entity container, Element element) {
2690: return new BaseUserEdit(element);
2691: }
2692:
2693: /**
2694: * @inheritDoc
2695: */
2696: public Entity newResource(Entity container, Entity other) {
2697: return new BaseUserEdit((User) other);
2698: }
2699:
2700: /**
2701: * @inheritDoc
2702: */
2703: public Edit newContainerEdit(String ref) {
2704: return null;
2705: }
2706:
2707: /**
2708: * @inheritDoc
2709: */
2710: public Edit newContainerEdit(Element element) {
2711: return null;
2712: }
2713:
2714: /**
2715: * @inheritDoc
2716: */
2717: public Edit newContainerEdit(Entity other) {
2718: return null;
2719: }
2720:
2721: /**
2722: * @inheritDoc
2723: */
2724: public Edit newResourceEdit(Entity container, String id,
2725: Object[] others) {
2726: BaseUserEdit e = new BaseUserEdit(id);
2727: e.activate();
2728: return e;
2729: }
2730:
2731: /**
2732: * @inheritDoc
2733: */
2734: public Edit newResourceEdit(Entity container, Element element) {
2735: BaseUserEdit e = new BaseUserEdit(element);
2736: e.activate();
2737: return e;
2738: }
2739:
2740: /**
2741: * @inheritDoc
2742: */
2743: public Edit newResourceEdit(Entity container, Entity other) {
2744: BaseUserEdit e = new BaseUserEdit((User) other);
2745: e.activate();
2746: return e;
2747: }
2748:
2749: /**
2750: * @inheritDoc
2751: */
2752: public Object[] storageFields(Entity r) {
2753: return null;
2754: }
2755:
2756: /**
2757: * @inheritDoc
2758: */
2759: public boolean isDraft(Entity r) {
2760: return false;
2761: }
2762:
2763: /**
2764: * @inheritDoc
2765: */
2766: public String getOwnerId(Entity r) {
2767: return null;
2768: }
2769:
2770: /**
2771: * @inheritDoc
2772: */
2773: public Time getDate(Entity r) {
2774: return null;
2775: }
2776: }
|