/*
 * Copyright 2011 gitblit.com.
 *
 * 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 com.gitblit;

import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitblit.Constants.AccessPermission;
import com.gitblit.Constants.AccountType;
import com.gitblit.Constants.Transport;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.models.UserRepositoryPreferences;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.DeepCopier;
import com.gitblit.utils.StringUtils;

/**
 * ConfigUserService is Gitblit's default user service implementation since
 * version 0.8.0.
 *
 * Users and their repository memberships are stored in a git-style config file
 * which is cached and dynamically reloaded when modified. This file is
 * plain-text, human-readable, and may be edited with a text editor.
 *
 * Additionally, this format allows for expansion of the user model without
 * bringing in the complexity of a database.
 *
 * @author James Moger
 *
 */
public class ConfigUserService implements IUserService {

	private static final String TEAM = "team";

	private static final String USER = "user";

	private static final String PASSWORD = "password";

	private static final String DISPLAYNAME = "displayName";

	private static final String EMAILADDRESS = "emailAddress";

	private static final String ORGANIZATIONALUNIT = "organizationalUnit";

	private static final String ORGANIZATION = "organization";

	private static final String LOCALITY = "locality";

	private static final String STATEPROVINCE = "stateProvince";

	private static final String COUNTRYCODE = "countryCode";

	private static final String COOKIE = "cookie";

	private static final String REPOSITORY = "repository";

	private static final String ROLE = "role";

	private static final String MAILINGLIST = "mailingList";

	private static final String PRERECEIVE = "preReceiveScript";

	private static final String POSTRECEIVE = "postReceiveScript";

	private static final String STARRED = "starred";

	private static final String LOCALE = "locale";

	private static final String EMAILONMYTICKETCHANGES = "emailMeOnMyTicketChanges";

	private static final String TRANSPORT = "transport";

	private static final String ACCOUNTTYPE = "accountType";

	private static final String DISABLED = "disabled";

	private final File realmFile;

	private final Logger logger = LoggerFactory.getLogger(ConfigUserService.class);

	private final Map<String, UserModel> users = new ConcurrentHashMap<String, UserModel>();

	private final Map<String, UserModel> cookies = new ConcurrentHashMap<String, UserModel>();

	private final Map<String, TeamModel> teams = new ConcurrentHashMap<String, TeamModel>();

	private volatile long lastModified;

	private volatile boolean forceReload;

	public ConfigUserService(File realmFile) {
		this.realmFile = realmFile;
	}

	/**
	 * Setup the user service.
	 *
	 * @param runtimeManager
	 * @since 1.4.0
	 */
	@Override
	public void setup(IRuntimeManager runtimeManager) {
	}

	/**
	 * Returns the cookie value for the specified user.
	 *
	 * @param model
	 * @return cookie value
	 */
	@Override
	public synchronized String getCookie(UserModel model) {
		if (!StringUtils.isEmpty(model.cookie)) {
			return model.cookie;
		}
		UserModel storedModel = getUserModel(model.username);
		if (storedModel == null) {
			return null;
		}
		return storedModel.cookie;
	}

	/**
	 * Gets the user object for the specified cookie.
	 *
	 * @param cookie
	 * @return a user object or null
	 */
	@Override
	public synchronized UserModel getUserModel(char[] cookie) {
		String hash = new String(cookie);
		if (StringUtils.isEmpty(hash)) {
			return null;
		}
		read();
		UserModel model = null;
		if (cookies.containsKey(hash)) {
			model = cookies.get(hash);
		}

		if (model != null) {
			// clone the model, otherwise all changes to this object are
			// live and unpersisted
			model = DeepCopier.copy(model);
		}
		return model;
	}

	/**
	 * Retrieve the user object for the specified username.
	 *
	 * @param username
	 * @return a user object or null
	 */
	@Override
	public synchronized UserModel getUserModel(String username) {
		read();
		UserModel model = users.get(username.toLowerCase());
		if (model != null) {
			// clone the model, otherwise all changes to this object are
			// live and unpersisted
			model = DeepCopier.copy(model);
		}
		return model;
	}

