View Javadoc

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      // Core Abstract methods - override these for a functional UserRepository.
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      // Extended protected methods.
68      // These provide very basic default implementations, which will work,
69      // but may need to be overridden by subclasses for performance reasons.
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          // Just iterate through all of the users until we find one matching.
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         // Not found - return null
109         return null;
110     }
111 
112     //
113     // UsersRepository interface implementation.
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         // Return false if it's not found.
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         // Get the user by name, ignoring case, and return the correct name.
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 }