1 package org.eclipse.jetty.security;
2
3 import java.io.File;
4 import java.io.FilenameFilter;
5 import java.io.IOException;
6 import java.security.Principal;
7 import java.util.ArrayList;
8 import java.util.HashMap;
9 import java.util.HashSet;
10 import java.util.Iterator;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.Properties;
14 import java.util.Set;
15
16 import javax.security.auth.Subject;
17
18 import org.eclipse.jetty.http.security.Credential;
19 import org.eclipse.jetty.security.MappedLoginService.KnownUser;
20 import org.eclipse.jetty.security.MappedLoginService.RolePrincipal;
21 import org.eclipse.jetty.server.UserIdentity;
22 import org.eclipse.jetty.util.Scanner;
23 import org.eclipse.jetty.util.Scanner.BulkListener;
24 import org.eclipse.jetty.util.component.AbstractLifeCycle;
25 import org.eclipse.jetty.util.log.Log;
26 import org.eclipse.jetty.util.log.Logger;
27 import org.eclipse.jetty.util.resource.Resource;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 public class PropertyUserStore extends AbstractLifeCycle
44 {
45 private static final Logger LOG = Log.getLogger(PropertyUserStore.class);
46
47 private String _config;
48 private Resource _configResource;
49 private Scanner _scanner;
50 private int _refreshInterval = 0;
51
52 private IdentityService _identityService = new DefaultIdentityService();
53 private boolean _firstLoad = true;
54 private final List<String> _knownUsers = new ArrayList<String>();
55 private final Map<String, UserIdentity> _knownUserIdentities = new HashMap<String, UserIdentity>();
56 private List<UserListener> _listeners;
57
58
59 public String getConfig()
60 {
61 return _config;
62 }
63
64
65 public void setConfig(String config)
66 {
67 _config = config;
68 }
69
70
71 public UserIdentity getUserIdentity(String userName)
72 {
73 return _knownUserIdentities.get(userName);
74 }
75
76
77
78
79
80 public Resource getConfigResource() throws IOException
81 {
82 if (_configResource == null)
83 {
84 _configResource = Resource.newResource(_config);
85 }
86
87 return _configResource;
88 }
89
90
91
92
93
94 public void setRefreshInterval(int msec)
95 {
96 _refreshInterval = msec;
97 }
98
99
100
101
102
103 public int getRefreshInterval()
104 {
105 return _refreshInterval;
106 }
107
108
109 private void loadUsers() throws IOException
110 {
111 if (_config == null)
112 return;
113
114 if (LOG.isDebugEnabled())
115 LOG.debug("Load " + this + " from " + _config);
116 Properties properties = new Properties();
117 if (getConfigResource().exists())
118 properties.load(getConfigResource().getInputStream());
119 Set<String> known = new HashSet<String>();
120
121 for (Map.Entry<Object, Object> entry : properties.entrySet())
122 {
123 String username = ((String)entry.getKey()).trim();
124 String credentials = ((String)entry.getValue()).trim();
125 String roles = null;
126 int c = credentials.indexOf(',');
127 if (c > 0)
128 {
129 roles = credentials.substring(c + 1).trim();
130 credentials = credentials.substring(0,c).trim();
131 }
132
133 if (username != null && username.length() > 0 && credentials != null && credentials.length() > 0)
134 {
135 String[] roleArray = IdentityService.NO_ROLES;
136 if (roles != null && roles.length() > 0)
137 {
138 roleArray = roles.split(",");
139 }
140 known.add(username);
141 Credential credential = Credential.getCredential(credentials);
142
143 Principal userPrincipal = new KnownUser(username,credential);
144 Subject subject = new Subject();
145 subject.getPrincipals().add(userPrincipal);
146 subject.getPrivateCredentials().add(credential);
147
148 if (roles != null)
149 {
150 for (String role : roleArray)
151 {
152 subject.getPrincipals().add(new RolePrincipal(role));
153 }
154 }
155
156 subject.setReadOnly();
157
158 _knownUserIdentities.put(username,_identityService.newUserIdentity(subject,userPrincipal,roleArray));
159 notifyUpdate(username,credential,roleArray);
160 }
161 }
162
163 synchronized (_knownUsers)
164 {
165
166
167
168 if (!_firstLoad)
169 {
170 Iterator<String> users = _knownUsers.iterator();
171 while (users.hasNext())
172 {
173 String user = users.next();
174 if (!known.contains(user))
175 {
176 _knownUserIdentities.remove(user);
177 notifyRemove(user);
178 }
179 }
180 }
181
182
183
184
185
186 _knownUsers.clear();
187 _knownUsers.addAll(known);
188
189 }
190
191
192
193
194 _firstLoad = false;
195 }
196
197
198
199
200
201
202
203
204
205 protected void doStart() throws Exception
206 {
207 super.doStart();
208
209 if (getRefreshInterval() > 0)
210 {
211 _scanner = new Scanner();
212 _scanner.setScanInterval(getRefreshInterval());
213 List<File> dirList = new ArrayList<File>(1);
214 dirList.add(getConfigResource().getFile().getParentFile());
215 _scanner.setScanDirs(dirList);
216 _scanner.setFilenameFilter(new FilenameFilter()
217 {
218 public boolean accept(File dir, String name)
219 {
220 File f = new File(dir,name);
221 try
222 {
223 if (f.compareTo(getConfigResource().getFile()) == 0)
224 {
225 return true;
226 }
227 }
228 catch (IOException e)
229 {
230 return false;
231 }
232
233 return false;
234 }
235
236 });
237
238 _scanner.addListener(new BulkListener()
239 {
240 public void filesChanged(List<String> filenames) throws Exception
241 {
242 if (filenames == null)
243 return;
244 if (filenames.isEmpty())
245 return;
246 if (filenames.size() == 1)
247 {
248 Resource r = Resource.newResource(filenames.get(0));
249 if (r.getFile().equals(_configResource.getFile()))
250 loadUsers();
251 }
252 }
253
254 public String toString()
255 {
256 return "PropertyUserStore$Scanner";
257 }
258
259 });
260
261 _scanner.setReportExistingFilesOnStartup(true);
262 _scanner.setRecursive(false);
263 _scanner.start();
264 }
265 else
266 {
267 loadUsers();
268 }
269 }
270
271
272
273
274
275 protected void doStop() throws Exception
276 {
277 super.doStop();
278 if (_scanner != null)
279 _scanner.stop();
280 _scanner = null;
281 }
282
283
284
285
286
287
288
289
290 private void notifyUpdate(String username, Credential credential, String[] roleArray)
291 {
292 if (_listeners != null)
293 {
294 for (Iterator<UserListener> i = _listeners.iterator(); i.hasNext();)
295 {
296 i.next().update(username,credential,roleArray);
297 }
298 }
299 }
300
301
302
303
304
305
306 private void notifyRemove(String username)
307 {
308 if (_listeners != null)
309 {
310 for (Iterator<UserListener> i = _listeners.iterator(); i.hasNext();)
311 {
312 i.next().remove(username);
313 }
314 }
315 }
316
317
318
319
320 public void registerUserListener(UserListener listener)
321 {
322 if (_listeners == null)
323 {
324 _listeners = new ArrayList<UserListener>();
325 }
326 _listeners.add(listener);
327 }
328
329
330
331
332 public interface UserListener
333 {
334 public void update(String username, Credential credential, String[] roleArray);
335
336 public void remove(String username);
337 }
338 }