103928aee4356845252ac6b662d5c72c29903813eJake Slack// 203928aee4356845252ac6b662d5c72c29903813eJake Slack// ======================================================================== 303928aee4356845252ac6b662d5c72c29903813eJake Slack// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. 403928aee4356845252ac6b662d5c72c29903813eJake Slack// ------------------------------------------------------------------------ 503928aee4356845252ac6b662d5c72c29903813eJake Slack// All rights reserved. This program and the accompanying materials 603928aee4356845252ac6b662d5c72c29903813eJake Slack// are made available under the terms of the Eclipse Public License v1.0 703928aee4356845252ac6b662d5c72c29903813eJake Slack// and Apache License v2.0 which accompanies this distribution. 803928aee4356845252ac6b662d5c72c29903813eJake Slack// 903928aee4356845252ac6b662d5c72c29903813eJake Slack// The Eclipse Public License is available at 1003928aee4356845252ac6b662d5c72c29903813eJake Slack// http://www.eclipse.org/legal/epl-v10.html 1103928aee4356845252ac6b662d5c72c29903813eJake Slack// 1203928aee4356845252ac6b662d5c72c29903813eJake Slack// The Apache License v2.0 is available at 1303928aee4356845252ac6b662d5c72c29903813eJake Slack// http://www.opensource.org/licenses/apache2.0.php 1403928aee4356845252ac6b662d5c72c29903813eJake Slack// 1503928aee4356845252ac6b662d5c72c29903813eJake Slack// You may elect to redistribute this code under either of these licenses. 1603928aee4356845252ac6b662d5c72c29903813eJake Slack// ======================================================================== 1703928aee4356845252ac6b662d5c72c29903813eJake Slack// 1803928aee4356845252ac6b662d5c72c29903813eJake Slack 1903928aee4356845252ac6b662d5c72c29903813eJake Slackpackage org.eclipse.jetty.security; 2003928aee4356845252ac6b662d5c72c29903813eJake Slack 2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.File; 2203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.FilenameFilter; 2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.IOException; 2403928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.security.Principal; 2503928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.ArrayList; 2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.HashMap; 2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.HashSet; 2803928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Iterator; 2903928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.List; 3003928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Map; 3103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Properties; 3203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Set; 3303928aee4356845252ac6b662d5c72c29903813eJake Slack 3403928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.security.auth.Subject; 3503928aee4356845252ac6b662d5c72c29903813eJake Slack 3603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.security.MappedLoginService.KnownUser; 3703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.security.MappedLoginService.RolePrincipal; 3803928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.UserIdentity; 3903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.Scanner; 4003928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.Scanner.BulkListener; 4103928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.component.AbstractLifeCycle; 4203928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Log; 4303928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Logger; 4403928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.resource.Resource; 4503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.security.Credential; 4603928aee4356845252ac6b662d5c72c29903813eJake Slack 4703928aee4356845252ac6b662d5c72c29903813eJake Slack/** 4803928aee4356845252ac6b662d5c72c29903813eJake Slack * PropertyUserStore 4903928aee4356845252ac6b662d5c72c29903813eJake Slack * 5003928aee4356845252ac6b662d5c72c29903813eJake Slack * This class monitors a property file of the format mentioned below and notifies registered listeners of the changes to the the given file. 5103928aee4356845252ac6b662d5c72c29903813eJake Slack * 5203928aee4356845252ac6b662d5c72c29903813eJake Slack * <PRE> 5303928aee4356845252ac6b662d5c72c29903813eJake Slack * username: password [,rolename ...] 5403928aee4356845252ac6b662d5c72c29903813eJake Slack * </PRE> 5503928aee4356845252ac6b662d5c72c29903813eJake Slack * 5603928aee4356845252ac6b662d5c72c29903813eJake Slack * Passwords may be clear text, obfuscated or checksummed. The class com.eclipse.Util.Password should be used to generate obfuscated passwords or password 5703928aee4356845252ac6b662d5c72c29903813eJake Slack * checksums. 5803928aee4356845252ac6b662d5c72c29903813eJake Slack * 5903928aee4356845252ac6b662d5c72c29903813eJake Slack * If DIGEST Authentication is used, the password must be in a recoverable format, either plain text or OBF:. 6003928aee4356845252ac6b662d5c72c29903813eJake Slack */ 6103928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class PropertyUserStore extends AbstractLifeCycle 6203928aee4356845252ac6b662d5c72c29903813eJake Slack{ 6303928aee4356845252ac6b662d5c72c29903813eJake Slack private static final Logger LOG = Log.getLogger(PropertyUserStore.class); 6403928aee4356845252ac6b662d5c72c29903813eJake Slack 6503928aee4356845252ac6b662d5c72c29903813eJake Slack private String _config; 6603928aee4356845252ac6b662d5c72c29903813eJake Slack private Resource _configResource; 6703928aee4356845252ac6b662d5c72c29903813eJake Slack private Scanner _scanner; 6803928aee4356845252ac6b662d5c72c29903813eJake Slack private int _refreshInterval = 0;// default is not to reload 6903928aee4356845252ac6b662d5c72c29903813eJake Slack 7003928aee4356845252ac6b662d5c72c29903813eJake Slack private IdentityService _identityService = new DefaultIdentityService(); 7103928aee4356845252ac6b662d5c72c29903813eJake Slack private boolean _firstLoad = true; // true if first load, false from that point on 7203928aee4356845252ac6b662d5c72c29903813eJake Slack private final List<String> _knownUsers = new ArrayList<String>(); 7303928aee4356845252ac6b662d5c72c29903813eJake Slack private final Map<String, UserIdentity> _knownUserIdentities = new HashMap<String, UserIdentity>(); 7403928aee4356845252ac6b662d5c72c29903813eJake Slack private List<UserListener> _listeners; 7503928aee4356845252ac6b662d5c72c29903813eJake Slack 7603928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 7703928aee4356845252ac6b662d5c72c29903813eJake Slack public String getConfig() 7803928aee4356845252ac6b662d5c72c29903813eJake Slack { 7903928aee4356845252ac6b662d5c72c29903813eJake Slack return _config; 8003928aee4356845252ac6b662d5c72c29903813eJake Slack } 8103928aee4356845252ac6b662d5c72c29903813eJake Slack 8203928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 8303928aee4356845252ac6b662d5c72c29903813eJake Slack public void setConfig(String config) 8403928aee4356845252ac6b662d5c72c29903813eJake Slack { 8503928aee4356845252ac6b662d5c72c29903813eJake Slack _config = config; 8603928aee4356845252ac6b662d5c72c29903813eJake Slack } 8703928aee4356845252ac6b662d5c72c29903813eJake Slack 8803928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 8903928aee4356845252ac6b662d5c72c29903813eJake Slack public UserIdentity getUserIdentity(String userName) 9003928aee4356845252ac6b662d5c72c29903813eJake Slack { 9103928aee4356845252ac6b662d5c72c29903813eJake Slack return _knownUserIdentities.get(userName); 9203928aee4356845252ac6b662d5c72c29903813eJake Slack } 9303928aee4356845252ac6b662d5c72c29903813eJake Slack 9403928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 9503928aee4356845252ac6b662d5c72c29903813eJake Slack /** 9603928aee4356845252ac6b662d5c72c29903813eJake Slack * returns the resource associated with the configured properties file, creating it if necessary 9703928aee4356845252ac6b662d5c72c29903813eJake Slack */ 9803928aee4356845252ac6b662d5c72c29903813eJake Slack public Resource getConfigResource() throws IOException 9903928aee4356845252ac6b662d5c72c29903813eJake Slack { 10003928aee4356845252ac6b662d5c72c29903813eJake Slack if (_configResource == null) 10103928aee4356845252ac6b662d5c72c29903813eJake Slack { 10203928aee4356845252ac6b662d5c72c29903813eJake Slack _configResource = Resource.newResource(_config); 10303928aee4356845252ac6b662d5c72c29903813eJake Slack } 10403928aee4356845252ac6b662d5c72c29903813eJake Slack 10503928aee4356845252ac6b662d5c72c29903813eJake Slack return _configResource; 10603928aee4356845252ac6b662d5c72c29903813eJake Slack } 10703928aee4356845252ac6b662d5c72c29903813eJake Slack 10803928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 10903928aee4356845252ac6b662d5c72c29903813eJake Slack /** 11003928aee4356845252ac6b662d5c72c29903813eJake Slack * sets the refresh interval (in seconds) 11103928aee4356845252ac6b662d5c72c29903813eJake Slack */ 11203928aee4356845252ac6b662d5c72c29903813eJake Slack public void setRefreshInterval(int msec) 11303928aee4356845252ac6b662d5c72c29903813eJake Slack { 11403928aee4356845252ac6b662d5c72c29903813eJake Slack _refreshInterval = msec; 11503928aee4356845252ac6b662d5c72c29903813eJake Slack } 11603928aee4356845252ac6b662d5c72c29903813eJake Slack 11703928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 11803928aee4356845252ac6b662d5c72c29903813eJake Slack /** 11903928aee4356845252ac6b662d5c72c29903813eJake Slack * refresh interval in seconds for how often the properties file should be checked for changes 12003928aee4356845252ac6b662d5c72c29903813eJake Slack */ 12103928aee4356845252ac6b662d5c72c29903813eJake Slack public int getRefreshInterval() 12203928aee4356845252ac6b662d5c72c29903813eJake Slack { 12303928aee4356845252ac6b662d5c72c29903813eJake Slack return _refreshInterval; 12403928aee4356845252ac6b662d5c72c29903813eJake Slack } 12503928aee4356845252ac6b662d5c72c29903813eJake Slack 12603928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 12703928aee4356845252ac6b662d5c72c29903813eJake Slack private void loadUsers() throws IOException 12803928aee4356845252ac6b662d5c72c29903813eJake Slack { 12903928aee4356845252ac6b662d5c72c29903813eJake Slack if (_config == null) 13003928aee4356845252ac6b662d5c72c29903813eJake Slack return; 13103928aee4356845252ac6b662d5c72c29903813eJake Slack 13203928aee4356845252ac6b662d5c72c29903813eJake Slack if (LOG.isDebugEnabled()) 13303928aee4356845252ac6b662d5c72c29903813eJake Slack LOG.debug("Load " + this + " from " + _config); 13403928aee4356845252ac6b662d5c72c29903813eJake Slack Properties properties = new Properties(); 13503928aee4356845252ac6b662d5c72c29903813eJake Slack if (getConfigResource().exists()) 13603928aee4356845252ac6b662d5c72c29903813eJake Slack properties.load(getConfigResource().getInputStream()); 13703928aee4356845252ac6b662d5c72c29903813eJake Slack Set<String> known = new HashSet<String>(); 13803928aee4356845252ac6b662d5c72c29903813eJake Slack 13903928aee4356845252ac6b662d5c72c29903813eJake Slack for (Map.Entry<Object, Object> entry : properties.entrySet()) 14003928aee4356845252ac6b662d5c72c29903813eJake Slack { 14103928aee4356845252ac6b662d5c72c29903813eJake Slack String username = ((String)entry.getKey()).trim(); 14203928aee4356845252ac6b662d5c72c29903813eJake Slack String credentials = ((String)entry.getValue()).trim(); 14303928aee4356845252ac6b662d5c72c29903813eJake Slack String roles = null; 14403928aee4356845252ac6b662d5c72c29903813eJake Slack int c = credentials.indexOf(','); 14503928aee4356845252ac6b662d5c72c29903813eJake Slack if (c > 0) 14603928aee4356845252ac6b662d5c72c29903813eJake Slack { 14703928aee4356845252ac6b662d5c72c29903813eJake Slack roles = credentials.substring(c + 1).trim(); 14803928aee4356845252ac6b662d5c72c29903813eJake Slack credentials = credentials.substring(0,c).trim(); 14903928aee4356845252ac6b662d5c72c29903813eJake Slack } 15003928aee4356845252ac6b662d5c72c29903813eJake Slack 15103928aee4356845252ac6b662d5c72c29903813eJake Slack if (username != null && username.length() > 0 && credentials != null && credentials.length() > 0) 15203928aee4356845252ac6b662d5c72c29903813eJake Slack { 15303928aee4356845252ac6b662d5c72c29903813eJake Slack String[] roleArray = IdentityService.NO_ROLES; 15403928aee4356845252ac6b662d5c72c29903813eJake Slack if (roles != null && roles.length() > 0) 15503928aee4356845252ac6b662d5c72c29903813eJake Slack { 15603928aee4356845252ac6b662d5c72c29903813eJake Slack roleArray = roles.split(","); 15703928aee4356845252ac6b662d5c72c29903813eJake Slack } 15803928aee4356845252ac6b662d5c72c29903813eJake Slack known.add(username); 15903928aee4356845252ac6b662d5c72c29903813eJake Slack Credential credential = Credential.getCredential(credentials); 16003928aee4356845252ac6b662d5c72c29903813eJake Slack 16103928aee4356845252ac6b662d5c72c29903813eJake Slack Principal userPrincipal = new KnownUser(username,credential); 16203928aee4356845252ac6b662d5c72c29903813eJake Slack Subject subject = new Subject(); 16303928aee4356845252ac6b662d5c72c29903813eJake Slack subject.getPrincipals().add(userPrincipal); 16403928aee4356845252ac6b662d5c72c29903813eJake Slack subject.getPrivateCredentials().add(credential); 16503928aee4356845252ac6b662d5c72c29903813eJake Slack 16603928aee4356845252ac6b662d5c72c29903813eJake Slack if (roles != null) 16703928aee4356845252ac6b662d5c72c29903813eJake Slack { 16803928aee4356845252ac6b662d5c72c29903813eJake Slack for (String role : roleArray) 16903928aee4356845252ac6b662d5c72c29903813eJake Slack { 17003928aee4356845252ac6b662d5c72c29903813eJake Slack subject.getPrincipals().add(new RolePrincipal(role)); 17103928aee4356845252ac6b662d5c72c29903813eJake Slack } 17203928aee4356845252ac6b662d5c72c29903813eJake Slack } 17303928aee4356845252ac6b662d5c72c29903813eJake Slack 17403928aee4356845252ac6b662d5c72c29903813eJake Slack subject.setReadOnly(); 17503928aee4356845252ac6b662d5c72c29903813eJake Slack 17603928aee4356845252ac6b662d5c72c29903813eJake Slack _knownUserIdentities.put(username,_identityService.newUserIdentity(subject,userPrincipal,roleArray)); 17703928aee4356845252ac6b662d5c72c29903813eJake Slack notifyUpdate(username,credential,roleArray); 17803928aee4356845252ac6b662d5c72c29903813eJake Slack } 17903928aee4356845252ac6b662d5c72c29903813eJake Slack } 18003928aee4356845252ac6b662d5c72c29903813eJake Slack 18103928aee4356845252ac6b662d5c72c29903813eJake Slack synchronized (_knownUsers) 18203928aee4356845252ac6b662d5c72c29903813eJake Slack { 18303928aee4356845252ac6b662d5c72c29903813eJake Slack /* 18403928aee4356845252ac6b662d5c72c29903813eJake Slack * if its not the initial load then we want to process removed users 18503928aee4356845252ac6b662d5c72c29903813eJake Slack */ 18603928aee4356845252ac6b662d5c72c29903813eJake Slack if (!_firstLoad) 18703928aee4356845252ac6b662d5c72c29903813eJake Slack { 18803928aee4356845252ac6b662d5c72c29903813eJake Slack Iterator<String> users = _knownUsers.iterator(); 18903928aee4356845252ac6b662d5c72c29903813eJake Slack while (users.hasNext()) 19003928aee4356845252ac6b662d5c72c29903813eJake Slack { 19103928aee4356845252ac6b662d5c72c29903813eJake Slack String user = users.next(); 19203928aee4356845252ac6b662d5c72c29903813eJake Slack if (!known.contains(user)) 19303928aee4356845252ac6b662d5c72c29903813eJake Slack { 19403928aee4356845252ac6b662d5c72c29903813eJake Slack _knownUserIdentities.remove(user); 19503928aee4356845252ac6b662d5c72c29903813eJake Slack notifyRemove(user); 19603928aee4356845252ac6b662d5c72c29903813eJake Slack } 19703928aee4356845252ac6b662d5c72c29903813eJake Slack } 19803928aee4356845252ac6b662d5c72c29903813eJake Slack } 19903928aee4356845252ac6b662d5c72c29903813eJake Slack 20003928aee4356845252ac6b662d5c72c29903813eJake Slack /* 20103928aee4356845252ac6b662d5c72c29903813eJake Slack * reset the tracked _users list to the known users we just processed 20203928aee4356845252ac6b662d5c72c29903813eJake Slack */ 20303928aee4356845252ac6b662d5c72c29903813eJake Slack 20403928aee4356845252ac6b662d5c72c29903813eJake Slack _knownUsers.clear(); 20503928aee4356845252ac6b662d5c72c29903813eJake Slack _knownUsers.addAll(known); 20603928aee4356845252ac6b662d5c72c29903813eJake Slack 20703928aee4356845252ac6b662d5c72c29903813eJake Slack } 20803928aee4356845252ac6b662d5c72c29903813eJake Slack 20903928aee4356845252ac6b662d5c72c29903813eJake Slack /* 21003928aee4356845252ac6b662d5c72c29903813eJake Slack * set initial load to false as there should be no more initial loads 21103928aee4356845252ac6b662d5c72c29903813eJake Slack */ 21203928aee4356845252ac6b662d5c72c29903813eJake Slack _firstLoad = false; 21303928aee4356845252ac6b662d5c72c29903813eJake Slack } 21403928aee4356845252ac6b662d5c72c29903813eJake Slack 21503928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 21603928aee4356845252ac6b662d5c72c29903813eJake Slack /** 21703928aee4356845252ac6b662d5c72c29903813eJake Slack * Depending on the value of the refresh interval, this method will either start up a scanner thread that will monitor the properties file for changes after 21803928aee4356845252ac6b662d5c72c29903813eJake Slack * it has initially loaded it. Otherwise the users will be loaded and there will be no active monitoring thread so changes will not be detected. 21903928aee4356845252ac6b662d5c72c29903813eJake Slack * 22003928aee4356845252ac6b662d5c72c29903813eJake Slack * 22103928aee4356845252ac6b662d5c72c29903813eJake Slack * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart() 22203928aee4356845252ac6b662d5c72c29903813eJake Slack */ 22303928aee4356845252ac6b662d5c72c29903813eJake Slack protected void doStart() throws Exception 22403928aee4356845252ac6b662d5c72c29903813eJake Slack { 22503928aee4356845252ac6b662d5c72c29903813eJake Slack super.doStart(); 22603928aee4356845252ac6b662d5c72c29903813eJake Slack 22703928aee4356845252ac6b662d5c72c29903813eJake Slack if (getRefreshInterval() > 0) 22803928aee4356845252ac6b662d5c72c29903813eJake Slack { 22903928aee4356845252ac6b662d5c72c29903813eJake Slack _scanner = new Scanner(); 23003928aee4356845252ac6b662d5c72c29903813eJake Slack _scanner.setScanInterval(getRefreshInterval()); 23103928aee4356845252ac6b662d5c72c29903813eJake Slack List<File> dirList = new ArrayList<File>(1); 23203928aee4356845252ac6b662d5c72c29903813eJake Slack dirList.add(getConfigResource().getFile().getParentFile()); 23303928aee4356845252ac6b662d5c72c29903813eJake Slack _scanner.setScanDirs(dirList); 23403928aee4356845252ac6b662d5c72c29903813eJake Slack _scanner.setFilenameFilter(new FilenameFilter() 23503928aee4356845252ac6b662d5c72c29903813eJake Slack { 23603928aee4356845252ac6b662d5c72c29903813eJake Slack public boolean accept(File dir, String name) 23703928aee4356845252ac6b662d5c72c29903813eJake Slack { 23803928aee4356845252ac6b662d5c72c29903813eJake Slack File f = new File(dir,name); 23903928aee4356845252ac6b662d5c72c29903813eJake Slack try 24003928aee4356845252ac6b662d5c72c29903813eJake Slack { 24103928aee4356845252ac6b662d5c72c29903813eJake Slack if (f.compareTo(getConfigResource().getFile()) == 0) 24203928aee4356845252ac6b662d5c72c29903813eJake Slack { 24303928aee4356845252ac6b662d5c72c29903813eJake Slack return true; 24403928aee4356845252ac6b662d5c72c29903813eJake Slack } 24503928aee4356845252ac6b662d5c72c29903813eJake Slack } 24603928aee4356845252ac6b662d5c72c29903813eJake Slack catch (IOException e) 24703928aee4356845252ac6b662d5c72c29903813eJake Slack { 24803928aee4356845252ac6b662d5c72c29903813eJake Slack return false; 24903928aee4356845252ac6b662d5c72c29903813eJake Slack } 25003928aee4356845252ac6b662d5c72c29903813eJake Slack 25103928aee4356845252ac6b662d5c72c29903813eJake Slack return false; 25203928aee4356845252ac6b662d5c72c29903813eJake Slack } 25303928aee4356845252ac6b662d5c72c29903813eJake Slack 25403928aee4356845252ac6b662d5c72c29903813eJake Slack }); 25503928aee4356845252ac6b662d5c72c29903813eJake Slack 25603928aee4356845252ac6b662d5c72c29903813eJake Slack _scanner.addListener(new BulkListener() 25703928aee4356845252ac6b662d5c72c29903813eJake Slack { 25803928aee4356845252ac6b662d5c72c29903813eJake Slack public void filesChanged(List<String> filenames) throws Exception 25903928aee4356845252ac6b662d5c72c29903813eJake Slack { 26003928aee4356845252ac6b662d5c72c29903813eJake Slack if (filenames == null) 26103928aee4356845252ac6b662d5c72c29903813eJake Slack return; 26203928aee4356845252ac6b662d5c72c29903813eJake Slack if (filenames.isEmpty()) 26303928aee4356845252ac6b662d5c72c29903813eJake Slack return; 26403928aee4356845252ac6b662d5c72c29903813eJake Slack if (filenames.size() == 1) 26503928aee4356845252ac6b662d5c72c29903813eJake Slack { 26603928aee4356845252ac6b662d5c72c29903813eJake Slack Resource r = Resource.newResource(filenames.get(0)); 26703928aee4356845252ac6b662d5c72c29903813eJake Slack if (r.getFile().equals(_configResource.getFile())) 26803928aee4356845252ac6b662d5c72c29903813eJake Slack loadUsers(); 26903928aee4356845252ac6b662d5c72c29903813eJake Slack } 27003928aee4356845252ac6b662d5c72c29903813eJake Slack } 27103928aee4356845252ac6b662d5c72c29903813eJake Slack 27203928aee4356845252ac6b662d5c72c29903813eJake Slack public String toString() 27303928aee4356845252ac6b662d5c72c29903813eJake Slack { 27403928aee4356845252ac6b662d5c72c29903813eJake Slack return "PropertyUserStore$Scanner"; 27503928aee4356845252ac6b662d5c72c29903813eJake Slack } 27603928aee4356845252ac6b662d5c72c29903813eJake Slack 27703928aee4356845252ac6b662d5c72c29903813eJake Slack }); 27803928aee4356845252ac6b662d5c72c29903813eJake Slack 27903928aee4356845252ac6b662d5c72c29903813eJake Slack _scanner.setReportExistingFilesOnStartup(true); 28003928aee4356845252ac6b662d5c72c29903813eJake Slack _scanner.setRecursive(false); 28103928aee4356845252ac6b662d5c72c29903813eJake Slack _scanner.start(); 28203928aee4356845252ac6b662d5c72c29903813eJake Slack } 28303928aee4356845252ac6b662d5c72c29903813eJake Slack else 28403928aee4356845252ac6b662d5c72c29903813eJake Slack { 28503928aee4356845252ac6b662d5c72c29903813eJake Slack loadUsers(); 28603928aee4356845252ac6b662d5c72c29903813eJake Slack } 28703928aee4356845252ac6b662d5c72c29903813eJake Slack } 28803928aee4356845252ac6b662d5c72c29903813eJake Slack 28903928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 29003928aee4356845252ac6b662d5c72c29903813eJake Slack /** 29103928aee4356845252ac6b662d5c72c29903813eJake Slack * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop() 29203928aee4356845252ac6b662d5c72c29903813eJake Slack */ 29303928aee4356845252ac6b662d5c72c29903813eJake Slack protected void doStop() throws Exception 29403928aee4356845252ac6b662d5c72c29903813eJake Slack { 29503928aee4356845252ac6b662d5c72c29903813eJake Slack super.doStop(); 29603928aee4356845252ac6b662d5c72c29903813eJake Slack if (_scanner != null) 29703928aee4356845252ac6b662d5c72c29903813eJake Slack _scanner.stop(); 29803928aee4356845252ac6b662d5c72c29903813eJake Slack _scanner = null; 29903928aee4356845252ac6b662d5c72c29903813eJake Slack } 30003928aee4356845252ac6b662d5c72c29903813eJake Slack 30103928aee4356845252ac6b662d5c72c29903813eJake Slack /** 30203928aee4356845252ac6b662d5c72c29903813eJake Slack * Notifies the registered listeners of potential updates to a user 30303928aee4356845252ac6b662d5c72c29903813eJake Slack * 30403928aee4356845252ac6b662d5c72c29903813eJake Slack * @param username 30503928aee4356845252ac6b662d5c72c29903813eJake Slack * @param credential 30603928aee4356845252ac6b662d5c72c29903813eJake Slack * @param roleArray 30703928aee4356845252ac6b662d5c72c29903813eJake Slack */ 30803928aee4356845252ac6b662d5c72c29903813eJake Slack private void notifyUpdate(String username, Credential credential, String[] roleArray) 30903928aee4356845252ac6b662d5c72c29903813eJake Slack { 31003928aee4356845252ac6b662d5c72c29903813eJake Slack if (_listeners != null) 31103928aee4356845252ac6b662d5c72c29903813eJake Slack { 31203928aee4356845252ac6b662d5c72c29903813eJake Slack for (Iterator<UserListener> i = _listeners.iterator(); i.hasNext();) 31303928aee4356845252ac6b662d5c72c29903813eJake Slack { 31403928aee4356845252ac6b662d5c72c29903813eJake Slack i.next().update(username,credential,roleArray); 31503928aee4356845252ac6b662d5c72c29903813eJake Slack } 31603928aee4356845252ac6b662d5c72c29903813eJake Slack } 31703928aee4356845252ac6b662d5c72c29903813eJake Slack } 31803928aee4356845252ac6b662d5c72c29903813eJake Slack 31903928aee4356845252ac6b662d5c72c29903813eJake Slack /** 32003928aee4356845252ac6b662d5c72c29903813eJake Slack * notifies the registered listeners that a user has been removed. 32103928aee4356845252ac6b662d5c72c29903813eJake Slack * 32203928aee4356845252ac6b662d5c72c29903813eJake Slack * @param username 32303928aee4356845252ac6b662d5c72c29903813eJake Slack */ 32403928aee4356845252ac6b662d5c72c29903813eJake Slack private void notifyRemove(String username) 32503928aee4356845252ac6b662d5c72c29903813eJake Slack { 32603928aee4356845252ac6b662d5c72c29903813eJake Slack if (_listeners != null) 32703928aee4356845252ac6b662d5c72c29903813eJake Slack { 32803928aee4356845252ac6b662d5c72c29903813eJake Slack for (Iterator<UserListener> i = _listeners.iterator(); i.hasNext();) 32903928aee4356845252ac6b662d5c72c29903813eJake Slack { 33003928aee4356845252ac6b662d5c72c29903813eJake Slack i.next().remove(username); 33103928aee4356845252ac6b662d5c72c29903813eJake Slack } 33203928aee4356845252ac6b662d5c72c29903813eJake Slack } 33303928aee4356845252ac6b662d5c72c29903813eJake Slack } 33403928aee4356845252ac6b662d5c72c29903813eJake Slack 33503928aee4356845252ac6b662d5c72c29903813eJake Slack /** 33603928aee4356845252ac6b662d5c72c29903813eJake Slack * registers a listener to be notified of the contents of the property file 33703928aee4356845252ac6b662d5c72c29903813eJake Slack */ 33803928aee4356845252ac6b662d5c72c29903813eJake Slack public void registerUserListener(UserListener listener) 33903928aee4356845252ac6b662d5c72c29903813eJake Slack { 34003928aee4356845252ac6b662d5c72c29903813eJake Slack if (_listeners == null) 34103928aee4356845252ac6b662d5c72c29903813eJake Slack { 34203928aee4356845252ac6b662d5c72c29903813eJake Slack _listeners = new ArrayList<UserListener>(); 34303928aee4356845252ac6b662d5c72c29903813eJake Slack } 34403928aee4356845252ac6b662d5c72c29903813eJake Slack _listeners.add(listener); 34503928aee4356845252ac6b662d5c72c29903813eJake Slack } 34603928aee4356845252ac6b662d5c72c29903813eJake Slack 34703928aee4356845252ac6b662d5c72c29903813eJake Slack /** 34803928aee4356845252ac6b662d5c72c29903813eJake Slack * UserListener 34903928aee4356845252ac6b662d5c72c29903813eJake Slack */ 35003928aee4356845252ac6b662d5c72c29903813eJake Slack public interface UserListener 35103928aee4356845252ac6b662d5c72c29903813eJake Slack { 35203928aee4356845252ac6b662d5c72c29903813eJake Slack public void update(String username, Credential credential, String[] roleArray); 35303928aee4356845252ac6b662d5c72c29903813eJake Slack 35403928aee4356845252ac6b662d5c72c29903813eJake Slack public void remove(String username); 35503928aee4356845252ac6b662d5c72c29903813eJake Slack } 35603928aee4356845252ac6b662d5c72c29903813eJake Slack} 357