View Javadoc

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