Newer
Older
KeeperJerry_Launcher / LaunchServer / source / auth / provider / FileAuthProvider.java
package launchserver.auth.provider;

import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.attribute.FileTime;
import java.util.HashMap;
import java.util.Map;

import launcher.helper.IOHelper;
import launcher.helper.LogHelper;
import launcher.serialize.config.entry.BlockConfigEntry;
import launcher.serialize.config.entry.StringConfigEntry;
import launchserver.helper.LineReader;

public final class FileAuthProvider extends DigestAuthProvider {
	private final Path file;

	// Cache
	private final Map<String, String> cache = new HashMap<>(8192);
	private final Object cacheLock = new Object();
	private FileTime cacheLastModified;

	public FileAuthProvider(BlockConfigEntry block) {
		super(block);
		file = IOHelper.toPath(block.getEntryValue("file", StringConfigEntry.class));
	}

	@Override
	public String auth(String login, String password) throws IOException {
		String validDigest;
		synchronized (cacheLock) {
			updateCache();
			validDigest = cache.get(login);
		}
		verifyDigest(validDigest, password);
		return login;
	}

	@Override
	public void flush() {
		// Do nothing
	}

	private void updateCache() throws IOException {
		FileTime lastModified = IOHelper.readAttributes(file).lastModifiedTime();
		if (lastModified.equals(cacheLastModified)) {
			return; // Not modified, so cache is up-to-date
		}

		// Read file
		cache.clear();
		LogHelper.info("Recaching users file: '%s'", file);
		try (BufferedReader reader = new LineReader(IOHelper.newReader(file))) {
			for (String line = reader.readLine(); line != null; line = reader.readLine()) {
				// Get and verify split index
				int splitIndex = line.indexOf(':');
				if (splitIndex < 0) {
					throw new IOException(String.format("Illegal line in users file: '%s'", line));
				}

				// Split and verify username and password
				String username = line.substring(0, splitIndex).trim();
				String password = line.substring(splitIndex + 1).trim();
				if (username.isEmpty() || password.isEmpty()) {
					throw new IOException(String.format("Empty username or password in users file: '%s'", line));
				}

				// Try put to cache
				if (cache.put(username, password) != null) {
					throw new IOException(String.format("Duplicate username in users file: '%s'", username));
				}
			}
		}

		// Update last modified time
		cacheLastModified = lastModified;
	}
}