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