001: /****************************************************************
002: * Licensed to the Apache Software Foundation (ASF) under one *
003: * or more contributor license agreements. See the NOTICE file *
004: * distributed with this work for additional information *
005: * regarding copyright ownership. The ASF licenses this file *
006: * to you under the Apache License, Version 2.0 (the *
007: * "License"); you may not use this file except in compliance *
008: * with the License. You may obtain a copy of the License at *
009: * *
010: * http://www.apache.org/licenses/LICENSE-2.0 *
011: * *
012: * Unless required by applicable law or agreed to in writing, *
013: * software distributed under the License is distributed on an *
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015: * KIND, either express or implied. See the License for the *
016: * specific language governing permissions and limitations *
017: * under the License. *
018: ****************************************************************/package org.apache.james.userrepository;
019:
020: import org.apache.avalon.framework.component.Component;
021: import org.apache.avalon.framework.logger.AbstractLogEnabled;
022: import org.apache.james.services.User;
023: import org.apache.james.services.UsersRepository;
024:
025: import java.util.Iterator;
026: import java.util.LinkedList;
027: import java.util.List;
028:
029: /**
030: * A partial implementation of a Repository to store users.
031: * <p>This implements common functionality found in different UsersRespository
032: * implementations, and makes it easier to create new User repositories.</p>
033: *
034: */
035: public abstract class AbstractUsersRepository extends
036: AbstractLogEnabled implements UsersRepository, Component {
037:
038: //
039: // Core Abstract methods - override these for a functional UserRepository.
040: //
041:
042: /**
043: * Returns a list populated with all of the Users in the repository.
044: * @return an <code>Iterator</code> of <code>User</code>s.
045: */
046: protected abstract Iterator listAllUsers();
047:
048: /**
049: * Adds a user to the underlying Repository.
050: * The user name must not clash with an existing user.
051: */
052: protected abstract void doAddUser(User user);
053:
054: /**
055: * Removes a user from the underlying repository.
056: * If the user doesn't exist, returns ok.
057: */
058: protected abstract void doRemoveUser(User user);
059:
060: /**
061: * Updates a user record to match the supplied User.
062: */
063: protected abstract void doUpdateUser(User user);
064:
065: //
066: // Extended protected methods.
067: // These provide very basic default implementations, which will work,
068: // but may need to be overridden by subclasses for performance reasons.
069: //
070: /**
071: * Produces the complete list of User names, with correct case.
072: * @return a <code>List</code> of <code>String</code>s representing
073: * user names.
074: */
075: protected List listUserNames() {
076: Iterator users = listAllUsers();
077: List userNames = new LinkedList();
078: while (users.hasNext()) {
079: User user = (User) users.next();
080: userNames.add(user.getUserName());
081: }
082:
083: return userNames;
084: }
085:
086: /**
087: * Gets a user by name, ignoring case if specified.
088: * This implementation gets the entire set of users,
089: * and scrolls through searching for one matching <code>name</code>.
090: *
091: * @param name the name of the user being retrieved
092: * @param ignoreCase whether the name is regarded as case-insensitive
093: *
094: * @return the user being retrieved, null if the user doesn't exist
095: */
096: protected User getUserByName(String name, boolean ignoreCase) {
097: // Just iterate through all of the users until we find one matching.
098: Iterator users = listAllUsers();
099: while (users.hasNext()) {
100: User user = (User) users.next();
101: String username = user.getUserName();
102: if ((!ignoreCase && username.equals(name))
103: || (ignoreCase && username.equalsIgnoreCase(name))) {
104: return user;
105: }
106: }
107: // Not found - return null
108: return null;
109: }
110:
111: //
112: // UsersRepository interface implementation.
113: //
114: /**
115: * Adds a user to the repository with the specified User object.
116: * Users names must be unique-case-insensitive in the repository.
117: *
118: * @param user the user to be added
119: *
120: * @return true if succesful, false otherwise
121: * @since James 1.2.2
122: */
123: public boolean addUser(User user) {
124: String username = user.getUserName();
125:
126: if (containsCaseInsensitive(username)) {
127: return false;
128: }
129:
130: doAddUser(user);
131: return true;
132: }
133:
134: /**
135: * Adds a user to the repository with the specified attributes. In current
136: * implementations, the Object attributes is generally a String password.
137: *
138: * @param name the name of the user to be added
139: * @param attributes the password value as a String
140: */
141: public void addUser(String name, Object attributes) {
142: if (attributes instanceof String) {
143: User newbie = new DefaultUser(name, "SHA");
144: newbie.setPassword((String) attributes);
145: addUser(newbie);
146: } else {
147: throw new RuntimeException(
148: "Improper use of deprecated method"
149: + " - use addUser(User user)");
150: }
151: }
152:
153: /**
154: * @see org.apache.james.services.UsersRepository#addUser(java.lang.String, java.lang.String)
155: */
156: public boolean addUser(String username, String password) {
157: User newbie = new DefaultJamesUser(username, "SHA");
158: newbie.setPassword(password);
159: return addUser(newbie);
160: }
161:
162: /**
163: * Update the repository with the specified user object. A user object
164: * with this username must already exist.
165: *
166: * @param user the user to be updated
167: *
168: * @return true if successful.
169: */
170: public boolean updateUser(User user) {
171: // Return false if it's not found.
172: if (!contains(user.getUserName())) {
173: return false;
174: } else {
175: doUpdateUser(user);
176: return true;
177: }
178: }
179:
180: /**
181: * Removes a user from the repository
182: *
183: * @param user the user to be removed
184: */
185: public void removeUser(String name) {
186: User user = getUserByName(name);
187: if (user != null) {
188: doRemoveUser(user);
189: }
190: }
191:
192: /**
193: * Get the user object with the specified user name. Return null if no
194: * such user.
195: *
196: * @param name the name of the user to retrieve
197: *
198: * @return the user if found, null otherwise
199: *
200: * @since James 1.2.2
201: */
202: public User getUserByName(String name) {
203: return getUserByName(name, false);
204: }
205:
206: /**
207: * Get the user object with the specified user name. Match user naems on
208: * a case insensitive basis. Return null if no such user.
209: *
210: * @param name the name of the user to retrieve
211: *
212: * @return the user if found, null otherwise
213: *
214: * @since James 1.2.2
215: */
216: public User getUserByNameCaseInsensitive(String name) {
217: return getUserByName(name, true);
218: }
219:
220: /**
221: * Returns the user name of the user matching name on an equalsIgnoreCase
222: * basis. Returns null if no match.
223: *
224: * @param name the name of the user to retrieve
225: *
226: * @return the correct case sensitive name of the user
227: */
228: public String getRealName(String name) {
229: // Get the user by name, ignoring case, and return the correct name.
230: User user = getUserByName(name, true);
231: if (user == null) {
232: return null;
233: } else {
234: return user.getUserName();
235: }
236: }
237:
238: /**
239: * Returns whether or not this user is in the repository
240: */
241: public boolean contains(String name) {
242: User user = getUserByName(name, false);
243: return (user != null);
244: }
245:
246: /**
247: * Returns whether or not this user is in the repository. Names are
248: * matched on a case insensitive basis.
249: */
250: public boolean containsCaseInsensitive(String name) {
251: User user = getUserByName(name, true);
252: return (user != null);
253: }
254:
255: /**
256: * Test if user with name 'name' has password 'password'.
257: *
258: * @param name the name of the user to be tested
259: * @param password the password to be tested
260: *
261: * @return true if the test is successful, false if the
262: * password is incorrect or the user doesn't
263: * exist
264: * @since James 1.2.2
265: */
266: public boolean test(String name, String password) {
267: User user = getUserByName(name, false);
268: if (user == null) {
269: return false;
270: } else {
271: return user.verifyPassword(password);
272: }
273: }
274:
275: /**
276: * Returns a count of the users in the repository.
277: *
278: * @return the number of users in the repository
279: */
280: public int countUsers() {
281: List usernames = listUserNames();
282: return usernames.size();
283: }
284:
285: /**
286: * List users in repository.
287: *
288: * @return Iterator over a collection of Strings, each being one user in the repository.
289: */
290: public Iterator list() {
291: return listUserNames().iterator();
292: }
293: }
|