001: /*
002: * JOSSO: Java Open Single Sign-On
003: *
004: * Copyright 2004-2008, Atricore, Inc.
005: *
006: * This is free software; you can redistribute it and/or modify it
007: * under the terms of the GNU Lesser General Public License as
008: * published by the Free Software Foundation; either version 2.1 of
009: * the License, or (at your option) any later version.
010: *
011: * This software is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this software; if not, write to the Free
018: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
019: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
020: */
021: package org.josso.gateway.identity.service.store;
022:
023: import org.apache.commons.configuration.Configuration;
024: import org.apache.commons.configuration.HierarchicalXMLConfiguration;
025: import org.apache.commons.logging.Log;
026: import org.apache.commons.logging.LogFactory;
027: import org.josso.auth.Credential;
028: import org.josso.auth.CredentialKey;
029: import org.josso.auth.CredentialStore;
030: import org.josso.auth.CredentialProvider;
031: import org.josso.gateway.SSONameValuePair;
032: import org.josso.gateway.identity.exceptions.NoSuchRoleException;
033: import org.josso.gateway.identity.exceptions.NoSuchUserException;
034: import org.josso.gateway.identity.exceptions.SSOIdentityException;
035: import org.josso.gateway.identity.service.BaseRole;
036: import org.josso.gateway.identity.service.BaseRoleImpl;
037: import org.josso.gateway.identity.service.BaseUser;
038: import org.josso.gateway.identity.service.BaseUserImpl;
039: import org.josso.Lookup;
040:
041: import java.util.*;
042:
043: /**
044: * Memory based implementation of an IdentityStore and CredentialStore that reads
045: * data from XML files.
046: *
047: * @author <a href="mailto:sgonzalez@josso.org">Sebastian Gonzalez Oyuela</a>
048: * @version $Id: MemoryIdentityStore.java 508 2008-02-18 13:32:29Z sgonzalez $
049: */
050:
051: public class MemoryIdentityStore extends AbstractStore {
052:
053: private static final Log logger = LogFactory
054: .getLog(MemoryIdentityStore.class);
055:
056: // A map with BaseRole instances, the map key is the role name.
057: private Map _roles;
058:
059: // A map with BaseUser instances, the key is the username.
060: private Map _users;
061:
062: // Stores BaseRoles associated to each user.
063: // The map key is the username.
064: // The map value is a Set of rolenames.
065: private Map _userRoles;
066:
067: // Stores credential values (Object) associated to each user.
068: // The map key is the username.
069: // THe map value is another Map with credetinals (name=key/value)
070: private Map _principalCredentials;
071:
072: private boolean _initialized;
073:
074: private String _credentialsFileName;
075: private String _usersFileName;
076:
077: private CredentialProvider credentialProvider;
078:
079: public MemoryIdentityStore() {
080: super ();
081: _users = new HashMap(7);
082: _userRoles = new HashMap(11);
083: _roles = new HashMap(11);
084: _principalCredentials = new HashMap(11);
085: _initialized = false;
086: }
087:
088: /**
089: * Initializes the store, reads data from XML files.
090: */
091: public synchronized void initialize() {
092: try {
093: // This store can work as an identityStore and as a credentialStore, so
094: // configuration parameters are optional.
095: if (_usersFileName != null)
096: loadUsersData(_usersFileName);
097: if (_credentialsFileName != null)
098: loadCredentialsData(_credentialsFileName);
099: _initialized = true;
100: } catch (Exception e) {
101: logger.error(e, e);
102: throw new RuntimeException(
103: "Can't initialize memory store : " + e.getMessage(),
104: e);
105: }
106: }
107:
108: /**
109: * Loads users from file.
110: * @param fName the file containing user definitions.
111: */
112: protected void loadUsersData(String fName) throws Exception {
113: // First, users
114: logger.info("Reading users from : " + fName);
115: HierarchicalXMLConfiguration config;
116: config = new HierarchicalXMLConfiguration();
117: //config.setFileName(fName);
118: config.load(getClass().getResource("/" + fName));
119:
120: loadRoles(config);
121:
122: loadUsers(config);
123:
124: }
125:
126: protected void loadRoles(Configuration config) {
127:
128: if (config.getList("roles.role.name").size() < 1)
129: return;
130:
131: Collection c = null;
132:
133: // Load Roles
134: if (!(config.getProperty("roles.role.name") instanceof java.util.Collection)) {
135: List nCol = new ArrayList();
136: nCol.add(config.getProperty("roles.role.name"));
137: c = nCol;
138: } else
139: c = (Collection) config.getProperty("roles.role.name");
140:
141: for (int i = 0; i < c.size(); i++) {
142: String name = config
143: .getString("roles.role(" + i + ").name");
144: BaseRole role = createRole(name);
145: RoleKey key = createRoleKey(role);
146: _roles.put(key, role);
147: logger.info("Role : " + role);
148: }
149: }
150:
151: protected void loadUsers(Configuration config) throws Exception {
152:
153: // Load Users
154: Collection c = null;
155: if (!(config.getProperty("users.user.name") instanceof java.util.Collection)) {
156: List nCol = new ArrayList();
157: nCol.add(config.getProperty("users.user.name"));
158: c = nCol;
159: } else
160: c = (Collection) config.getProperty("users.user.name");
161:
162: for (int i = 0; i < c.size(); i++) {
163: String name = config
164: .getString("users.user(" + i + ").name");
165: BaseUser user = createUser(name);
166: UserKey key = createUserKey(user);
167: _users.put(key, user);
168: logger.info("User : " + user);
169:
170: // Load user properties
171: SSONameValuePair[] props = loadUserProperties(config
172: .subset("users.user(" + i + ")"));
173: user.setProperties(props);
174:
175: // Load user roles, optional
176: if (config.getList("users.user(" + i + ").roles").size() > 0) {
177:
178: String roles = config.getString("users.user(" + i
179: + ").roles");
180: StringTokenizer st = new StringTokenizer(
181: roles != null ? roles : "", ",");
182: while (st.hasMoreTokens()) {
183: String roleName = st.nextToken().trim();
184: BaseRole role = findRoleByName(roleName);
185: RoleKey roleKey = createRoleKey(role);
186: assignRole(key, roleKey);
187: logger.info("User is in role : " + role);
188: }
189: }
190: }
191: }
192:
193: protected SSONameValuePair[] loadUserProperties(Configuration config) {
194:
195: if (config.getList("properties.property.name").size() < 1)
196: return new SSONameValuePair[0];
197:
198: Collection c = null;
199: if (!(config.getProperty("properties.property.name") instanceof java.util.Collection)) {
200: List nCol = new ArrayList();
201: nCol.add(config.getProperty("properties.property.name"));
202: c = nCol;
203: } else
204: c = (Collection) config
205: .getProperty("properties.property.name");
206:
207: ArrayList props = new ArrayList(c.size());
208: for (int i = 0; i < c.size(); i++) {
209: String name = config.getString("properties.property(" + i
210: + ").name");
211: String value = config.getString("properties.property(" + i
212: + ").value");
213: SSONameValuePair p = new SSONameValuePair(name, value);
214: props.add(p);
215: logger.info("Property : " + name + "=" + value);
216: }
217: return (SSONameValuePair[]) props
218: .toArray(new SSONameValuePair[props.size()]);
219:
220: }
221:
222: /**
223: * Loads credentials from file.
224: * @param fName the file containing user definitions.
225: */
226: protected void loadCredentialsData(String fName) throws Exception {
227: logger.info("Reading credentials from : " + fName);
228:
229: HierarchicalXMLConfiguration config;
230: config = new HierarchicalXMLConfiguration();
231: //config.setFileName(fName);
232: config.load(getClass().getResource("/" + fName));
233:
234: loadCredentialSet(config);
235:
236: }
237:
238: protected void loadCredentialSet(Configuration config)
239: throws Exception {
240: // Load Credentials
241: Collection c = null;
242: if (!(config.getProperty("credential-set.key") instanceof java.util.Collection)) {
243: List nCol = new ArrayList();
244: nCol.add(config.getProperty("credential-set.key"));
245: c = nCol;
246: } else
247: c = (Collection) config.getProperty("credential-set.key");
248:
249: for (int i = 0; i < c.size(); i++) {
250: String keyName = config.getString("credential-set(" + i
251: + ").key");
252: logger.info("Credential-set : " + keyName);
253: Credential[] creds = loadCredentials(config
254: .subset("credential-set(" + i + ")"));
255: CredentialKey key = createCredentialKey(keyName);
256: addCredentials(key, creds);
257: }
258:
259: }
260:
261: protected Credential[] loadCredentials(Configuration config)
262: throws Exception {
263: if (config.getList("credential.name").size() < 1)
264: return new Credential[0];
265:
266: Collection c = null;
267: if (!(config.getProperty("credential.name") instanceof java.util.Collection)) {
268: List nCol = new ArrayList();
269: nCol.add(config.getProperty("credential.name"));
270: c = nCol;
271: } else
272: c = (Collection) config.getProperty("credential.name");
273:
274: List creds = new ArrayList();
275: for (int i = 0; i < c.size(); i++) {
276: String name = config
277: .getString("credential(" + i + ").name");
278: String value = config.getString("credential(" + i
279: + ").value");
280: logger.info("Credential : " + name + "=*");
281:
282: if (getAuthenticationScheme() == null) {
283: creds
284: .add(credentialProvider.newCredential(name,
285: value));
286: } else {
287: creds.add(getAuthenticationScheme().newCredential(name,
288: value));
289: }
290:
291: }
292: return (Credential[]) creds
293: .toArray(new Credential[creds.size()]);
294: }
295:
296: // ------------------------------------------------------------------------------
297: // IdentityStore
298: // ------------------------------------------------------------------------------
299:
300: // BaseUser related methods.
301:
302: public synchronized BaseUser loadUser(UserKey key)
303: throws NoSuchUserException, SSOIdentityException {
304: // TODO : This should be added to the store lifecycle
305: if (!_initialized)
306: initialize();
307:
308: BaseUser user = (BaseUser) _users.get(key);
309: if (user == null)
310: throw new NoSuchUserException(key);
311:
312: if (logger.isDebugEnabled())
313: logger.debug("[load(" + key + ")] : ok");
314:
315: return user;
316: }
317:
318: /**
319: * @param key
320: *
321: * @throws SSOIdentityException
322: */
323: public synchronized BaseRole[] findRolesByUserKey(UserKey key)
324: throws SSOIdentityException {
325:
326: // TODO : This should be added to the store lifecycle
327: if (!_initialized)
328: initialize();
329:
330: Set roles = new HashSet();
331: Set roleKeys = (Set) _userRoles.get(key);
332:
333: Iterator it = roleKeys.iterator();
334: while (it.hasNext()) {
335: RoleKey roleKey = (RoleKey) it.next();
336: roles.add(loadRole(roleKey));
337: }
338:
339: return (BaseRole[]) roles.toArray(new BaseRole[roles.size()]);
340: }
341:
342: // ------------------------------------------------------------------------------
343: // CredentialStore
344: // ------------------------------------------------------------------------------
345: /**
346: * Gets configured credentials for this principal.
347: *
348: * @param key used to retrieve this credentials.
349: * @throws SSOIdentityException
350: */
351: public Credential[] loadCredentials(CredentialKey key)
352: throws SSOIdentityException {
353:
354: // TODO : This should be added to the store lifecycle
355: if (!_initialized)
356: initialize();
357:
358: Set c = (Set) _principalCredentials.get(key);
359: if (c == null) {
360: logger.info("No credentials found for principal : " + key);
361: return new Credential[0];
362: }
363:
364: return (Credential[]) c.toArray(new Credential[c.size()]);
365: }
366:
367: // ------------------------------------------------------------------------------
368: // utils ....
369: // ------------------------------------------------------------------------------
370: protected void addCredentials(CredentialKey key, Credential[] c) {
371: for (int i = 0; i < c.length; i++) {
372: Credential credential = c[i];
373: addCredential(key, credential);
374: }
375: }
376:
377: protected void addCredential(CredentialKey key, Credential c) {
378: Set credentials = (Set) _principalCredentials.get(key);
379: if (credentials == null) {
380: credentials = new HashSet();
381: _principalCredentials.put(key, credentials);
382: }
383:
384: credentials.add(c);
385:
386: }
387:
388: protected CredentialKey createCredentialKey(String name) {
389: // TODO : Use propper key adapter.
390: return new SimpleUserKey(name);
391: }
392:
393: public synchronized Set getRoleKeys() throws SSOIdentityException {
394: return _roles.keySet();
395: }
396:
397: public synchronized BaseRole loadRole(RoleKey roleKey)
398: throws NoSuchRoleException, SSOIdentityException {
399: BaseRole role = (BaseRole) _roles.get(roleKey);
400: if (role == null)
401: throw new NoSuchRoleException(roleKey);
402:
403: return role;
404: }
405:
406: public synchronized void saveUser(BaseUser user)
407: throws SSOIdentityException {
408: BaseUser old = (BaseUser) _users.put(new SimpleUserKey(user
409: .getName()), user);
410:
411: if (logger.isDebugEnabled())
412: logger.debug("[save(" + user + ")] : ok");
413:
414: if (logger.isDebugEnabled())
415: logger.debug("[save(" + user + ")] : User "
416: + (old != null ? "" : " not") + " replaced");
417: }
418:
419: public synchronized void removeUser(UserKey key)
420: throws NoSuchUserException, SSOIdentityException {
421: BaseUser old = (BaseUser) _users.remove(key);
422: if (old == null)
423: throw new NoSuchUserException(key);
424:
425: // Reomve roles
426: _userRoles.remove(key);
427:
428: if (logger.isDebugEnabled())
429: logger.debug("[remove(" + key + ")] : ok");
430: }
431:
432: public synchronized BaseRole findRoleByName(String name)
433: throws SSOIdentityException {
434: for (Iterator it = _roles.values().iterator(); it.hasNext();) {
435: BaseRole role = (BaseRole) it.next();
436: if (role.getName().equals(name))
437: return role;
438: }
439: throw new SSOIdentityException("No such role : " + name);
440: }
441:
442: public synchronized void removeRole(RoleKey key)
443: throws NoSuchRoleException, SSOIdentityException {
444: BaseRole role = (BaseRole) _roles.remove(key);
445: if (role == null)
446: throw new NoSuchRoleException(key);
447:
448: // Check all userroles ...
449: Iterator it = _userRoles.values().iterator();
450: while (it.hasNext()) {
451: Set roleKeys = (Set) it.next();
452: roleKeys.remove(key);
453: }
454:
455: }
456:
457: public synchronized void saveRole(BaseRole role)
458: throws SSOIdentityException {
459: _roles.put(new SimpleRoleKey(role.getName()), role);
460: }
461:
462: public synchronized void assignRole(UserKey userKey, RoleKey roleKey)
463: throws SSOIdentityException {
464:
465: Set roles = (Set) _userRoles.get(userKey);
466: if (roles == null) {
467: roles = new HashSet();
468: _userRoles.put(userKey, roles);
469: }
470: roles.add(roleKey);
471: }
472:
473: public synchronized void deasignRole(UserKey userKey,
474: RoleKey roleKey) throws SSOIdentityException {
475:
476: Set roles = (Set) _userRoles.get(userKey);
477: if (roles == null)
478: return;
479:
480: roles.remove(roleKey);
481: }
482:
483: // -----------------------------------------------------------------------------------------
484: // Private Utils.
485: // -----------------------------------------------------------------------------------------
486:
487: protected BaseUser createUser(String username) {
488:
489: BaseUser user = new BaseUserImpl();
490: UserKey key = new SimpleUserKey(username);
491: user.setName(username);
492:
493: _users.put(key, user);
494: return user;
495:
496: }
497:
498: protected UserKey createUserKey(BaseUser user) {
499: // TODO : Use propper key adapter ...
500: return new SimpleUserKey(user.getName());
501: }
502:
503: protected BaseRole createRole(String name) {
504: BaseRole role = new BaseRoleImpl();
505: role.setName(name);
506: return role;
507: }
508:
509: protected RoleKey createRoleKey(BaseRole role) {
510: // TODO : Use propper key adapter ...
511: return new SimpleRoleKey(role.getName());
512: }
513:
514: /**
515: * Creates a credential for the specific value.
516: *
517: * @param name the credential name (i.e. username, password, challenge, etc.)
518: * @param value
519: *
520: */
521: protected Credential doMakeCredential(String name, Object value)
522: throws SSOIdentityException {
523:
524: return getAuthenticationScheme().newCredential(name, value);
525: }
526:
527: // ---------------------------------------------------------------------
528: // Configuration properties
529: // ---------------------------------------------------------------------
530:
531: public void setCredentialsFileName(String credentialsFileName) {
532: logger.debug("Setting crednetials file name to : "
533: + credentialsFileName);
534: _credentialsFileName = credentialsFileName;
535: }
536:
537: public String getCredentialsFileName() {
538: return _credentialsFileName;
539: }
540:
541: public void setUsersFileName(String usersFileName) {
542: logger.debug("Setting users file name to : " + usersFileName);
543: _usersFileName = usersFileName;
544: }
545:
546: public CredentialProvider getCredentialProvider() {
547: return credentialProvider;
548: }
549:
550: public void setCredentialProvider(
551: CredentialProvider credentialProvider) {
552: this.credentialProvider = credentialProvider;
553: }
554: }
|