[app-wiring-refactor]: Apply review comments:

- Add reference to original library in `FluentBuilder`.
- Change `I<Name>` notation to `<Name>Impl` notation.
- Move error config to test resources
- Add comment with config instruction
- Add config to the documentation
This commit is contained in:
Francesco Burato 2020-10-30 22:37:25 +00:00
parent e8bb8ae24b
commit 6e3750d50a
41 changed files with 171 additions and 146 deletions

View file

@ -4,6 +4,11 @@ import java.util.ArrayList;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier; import java.util.function.Supplier;
/**
* A base class for fluent, immutable, composable builders.
*
* @see <a href="https://github.com/fburato/functionalutils/blob/master/utils/src/main/java/com/github/fburato/functionalutils/utils/Builder.java">Builder</a>
*/
public abstract class FluentBuilder<ToBuild, RealBuilder extends FluentBuilder<ToBuild, RealBuilder>> { public abstract class FluentBuilder<ToBuild, RealBuilder extends FluentBuilder<ToBuild, RealBuilder>> {
final ArrayList<Consumer<RealBuilder>> buildSequence; final ArrayList<Consumer<RealBuilder>> buildSequence;

View file

@ -5,7 +5,7 @@ import mage.cards.repository.CardRepository;
import mage.game.Game; import mage.game.Game;
import mage.server.exceptions.UserNotFoundException; import mage.server.exceptions.UserNotFoundException;
import mage.server.game.GameController; import mage.server.game.GameController;
import mage.server.managers.IChatManager; import mage.server.managers.ChatManager;
import mage.server.managers.ManagerFactory; import mage.server.managers.ManagerFactory;
import mage.server.util.SystemUtil; import mage.server.util.SystemUtil;
import mage.view.ChatMessage.MessageColor; import mage.view.ChatMessage.MessageColor;
@ -26,16 +26,16 @@ import java.util.stream.Collectors;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class ChatManager implements IChatManager { public class ChatManagerImpl implements ChatManager {
private static final Logger logger = Logger.getLogger(ChatManager.class); private static final Logger logger = Logger.getLogger(ChatManagerImpl.class);
private static final HashMap<String, String> userMessages = new HashMap<>(); private static final HashMap<String, String> userMessages = new HashMap<>();
private final ManagerFactory managerFactory; private final ManagerFactory managerFactory;
private final ConcurrentHashMap<UUID, ChatSession> chatSessions = new ConcurrentHashMap<>(); private final ConcurrentHashMap<UUID, ChatSession> chatSessions = new ConcurrentHashMap<>();
private final ReadWriteLock lock = new ReentrantReadWriteLock(); private final ReadWriteLock lock = new ReentrantReadWriteLock();
public ChatManager(ManagerFactory managerFactory) { public ChatManagerImpl(ManagerFactory managerFactory) {
this.managerFactory = managerFactory; this.managerFactory = managerFactory;
} }

View file

@ -1,7 +1,7 @@
package mage.server; package mage.server;
import mage.server.managers.IConfigSettings; import mage.server.managers.ConfigSettings;
import mage.server.managers.IMailClient; import mage.server.managers.MailClient;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import javax.mail.Message; import javax.mail.Message;
@ -12,13 +12,13 @@ import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMessage;
import java.util.Properties; import java.util.Properties;
public class MailClient implements IMailClient { public class MailClientImpl implements MailClient {
private static final Logger logger = Logger.getLogger(Main.class); private static final Logger logger = Logger.getLogger(Main.class);
private final IConfigSettings config; private final ConfigSettings config;
public MailClient(IConfigSettings config) { public MailClientImpl(ConfigSettings config) {
this.config = config; this.config = config;
} }

View file

@ -5,19 +5,19 @@ import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource; import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
import com.sun.jersey.core.util.MultivaluedMapImpl; import com.sun.jersey.core.util.MultivaluedMapImpl;
import mage.server.managers.IConfigSettings; import mage.server.managers.ConfigSettings;
import mage.server.managers.IMailClient; import mage.server.managers.MailClient;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
public class MailgunClient implements IMailClient { public class MailgunClientImpl implements MailClient {
private static final Logger logger = Logger.getLogger(Main.class); private static final Logger logger = Logger.getLogger(Main.class);
private final IConfigSettings config; private final ConfigSettings config;
public MailgunClient(IConfigSettings config) { public MailgunClientImpl(ConfigSettings config) {
this.config = config; this.config = config;
} }

View file

@ -14,7 +14,7 @@ import mage.remote.Connection;
import mage.server.draft.CubeFactory; import mage.server.draft.CubeFactory;
import mage.server.game.GameFactory; import mage.server.game.GameFactory;
import mage.server.game.PlayerFactory; import mage.server.game.PlayerFactory;
import mage.server.managers.IConfigSettings; import mage.server.managers.ConfigSettings;
import mage.server.managers.ManagerFactory; import mage.server.managers.ManagerFactory;
import mage.server.record.UserStatsRepository; import mage.server.record.UserStatsRepository;
import mage.server.tournament.TournamentFactory; import mage.server.tournament.TournamentFactory;
@ -53,6 +53,11 @@ public final class Main {
private static final String testModeArg = "-testMode="; private static final String testModeArg = "-testMode=";
private static final String fastDBModeArg = "-fastDbMode="; private static final String fastDBModeArg = "-fastDbMode=";
private static final String adminPasswordArg = "-adminPassword="; private static final String adminPasswordArg = "-adminPassword=";
/**
* The property that holds the path to the configuration file. Defaults to "config/config.xml".
*
* To set up a different one, start the application with the java option "-Dxmage.config.path=&lt;path&gt;"
*/
private static final String configPathProp = "xmage.config.path"; private static final String configPathProp = "xmage.config.path";
private static final File pluginFolder = new File("plugins"); private static final File pluginFolder = new File("plugins");
@ -238,7 +243,7 @@ public final class Main {
ServerMessagesUtil.instance.setStartDate(System.currentTimeMillis()); ServerMessagesUtil.instance.setStartDate(System.currentTimeMillis());
} }
static boolean isAlreadyRunning(IConfigSettings config, InvokerLocator serverLocator) { static boolean isAlreadyRunning(ConfigSettings config, InvokerLocator serverLocator) {
Map<String, String> metadata = new HashMap<>(); Map<String, String> metadata = new HashMap<>();
metadata.put(SocketWrapper.WRITE_TIMEOUT, String.valueOf(config.getSocketWriteTimeout())); metadata.put(SocketWrapper.WRITE_TIMEOUT, String.valueOf(config.getSocketWriteTimeout()));
metadata.put("generalizeSocketException", "true"); metadata.put("generalizeSocketException", "true");

View file

@ -1,118 +1,124 @@
package mage.server; package mage.server;
import mage.server.draft.DraftManager; import mage.server.draft.DraftManagerImpl;
import mage.server.game.GameManager; import mage.server.game.GameManagerImpl;
import mage.server.game.GamesRoomManager; import mage.server.game.GamesRoomManagerImpl;
import mage.server.game.ReplayManager; import mage.server.game.ReplayManagerImpl;
import mage.server.managers.*; import mage.server.managers.*;
import mage.server.tournament.TournamentManager; import mage.server.tournament.TournamentManagerImpl;
import mage.server.util.ThreadExecutor; import mage.server.util.ThreadExecutorImpl;
public class MainManagerFactory implements ManagerFactory { public class MainManagerFactory implements ManagerFactory {
private final IConfigSettings configSettings; private final ConfigSettings configSettings;
private final IThreadExecutor threadExecutor; private final ThreadExecutor threadExecutor;
private final IChatManager chatManager; private final ChatManager chatManager;
private final IDraftManager draftManager; private final DraftManager draftManager;
private final IGameManager gameManager; private final GameManager gameManager;
private final IGamesRoomManager gamesRoomManager; private final GamesRoomManager gamesRoomManager;
private final IMailClient mailClient; private final MailClient mailClient;
private final IMailClient mailgunClient; private final MailClient mailgunClient;
private final IReplayManager replayManager; private final ReplayManager replayManager;
private final ISessionManager sessionManager; private final SessionManager sessionManager;
private final ITableManager tableManager; private final TableManager tableManager;
private final IUserManager userManager; private final UserManager userManager;
private final ITournamentManager tournamentManager; private final TournamentManager tournamentManager;
public MainManagerFactory(IConfigSettings configSettings) { public MainManagerFactory(ConfigSettings configSettings) {
this.configSettings = configSettings; this.configSettings = configSettings;
this.threadExecutor = new ThreadExecutor(configSettings); // ThreadExecutorImpl, MailClientImpl and MailGunClient depend only on the config, so they are initialised first
this.mailClient = new MailClient(configSettings); this.threadExecutor = new ThreadExecutorImpl(configSettings);
this.mailgunClient = new MailgunClient(configSettings); this.mailClient = new MailClientImpl(configSettings);
this.chatManager = new ChatManager(this); this.mailgunClient = new MailgunClientImpl(configSettings);
this.draftManager = new DraftManager(this); // Chat, Draft, Game, Replay, Session and Tournament managers only require access to the ManagerFactory
this.gameManager = new GameManager(this); // but do not use them in initialisation
this.replayManager = new ReplayManager(this); this.chatManager = new ChatManagerImpl(this);
this.sessionManager = new SessionManager(this); this.draftManager = new DraftManagerImpl(this);
this.tournamentManager = new TournamentManager(this); this.gameManager = new GameManagerImpl(this);
final GamesRoomManager gamesRoomManager = new GamesRoomManager(this); this.replayManager = new ReplayManagerImpl(this);
final TableManager tableManager = new TableManager(this); this.sessionManager = new SessionManagerImpl(this);
final UserManager userManager = new UserManager(this); this.tournamentManager = new TournamentManagerImpl(this);
// GamesRoom, Table, User managers depend on the ManagerFactory and have an initialisation block which is delayed
// to the end of the construction
final GamesRoomManagerImpl gamesRoomManager = new GamesRoomManagerImpl(this);
final TableManagerImpl tableManager = new TableManagerImpl(this);
final UserManagerImpl userManager = new UserManagerImpl(this);
this.gamesRoomManager = gamesRoomManager; this.gamesRoomManager = gamesRoomManager;
this.tableManager = tableManager; this.tableManager = tableManager;
this.userManager = userManager; this.userManager = userManager;
// execute the initialisation block of the relevant manager (they start the executor services)
startThreads(gamesRoomManager, tableManager, userManager); startThreads(gamesRoomManager, tableManager, userManager);
} }
private void startThreads(GamesRoomManager gamesRoomManager, TableManager tableManager, UserManager userManager) { private void startThreads(GamesRoomManagerImpl gamesRoomManager, TableManagerImpl tableManager, UserManagerImpl userManager) {
userManager.init(); userManager.init();
tableManager.init(); tableManager.init();
gamesRoomManager.init(); gamesRoomManager.init();
} }
@Override @Override
public IChatManager chatManager() { public ChatManager chatManager() {
return chatManager; return chatManager;
} }
@Override @Override
public IDraftManager draftManager() { public DraftManager draftManager() {
return draftManager; return draftManager;
} }
@Override @Override
public IGameManager gameManager() { public GameManager gameManager() {
return gameManager; return gameManager;
} }
@Override @Override
public IGamesRoomManager gamesRoomManager() { public GamesRoomManager gamesRoomManager() {
return gamesRoomManager; return gamesRoomManager;
} }
@Override @Override
public IMailClient mailClient() { public MailClient mailClient() {
return mailClient; return mailClient;
} }
@Override @Override
public IMailClient mailgunClient() { public MailClient mailgunClient() {
return mailgunClient; return mailgunClient;
} }
@Override @Override
public IReplayManager replayManager() { public ReplayManager replayManager() {
return replayManager; return replayManager;
} }
@Override @Override
public ISessionManager sessionManager() { public SessionManager sessionManager() {
return sessionManager; return sessionManager;
} }
@Override @Override
public ITableManager tableManager() { public TableManager tableManager() {
return tableManager; return tableManager;
} }
@Override @Override
public IUserManager userManager() { public UserManager userManager() {
return userManager; return userManager;
} }
@Override @Override
public IConfigSettings configSettings() { public ConfigSettings configSettings() {
return configSettings; return configSettings;
} }
@Override @Override
public IThreadExecutor threadExecutor() { public ThreadExecutor threadExecutor() {
return threadExecutor; return threadExecutor;
} }
@Override @Override
public ITournamentManager tournamentManager() { public TournamentManager tournamentManager() {
return tournamentManager; return tournamentManager;
} }
} }

View file

@ -1,6 +1,6 @@
package mage.server; package mage.server;
import mage.server.managers.IChatManager; import mage.server.managers.ChatManager;
import java.util.UUID; import java.util.UUID;
@ -12,7 +12,7 @@ public abstract class RoomImpl implements Room {
private final UUID chatId; private final UUID chatId;
private final UUID roomId; private final UUID roomId;
public RoomImpl(IChatManager chatManager) { public RoomImpl(ChatManager chatManager) {
roomId = UUID.randomUUID(); roomId = UUID.randomUUID();
chatId = chatManager.createChatSession("Room " + roomId); chatId = chatManager.createChatSession("Room " + roomId);
} }

View file

@ -7,7 +7,7 @@ import mage.interfaces.callback.ClientCallbackMethod;
import mage.players.net.UserData; import mage.players.net.UserData;
import mage.players.net.UserGroup; import mage.players.net.UserGroup;
import mage.server.game.GamesRoom; import mage.server.game.GamesRoom;
import mage.server.managers.IConfigSettings; import mage.server.managers.ConfigSettings;
import mage.server.managers.ManagerFactory; import mage.server.managers.ManagerFactory;
import mage.server.util.SystemUtil; import mage.server.util.SystemUtil;
import mage.util.RandomUtil; import mage.util.RandomUtil;
@ -115,7 +115,7 @@ public class Session {
if (userName.equals("Admin")) { if (userName.equals("Admin")) {
return "User name Admin already in use"; return "User name Admin already in use";
} }
IConfigSettings config = managerFactory.configSettings(); ConfigSettings config = managerFactory.configSettings();
if (userName.length() < config.getMinUserNameLength()) { if (userName.length() < config.getMinUserNameLength()) {
return "User name may not be shorter than " + config.getMinUserNameLength() + " characters"; return "User name may not be shorter than " + config.getMinUserNameLength() + " characters";
} }
@ -135,7 +135,7 @@ public class Session {
} }
private String validatePassword(String password, String userName) { private String validatePassword(String password, String userName) {
IConfigSettings config = managerFactory.configSettings(); ConfigSettings config = managerFactory.configSettings();
if (password.length() < config.getMinPasswordLength()) { if (password.length() < config.getMinPasswordLength()) {
return "Password may not be shorter than " + config.getMinPasswordLength() + " characters"; return "Password may not be shorter than " + config.getMinPasswordLength() + " characters";
} }

View file

@ -2,7 +2,7 @@ package mage.server;
import mage.MageException; import mage.MageException;
import mage.players.net.UserData; import mage.players.net.UserData;
import mage.server.managers.ISessionManager; import mage.server.managers.SessionManager;
import mage.server.managers.ManagerFactory; import mage.server.managers.ManagerFactory;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.jboss.remoting.callback.InvokerCallbackHandler; import org.jboss.remoting.callback.InvokerCallbackHandler;
@ -14,14 +14,14 @@ import java.util.concurrent.ConcurrentHashMap;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class SessionManager implements ISessionManager { public class SessionManagerImpl implements SessionManager {
private static final Logger logger = Logger.getLogger(SessionManager.class); private static final Logger logger = Logger.getLogger(SessionManagerImpl.class);
private final ManagerFactory managerFactory; private final ManagerFactory managerFactory;
private final ConcurrentHashMap<String, Session> sessions = new ConcurrentHashMap<>(); private final ConcurrentHashMap<String, Session> sessions = new ConcurrentHashMap<>();
public SessionManager(ManagerFactory managerFactory) { public SessionManagerImpl(ManagerFactory managerFactory) {
this.managerFactory = managerFactory; this.managerFactory = managerFactory;
} }

View file

@ -84,7 +84,7 @@ public class TableController {
if (userId != null) { if (userId != null) {
Optional<User> user = managerFactory.userManager().getUser(userId); Optional<User> user = managerFactory.userManager().getUser(userId);
if (!user.isPresent()) { if (!user.isPresent()) {
logger.fatal(new StringBuilder("User for userId ").append(userId).append(" could not be retrieved from UserManager").toString()); logger.fatal(new StringBuilder("User for userId ").append(userId).append(" could not be retrieved from UserManagerImpl").toString());
controllerName = "[unknown]"; controllerName = "[unknown]";
} else { } else {
controllerName = user.get().getName(); controllerName = user.get().getName();

View file

@ -14,7 +14,7 @@ import mage.game.tournament.TournamentOptions;
import mage.game.tournament.TournamentPlayer; import mage.game.tournament.TournamentPlayer;
import mage.players.PlayerType; import mage.players.PlayerType;
import mage.server.game.GameController; import mage.server.game.GameController;
import mage.server.managers.ITableManager; import mage.server.managers.TableManager;
import mage.server.managers.ManagerFactory; import mage.server.managers.ManagerFactory;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -33,12 +33,12 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class TableManager implements ITableManager { public class TableManagerImpl implements TableManager {
protected final ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor(); protected final ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor();
// protected static ScheduledExecutorService expireExecutor = ThreadExecutor.getInstance().getExpireExecutor(); // protected static ScheduledExecutorService expireExecutor = ThreadExecutorImpl.getInstance().getExpireExecutor();
private final ManagerFactory managerFactory; private final ManagerFactory managerFactory;
private final Logger logger = Logger.getLogger(TableManager.class); private final Logger logger = Logger.getLogger(TableManagerImpl.class);
private final DateFormat formatter = new SimpleDateFormat("HH:mm:ss"); private final DateFormat formatter = new SimpleDateFormat("HH:mm:ss");
private final ConcurrentHashMap<UUID, TableController> controllers = new ConcurrentHashMap<>(); private final ConcurrentHashMap<UUID, TableController> controllers = new ConcurrentHashMap<>();
@ -54,7 +54,7 @@ public class TableManager implements ITableManager {
*/ */
private static final int EXPIRE_CHECK_PERIOD = 10; private static final int EXPIRE_CHECK_PERIOD = 10;
public TableManager(ManagerFactory managerFactory) { public TableManagerImpl(ManagerFactory managerFactory) {
this.managerFactory = managerFactory; this.managerFactory = managerFactory;
} }
@ -206,7 +206,7 @@ public class TableManager implements ITableManager {
controller.leaveTable(userId); controller.leaveTable(userId);
} }
} else { } else {
logger.error("TableManager.userQuitTournamentSubTables table == null - userId " + userId); logger.error("TableManagerImpl.userQuitTournamentSubTables table == null - userId " + userId);
} }
} }
} }

View file

@ -1,7 +1,7 @@
package mage.server; package mage.server;
import mage.server.User.UserState; import mage.server.User.UserState;
import mage.server.managers.IUserManager; import mage.server.managers.UserManager;
import mage.server.managers.ManagerFactory; import mage.server.managers.ManagerFactory;
import mage.server.record.UserStats; import mage.server.record.UserStats;
import mage.server.record.UserStatsRepository; import mage.server.record.UserStatsRepository;
@ -20,13 +20,13 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class UserManager implements IUserManager { public class UserManagerImpl implements UserManager {
private static final int SERVER_TIMEOUTS_USER_INFORM_OPPONENTS_ABOUT_DISCONNECT_AFTER_SECS = 30; // send to chat info about disconnection troubles, must be more than ping timeout private static final int SERVER_TIMEOUTS_USER_INFORM_OPPONENTS_ABOUT_DISCONNECT_AFTER_SECS = 30; // send to chat info about disconnection troubles, must be more than ping timeout
private static final int SERVER_TIMEOUTS_USER_DISCONNECT_FROM_SERVER_AFTER_SECS = 3 * 60; // removes from all games and chats too (can be seen in users list with disconnected status) private static final int SERVER_TIMEOUTS_USER_DISCONNECT_FROM_SERVER_AFTER_SECS = 3 * 60; // removes from all games and chats too (can be seen in users list with disconnected status)
private static final int SERVER_TIMEOUTS_USER_REMOVE_FROM_SERVER_AFTER_SECS = 8 * 60; // removes from users list private static final int SERVER_TIMEOUTS_USER_REMOVE_FROM_SERVER_AFTER_SECS = 8 * 60; // removes from users list
private static final Logger logger = Logger.getLogger(UserManager.class); private static final Logger logger = Logger.getLogger(UserManagerImpl.class);
protected final ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor(); protected final ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor();
protected final ScheduledExecutorService userListExecutor = Executors.newSingleThreadScheduledExecutor(); protected final ScheduledExecutorService userListExecutor = Executors.newSingleThreadScheduledExecutor();
@ -40,7 +40,7 @@ public class UserManager implements IUserManager {
private ExecutorService USER_EXECUTOR; private ExecutorService USER_EXECUTOR;
public UserManager(ManagerFactory managerFactory) { public UserManagerImpl(ManagerFactory managerFactory) {
this.managerFactory = managerFactory; this.managerFactory = managerFactory;
} }

View file

@ -1,7 +1,7 @@
package mage.server.draft; package mage.server.draft;
import mage.game.draft.Draft; import mage.game.draft.Draft;
import mage.server.managers.IDraftManager; import mage.server.managers.DraftManager;
import mage.server.managers.ManagerFactory; import mage.server.managers.ManagerFactory;
import mage.view.DraftPickView; import mage.view.DraftPickView;
@ -14,12 +14,12 @@ import java.util.concurrent.ConcurrentMap;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class DraftManager implements IDraftManager { public class DraftManagerImpl implements DraftManager {
private final ManagerFactory managerFactory; private final ManagerFactory managerFactory;
private final ConcurrentMap<UUID, DraftController> draftControllers = new ConcurrentHashMap<>(); private final ConcurrentMap<UUID, DraftController> draftControllers = new ConcurrentHashMap<>();
public DraftManager(ManagerFactory managerFactory) { public DraftManagerImpl(ManagerFactory managerFactory) {
this.managerFactory = managerFactory; this.managerFactory = managerFactory;
} }

View file

@ -5,7 +5,7 @@ import mage.constants.ManaType;
import mage.constants.PlayerAction; import mage.constants.PlayerAction;
import mage.game.Game; import mage.game.Game;
import mage.game.GameOptions; import mage.game.GameOptions;
import mage.server.managers.IGameManager; import mage.server.managers.GameManager;
import mage.server.managers.ManagerFactory; import mage.server.managers.ManagerFactory;
import mage.view.GameView; import mage.view.GameView;
@ -22,13 +22,13 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class GameManager implements IGameManager { public class GameManagerImpl implements GameManager {
private final ManagerFactory managerFactory; private final ManagerFactory managerFactory;
private final ConcurrentMap<UUID, GameController> gameControllers = new ConcurrentHashMap<>(); private final ConcurrentMap<UUID, GameController> gameControllers = new ConcurrentHashMap<>();
private final ReadWriteLock gameControllersLock = new ReentrantReadWriteLock(); private final ReadWriteLock gameControllersLock = new ReentrantReadWriteLock();
public GameManager(ManagerFactory managerFactory) { public GameManagerImpl(ManagerFactory managerFactory) {
this.managerFactory = managerFactory; this.managerFactory = managerFactory;
} }

View file

@ -11,7 +11,7 @@ import mage.interfaces.callback.ClientCallback;
import mage.interfaces.callback.ClientCallbackMethod; import mage.interfaces.callback.ClientCallbackMethod;
import mage.players.Player; import mage.players.Player;
import mage.server.User; import mage.server.User;
import mage.server.managers.IUserManager; import mage.server.managers.UserManager;
import mage.server.managers.ManagerFactory; import mage.server.managers.ManagerFactory;
import mage.view.*; import mage.view.*;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -28,7 +28,7 @@ public class GameSessionPlayer extends GameSessionWatcher {
private static final Logger logger = Logger.getLogger(GameSessionPlayer.class); private static final Logger logger = Logger.getLogger(GameSessionPlayer.class);
private final IUserManager userManager; private final UserManager userManager;
private final UUID playerId; private final UUID playerId;
private final ExecutorService callExecutor; private final ExecutorService callExecutor;

View file

@ -6,7 +6,7 @@ import mage.interfaces.callback.ClientCallback;
import mage.interfaces.callback.ClientCallbackMethod; import mage.interfaces.callback.ClientCallbackMethod;
import mage.players.Player; import mage.players.Player;
import mage.server.User; import mage.server.User;
import mage.server.managers.IUserManager; import mage.server.managers.UserManager;
import mage.view.GameClientMessage; import mage.view.GameClientMessage;
import mage.view.GameEndView; import mage.view.GameEndView;
import mage.view.GameView; import mage.view.GameView;
@ -25,13 +25,13 @@ public class GameSessionWatcher {
protected static final Logger logger = Logger.getLogger(GameSessionWatcher.class); protected static final Logger logger = Logger.getLogger(GameSessionWatcher.class);
private final IUserManager userManager; private final UserManager userManager;
protected final UUID userId; protected final UUID userId;
protected final Game game; protected final Game game;
protected boolean killed = false; protected boolean killed = false;
protected final boolean isPlayer; protected final boolean isPlayer;
public GameSessionWatcher(IUserManager userManager, UUID userId, Game game, boolean isPlayer) { public GameSessionWatcher(UserManager userManager, UUID userId, Game game, boolean isPlayer) {
this.userManager = userManager; this.userManager = userManager;
this.userId = userId; this.userId = userId;
this.game = game; this.game = game;

View file

@ -1,6 +1,6 @@
package mage.server.game; package mage.server.game;
import mage.server.managers.IGamesRoomManager; import mage.server.managers.GamesRoomManager;
import mage.server.managers.ManagerFactory; import mage.server.managers.ManagerFactory;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -11,16 +11,16 @@ import java.util.concurrent.ConcurrentHashMap;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class GamesRoomManager implements IGamesRoomManager { public class GamesRoomManagerImpl implements GamesRoomManager {
private final ManagerFactory managerFactory; private final ManagerFactory managerFactory;
private final ConcurrentHashMap<UUID, GamesRoom> rooms = new ConcurrentHashMap<>(); private final ConcurrentHashMap<UUID, GamesRoom> rooms = new ConcurrentHashMap<>();
private UUID mainRoomId; private UUID mainRoomId;
private UUID mainChatId; private UUID mainChatId;
private static final Logger logger = Logger.getLogger(GamesRoomManager.class); private static final Logger logger = Logger.getLogger(GamesRoomManagerImpl.class);
public GamesRoomManager(ManagerFactory managerFactory) { public GamesRoomManagerImpl(ManagerFactory managerFactory) {
this.managerFactory = managerFactory; this.managerFactory = managerFactory;
} }

View file

@ -1,6 +1,6 @@
package mage.server.game; package mage.server.game;
import mage.server.managers.IReplayManager; import mage.server.managers.ReplayManager;
import mage.server.managers.ManagerFactory; import mage.server.managers.ManagerFactory;
import java.util.UUID; import java.util.UUID;
@ -9,12 +9,12 @@ import java.util.concurrent.ConcurrentHashMap;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class ReplayManager implements IReplayManager { public class ReplayManagerImpl implements ReplayManager {
private final ConcurrentHashMap<String, ReplaySession> replaySessions = new ConcurrentHashMap<>(); private final ConcurrentHashMap<String, ReplaySession> replaySessions = new ConcurrentHashMap<>();
private final ManagerFactory managerFactory; private final ManagerFactory managerFactory;
public ReplayManager(ManagerFactory managerFactory) { public ReplayManagerImpl(ManagerFactory managerFactory) {
this.managerFactory = managerFactory; this.managerFactory = managerFactory;
} }

View file

@ -9,7 +9,7 @@ import mage.view.ChatMessage;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
public interface IChatManager { public interface ChatManager {
UUID createChatSession(String info); UUID createChatSession(String info);
void joinChat(UUID chatId, UUID userId); void joinChat(UUID chatId, UUID userId);

View file

@ -5,7 +5,7 @@ import mage.server.util.config.Plugin;
import java.util.List; import java.util.List;
public interface IConfigSettings { public interface ConfigSettings {
String getServerAddress(); String getServerAddress();
String getServerName(); String getServerName();

View file

@ -9,7 +9,7 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
public interface IDraftManager { public interface DraftManager {
UUID createDraftSession(Draft draft, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId); UUID createDraftSession(Draft draft, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId);
void joinDraft(UUID draftId, UUID userId); void joinDraft(UUID draftId, UUID userId);

View file

@ -13,7 +13,7 @@ import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
public interface IGameManager { public interface GameManager {
UUID createGameSession(Game game, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId, UUID choosingPlayerId, GameOptions gameOptions); UUID createGameSession(Game game, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId, UUID choosingPlayerId, GameOptions gameOptions);
void joinGame(UUID gameId, UUID userId); void joinGame(UUID gameId, UUID userId);

View file

@ -5,7 +5,7 @@ import mage.server.game.GamesRoom;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
public interface IGamesRoomManager { public interface GamesRoomManager {
UUID createRoom(); UUID createRoom();
UUID getMainRoomId(); UUID getMainRoomId();

View file

@ -1,6 +1,6 @@
package mage.server.managers; package mage.server.managers;
public interface IMailClient { public interface MailClient {
boolean sendMessage(String email, String subject, String text); boolean sendMessage(String email, String subject, String text);

View file

@ -1,29 +1,29 @@
package mage.server.managers; package mage.server.managers;
public interface ManagerFactory { public interface ManagerFactory {
IChatManager chatManager(); ChatManager chatManager();
IDraftManager draftManager(); DraftManager draftManager();
IGameManager gameManager(); GameManager gameManager();
IGamesRoomManager gamesRoomManager(); GamesRoomManager gamesRoomManager();
IMailClient mailClient(); MailClient mailClient();
IMailClient mailgunClient(); MailClient mailgunClient();
IReplayManager replayManager(); ReplayManager replayManager();
ISessionManager sessionManager(); SessionManager sessionManager();
ITableManager tableManager(); TableManager tableManager();
IUserManager userManager(); UserManager userManager();
IConfigSettings configSettings(); ConfigSettings configSettings();
IThreadExecutor threadExecutor(); ThreadExecutor threadExecutor();
ITournamentManager tournamentManager(); TournamentManager tournamentManager();
} }

View file

@ -2,7 +2,7 @@ package mage.server.managers;
import java.util.UUID; import java.util.UUID;
public interface IReplayManager { public interface ReplayManager {
void replayGame(UUID gameId, UUID userId); void replayGame(UUID gameId, UUID userId);
void startReplay(UUID gameId, UUID userId); void startReplay(UUID gameId, UUID userId);

View file

@ -10,7 +10,7 @@ import org.jboss.remoting.callback.InvokerCallbackHandler;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.Optional; import java.util.Optional;
public interface ISessionManager { public interface SessionManager {
Optional<Session> getSession(@Nonnull String sessionId); Optional<Session> getSession(@Nonnull String sessionId);
void createSession(String sessionId, InvokerCallbackHandler callbackHandler); void createSession(String sessionId, InvokerCallbackHandler callbackHandler);

View file

@ -17,7 +17,7 @@ import java.util.Collection;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
public interface ITableManager { public interface TableManager {
Table createTable(UUID roomId, UUID userId, MatchOptions options); Table createTable(UUID roomId, UUID userId, MatchOptions options);
Table createTable(UUID roomId, MatchOptions options); Table createTable(UUID roomId, MatchOptions options);

View file

@ -3,7 +3,7 @@ package mage.server.managers;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
public interface IThreadExecutor { public interface ThreadExecutor {
int getActiveThreads(ExecutorService executerService); int getActiveThreads(ExecutorService executerService);
ExecutorService getCallExecutor(); ExecutorService getCallExecutor();

View file

@ -9,7 +9,7 @@ import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
public interface ITournamentManager { public interface TournamentManager {
Optional<TournamentController> getTournamentController(UUID tournamentId); Optional<TournamentController> getTournamentController(UUID tournamentId);
void createTournamentSession(Tournament tournament, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId); void createTournamentSession(Tournament tournament, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId);

View file

@ -10,7 +10,7 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
public interface IUserManager { public interface UserManager {
Optional<User> createUser(String userName, String host, AuthorizedUser authorizedUser); Optional<User> createUser(String userName, String host, AuthorizedUser authorizedUser);
Optional<User> getUser(UUID userId); Optional<User> getUser(UUID userId);

View file

@ -3,13 +3,13 @@ package mage.server.record;
import mage.game.Table; import mage.game.Table;
import mage.game.Table.TableRecorder; import mage.game.Table.TableRecorder;
import mage.game.result.ResultProtos.TableProto; import mage.game.result.ResultProtos.TableProto;
import mage.server.managers.IUserManager; import mage.server.managers.UserManager;
public class TableRecorderImpl implements TableRecorder { public class TableRecorderImpl implements TableRecorder {
private final IUserManager userManager; private final UserManager userManager;
public TableRecorderImpl(IUserManager userManager) { public TableRecorderImpl(UserManager userManager) {
this.userManager = userManager; this.userManager = userManager;
} }

View file

@ -19,7 +19,7 @@ import mage.game.tournament.TournamentPlayer;
import mage.players.PlayerType; import mage.players.PlayerType;
import mage.server.User; import mage.server.User;
import mage.server.draft.DraftController; import mage.server.draft.DraftController;
import mage.server.managers.ITableManager; import mage.server.managers.TableManager;
import mage.server.managers.ManagerFactory; import mage.server.managers.ManagerFactory;
import mage.view.ChatMessage.MessageColor; import mage.view.ChatMessage.MessageColor;
import mage.view.ChatMessage.MessageType; import mage.view.ChatMessage.MessageType;
@ -216,7 +216,7 @@ public class TournamentController {
private void startMatch(TournamentPairing pair, MatchOptions matchOptions) { private void startMatch(TournamentPairing pair, MatchOptions matchOptions) {
try { try {
ITableManager tableManager = managerFactory.tableManager(); TableManager tableManager = managerFactory.tableManager();
Table table = tableManager.createTable(managerFactory.gamesRoomManager().getMainRoomId(), matchOptions); Table table = tableManager.createTable(managerFactory.gamesRoomManager().getMainRoomId(), matchOptions);
table.setTournamentSubTable(true); table.setTournamentSubTable(true);
table.setTournament(tournament); table.setTournament(tournament);
@ -259,7 +259,7 @@ public class TournamentController {
private void startMultiplayerMatch(MultiplayerRound round, MatchOptions matchOptions) { private void startMultiplayerMatch(MultiplayerRound round, MatchOptions matchOptions) {
try { try {
ITableManager tableManager = managerFactory.tableManager(); TableManager tableManager = managerFactory.tableManager();
Table table = tableManager.createTable(managerFactory.gamesRoomManager().getMainRoomId(), matchOptions); Table table = tableManager.createTable(managerFactory.gamesRoomManager().getMainRoomId(), matchOptions);
table.setTournamentSubTable(true); table.setTournamentSubTable(true);
table.setTournament(tournament); table.setTournament(tournament);

View file

@ -2,7 +2,7 @@ package mage.server.tournament;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.game.tournament.Tournament; import mage.game.tournament.Tournament;
import mage.server.managers.ITournamentManager; import mage.server.managers.TournamentManager;
import mage.server.managers.ManagerFactory; import mage.server.managers.ManagerFactory;
import mage.view.TournamentView; import mage.view.TournamentView;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -15,12 +15,12 @@ import java.util.concurrent.ConcurrentMap;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class TournamentManager implements ITournamentManager { public class TournamentManagerImpl implements TournamentManager {
private final ManagerFactory managerFactory; private final ManagerFactory managerFactory;
private final ConcurrentMap<UUID, TournamentController> controllers = new ConcurrentHashMap<>(); private final ConcurrentMap<UUID, TournamentController> controllers = new ConcurrentHashMap<>();
public TournamentManager(ManagerFactory managerFactory) { public TournamentManagerImpl(ManagerFactory managerFactory) {
this.managerFactory = managerFactory; this.managerFactory = managerFactory;
} }
@ -46,7 +46,7 @@ public class TournamentManager implements ITournamentManager {
if (tournamentController != null) { if (tournamentController != null) {
tournamentController.quit(userId); tournamentController.quit(userId);
} else { } else {
Logger.getLogger(TournamentManager.class).error("Tournament controller missing tournamentid: " + tournamentId + " userId: " + userId); Logger.getLogger(TournamentManagerImpl.class).error("Tournament controller missing tournamentid: " + tournamentId + " userId: " + userId);
} }
} }

View file

@ -1,13 +1,13 @@
package mage.server.util; package mage.server.util;
import mage.server.managers.IConfigSettings; import mage.server.managers.ConfigSettings;
import mage.server.util.config.Config; import mage.server.util.config.Config;
import mage.server.util.config.GamePlugin; import mage.server.util.config.GamePlugin;
import mage.server.util.config.Plugin; import mage.server.util.config.Plugin;
import java.util.List; import java.util.List;
public class ConfigWrapper implements IConfigSettings { public class ConfigWrapper implements ConfigSettings {
private final Config config; private final Config config;

View file

@ -1,14 +1,14 @@
package mage.server.util; package mage.server.util;
import mage.server.managers.IConfigSettings; import mage.server.managers.ConfigSettings;
import mage.server.managers.IThreadExecutor; import mage.server.managers.ThreadExecutor;
import java.util.concurrent.*; import java.util.concurrent.*;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class ThreadExecutor implements IThreadExecutor { public class ThreadExecutorImpl implements ThreadExecutor {
private final ExecutorService callExecutor; private final ExecutorService callExecutor;
private final ExecutorService gameExecutor; private final ExecutorService gameExecutor;
private final ScheduledExecutorService timeoutExecutor; private final ScheduledExecutorService timeoutExecutor;
@ -25,7 +25,7 @@ public class ThreadExecutor implements IThreadExecutor {
* resource consuming process. * resource consuming process.
*/ */
public ThreadExecutor(IConfigSettings config) { public ThreadExecutorImpl(ConfigSettings config) {
callExecutor = Executors.newCachedThreadPool(); callExecutor = Executors.newCachedThreadPool();
gameExecutor = Executors.newFixedThreadPool(config.getMaxGameThreads()); gameExecutor = Executors.newFixedThreadPool(config.getMaxGameThreads());
timeoutExecutor = Executors.newScheduledThreadPool(4); timeoutExecutor = Executors.newScheduledThreadPool(4);

View file

@ -4,6 +4,8 @@ import mage.server.util.config.Config;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.nio.file.Paths;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@ -22,7 +24,7 @@ public class ConfigFactoryTest {
@DisplayName("should fail if config is malformed") @DisplayName("should fail if config is malformed")
void failOnMalformed() { void failOnMalformed() {
assertThatExceptionOfType(ConfigurationException.class) assertThatExceptionOfType(ConfigurationException.class)
.isThrownBy(() -> ConfigFactory.loadFromFile("config/config_error.xml")); .isThrownBy(() -> ConfigFactory.loadFromFile(Paths.get("src", "test", "resources", "config_error.xml").toString()));
} }
@Test @Test

View file

@ -14,7 +14,7 @@ import mage.players.Player;
import mage.players.PlayerType; import mage.players.PlayerType;
import mage.server.game.GameFactory; import mage.server.game.GameFactory;
import mage.server.game.PlayerFactory; import mage.server.game.PlayerFactory;
import mage.server.managers.IConfigSettings; import mage.server.managers.ConfigSettings;
import mage.server.tournament.TournamentFactory; import mage.server.tournament.TournamentFactory;
import mage.server.util.ConfigFactory; import mage.server.util.ConfigFactory;
import mage.server.util.ConfigWrapper; import mage.server.util.ConfigWrapper;
@ -102,7 +102,7 @@ public abstract class MageTestBase {
public static void init() { public static void init() {
Logger.getRootLogger().setLevel(Level.DEBUG); Logger.getRootLogger().setLevel(Level.DEBUG);
deleteSavedGames(); deleteSavedGames();
IConfigSettings config = new ConfigWrapper(ConfigFactory.loadFromFile("config/config.xml")); ConfigSettings config = new ConfigWrapper(ConfigFactory.loadFromFile("config/config.xml"));
config.getGameTypes().forEach((gameType) -> { config.getGameTypes().forEach((gameType) -> {
GameFactory.instance.addGameType(gameType.getName(), loadGameType(gameType), loadPlugin(gameType)); GameFactory.instance.addGameType(gameType.getName(), loadGameType(gameType), loadPlugin(gameType));
}); });

View file

@ -23,7 +23,7 @@ import mage.game.permanent.PermanentCard;
import mage.game.tournament.TournamentType; import mage.game.tournament.TournamentType;
import mage.players.Player; import mage.players.Player;
import mage.server.game.GameFactory; import mage.server.game.GameFactory;
import mage.server.managers.IConfigSettings; import mage.server.managers.ConfigSettings;
import mage.server.util.ConfigFactory; import mage.server.util.ConfigFactory;
import mage.server.util.ConfigWrapper; import mage.server.util.ConfigWrapper;
import mage.server.util.PluginClassLoader; import mage.server.util.PluginClassLoader;
@ -116,7 +116,7 @@ public abstract class MageTestPlayerBase {
logger.debug("Default charset: " + Charset.defaultCharset()); logger.debug("Default charset: " + Charset.defaultCharset());
deleteSavedGames(); deleteSavedGames();
IConfigSettings config = new ConfigWrapper(ConfigFactory.loadFromFile("config/config.xml")); ConfigSettings config = new ConfigWrapper(ConfigFactory.loadFromFile("config/config.xml"));
for (GamePlugin plugin : config.getGameTypes()) { for (GamePlugin plugin : config.getGameTypes()) {
GameFactory.instance.addGameType(plugin.getName(), loadGameType(plugin), loadPlugin(plugin)); GameFactory.instance.addGameType(plugin.getName(), loadGameType(plugin), loadPlugin(plugin));
} }

View file

@ -58,6 +58,13 @@ Look [here](http://www.slightlymagic.net/forum/viewtopic.php?f=70&t=13632) for m
[Wiki page](https://github.com/magefree/mage/wiki) contains detail information about private or public server setup. [Wiki page](https://github.com/magefree/mage/wiki) contains detail information about private or public server setup.
### Server options
The XMage server locates by default the configuration file from the current working directory to the relative path `config/config.xml`
(`config\config.xml` in Windows). To change this location, start the server with the property `xmage.config.path` set
to the desired location, for example `-Dxmage.config.path=config/otherconfig.xml`. The option can be set from the
XMageLauncher in `Settings > Java > Server java options`.
## Troubleshooting / FAQ ## Troubleshooting / FAQ
Github issues page contain [popular problems and fixes](https://github.com/magefree/mage/issues?q=is%3Aissue+label%3AFAQ+): Github issues page contain [popular problems and fixes](https://github.com/magefree/mage/issues?q=is%3Aissue+label%3AFAQ+):