	/**
	 * Updates/writes a complete user object.
	 *
	 * @param model
	 * @return true if update is successful
	 */
	@Override
	public synchronized boolean updateUserModel(UserModel model) {
		return updateUserModel(model.username, model);
	}

	/**
	 * Updates/writes all specified user objects.
	 *
	 * @param models a list of user models
	 * @return true if update is successful
	 * @since 1.2.0
	 */
	@Override
	public synchronized boolean updateUserModels(Collection<UserModel> models) {
		try {
			read();
			for (UserModel model : models) {
				UserModel originalUser = users.remove(model.username.toLowerCase());
				users.put(model.username.toLowerCase(), model);
				// null check on "final" teams because JSON-sourced UserModel
				// can have a null teams object
				if (model.teams != null) {
					Set<TeamModel> userTeams = new HashSet<TeamModel>();
					for (TeamModel team : model.teams) {
						TeamModel t = teams.get(team.name.toLowerCase());
						if (t == null) {
							// new team
							t = team;
							teams.put(team.name.toLowerCase(), t);
						}
						// do not clobber existing team definition
						// maybe because this is a federated user
						t.addUser(model.username);
						userTeams.add(t);
					}
					// replace Team-Models in users by new ones.
					model.teams.clear();
					model.teams.addAll(userTeams);

					// check for implicit team removal
					if (originalUser != null) {
						for (TeamModel team : originalUser.teams) {
							if (!model.isTeamMember(team.name)) {
								team.removeUser(model.username);
							}
						}
					}
				}
			}
			write();
			return true;
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to update user {0} models!", models.size()),
					t);
		}
		return false;
	}

	/**
	 * Updates/writes and replaces a complete user object keyed by username.
	 * This method allows for renaming a user.
	 *
	 * @param username
	 *            the old username
	 * @param model
	 *            the user object to use for username
	 * @return true if update is successful
	 */
	@Override
	public synchronized boolean updateUserModel(String username, UserModel model) {
		UserModel originalUser = null;
		try {
			if (!model.isLocalAccount()) {
				// do not persist password
				model.password = Constants.EXTERNAL_ACCOUNT;
			}
			read();
			originalUser = users.remove(username.toLowerCase());
			if (originalUser != null) {
				cookies.remove(originalUser.cookie);
			}
			users.put(model.username.toLowerCase(), model);
			// null check on "final" teams because JSON-sourced UserModel
			// can have a null teams object
			if (model.teams != null) {
				for (TeamModel team : model.teams) {
					TeamModel t = teams.get(team.name.toLowerCase());
					if (t == null) {
						// new team
						team.addUser(username);
						teams.put(team.name.toLowerCase(), team);
					} else {
						// do not clobber existing team definition
						// maybe because this is a federated user
						t.removeUser(username);
						t.addUser(model.username);
					}
				}

				// check for implicit team removal
				if (originalUser != null) {
					for (TeamModel team : originalUser.teams) {
						if (!model.isTeamMember(team.name)) {
							team.removeUser(username);
						}
					}
				}
			}
			write();
			return true;
		} catch (Throwable t) {
			if (originalUser != null) {
				// restore original user
				users.put(originalUser.username.toLowerCase(), originalUser);
			} else {
				// drop attempted add
				users.remove(model.username.toLowerCase());
			}
			logger.error(MessageFormat.format("Failed to update user model {0}!", model.username),
					t);
		}
		return false;
	}

	/**
	 * Deletes the user object from the user service.
	 *
	 * @param model
	 * @return true if successful
	 */
	@Override
	public synchronized boolean deleteUserModel(UserModel model) {
		return deleteUser(model.username);
	}

	/**
	 * Delete the user object with the specified username
	 *
	 * @param username
	 * @return true if successful
	 */
	@Override
	public synchronized boolean deleteUser(String username) {
		try {
			// Read realm file
			read();
			UserModel model = users.remove(username.toLowerCase());
			if (model == null) {
				// user does not exist
				return false;
			}
			// remove user from team
			for (TeamModel team : model.teams) {
				TeamModel t = teams.get(team.name);
				if (t == null) {
					// new team
					team.removeUser(username);
					teams.put(team.name.toLowerCase(), team);
				} else {
					// existing team
					t.removeUser(username);
				}
			}
			write();
			return true;
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to delete user {0}!", username), t);
		}
		return false;
	}

	/**
	 * Returns the list of all teams available to the login service.
	 *
	 * @return list of all teams
	 * @since 0.8.0
	 */
	@Override
	public synchronized List<String> getAllTeamNames() {
		read();
		List<String> list = new ArrayList<String>(teams.keySet());
		Collections.sort(list);
		return list;
	}

	/**
	 * Returns the list of all teams available to the login service.
	 *
	 * @return list of all teams
	 * @since 0.8.0
	 */
	@Override
	public synchronized List<TeamModel> getAllTeams() {
		read();
		List<TeamModel> list = new ArrayList<TeamModel>(teams.values());
		list = DeepCopier.copy(list);
		Collections.sort(list);
		return list;
	}

	/**
	 * Returns the list of all users who are allowed to bypass the access
	 * restriction placed on the specified repository.
	 *
	 * @param role
	 *            the repository name
	 * @return list of all usernames that can bypass the access restriction
	 */
	@Override
	public synchronized List<String> getTeamNamesForRepositoryRole(String role) {
		List<String> list = new ArrayList<String>();
		try {
			read();
			for (Map.Entry<String, TeamModel> entry : teams.entrySet()) {
				TeamModel model = entry.getValue();
				if (model.hasRepositoryPermission(role)) {
					list.add(model.name);
				}
			}
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to get teamnames for role {0}!", role), t);
		}
		Collections.sort(list);
		return list;
	}

	/**
	 * Retrieve the team object for the specified team name.
	 *
	 * @param teamname
	 * @return a team object or null
	 * @since 0.8.0
	 */
	@Override
	public synchronized TeamModel getTeamModel(String teamname) {
		read();
		TeamModel model = teams.get(teamname.toLowerCase());
		if (model != null) {
			// clone the model, otherwise all changes to this object are
			// live and unpersisted
			model = DeepCopier.copy(model);
		}
		return model;
	}

	/**
	 * Updates/writes a complete team object.
	 *
	 * @param model
	 * @return true if update is successful
	 * @since 0.8.0
	 */
	@Override
	public synchronized boolean updateTeamModel(TeamModel model) {
		return updateTeamModel(model.name, model);
	}

	/**
	 * Updates/writes all specified team objects.
	 *
	 * @param models a list of team models
	 * @return true if update is successful
	 * @since 1.2.0
	 */
	@Override
	public synchronized boolean updateTeamModels(Collection<TeamModel> models) {
		try {
			read();
			for (TeamModel team : models) {
				teams.put(team.name.toLowerCase(), team);
			}
			write();
			return true;
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to update team {0} models!", models.size()), t);
		}
		return false;
	}

	/**
	 * Updates/writes and replaces a complete team object keyed by teamname.
	 * This method allows for renaming a team.
	 *
	 * @param teamname
	 *            the old teamname
	 * @param model
	 *            the team object to use for teamname
	 * @return true if update is successful
	 * @since 0.8.0
	 */
	@Override
	public synchronized boolean updateTeamModel(String teamname, TeamModel model) {
		TeamModel original = null;
		try {
			read();
			original = teams.remove(teamname.toLowerCase());
			teams.put(model.name.toLowerCase(), model);
			write();
			return true;
		} catch (Throwable t) {
			if (original != null) {
				// restore original team
				teams.put(original.name.toLowerCase(), original);
			} else {
				// drop attempted add
				teams.remove(model.name.toLowerCase());
			}
			logger.error(MessageFormat.format("Failed to update team model {0}!", model.name), t);
		}
		return false;
	}

	/**
	 * Deletes the team object from the user service.
	 *
	 * @param model
	 * @return true if successful
	 * @since 0.8.0
	 */
	@Override
	public synchronized boolean deleteTeamModel(TeamModel model) {
		return deleteTeam(model.name);
	}

	/**
	 * Delete the team object with the specified teamname
	 *
	 * @param teamname
	 * @return true if successful
	 * @since 0.8.0
	 */
	@Override
	public synchronized boolean deleteTeam(String teamname) {
		try {
			// Read realm file
			read();
			teams.remove(teamname.toLowerCase());
			write();
			return true;
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to delete team {0}!", teamname), t);
		}
		return false;
	}

	/**
	 * Returns the list of all users available to the login service.
	 *
	 * @return list of all usernames
	 */
	@Override
	public synchronized List<String> getAllUsernames() {
		read();
		List<String> list = new ArrayList<String>(users.keySet());
		Collections.sort(list);
		return list;
	}

	/**
	 * Returns the list of all users available to the login service.
	 *
	 * @return list of all usernames
	 */
	@Override
	public synchronized List<UserModel> getAllUsers() {
		read();
		List<UserModel> list = new ArrayList<UserModel>(users.values());
		list = DeepCopier.copy(list);
		Collections.sort(list);
		return list;
	}

	/**
	 * Returns the list of all users who are allowed to bypass the access
	 * restriction placed on the specified repository.
	 *
	 * @param role
	 *            the repository name
	 * @return list of all usernames that can bypass the access restriction
	 */
	@Override
	public synchronized List<String> getUsernamesForRepositoryRole(String role) {
		List<String> list = new ArrayList<String>();
		try {
			read();
			for (Map.Entry<String, UserModel> entry : users.entrySet()) {
				UserModel model = entry.getValue();
				if (model.hasRepositoryPermission(role)) {
					list.add(model.username);
				}
			}
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to get usernames for role {0}!", role), t);
		}
		Collections.sort(list);
		return list;
	}

	/**
	 * Renames a repository role.
	 *
	 * @param oldRole
	 * @param newRole
	 * @return true if successful
	 */
	@Override
	public synchronized boolean renameRepositoryRole(String oldRole, String newRole) {
		try {
			read();
			// identify users which require role rename
			for (UserModel model : users.values()) {
				if (model.hasRepositoryPermission(oldRole)) {
					AccessPermission permission = model.removeRepositoryPermission(oldRole);
					model.setRepositoryPermission(newRole, permission);
				}
			}

			// identify teams which require role rename
			for (TeamModel model : teams.values()) {
				if (model.hasRepositoryPermission(oldRole)) {
					AccessPermission permission = model.removeRepositoryPermission(oldRole);
					model.setRepositoryPermission(newRole, permission);
				}
			}
			// persist changes
			write();
			return true;
		} catch (Throwable t) {
			logger.error(
					MessageFormat.format("Failed to rename role {0} to {1}!", oldRole, newRole), t);
		}
		return false;
	}

	/**
	 * Removes a repository role from all users.
	 *
	 * @param role
	 * @return true if successful
	 */
	@Override
	public synchronized boolean deleteRepositoryRole(String role) {
		try {
			read();

			// identify users which require role rename
			for (UserModel user : users.values()) {
				user.removeRepositoryPermission(role);
			}

			// identify teams which require role rename
			for (TeamModel team : teams.values()) {
				team.removeRepositoryPermission(role);
			}

			// persist changes
			write();
			return true;
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to delete role {0}!", role), t);
		}
		return false;
	}

	/**
	 * Writes the properties file.
	 *
	 * @throws IOException
	 */
	private synchronized void write() throws IOException {
		// Write a temporary copy of the users file
		File realmFileCopy = new File(realmFile.getAbsolutePath() + ".tmp");

		StoredConfig config = new FileBasedConfig(realmFileCopy, FS.detect());

		// write users
		for (UserModel model : users.values()) {
			if (!StringUtils.isEmpty(model.password)) {
				config.setString(USER, model.username, PASSWORD, model.password);
			}
			if (!StringUtils.isEmpty(model.cookie)) {
				config.setString(USER, model.username, COOKIE, model.cookie);
			}
			if (!StringUtils.isEmpty(model.displayName)) {
				config.setString(USER, model.username, DISPLAYNAME, model.displayName);
			}
			if (!StringUtils.isEmpty(model.emailAddress)) {
				config.setString(USER, model.username, EMAILADDRESS, model.emailAddress);
			}
			if (model.accountType != null) {
				config.setString(USER, model.username, ACCOUNTTYPE, model.accountType.name());
			}
			if (!StringUtils.isEmpty(model.organizationalUnit)) {
				config.setString(USER, model.username, ORGANIZATIONALUNIT, model.organizationalUnit);
			}
			if (!StringUtils.isEmpty(model.organization)) {
				config.setString(USER, model.username, ORGANIZATION, model.organization);
			}
			if (!StringUtils.isEmpty(model.locality)) {
				config.setString(USER, model.username, LOCALITY, model.locality);
			}
			if (!StringUtils.isEmpty(model.stateProvince)) {
				config.setString(USER, model.username, STATEPROVINCE, model.stateProvince);
			}
			if (!StringUtils.isEmpty(model.countryCode)) {
				config.setString(USER, model.username, COUNTRYCODE, model.countryCode);
			}
			if (model.disabled) {
				config.setBoolean(USER, model.username, DISABLED, true);
			}
			if (model.getPreferences() != null) {
				Locale locale = model.getPreferences().getLocale();
				if (locale != null) {
					String val;
					if (StringUtils.isEmpty(locale.getCountry())) {
						val = locale.getLanguage();
					} else {
						val = locale.getLanguage() + "_" + locale.getCountry();
					}
					config.setString(USER, model.username, LOCALE, val);
				}

				config.setBoolean(USER, model.username, EMAILONMYTICKETCHANGES, model.getPreferences().isEmailMeOnMyTicketChanges());

				if (model.getPreferences().getTransport() != null) {
					config.setString(USER, model.username, TRANSPORT, model.getPreferences().getTransport().name());
				}
			}

			// user roles
			List<String> roles = new ArrayList<String>();
			if (model.canAdmin) {
				roles.add(Constants.ADMIN_ROLE);
			}
			if (model.canFork) {
				roles.add(Constants.FORK_ROLE);
			}
			if (model.canCreate) {
				roles.add(Constants.CREATE_ROLE);
			}
			if (model.excludeFromFederation) {
				roles.add(Constants.NOT_FEDERATED_ROLE);
			}
			if (roles.size() == 0) {
				// we do this to ensure that user record with no password
				// is written.  otherwise, StoredConfig optimizes that account
				// away. :(
				roles.add(Constants.NO_ROLE);
			}
			config.setStringList(USER, model.username, ROLE, roles);

			// discrete repository permissions
			if (model.permissions != null && !model.canAdmin) {
				List<String> permissions = new ArrayList<String>();
				for (Map.Entry<String, AccessPermission> entry : model.permissions.entrySet()) {
					if (entry.getValue().exceeds(AccessPermission.NONE)) {
						permissions.add(entry.getValue().asRole(entry.getKey()));
					}
				}
				config.setStringList(USER, model.username, REPOSITORY, permissions);
			}

			// user preferences
			if (model.getPreferences() != null) {
				List<String> starred =  model.getPreferences().getStarredRepositories();
				if (starred.size() > 0) {
					config.setStringList(USER, model.username, STARRED, starred);
				}
			}
		}

		// write teams
		for (TeamModel model : teams.values()) {
			// team roles
			List<String> roles = new ArrayList<String>();
			if (model.canAdmin) {
				roles.add(Constants.ADMIN_ROLE);
			}
			if (model.canFork) {
				roles.add(Constants.FORK_ROLE);
			}
			if (model.canCreate) {
				roles.add(Constants.CREATE_ROLE);
			}
			if (roles.size() == 0) {
				// we do this to ensure that team record is written.
				// Otherwise, StoredConfig might optimizes that record away.
				roles.add(Constants.NO_ROLE);
			}
			config.setStringList(TEAM, model.name, ROLE, roles);
			if (model.accountType != null) {
				config.setString(TEAM, model.name, ACCOUNTTYPE, model.accountType.name());
			}

			if (!model.canAdmin) {
				// write team permission for non-admin teams
				if (model.permissions == null) {
					// null check on "final" repositories because JSON-sourced TeamModel
					// can have a null repositories object
					if (!ArrayUtils.isEmpty(model.repositories)) {
						config.setStringList(TEAM, model.name, REPOSITORY, new ArrayList<String>(
								model.repositories));
					}
				} else {
					// discrete repository permissions
					List<String> permissions = new ArrayList<String>();
					for (Map.Entry<String, AccessPermission> entry : model.permissions.entrySet()) {
						if (entry.getValue().exceeds(AccessPermission.NONE)) {
							// code:repository (e.g. RW+:~james/myrepo.git
							permissions.add(entry.getValue().asRole(entry.getKey()));
						}
					}
					config.setStringList(TEAM, model.name, REPOSITORY, permissions);
				}
			}

			// null check on "final" users because JSON-sourced TeamModel
			// can have a null users object
			if (!ArrayUtils.isEmpty(model.users)) {
				config.setStringList(TEAM, model.name, USER, new ArrayList<String>(model.users));
			}

			// null check on "final" mailing lists because JSON-sourced
			// TeamModel can have a null users object
			if (!ArrayUtils.isEmpty(model.mailingLists)) {
				config.setStringList(TEAM, model.name, MAILINGLIST, new ArrayList<String>(
						model.mailingLists));
			}

			// null check on "final" preReceiveScripts because JSON-sourced
			// TeamModel can have a null preReceiveScripts object
			if (!ArrayUtils.isEmpty(model.preReceiveScripts)) {
				config.setStringList(TEAM, model.name, PRERECEIVE, model.preReceiveScripts);
			}

			// null check on "final" postReceiveScripts because JSON-sourced
			// TeamModel can have a null postReceiveScripts object
			if (!ArrayUtils.isEmpty(model.postReceiveScripts)) {
				config.setStringList(TEAM, model.name, POSTRECEIVE, model.postReceiveScripts);
			}
		}

		config.save();
		// manually set the forceReload flag because not all JVMs support real
		// millisecond resolution of lastModified. (issue-55)
		forceReload = true;

		// If the write is successful, delete the current file and rename
		// the temporary copy to the original filename.
		if (realmFileCopy.exists() && realmFileCopy.length() > 0) {
			if (realmFile.exists()) {
				if (!realmFile.delete()) {
					throw new IOException(MessageFormat.format("Failed to delete {0}!",
							realmFile.getAbsolutePath()));
				}
			}
			if (!realmFileCopy.renameTo(realmFile)) {
				throw new IOException(MessageFormat.format("Failed to rename {0} to {1}!",
						realmFileCopy.getAbsolutePath(), realmFile.getAbsolutePath()));
			}
		} else {
			throw new IOException(MessageFormat.format("Failed to save {0}!",
					realmFileCopy.getAbsolutePath()));
		}
	}

	/**
	 * Reads the realm file and rebuilds the in-memory lookup tables.
	 */
	protected synchronized void read() {
		if (realmFile.exists() && (forceReload || (realmFile.lastModified() != lastModified))) {
			forceReload = false;
			lastModified = realmFile.lastModified();
			users.clear();
			cookies.clear();
			teams.clear();

			try {
				StoredConfig config = new FileBasedConfig(realmFile, FS.detect());
				config.load();
				Set<String> usernames = config.getSubsections(USER);
				for (String username : usernames) {
					UserModel user = new UserModel(username.toLowerCase());
					user.password = config.getString(USER, username, PASSWORD);
					user.displayName = config.getString(USER, username, DISPLAYNAME);
					user.emailAddress = config.getString(USER, username, EMAILADDRESS);
					user.accountType = AccountType.fromString(config.getString(USER, username, ACCOUNTTYPE));
					if (Constants.EXTERNAL_ACCOUNT.equals(user.password) && user.accountType.isLocal()) {
						user.accountType = AccountType.EXTERNAL;
					}
					user.disabled = config.getBoolean(USER, username, DISABLED, false);
					user.organizationalUnit = config.getString(USER, username, ORGANIZATIONALUNIT);
					user.organization = config.getString(USER, username, ORGANIZATION);
					user.locality = config.getString(USER, username, LOCALITY);
					user.stateProvince = config.getString(USER, username, STATEPROVINCE);
					user.countryCode = config.getString(USER, username, COUNTRYCODE);
					user.cookie = config.getString(USER, username, COOKIE);
					if (StringUtils.isEmpty(user.cookie) && !StringUtils.isEmpty(user.password)) {
						user.cookie = StringUtils.getSHA1(user.username + user.password);
					}

					// preferences
					user.getPreferences().setLocale(config.getString(USER, username, LOCALE));
					user.getPreferences().setEmailMeOnMyTicketChanges(config.getBoolean(USER, username, EMAILONMYTICKETCHANGES, true));
					user.getPreferences().setTransport(Transport.fromString(config.getString(USER, username, TRANSPORT)));

					// user roles
					Set<String> roles = new HashSet<String>(Arrays.asList(config.getStringList(
							USER, username, ROLE)));
					user.canAdmin = roles.contains(Constants.ADMIN_ROLE);
					user.canFork = roles.contains(Constants.FORK_ROLE);
					user.canCreate = roles.contains(Constants.CREATE_ROLE);
					user.excludeFromFederation = roles.contains(Constants.NOT_FEDERATED_ROLE);

					// repository memberships
					if (!user.canAdmin) {
						// non-admin, read permissions
						Set<String> repositories = new HashSet<String>(Arrays.asList(config
								.getStringList(USER, username, REPOSITORY)));
						for (String repository : repositories) {
							user.addRepositoryPermission(repository);
						}
					}

					// starred repositories
					Set<String> starred = new HashSet<String>(Arrays.asList(config
							.getStringList(USER, username, STARRED)));
					for (String repository : starred) {
						UserRepositoryPreferences prefs = user.getPreferences().getRepositoryPreferences(repository);
						prefs.starred = true;
					}

					// update cache
					users.put(user.username, user);
					if (!StringUtils.isEmpty(user.cookie)) {
						cookies.put(user.cookie, user);
					}
				}

				// load the teams
				Set<String> teamnames = config.getSubsections(TEAM);
				for (String teamname : teamnames) {
					TeamModel team = new TeamModel(teamname);
					Set<String> roles = new HashSet<String>(Arrays.asList(config.getStringList(
							TEAM, teamname, ROLE)));
					team.canAdmin = roles.contains(Constants.ADMIN_ROLE);
					team.canFork = roles.contains(Constants.FORK_ROLE);
					team.canCreate = roles.contains(Constants.CREATE_ROLE);
					team.accountType = AccountType.fromString(config.getString(TEAM, teamname, ACCOUNTTYPE));

					if (!team.canAdmin) {
						// non-admin team, read permissions
						team.addRepositoryPermissions(Arrays.asList(config.getStringList(TEAM, teamname,
								REPOSITORY)));
					}
					team.addUsers(Arrays.asList(config.getStringList(TEAM, teamname, USER)));
					team.addMailingLists(Arrays.asList(config.getStringList(TEAM, teamname,
							MAILINGLIST)));
					team.preReceiveScripts.addAll(Arrays.asList(config.getStringList(TEAM,
							teamname, PRERECEIVE)));
					team.postReceiveScripts.addAll(Arrays.asList(config.getStringList(TEAM,
							teamname, POSTRECEIVE)));

					teams.put(team.name.toLowerCase(), team);

					// set the teams on the users
					for (String user : team.users) {
						UserModel model = users.get(user);
						if (model != null) {
							model.teams.add(team);
						}
					}
				}
			} catch (Exception e) {
				logger.error(MessageFormat.format("Failed to read {0}", realmFile), e);
			}
		}
	}

	protected long lastModified() {
		return lastModified;
	}

	@Override
	public String toString() {
		return getClass().getSimpleName() + "(" + realmFile.getAbsolutePath() + ")";
	}
}
