/* * Copyright 2015-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sockslib.server.manager; import com.google.common.base.Strings; import sockslib.utils.PathUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; /** * The class <code>FileBasedUserManager</code> represents an user manager which can manage users * in a file. * * @author Youchao Feng * @version 1.0 * @date Aug 28, 2015 */ public class FileBasedUserManager implements UserManager { private static final Logger logger = LoggerFactory.getLogger(FileBasedUserManager.class); private File storeFile; private StoreType storeType = StoreType.PROPERTIES; private Map<String, User> managedUsers; private boolean autoReload = false; private long reloadAfter = 20000; private AutoReloadService autoReloadService; public FileBasedUserManager(File storeFile, StoreType storeType) throws IOException { this.storeFile = checkNotNull(storeFile, "Argument [storeFile] may not be null"); this.storeType = checkNotNull(storeType, "Argument [storeType] may not be null"); loadFromFile(); } public FileBasedUserManager(File storeFile) throws IOException { this(storeFile, StoreType.PROPERTIES); } public FileBasedUserManager(String storeFile, boolean autoReload, long reloadAfter) throws IOException { storeFile = PathUtil.getAbstractPath(storeFile); this.storeFile = new File(storeFile); this.autoReload = autoReload; this.reloadAfter = reloadAfter; loadFromFile(); if (this.autoReload) { autoReloadService = new AutoReloadService(this.reloadAfter); autoReloadService.start(); } } public FileBasedUserManager(String storeFile) throws IOException { this(storeFile, false, 0); } private void synchronizedWithFile() { } private void loadFromFile() throws IOException { if (managedUsers == null) { managedUsers = new HashMap<>(); } Properties properties = new Properties(); properties.load(new FileInputStream(storeFile)); Enumeration enum1 = properties.propertyNames(); while (enum1.hasMoreElements()) { String username = (String) enum1.nextElement(); String password = properties.getProperty(username); User user = new User(); user.setUsername(username); user.setPassword(password); managedUsers.put(username, user); } } @Override public void create(User user) { checkArgument(!(user == null || user.getUsername() == null), "User or username can't be null"); managedUsers.put(user.getUsername(), user); logger.warn("Create a temporary user[{}]", user.getUsername()); } @Override public UserManager addUser(String username, String password) { if (username == null) { throw new IllegalArgumentException("Username can't be null"); } logger.warn("Create a temporary user[{}]", username); managedUsers.put(username, new User(username, password)); return this; } @Override public User check(String username, String password) { User user = find(username); if (user != null && user.getPassword() != null && user.getPassword().equals(password)) { return user; } return null; } @Override public void delete(String username) { managedUsers.remove(username); } @Override public List<User> findAll() { return null; } @Override public void update(User user) { if (user == null) { throw new IllegalArgumentException("User can't null"); } if (Strings.isNullOrEmpty(user.getUsername())) { throw new IllegalArgumentException("Username of the user can't be null or empty"); } managedUsers.put(user.getUsername(), user); logger.warn("Update user[{}] temporarily", user.getUsername()); } @Override public User find(String username) { if (Strings.isNullOrEmpty(username)) { throw new IllegalArgumentException("Username can't be null or empty"); } return managedUsers.get(username); } public File getStoreFile() { return storeFile; } public void setStoreFile(File storeFile) { this.storeFile = storeFile; } public StoreType getStoreType() { return storeType; } public void setStoreType(StoreType storeType) { this.storeType = storeType; } public Map<String, User> getManagedUsers() { return managedUsers; } public void setManagedUsers(Map<String, User> managedUsers) { this.managedUsers = managedUsers; } public boolean isAutoReload() { return autoReload; } public void setAutoReload(boolean autoReload) { this.autoReload = autoReload; } public long getReloadAfter() { return reloadAfter; } public void setReloadAfter(long reloadAfter) { this.reloadAfter = reloadAfter; } public AutoReloadService getAutoReloadService() { return autoReloadService; } public void setAutoReloadService(AutoReloadService autoReloadService) { this.autoReloadService = autoReloadService; } public enum StoreType { PROPERTIES } private class AutoReloadService implements Runnable { private Thread thread; private long reloadAfter; private boolean stop; public AutoReloadService(long reloadAfter) { this.reloadAfter = reloadAfter; } public void start() { stop = false; thread = new Thread(this, "AutoReloadService"); thread.setDaemon(true); thread.start(); ; } public void stop() { stop = true; if (thread != null) { thread.interrupt(); } } @Override public void run() { while (!stop) { try { Thread.sleep(reloadAfter); } catch (InterruptedException e) { logger.error(e.getMessage(), e); } try { loadFromFile(); } catch (IOException e) { logger.error(e.getMessage(), e); } } } } }