1 /************************************************************************
2 * Copyright (c) 2000-2006 The Apache Software Foundation. *
3 * All rights reserved. *
4 * ------------------------------------------------------------------- *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you *
6 * may not use this file except in compliance with the License. You *
7 * may obtain a copy of the License at: *
8 * *
9 * http://www.apache.org/licenses/LICENSE-2.0 *
10 * *
11 * Unless required by applicable law or agreed to in writing, software *
12 * distributed under the License is distributed on an "AS IS" BASIS, *
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
14 * implied. See the License for the specific language governing *
15 * permissions and limitations under the License. *
16 ***********************************************************************/
17
18 package org.apache.james.userrepository;
19
20 import org.apache.avalon.framework.component.Component;
21 import org.apache.avalon.framework.logger.AbstractLogEnabled;
22 import org.apache.james.services.User;
23 import org.apache.james.services.UsersRepository;
24
25 import java.util.Iterator;
26 import java.util.LinkedList;
27 import java.util.List;
28
29 /***
30 * A partial implementation of a Repository to store users.
31 * <p>This implements common functionality found in different UsersRespository
32 * implementations, and makes it easier to create new User repositories.</p>
33 *
34 */
35 public abstract class AbstractUsersRepository
36 extends AbstractLogEnabled
37 implements UsersRepository, Component {
38
39
40
41
42
43 /***
44 * Returns a list populated with all of the Users in the repository.
45 * @return an <code>Iterator</code> of <code>User</code>s.
46 */
47 protected abstract Iterator listAllUsers();
48
49 /***
50 * Adds a user to the underlying Repository.
51 * The user name must not clash with an existing user.
52 */
53 protected abstract void doAddUser(User user);
54
55 /***
56 * Removes a user from the underlying repository.
57 * If the user doesn't exist, returns ok.
58 */
59 protected abstract void doRemoveUser(User user);
60
61 /***
62 * Updates a user record to match the supplied User.
63 */
64 protected abstract void doUpdateUser(User user);
65
66
67
68
69
70
71 /***
72 * Produces the complete list of User names, with correct case.
73 * @return a <code>List</code> of <code>String</code>s representing
74 * user names.
75 */
76 protected List listUserNames() {
77 Iterator users = listAllUsers();
78 List userNames = new LinkedList();
79 while ( users.hasNext() ) {
80 User user = (User)users.next();
81 userNames.add(user.getUserName());
82 }
83
84 return userNames;
85 }
86
87 /***
88 * Gets a user by name, ignoring case if specified.
89 * This implementation gets the entire set of users,
90 * and scrolls through searching for one matching <code>name</code>.
91 *
92 * @param name the name of the user being retrieved
93 * @param ignoreCase whether the name is regarded as case-insensitive
94 *
95 * @return the user being retrieved, null if the user doesn't exist
96 */
97 protected User getUserByName(String name, boolean ignoreCase) {
98
99 Iterator users = listAllUsers();
100 while ( users.hasNext() ) {
101 User user = (User)users.next();
102 String username = user.getUserName();
103 if (( !ignoreCase && username.equals(name) ) ||
104 ( ignoreCase && username.equalsIgnoreCase(name) )) {
105 return user;
106 }
107 }
108
109 return null;
110 }
111
112
113
114
115 /***
116 * Adds a user to the repository with the specified User object.
117 * Users names must be unique-case-insensitive in the repository.
118 *
119 * @param user the user to be added
120 *
121 * @return true if succesful, false otherwise
122 * @since James 1.2.2
123 */
124 public boolean addUser(User user) {
125 String username = user.getUserName();
126
127 if ( containsCaseInsensitive(username) ) {
128 return false;
129 }
130
131 doAddUser(user);
132 return true;
133 }
134
135 /***
136 * Adds a user to the repository with the specified attributes. In current
137 * implementations, the Object attributes is generally a String password.
138 *
139 * @param name the name of the user to be added
140 * @param attributes the password value as a String
141 */
142 public void addUser(String name, Object attributes) {
143 if (attributes instanceof String) {
144 User newbie = new DefaultUser(name, "SHA");
145 newbie.setPassword( (String) attributes );
146 addUser(newbie);
147 } else {
148 throw new RuntimeException("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
172 if ( ! contains(user.getUserName()) ) {
173 return false;
174 }
175 else {
176 doUpdateUser(user);
177 return true;
178 }
179 }
180
181 /***
182 * Removes a user from the repository
183 *
184 * @param user the user to be removed
185 */
186 public void removeUser(String name) {
187 User user = getUserByName(name);
188 if ( user != null ) {
189 doRemoveUser(user);
190 }
191 }
192
193 /***
194 * Get the user object with the specified user name. Return null if no
195 * such user.
196 *
197 * @param name the name of the user to retrieve
198 *
199 * @return the user if found, null otherwise
200 *
201 * @since James 1.2.2
202 */
203 public User getUserByName(String name) {
204 return getUserByName(name, false);
205 }
206
207 /***
208 * Get the user object with the specified user name. Match user naems on
209 * a case insensitive basis. Return null if no such user.
210 *
211 * @param name the name of the user to retrieve
212 *
213 * @return the user if found, null otherwise
214 *
215 * @since James 1.2.2
216 */
217 public User getUserByNameCaseInsensitive(String name) {
218 return getUserByName(name, true);
219 }
220
221 /***
222 * Returns the user name of the user matching name on an equalsIgnoreCase
223 * basis. Returns null if no match.
224 *
225 * @param name the name of the user to retrieve
226 *
227 * @return the correct case sensitive name of the user
228 */
229 public String getRealName(String name) {
230
231 User user = getUserByName(name, true);
232 if ( user == null ) {
233 return null;
234 } else {
235 return user.getUserName();
236 }
237 }
238
239 /***
240 * Returns whether or not this user is in the repository
241 */
242 public boolean contains(String name) {
243 User user = getUserByName(name, false);
244 return ( user != null );
245 }
246
247 /***
248 * Returns whether or not this user is in the repository. Names are
249 * matched on a case insensitive basis.
250 */
251 public boolean containsCaseInsensitive(String name) {
252 User user = getUserByName( name, true );
253 return ( user != null );
254 }
255
256 /***
257 * Test if user with name 'name' has password 'password'.
258 *
259 * @param name the name of the user to be tested
260 * @param password the password to be tested
261 *
262 * @return true if the test is successful, false if the
263 * password is incorrect or the user doesn't
264 * exist
265 * @since James 1.2.2
266 */
267 public boolean test(String name, String password) {
268 User user = getUserByName(name, false);
269 if ( user == null ) {
270 return false;
271 } else {
272 return user.verifyPassword(password);
273 }
274 }
275
276 /***
277 * Returns a count of the users in the repository.
278 *
279 * @return the number of users in the repository
280 */
281 public int countUsers() {
282 List usernames = listUserNames();
283 return usernames.size();
284 }
285
286 /***
287 * List users in repository.
288 *
289 * @return Iterator over a collection of Strings, each being one user in the repository.
290 */
291 public Iterator list() {
292 return listUserNames().iterator();
293 }
294 }