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.cornerstone.services.store.ObjectRepository;
21 import org.apache.avalon.cornerstone.services.store.Store;
22 import org.apache.avalon.framework.activity.Initializable;
23 import org.apache.avalon.framework.configuration.Configurable;
24 import org.apache.avalon.framework.configuration.Configuration;
25 import org.apache.avalon.framework.configuration.ConfigurationException;
26 import org.apache.avalon.framework.configuration.DefaultConfiguration;
27 import org.apache.avalon.framework.logger.AbstractLogEnabled;
28 import org.apache.avalon.framework.service.ServiceException;
29 import org.apache.avalon.framework.service.ServiceManager;
30 import org.apache.avalon.framework.service.Serviceable;
31 import org.apache.james.services.User;
32 import org.apache.james.services.UsersRepository;
33
34 import java.io.File;
35 import java.util.Iterator;
36
37 /***
38 * Implementation of a Repository to store users on the File System.
39 *
40 * Requires a configuration element in the .conf.xml file of the form:
41 * <repository destinationURL="file://path-to-root-dir-for-repository"
42 * type="USERS"
43 * model="SYNCHRONOUS"/>
44 * Requires a logger called UsersRepository.
45 *
46 *
47 * @version CVS $Revision: 407988 $
48 *
49 */
50 public class UsersFileRepository
51 extends AbstractLogEnabled
52 implements UsersRepository, Configurable, Serviceable, Initializable {
53
54 /***
55 * Whether 'deep debugging' is turned on.
56 */
57 protected static boolean DEEP_DEBUG = false;
58
59 private Store store;
60 private ObjectRepository or;
61
62 /***
63 * The destination URL used to define the repository.
64 */
65 private String destination;
66
67 /***
68 * @see org.apache.avalon.framework.service.Serviceable#service(ServiceManager)
69 */
70 public void service( final ServiceManager componentManager )
71 throws ServiceException {
72
73 try {
74 store = (Store)componentManager.lookup( Store.ROLE );
75 } catch (Exception e) {
76 final String message = "Failed to retrieve Store component:" + e.getMessage();
77 getLogger().error( message, e );
78 throw new ServiceException ("", message, e );
79 }
80 }
81
82 /***
83 * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
84 */
85 public void configure( final Configuration configuration )
86 throws ConfigurationException {
87
88 destination = configuration.getChild( "destination" ).getAttribute( "URL" );
89
90 if (!destination.endsWith(File.separator)) {
91 destination += File.separator;
92 }
93 }
94
95 /***
96 * @see org.apache.avalon.framework.activity.Initializable#initialize()
97 */
98 public void initialize()
99 throws Exception {
100
101 try {
102
103 final DefaultConfiguration objectConfiguration
104 = new DefaultConfiguration( "repository",
105 "generated:UsersFileRepository.compose()" );
106
107 objectConfiguration.setAttribute( "destinationURL", destination );
108 objectConfiguration.setAttribute( "type", "OBJECT" );
109 objectConfiguration.setAttribute( "model", "SYNCHRONOUS" );
110
111 or = (ObjectRepository)store.select( objectConfiguration );
112 if (getLogger().isDebugEnabled()) {
113 StringBuffer logBuffer =
114 new StringBuffer(192)
115 .append(this.getClass().getName())
116 .append(" created in ")
117 .append(destination);
118 getLogger().debug(logBuffer.toString());
119 }
120 } catch (Exception e) {
121 if (getLogger().isErrorEnabled()) {
122 getLogger().error("Failed to initialize repository:" + e.getMessage(), e );
123 }
124 throw e;
125 }
126 }
127
128 /***
129 * List users in repository.
130 *
131 * @return Iterator over a collection of Strings, each being one user in the repository.
132 */
133 public Iterator list() {
134 return or.list();
135 }
136
137 /***
138 * Update the repository with the specified user object. A user object
139 * with this username must already exist.
140 *
141 * @param user the user to be added.
142 *
143 * @return true if successful.
144 */
145 public synchronized boolean addUser(User user) {
146 String username = user.getUserName();
147 if (contains(username)) {
148 return false;
149 }
150 try {
151 or.put(username, user);
152 } catch (Exception e) {
153 throw new RuntimeException("Exception caught while storing user: " + e );
154 }
155 return true;
156 }
157
158 public void addUser(String name, Object attributes) {
159 if (attributes instanceof String) {
160 User newbie = new DefaultUser(name, "SHA");
161 newbie.setPassword( (String) attributes);
162 addUser(newbie);
163 }
164 else {
165 throw new RuntimeException("Improper use of deprecated method"
166 + " - use addUser(User user)");
167 }
168 }
169
170 public boolean addUser(String username, String password) {
171 User newbie = new DefaultJamesUser(username, "SHA");
172 newbie.setPassword(password);
173 return addUser(newbie);
174 }
175
176 public synchronized User getUserByName(String name) {
177 if (contains(name)) {
178 try {
179 return (User)or.get(name);
180 } catch (Exception e) {
181 throw new RuntimeException("Exception while retrieving user: "
182 + e.getMessage());
183 }
184 } else {
185 return null;
186 }
187 }
188
189 public User getUserByNameCaseInsensitive(String name) {
190 String realName = getRealName(name);
191 if (realName == null ) {
192 return null;
193 }
194 return getUserByName(realName);
195 }
196
197 public String getRealName(String name) {
198 Iterator it = list();
199 while (it.hasNext()) {
200 String temp = (String) it.next();
201 if (name.equalsIgnoreCase(temp)) {
202 return temp;
203 }
204 }
205 return null;
206 }
207
208 public boolean updateUser(User user) {
209 String username = user.getUserName();
210 if (!contains(username)) {
211 return false;
212 }
213 try {
214 or.put(username, user);
215 } catch (Exception e) {
216 throw new RuntimeException("Exception caught while storing user: " + e );
217 }
218 return true;
219 }
220
221 public synchronized void removeUser(String name) {
222 or.remove(name);
223 }
224
225 public boolean contains(String name) {
226 return or.containsKey(name);
227 }
228
229 public boolean containsCaseInsensitive(String name) {
230 Iterator it = list();
231 while (it.hasNext()) {
232 if (name.equalsIgnoreCase((String)it.next())) {
233 return true;
234 }
235 }
236 return false;
237 }
238
239 public boolean test(String name, String password) {
240 User user;
241 try {
242 if (contains(name)) {
243 user = (User) or.get(name);
244 } else {
245 return false;
246 }
247 } catch (Exception e) {
248 throw new RuntimeException("Exception retrieving User" + e);
249 }
250 return user.verifyPassword(password);
251 }
252
253 public int countUsers() {
254 int count = 0;
255 for (Iterator it = list(); it.hasNext(); it.next()) {
256 count++;
257 }
258 return count;
259 }
260
261 }