package org.lognavigator.mvc;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.annotation.PostConstruct;
import net.schmizz.sshj.common.IOUtils;
import org.lognavigator.exception.ConfigException;
import org.springframework.core.io.Resource;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
/**
* UserDetailsService based on a properties file, which is reloaded each time it is updated.
* Properties file format is :
* username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]
*/
public class ReloadableInMemoryUserDetailsService implements UserDetailsService {
/** Link to users properties file */
private Resource usersPropertiesResource;
/** Last time that 'usersPropertiesResource' has been modified */
private long usersFileLastModified;
/** Users InMemory Store */
private InMemoryUserDetailsManager inMemoryUserDetailsManager;
/**
* Load or Reload the users from users file, if necessary
*/
synchronized void reloadUsersIfNecessary() throws ConfigException {
// Should we reload users file ? (because it has been modified since last reload)
long lastModified;
try {
lastModified = usersPropertiesResource.lastModified();
boolean needReload = (lastModified > this.usersFileLastModified);
if (!needReload) {
return;
}
} catch (IOException e) {
throw new ConfigException("Error when trying to access users file " + usersPropertiesResource, e);
}
// Update the lastModified date information for users file
this.usersFileLastModified = lastModified;
// Load users file
InputStream usersFileInputStream = null;
try {
usersFileInputStream = usersPropertiesResource.getInputStream();
Properties usersProperties = new Properties();
usersProperties.load(usersFileInputStream);
this.inMemoryUserDetailsManager = new InMemoryUserDetailsManager(usersProperties);
}
catch (IOException e) {
throw new ConfigException("I/O error when trying to load users file " + usersPropertiesResource, e);
}
finally {
IOUtils.closeQuietly(usersFileInputStream);
}
}
@Override
public synchronized UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
reloadUsersIfNecessary();
return inMemoryUserDetailsManager.loadUserByUsername(username);
}
/**
* Init the Spring Service
*/
@PostConstruct
public synchronized void init() throws ConfigException {
// Does users file is configured ?
if (usersPropertiesResource == null) {
throw new ConfigException("'users' property must be set");
}
// Does users file exist ?
if (!usersPropertiesResource.exists()) {
throw new ConfigException("The users file " + usersPropertiesResource + " does not exist");
}
reloadUsersIfNecessary();
}
public void setProperties(Resource usersProperties) {
this.usersPropertiesResource = usersProperties;
}
}