package org.meaningfulweb.util.security;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ReloadableFileAuthenticationServiceImpl
implements AuthenticationService {
private final static Logger LOG = LoggerFactory
.getLogger(ReloadableFileAuthenticationServiceImpl.class);
private File authFile;
private long pollFrequencyInSeconds = 60;
private Map<String, String> authMap = new ConcurrentHashMap<String, String>();
private Thread reloaderThread;
private AtomicBoolean active = new AtomicBoolean(false);
private class ReloaderThread
extends Thread {
private AtomicLong lastModified = new AtomicLong(0L);
private void reloadAuthMap()
throws IOException {
Map<String, String> newAuths = new HashMap<String, String>();
Scanner scanner = new Scanner(authFile);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
String[] loginApiKeys = StringUtils.split(line, "=");
if (loginApiKeys != null && loginApiKeys.length > 0) {
newAuths.put(StringUtils.trim(loginApiKeys[0]),
StringUtils.trim(loginApiKeys[1]));
}
}
// remove any keys no longer in the map
for (String key : authMap.keySet()) {
if (!newAuths.containsKey(key)) {
authMap.remove(key);
}
}
// add and update keys in the map
for (Entry<String, String> entry : newAuths.entrySet()) {
authMap.put(entry.getKey(), entry.getValue());
}
}
@Override
public void run() {
while (active.get()) {
try {
if (authFile == null || !authFile.exists()) {
LOG.warn("No authentication file found");
}
else {
long currentMod = authFile.lastModified();
if (currentMod > lastModified.get()) {
LOG.info("Loading authentication keys file: "
+ authFile.getPath());
lastModified.set(currentMod);
reloadAuthMap();
}
}
Thread.sleep(pollFrequencyInSeconds * 1000);
}
catch (Exception e) {
LOG.error("Error loading auth file: " + authFile.getAbsolutePath(), e);
}
}
}
}
public ReloadableFileAuthenticationServiceImpl() {
}
public void initialize() {
active.set(true);
reloaderThread = new ReloaderThread();
reloaderThread.setDaemon(true);
reloaderThread.start();
}
public void shutdown() {
active.set(false);
}
public void setAuthFile(File authFile) {
this.authFile = authFile;
}
public void setPollFrequencyInSeconds(long pollFrequencyInSeconds) {
this.pollFrequencyInSeconds = pollFrequencyInSeconds;
}
@Override
public boolean isAuthorized(String login, String apiKey) {
if (StringUtils.isEmpty(login) || StringUtils.isEmpty(apiKey)) {
return false;
}
String value = authMap.get(login);
return value != null && value.equals(apiKey);
}
}