From cf3dd2d94cf948ce55c9e2377625c2e718243c2d Mon Sep 17 00:00:00 2001 From: Francesco Burato Date: Fri, 30 Oct 2020 13:37:01 +0000 Subject: [PATCH 1/4] [app-wiring-refactor]: Define external configuration --- Mage.Common/pom.xml | 20 +- .../main/java/mage/utils/FluentBuilder.java | 36 +++ .../test/java/mage/remote/ConnectionTest.java | 123 ++++++++ .../java/mage/utils/FluentBuilderTest.java | 116 +++++++ Mage.Server/config/config_error.xml | 173 +++++++++++ Mage.Server/pom.xml | 16 + .../java/mage/server/util/ConfigFactory.java | 20 ++ .../java/mage/server/util/ConfigSettings.java | 2 +- .../server/util/ConfigSettingsContract.java | 72 +++++ .../java/mage/server/util/ConfigWrapper.java | 145 +++++++++ .../server/util/ConfigurationException.java | 7 + .../mage/server/util/ConfigFactoryTest.java | 34 ++ .../mage/server/util/ConfigWrapperTest.java | 294 ++++++++++++++++++ pom.xml | 27 ++ 14 files changed, 1083 insertions(+), 2 deletions(-) create mode 100644 Mage.Common/src/main/java/mage/utils/FluentBuilder.java create mode 100644 Mage.Common/src/test/java/mage/remote/ConnectionTest.java create mode 100644 Mage.Common/src/test/java/mage/utils/FluentBuilderTest.java create mode 100644 Mage.Server/config/config_error.xml create mode 100644 Mage.Server/src/main/java/mage/server/util/ConfigFactory.java create mode 100644 Mage.Server/src/main/java/mage/server/util/ConfigSettingsContract.java create mode 100644 Mage.Server/src/main/java/mage/server/util/ConfigWrapper.java create mode 100644 Mage.Server/src/main/java/mage/server/util/ConfigurationException.java create mode 100644 Mage.Server/src/test/java/mage/server/util/ConfigFactoryTest.java create mode 100644 Mage.Server/src/test/java/mage/server/util/ConfigWrapperTest.java diff --git a/Mage.Common/pom.xml b/Mage.Common/pom.xml index f6b346f88c..a84170a4a9 100644 --- a/Mage.Common/pom.xml +++ b/Mage.Common/pom.xml @@ -56,6 +56,21 @@ gson 2.8.6 + + org.junit.jupiter + junit-jupiter + test + + + org.assertj + assertj-core + test + + + org.apache.commons + commons-lang3 + test + @@ -82,7 +97,10 @@ UTF-8 - + + org.apache.maven.plugins + maven-surefire-plugin + mage-common diff --git a/Mage.Common/src/main/java/mage/utils/FluentBuilder.java b/Mage.Common/src/main/java/mage/utils/FluentBuilder.java new file mode 100644 index 0000000000..3e4ab75b91 --- /dev/null +++ b/Mage.Common/src/main/java/mage/utils/FluentBuilder.java @@ -0,0 +1,36 @@ +package mage.utils; + +import java.util.ArrayList; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public abstract class FluentBuilder> { + + final ArrayList> buildSequence; + private final Supplier newReference; + + protected FluentBuilder(Supplier newReference) { + this.buildSequence = new ArrayList<>(); + this.newReference = newReference; + } + + private RealBuilder copy() { + final RealBuilder realBuilder = newReference.get(); + realBuilder.buildSequence.addAll(buildSequence); + return realBuilder; + } + + protected abstract ToBuild makeValue(); + + public RealBuilder with(Consumer consumer) { + final RealBuilder nextBuilder = this.copy(); + nextBuilder.buildSequence.add(consumer); + return nextBuilder; + } + + public ToBuild build() { + final RealBuilder instance = this.copy(); + instance.buildSequence.forEach(c -> c.accept(instance)); + return instance.makeValue(); + } +} \ No newline at end of file diff --git a/Mage.Common/src/test/java/mage/remote/ConnectionTest.java b/Mage.Common/src/test/java/mage/remote/ConnectionTest.java new file mode 100644 index 0000000000..1e49ed9c37 --- /dev/null +++ b/Mage.Common/src/test/java/mage/remote/ConnectionTest.java @@ -0,0 +1,123 @@ +package mage.remote; + +import mage.utils.FluentBuilder; +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.RandomUtils; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.net.URI; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ConnectionTest { + + static class ConnectionBuilder extends FluentBuilder { + + public int port; + public String host; + public String parameter; + + private ConnectionBuilder() { + super(ConnectionBuilder::new); + } + + @Override + protected Connection makeValue() { + final Connection result = new Connection(parameter); + result.setHost(host); + result.setPort(port); + return result; + } + } + + private ConnectionBuilder baseBuilder() { + return new ConnectionBuilder(); + } + + class TestsTemplate { + final ConnectionBuilder testeeBuilder; + + TestsTemplate(ConnectionBuilder testeeBuilder) { + this.testeeBuilder = testeeBuilder; + } + + @Test + @DisplayName("produce the expected scheme") + void scheme() throws Exception { + final URI testee = make(testeeBuilder); + assertThat(testee.getScheme()).isEqualTo("bisocket"); + } + + URI make(ConnectionBuilder builder) { + try { + return new URI(builder.build().getURI()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + @DisplayName("generate the expected port") + void port() { + final int expected = RandomUtils.nextInt(1000, 65000); + final int port = make(testeeBuilder.with(c -> c.port = expected)).getPort(); + + assertThat(port).isEqualTo(expected); + } + + @Test + @DisplayName("generate the expected serialisation parameter") + void serialisation() { + final String query = make(testeeBuilder).getQuery(); + + assertThat(query).contains("serializationtype=jboss"); + } + + @Test + @DisplayName("generate the expected threadpool parameter") + void threadpool() { + final String parameter = RandomStringUtils.randomAlphanumeric(12); + final String query = make(testeeBuilder.with(c -> c.parameter = parameter)).getQuery(); + + assertThat(query).contains("onewayThreadPool=mage.remote.CustomThreadPool" + parameter); + } + + } + + @Nested + @DisplayName("getUri when host is localhost should") + class LocalhostTest extends TestsTemplate { + + LocalhostTest() { + super(baseBuilder().with(c -> c.host = "localhost")); + } + + @Test + @DisplayName("generate an ipv4 as host") + void ipv4Gen() { + final String host = make(testeeBuilder).getHost(); + + assertThat(host).matches("[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+"); + } + } + + private final String randomHost = RandomStringUtils.randomAlphabetic(15); + + @Nested + @DisplayName("getUri when host is not localhost should") + class StandardHostTest extends TestsTemplate { + StandardHostTest() { + super(baseBuilder().with(c -> c.host = randomHost)); + } + + @Test + @DisplayName("generate the selected host as host") + void hostGen() { + final String host = make(testeeBuilder).getHost(); + + assertThat(host).isEqualTo(randomHost); + } + } +} diff --git a/Mage.Common/src/test/java/mage/utils/FluentBuilderTest.java b/Mage.Common/src/test/java/mage/utils/FluentBuilderTest.java new file mode 100644 index 0000000000..180f82ef20 --- /dev/null +++ b/Mage.Common/src/test/java/mage/utils/FluentBuilderTest.java @@ -0,0 +1,116 @@ +package mage.utils; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; + +public class FluentBuilderTest { + + + private ABuilder baseBuilder() { + return new ABuilder(); + } + + @Test + @DisplayName("build with default parameters") + void testDefault() { + final A actual = baseBuilder().build(); + + verifyAB(actual, null, 0); + } + + private void verifyAB(A actual, String a, int b) { + assertThat(actual.getA()).isEqualTo(a); + assertThat(actual.getB()).isEqualTo(b); + } + + @Test + @DisplayName("chain with clause and add new parameters") + void testBaseChain() { + final A actual = baseBuilder().with(a -> a.a = "hello").build(); + + verifyAB(actual, "hello", 0); + } + + @Test + @DisplayName("chain multiple with clauses and add new parameters") + void testMultiChain() { + final A actual = baseBuilder().with(a -> a.a = "world").with(a -> a.b = 6).build(); + + verifyAB(actual, "world", 6); + } + + @Test + @DisplayName("chain multiple with clauses and override latest writes") + void testMultiChainOverride() { + final A actual = baseBuilder().with(a -> a.a = "world").with(a -> a.b = 4).with(a -> a.a = "foobar").build(); + + verifyAB(actual, "foobar", 4); + } + + @Test + @DisplayName("not mutate the state of previous builder in the chain") + void testImmutability() { + final ABuilder builder1 = baseBuilder().with(a -> a.a = "world"); + final ABuilder builder2 = builder1.with(a -> { + a.a = "hello"; + a.b = 42; + }); + + verifyAB(builder1.build(), "world", 0); + verifyAB(builder2.build(), "hello", 42); + } + + @Test + @DisplayName("produce different objects") + void differentObjects() { + final ABuilder builder = baseBuilder().with(a -> { + a.a = "hello"; + a.b = 42; + }); + final A a1 = builder.build(); + final A a2 = builder.build(); + + assertThat(a1).isNotSameAs(a2); + verifyAB(a1, "hello", 42); + verifyAB(a2, "hello", 42); + } + + static class A { + public final String a; + private int b; + + public A(String a) { + this.a = a; + } + + public String getA() { + return a; + } + + public int getB() { + return b; + } + + public void setB(int b) { + this.b = b; + } + } + + static class ABuilder extends FluentBuilder { + public String a; + public int b; + + private ABuilder() { + super(ABuilder::new); + } + + @Override + protected A makeValue() { + final A result = new A(a); + result.setB(b); + return result; + } + } +} diff --git a/Mage.Server/config/config_error.xml b/Mage.Server/config/config_error.xml new file mode 100644 index 0000000000..cf0b854367 --- /dev/null +++ b/Mage.Server/config/config_error.xml @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Mage.Server/pom.xml b/Mage.Server/pom.xml index 826e3c5533..2136236c01 100644 --- a/Mage.Server/pom.xml +++ b/Mage.Server/pom.xml @@ -285,6 +285,18 @@ sqlite-jdbc 3.32.3.2 + + + + org.junit.jupiter + junit-jupiter + test + + + org.assertj + assertj-core + test + @@ -358,6 +370,10 @@ + + org.apache.maven.plugins + maven-surefire-plugin + mage-server diff --git a/Mage.Server/src/main/java/mage/server/util/ConfigFactory.java b/Mage.Server/src/main/java/mage/server/util/ConfigFactory.java new file mode 100644 index 0000000000..793419d06e --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/util/ConfigFactory.java @@ -0,0 +1,20 @@ +package mage.server.util; + +import mage.server.util.config.Config; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Unmarshaller; +import java.io.File; + +public class ConfigFactory { + + public static Config loadFromFile(final String filePath) { + try { + final JAXBContext jaxbContext = JAXBContext.newInstance("mage.server.util.config"); + final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + return (Config) unmarshaller.unmarshal(new File(filePath)); + } catch (Exception e) { + throw new ConfigurationException(e); + } + } +} diff --git a/Mage.Server/src/main/java/mage/server/util/ConfigSettings.java b/Mage.Server/src/main/java/mage/server/util/ConfigSettings.java index ac65aae03b..e66e8f9276 100644 --- a/Mage.Server/src/main/java/mage/server/util/ConfigSettings.java +++ b/Mage.Server/src/main/java/mage/server/util/ConfigSettings.java @@ -14,7 +14,7 @@ import org.apache.log4j.Logger; /** * @author BetaSteward_at_googlemail.com */ -public enum ConfigSettings { +public enum ConfigSettings implements ConfigSettingsContract { instance; private final Logger logger = Logger.getLogger(ConfigSettings.class); diff --git a/Mage.Server/src/main/java/mage/server/util/ConfigSettingsContract.java b/Mage.Server/src/main/java/mage/server/util/ConfigSettingsContract.java new file mode 100644 index 0000000000..a8ded69912 --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/util/ConfigSettingsContract.java @@ -0,0 +1,72 @@ +package mage.server.util; + +import mage.server.util.config.GamePlugin; +import mage.server.util.config.Plugin; + +import java.util.List; + +public interface ConfigSettingsContract { + String getServerAddress(); + + String getServerName(); + + int getPort(); + + int getSecondaryBindPort(); + + int getLeasePeriod(); + + int getSocketWriteTimeout(); + + int getMaxPoolSize(); + + int getNumAcceptThreads(); + + int getBacklogSize(); + + int getMaxGameThreads(); + + int getMaxSecondsIdle(); + + int getMinUserNameLength(); + + int getMaxUserNameLength(); + + String getInvalidUserNamePattern(); + + int getMinPasswordLength(); + + int getMaxPasswordLength(); + + String getMaxAiOpponents(); + + Boolean isSaveGameActivated(); + + Boolean isAuthenticationActivated(); + + String getGoogleAccount(); + + String getMailgunApiKey(); + + String getMailgunDomain(); + + String getMailSmtpHost(); + + String getMailSmtpPort(); + + String getMailUser(); + + String getMailPassword(); + + String getMailFromAddress(); + + List getPlayerTypes(); + + List getGameTypes(); + + List getTournamentTypes(); + + List getDraftCubes(); + + List getDeckTypes(); +} diff --git a/Mage.Server/src/main/java/mage/server/util/ConfigWrapper.java b/Mage.Server/src/main/java/mage/server/util/ConfigWrapper.java new file mode 100644 index 0000000000..1a461a73aa --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/util/ConfigWrapper.java @@ -0,0 +1,145 @@ +package mage.server.util; + +import mage.server.util.config.Config; +import mage.server.util.config.GamePlugin; +import mage.server.util.config.Plugin; + +import java.util.List; + +public class ConfigWrapper implements ConfigSettingsContract { + + private final Config config; + + public ConfigWrapper(final Config config) { + this.config = config; + } + + public String getServerAddress() { + return config.getServer().getServerAddress(); + } + + public String getServerName() { + return config.getServer().getServerName(); + } + + public int getPort() { + return config.getServer().getPort().intValue(); + } + + public int getSecondaryBindPort() { + return config.getServer().getSecondaryBindPort().intValue(); + } + + public int getLeasePeriod() { + return config.getServer().getLeasePeriod().intValue(); + } + + public int getSocketWriteTimeout() { + return config.getServer().getSocketWriteTimeout().intValue(); + } + + public int getMaxPoolSize() { + return config.getServer().getMaxPoolSize().intValue(); + } + + public int getNumAcceptThreads() { + return config.getServer().getNumAcceptThreads().intValue(); + } + + public int getBacklogSize() { + return config.getServer().getBacklogSize().intValue(); + } + + public int getMaxGameThreads() { + return config.getServer().getMaxGameThreads().intValue(); + } + + public int getMaxSecondsIdle() { + return config.getServer().getMaxSecondsIdle().intValue(); + } + + public int getMinUserNameLength() { + return config.getServer().getMinUserNameLength().intValue(); + } + + public int getMaxUserNameLength() { + return config.getServer().getMaxUserNameLength().intValue(); + } + + public String getInvalidUserNamePattern() { + return config.getServer().getInvalidUserNamePattern(); + } + + public int getMinPasswordLength() { + return config.getServer().getMinPasswordLength().intValue(); + } + + public int getMaxPasswordLength() { + return config.getServer().getMaxPasswordLength().intValue(); + } + + public String getMaxAiOpponents() { + return config.getServer().getMaxAiOpponents(); + } + + public Boolean isSaveGameActivated() { + return config.getServer().isSaveGameActivated(); + } + + public Boolean isAuthenticationActivated() { + return config.getServer().isAuthenticationActivated(); + } + + public String getGoogleAccount() { + return config.getServer().getGoogleAccount(); + } + + public String getMailgunApiKey() { + return config.getServer().getMailgunApiKey(); + } + + public String getMailgunDomain() { + return config.getServer().getMailgunDomain(); + } + + public String getMailSmtpHost() { + return config.getServer().getMailSmtpHost(); + } + + public String getMailSmtpPort() { + return config.getServer().getMailSmtpPort(); + } + + public String getMailUser() { + return config.getServer().getMailUser(); + } + + public String getMailPassword() { + return config.getServer().getMailPassword(); + } + + public String getMailFromAddress() { + return config.getServer().getMailFromAddress(); + } + + public List getPlayerTypes() { + return config.getPlayerTypes().getPlayerType(); + } + + public List getGameTypes() { + return config.getGameTypes().getGameType(); + } + + public List getTournamentTypes() { + return config.getTournamentTypes().getTournamentType(); + } + + public List getDraftCubes() { + return config.getDraftCubes().getDraftCube(); + } + + public List getDeckTypes() { + return config.getDeckTypes().getDeckType(); + } + +} diff --git a/Mage.Server/src/main/java/mage/server/util/ConfigurationException.java b/Mage.Server/src/main/java/mage/server/util/ConfigurationException.java new file mode 100644 index 0000000000..e1c1e5d0f0 --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/util/ConfigurationException.java @@ -0,0 +1,7 @@ +package mage.server.util; + +public class ConfigurationException extends RuntimeException { + public ConfigurationException(Throwable cause) { + super(cause); + } +} diff --git a/Mage.Server/src/test/java/mage/server/util/ConfigFactoryTest.java b/Mage.Server/src/test/java/mage/server/util/ConfigFactoryTest.java new file mode 100644 index 0000000000..aab38e713a --- /dev/null +++ b/Mage.Server/src/test/java/mage/server/util/ConfigFactoryTest.java @@ -0,0 +1,34 @@ +package mage.server.util; + +import mage.server.util.config.Config; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +public class ConfigFactoryTest { + + @Test + @DisplayName("should unmarshal configuration from file") + void loadConfig() { + final Config config = ConfigFactory.loadFromFile("config/config.xml"); + + assertThat(config.getServer().getServerName()).isEqualTo("mage-server"); + assertThat(config.getServer().getPort()).isEqualTo(17171); + } + + @Test + @DisplayName("should fail if config is malformed") + void failOnMalformed() { + assertThatExceptionOfType(ConfigurationException.class) + .isThrownBy(() -> ConfigFactory.loadFromFile("config/config_error.xml")); + } + + @Test + @DisplayName("should fail if file does not exist") + void failOnNotFound() { + assertThatExceptionOfType(ConfigurationException.class) + .isThrownBy(() -> ConfigFactory.loadFromFile("does not exist")); + } +} diff --git a/Mage.Server/src/test/java/mage/server/util/ConfigWrapperTest.java b/Mage.Server/src/test/java/mage/server/util/ConfigWrapperTest.java new file mode 100644 index 0000000000..c8a80c34c4 --- /dev/null +++ b/Mage.Server/src/test/java/mage/server/util/ConfigWrapperTest.java @@ -0,0 +1,294 @@ +package mage.server.util; + +import mage.server.util.config.*; +import mage.utils.FluentBuilder; +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.RandomUtils; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DynamicTest; +import org.junit.jupiter.api.TestFactory; + +import java.math.BigInteger; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ConfigWrapperTest { + + static class ConfigBuilder extends FluentBuilder { + + public String serverAddress; + public String serverName; + public int port; + public int secondaryBindPort; + public int leasePeriod; + public int socketWriteTimeout; + public int maxPoolSize; + public int numAcceptThreads; + public int backlogSize; + public int maxGameThreads; + public int maxSecondsIdle; + public int minUsernameLength; + public int maxUsernameLength; + public String invalidUsernamePattern; + public int minPasswordLength; + public int maxPasswordLength; + public String maxAiOpponents; + public boolean saveGameActivated; + public boolean authenticationActivated; + public String googleAccount; + public String mailgunApiKey; + public String mailgunDomain; + public String mailSmtpHost; + public String mailSmtpPort; + public String mailUser; + public String mailPassword; + public String mailFromAddress; + public List playerTypes = Collections.emptyList(); + public List gameTypes = Collections.emptyList(); + public List tournamentTypes = Collections.emptyList(); + public List draftCubes = Collections.emptyList(); + public List deckTypes = Collections.emptyList(); + + private ConfigBuilder() { + super(ConfigBuilder::new); + } + + @Override + protected Config makeValue() { + final Config result = new Config(); + result.setServer(makeServer()); + result.setPlayerTypes(makePlayerTypes()); + result.setGameTypes(makeGameTypes()); + result.setTournamentTypes(makeTournamentTypes()); + result.setDraftCubes(makeDraftCubes()); + result.setDeckTypes(makeDeckTypes()); + return result; + } + + private Server makeServer() { + final Server server = new Server(); + server.setServerAddress(serverAddress); + server.setServerName(serverName); + server.setPort(BigInteger.valueOf(port)); + server.setSecondaryBindPort(bi(secondaryBindPort)); + server.setLeasePeriod(bi(leasePeriod)); + server.setSocketWriteTimeout(bi(socketWriteTimeout)); + server.setMaxPoolSize(bi(maxPoolSize)); + server.setNumAcceptThreads(bi(numAcceptThreads)); + server.setBacklogSize(bi(backlogSize)); + server.setMaxGameThreads(bi(maxGameThreads)); + server.setMaxSecondsIdle(bi(maxSecondsIdle)); + server.setMinUserNameLength(bi(minUsernameLength)); + server.setMaxUserNameLength(bi(maxUsernameLength)); + server.setInvalidUserNamePattern(invalidUsernamePattern); + server.setMinPasswordLength(bi(minPasswordLength)); + server.setMaxPasswordLength(bi(maxPasswordLength)); + server.setMaxAiOpponents(maxAiOpponents); + server.setSaveGameActivated(saveGameActivated); + server.setAuthenticationActivated(authenticationActivated); + server.setGoogleAccount(googleAccount); + server.setMailgunApiKey(mailgunApiKey); + server.setMailgunDomain(mailgunDomain); + server.setMailSmtpHost(mailSmtpHost); + server.setMailSmtpPort(mailSmtpPort); + server.setMailUser(mailUser); + server.setMailPassword(mailPassword); + server.setMailFromAddress(mailFromAddress); + return server; + } + + private PlayerTypes makePlayerTypes() { + final PlayerTypes playerTypes = new PlayerTypes(); + this.playerTypes.forEach(p -> playerTypes.getPlayerType().add(p)); + return playerTypes; + } + + private GameTypes makeGameTypes() { + final GameTypes gameTypes = new GameTypes(); + this.gameTypes.forEach(g -> gameTypes.getGameType().add(g)); + return gameTypes; + } + + private TournamentTypes makeTournamentTypes() { + final TournamentTypes tournamentTypes = new TournamentTypes(); + this.tournamentTypes.forEach(t -> tournamentTypes.getTournamentType().add(t)); + return tournamentTypes; + } + + private DraftCubes makeDraftCubes() { + final DraftCubes draftCubes = new DraftCubes(); + this.draftCubes.forEach(d -> draftCubes.getDraftCube().add(d)); + return draftCubes; + } + + private DeckTypes makeDeckTypes() { + final DeckTypes deckTypes = new DeckTypes(); + this.deckTypes.forEach(d -> deckTypes.getDeckType().add(d)); + return deckTypes; + } + + private BigInteger bi(int value) { + return BigInteger.valueOf(value); + } + } + + private ConfigBuilder baseConfigBuilder() { + return new ConfigBuilder(); + } + + private final String expectedString = RandomStringUtils.randomAlphanumeric(15); + private final int expectedPositiveInt = RandomUtils.nextInt(0, Integer.MAX_VALUE); + + + @TestFactory + @DisplayName("should return from server") + Stream assignmentFromServer() { + return Stream.of( + testString("server address", c -> c.serverAddress = expectedString, ConfigWrapper::getServerAddress), + testString("server name", c -> c.serverName = expectedString, ConfigWrapper::getServerName), + testInt("port", c -> c.port = expectedPositiveInt, ConfigWrapper::getPort), + testInt("secondary bind port", c -> c.secondaryBindPort = expectedPositiveInt, ConfigWrapper::getSecondaryBindPort), + testInt("lease period", c -> c.leasePeriod = expectedPositiveInt, ConfigWrapper::getLeasePeriod), + testInt("socket write timeout", c -> c.socketWriteTimeout = expectedPositiveInt, ConfigWrapper::getSocketWriteTimeout), + testInt("max pool size", c -> c.maxPoolSize = expectedPositiveInt, ConfigWrapper::getMaxPoolSize), + testInt("number of accept threads", c -> c.numAcceptThreads = expectedPositiveInt, ConfigWrapper::getNumAcceptThreads), + testInt("backlog size", c -> c.backlogSize = expectedPositiveInt, ConfigWrapper::getBacklogSize), + testInt("max game threads", c -> c.maxGameThreads = expectedPositiveInt, ConfigWrapper::getMaxGameThreads), + testInt("max seconds idle", c -> c.maxSecondsIdle = expectedPositiveInt, ConfigWrapper::getMaxSecondsIdle), + testInt("min username length", c -> c.minUsernameLength = expectedPositiveInt, ConfigWrapper::getMinUserNameLength), + testInt("max username length", c -> c.maxUsernameLength = expectedPositiveInt, ConfigWrapper::getMaxUserNameLength), + testString("invalid username pattern", c -> c.invalidUsernamePattern = expectedString, ConfigWrapper::getInvalidUserNamePattern), + testInt("min password length", c -> c.minPasswordLength = expectedPositiveInt, ConfigWrapper::getMinPasswordLength), + testInt("max password length", c -> c.maxPasswordLength = expectedPositiveInt, ConfigWrapper::getMaxPasswordLength), + testString("max AI opponents", c -> c.maxAiOpponents = expectedString, ConfigWrapper::getMaxAiOpponents), + testTrue("save game activated", c -> c.saveGameActivated = true, ConfigWrapper::isSaveGameActivated), + testTrue("authentication activated", c -> c.authenticationActivated = true, ConfigWrapper::isAuthenticationActivated), + testString("google account", c -> c.googleAccount = expectedString, ConfigWrapper::getGoogleAccount), + testString("mailgun api key", c -> c.mailgunApiKey = expectedString, ConfigWrapper::getMailgunApiKey), + testString("mailgun domain", c -> c.mailgunDomain = expectedString, ConfigWrapper::getMailgunDomain), + testString("mail smtp host", c -> c.mailSmtpHost = expectedString, ConfigWrapper::getMailSmtpHost), + testString("mail smtp port", c -> c.mailSmtpPort = expectedString, ConfigWrapper::getMailSmtpPort), + testString("mail from address", c -> c.mailFromAddress = expectedString, ConfigWrapper::getMailFromAddress), + testString("mail user", c -> c.mailUser = expectedString, ConfigWrapper::getMailUser), + testString("mail password", c -> c.mailPassword = expectedString, ConfigWrapper::getMailPassword) + ); + } + + private DynamicTest testString(String description, Consumer builderSetter, Function valueExtractor) { + return testTemplate(description, builderSetter, valueExtractor, expectedString); + } + + private DynamicTest testTemplate(String description, Consumer builderSetter, Function valueExtractor, Object expectedValue) { + return DynamicTest.dynamicTest(description, () -> assertThat(valueExtractor.apply(makeTestee(baseConfigBuilder().with(builderSetter)))).isEqualTo(expectedValue)); + } + + private ConfigWrapper makeTestee(ConfigBuilder builder) { + return new ConfigWrapper(builder.build()); + } + + private DynamicTest testInt(String description, Consumer builderSetter, Function valueExtractor) { + return testTemplate(description, builderSetter, valueExtractor, expectedPositiveInt); + } + + private DynamicTest testTrue(String description, Consumer builderSetter, Function valueExtractor) { + return testTemplate(description, builderSetter, valueExtractor, true); + } + + + private final Comparator pluginComparator = (p1, p2) -> { + if (Objects.equals(p1.getName(), p2.getName()) && + Objects.equals(p1.getJar(), p2.getJar()) && + Objects.equals(p1.getClassName(), p2.getClassName())) { + return 0; + } else { + return -1; + } + }; + + private final Comparator gamePluginComparator = (p1, p2) -> { + if (Objects.equals(p1.getName(), p2.getName()) && + Objects.equals(p1.getJar(), p2.getJar()) && + Objects.equals(p1.getClassName(), p2.getClassName()) && + Objects.equals(p1.getTypeName(), p2.getTypeName())) { + return 0; + } else { + return -1; + } + }; + + private final List randomPlugins = IntStream.range(0, RandomUtils.nextInt(1, 10)) + .mapToObj(i -> makePlugin( + RandomStringUtils.randomAlphanumeric(15), + RandomStringUtils.randomAlphanumeric(16), + RandomStringUtils.randomAlphanumeric(17)) + ).collect(Collectors.toList()); + private final List randomGamePlugins = IntStream.range(0, RandomUtils.nextInt(1, 10)) + .mapToObj(i -> makeGamePlugin( + RandomStringUtils.randomAlphanumeric(15), + RandomStringUtils.randomAlphanumeric(16), + RandomStringUtils.randomAlphanumeric(17), + RandomStringUtils.randomAlphanumeric(18)) + ).collect(Collectors.toList()); + + private Plugin makePlugin(String name, String jar, String className) { + final Plugin plugin = new Plugin(); + plugin.setName(name); + plugin.setJar(jar); + plugin.setClassName(className); + return plugin; + } + + private GamePlugin makeGamePlugin(String name, String jar, String className, String typeName) { + final GamePlugin plugin = new GamePlugin(); + plugin.setName(name); + plugin.setJar(jar); + plugin.setClassName(className); + plugin.setTypeName(typeName); + return plugin; + } + + @TestFactory + @DisplayName("should extract") + Stream pluginsExtraction() { + return Stream.of( + pluginTest("playerTypes from playerTypes", c -> c.playerTypes = randomPlugins, ConfigWrapper::getPlayerTypes), + gamePluginTest("gameTypes from gameTypes", c -> c.gameTypes = randomGamePlugins, ConfigWrapper::getGameTypes), + gamePluginTest("tournamentTypes from tournamentTypes", c -> c.tournamentTypes = randomGamePlugins, ConfigWrapper::getTournamentTypes), + pluginTest("draftCubes from draftCubes", c -> c.draftCubes = randomPlugins, ConfigWrapper::getDraftCubes), + pluginTest("deckTypes from deckTypes", c -> c.deckTypes = randomPlugins, ConfigWrapper::getDeckTypes) + ); + } + + private DynamicTest pluginTest(String description, + Consumer builderSetter, + Function> listExtractor) { + return testTemplateForLists(description, builderSetter, listExtractor, randomPlugins, pluginComparator); + } + + private DynamicTest gamePluginTest(String description, + Consumer builderSetter, + Function> listExtractor) { + return testTemplateForLists(description, builderSetter, listExtractor, randomGamePlugins, gamePluginComparator); + } + + private DynamicTest testTemplateForLists(String description, + Consumer builderSetter, + Function> listExtractor, + List expectedValue, + Comparator comparator) { + return DynamicTest.dynamicTest(description, () -> + assertThat(listExtractor.apply(makeTestee(baseConfigBuilder().with(builderSetter)))) + .usingElementComparator(comparator) + .containsExactlyElementsOf(expectedValue) + ); + } +} diff --git a/pom.xml b/pom.xml index 61c118cd57..1032f1a955 100644 --- a/pom.xml +++ b/pom.xml @@ -52,6 +52,18 @@ + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + -Dfile.encoding=UTF-8 + + + + Mage @@ -113,6 +125,21 @@ guava 29.0-jre + + org.junit.jupiter + junit-jupiter + 5.7.0 + + + org.assertj + assertj-core + 3.18.0 + + + org.apache.commons + commons-lang3 + 3.11 + From d0c2135e176449d62cb8967649f61203473e5a82 Mon Sep 17 00:00:00 2001 From: Francesco Burato Date: Fri, 30 Oct 2020 17:37:12 +0000 Subject: [PATCH 2/4] [app-wiring-refactor]: Remove static initialisation - Remove all enum static managers - Introduce interfaces for the managers - Define new application wiring class (`ManagerFactory`) - Externalise the configuration --- .../main/java/mage/server/ChatManager.java | 52 ++- .../main/java/mage/server/ChatSession.java | 9 +- .../main/java/mage/server/GmailClient.java | 91 ------ .../main/java/mage/server/MageServerImpl.java | 309 ++++++++---------- .../src/main/java/mage/server/MailClient.java | 23 +- .../main/java/mage/server/MailgunClient.java | 22 +- .../src/main/java/mage/server/Main.java | 61 ++-- .../java/mage/server/MainManagerFactory.java | 118 +++++++ .../src/main/java/mage/server/RoomImpl.java | 10 +- .../src/main/java/mage/server/Session.java | 62 ++-- .../main/java/mage/server/SessionManager.java | 47 ++- .../java/mage/server/TableController.java | 111 +++---- .../main/java/mage/server/TableManager.java | 81 +++-- .../src/main/java/mage/server/User.java | 39 +-- .../main/java/mage/server/UserManager.java | 43 ++- .../mage/server/draft/DraftController.java | 49 ++- .../java/mage/server/draft/DraftManager.java | 34 +- .../java/mage/server/draft/DraftSession.java | 48 +-- .../java/mage/server/game/GameController.java | 80 ++--- .../java/mage/server/game/GameManager.java | 31 +- .../mage/server/game/GameSessionPlayer.java | 43 +-- .../mage/server/game/GameSessionWatcher.java | 18 +- .../java/mage/server/game/GamesRoomImpl.java | 47 ++- .../mage/server/game/GamesRoomManager.java | 25 +- .../java/mage/server/game/ReplayManager.java | 30 +- .../java/mage/server/game/ReplaySession.java | 20 +- .../mage/server/managers/IChatManager.java | 36 ++ .../IConfigSettings.java} | 4 +- .../mage/server/managers/IDraftManager.java | 34 ++ .../mage/server/managers/IGameManager.java | 54 +++ .../server/managers/IGamesRoomManager.java | 18 + .../mage/server/managers/IMailClient.java | 7 + .../mage/server/managers/IReplayManager.java | 19 ++ .../mage/server/managers/ISessionManager.java | 43 +++ .../mage/server/managers/ITableManager.java | 86 +++++ .../mage/server/managers/IThreadExecutor.java | 16 + .../server/managers/ITournamentManager.java | 32 ++ .../mage/server/managers/IUserManager.java | 41 +++ .../mage/server/managers/ManagerFactory.java | 29 ++ .../mage/server/record/TableRecorderImpl.java | 12 +- .../tournament/TournamentController.java | 72 ++-- .../server/tournament/TournamentManager.java | 34 +- .../server/tournament/TournamentSession.java | 38 ++- .../java/mage/server/util/ConfigSettings.java | 161 --------- .../java/mage/server/util/ConfigWrapper.java | 3 +- .../java/mage/server/util/ThreadExecutor.java | 42 +-- .../test/serverside/base/MageTestBase.java | 6 +- .../serverside/base/MageTestPlayerBase.java | 6 +- 48 files changed, 1385 insertions(+), 911 deletions(-) delete mode 100644 Mage.Server/src/main/java/mage/server/GmailClient.java create mode 100644 Mage.Server/src/main/java/mage/server/MainManagerFactory.java create mode 100644 Mage.Server/src/main/java/mage/server/managers/IChatManager.java rename Mage.Server/src/main/java/mage/server/{util/ConfigSettingsContract.java => managers/IConfigSettings.java} (94%) create mode 100644 Mage.Server/src/main/java/mage/server/managers/IDraftManager.java create mode 100644 Mage.Server/src/main/java/mage/server/managers/IGameManager.java create mode 100644 Mage.Server/src/main/java/mage/server/managers/IGamesRoomManager.java create mode 100644 Mage.Server/src/main/java/mage/server/managers/IMailClient.java create mode 100644 Mage.Server/src/main/java/mage/server/managers/IReplayManager.java create mode 100644 Mage.Server/src/main/java/mage/server/managers/ISessionManager.java create mode 100644 Mage.Server/src/main/java/mage/server/managers/ITableManager.java create mode 100644 Mage.Server/src/main/java/mage/server/managers/IThreadExecutor.java create mode 100644 Mage.Server/src/main/java/mage/server/managers/ITournamentManager.java create mode 100644 Mage.Server/src/main/java/mage/server/managers/IUserManager.java create mode 100644 Mage.Server/src/main/java/mage/server/managers/ManagerFactory.java delete mode 100644 Mage.Server/src/main/java/mage/server/util/ConfigSettings.java diff --git a/Mage.Server/src/main/java/mage/server/ChatManager.java b/Mage.Server/src/main/java/mage/server/ChatManager.java index 3ff8600963..92b1f03af0 100644 --- a/Mage.Server/src/main/java/mage/server/ChatManager.java +++ b/Mage.Server/src/main/java/mage/server/ChatManager.java @@ -5,8 +5,8 @@ import mage.cards.repository.CardRepository; import mage.game.Game; import mage.server.exceptions.UserNotFoundException; import mage.server.game.GameController; -import mage.server.game.GameManager; -import mage.server.game.GamesRoomManager; +import mage.server.managers.IChatManager; +import mage.server.managers.ManagerFactory; import mage.server.util.SystemUtil; import mage.view.ChatMessage.MessageColor; import mage.view.ChatMessage.MessageType; @@ -26,21 +26,27 @@ import java.util.stream.Collectors; /** * @author BetaSteward_at_googlemail.com */ -public enum ChatManager { +public class ChatManager implements IChatManager { - instance; private static final Logger logger = Logger.getLogger(ChatManager.class); private static final HashMap userMessages = new HashMap<>(); + private final ManagerFactory managerFactory; private final ConcurrentHashMap chatSessions = new ConcurrentHashMap<>(); private final ReadWriteLock lock = new ReentrantReadWriteLock(); + public ChatManager(ManagerFactory managerFactory) { + this.managerFactory = managerFactory; + } + + @Override public UUID createChatSession(String info) { - ChatSession chatSession = new ChatSession(info); + ChatSession chatSession = new ChatSession(managerFactory, info); chatSessions.put(chatSession.getChatId(), chatSession); return chatSession.getChatId(); } + @Override public void joinChat(UUID chatId, UUID userId) { ChatSession chatSession = chatSessions.get(chatId); if (chatSession != null) { @@ -51,10 +57,12 @@ public enum ChatManager { } + @Override public void clearUserMessageStorage() { userMessages.clear(); } + @Override public void leaveChat(UUID chatId, UUID userId) { ChatSession chatSession = chatSessions.get(chatId); if (chatSession != null && chatSession.hasUser(userId)) { @@ -62,6 +70,7 @@ public enum ChatManager { } } + @Override public void destroyChatSession(UUID chatId) { if (chatId != null) { ChatSession chatSession = chatSessions.get(chatId); @@ -84,11 +93,12 @@ public enum ChatManager { final Pattern cardNamePattern = Pattern.compile("\\[(.*?)\\]"); + @Override public void broadcast(UUID chatId, String userName, String message, MessageColor color, boolean withTime, Game game, MessageType messageType, SoundToPlay soundToPlay) { ChatSession chatSession = chatSessions.get(chatId); if (chatSession != null) { if (message.startsWith("\\") || message.startsWith("/")) { - Optional user = UserManager.instance.getUserByName(userName); + Optional user = managerFactory.userManager().getUserByName(userName); if (user.isPresent()) { if (!performUserCommand(user.get(), message, chatId, false)) { performUserCommand(user.get(), message, chatId, true); @@ -98,7 +108,7 @@ public enum ChatManager { } if (messageType != MessageType.GAME && !userName.isEmpty()) { - Optional u = UserManager.instance.getUserByName(userName); + Optional u = managerFactory.userManager().getUserByName(userName); if (u.isPresent()) { User user = u.get(); @@ -184,12 +194,12 @@ public enum ChatManager { } if (command.startsWith("H ") || command.startsWith("HISTORY ")) { - message += "
" + UserManager.instance.getUserHistory(message.substring(command.startsWith("H ") ? 3 : 9)); + message += "
" + managerFactory.userManager().getUserHistory(message.substring(command.startsWith("H ") ? 3 : 9)); chatSessions.get(chatId).broadcastInfoToUser(user, message); return true; } if (command.equals("ME")) { - message += "
" + UserManager.instance.getUserHistory(user.getName()); + message += "
" + managerFactory.userManager().getUserHistory(user.getName()); chatSessions.get(chatId).broadcastInfoToUser(user, message); return true; } @@ -200,7 +210,7 @@ public enum ChatManager { String gameId = session.getInfo(); if (gameId.startsWith("Game ")) { UUID id = java.util.UUID.fromString(gameId.substring(5)); - for (Entry entry : GameManager.instance.getGameController().entrySet()) { + for (Entry entry : managerFactory.gameManager().getGameController().entrySet()) { if (entry.getKey().equals(id)) { GameController controller = entry.getValue(); if (controller != null) { @@ -221,7 +231,7 @@ public enum ChatManager { String gameId = session.getInfo(); if (gameId.startsWith("Game ")) { UUID id = java.util.UUID.fromString(gameId.substring(5)); - for (Entry entry : GameManager.instance.getGameController().entrySet()) { + for (Entry entry : managerFactory.gameManager().getGameController().entrySet()) { if (entry.getKey().equals(id)) { GameController controller = entry.getValue(); if (controller != null) { @@ -242,7 +252,7 @@ public enum ChatManager { String gameId = session.getInfo(); if (gameId.startsWith("Game ")) { UUID id = java.util.UUID.fromString(gameId.substring(5)); - for (Entry entry : GameManager.instance.getGameController().entrySet()) { + for (Entry entry : managerFactory.gameManager().getGameController().entrySet()) { if (entry.getKey().equals(id)) { GameController controller = entry.getValue(); if (controller != null) { @@ -281,7 +291,7 @@ public enum ChatManager { if (first > 1) { String userToName = rest.substring(0, first); rest = rest.substring(first + 1).trim(); - Optional userTo = UserManager.instance.getUserByName(userToName); + Optional userTo = managerFactory.userManager().getUserByName(userToName); if (userTo.isPresent()) { if (!chatSessions.get(chatId).broadcastWhisperToUser(user, userTo.get(), rest)) { message += new StringBuilder("
User ").append(userToName).append(" not found").toString(); @@ -312,8 +322,9 @@ public enum ChatManager { * @param color * @throws mage.server.exceptions.UserNotFoundException */ + @Override public void broadcast(UUID userId, String message, MessageColor color) throws UserNotFoundException { - UserManager.instance.getUser(userId).ifPresent(user -> { + managerFactory.userManager().getUser(userId).ifPresent(user -> { getChatSessions() .stream() .filter(chat -> chat.hasUser(userId)) @@ -322,8 +333,9 @@ public enum ChatManager { }); } + @Override public void sendReconnectMessage(UUID userId) { - UserManager.instance.getUser(userId).ifPresent(user + managerFactory.userManager().getUser(userId).ifPresent(user -> getChatSessions() .stream() .filter(chat -> chat.hasUser(userId)) @@ -331,8 +343,9 @@ public enum ChatManager { } + @Override public void sendLostConnectionMessage(UUID userId, DisconnectReason reason) { - UserManager.instance.getUser(userId).ifPresent(user -> sendMessageToUserChats(userId, user.getName() + " " + reason.getMessage())); + managerFactory.userManager().getUser(userId).ifPresent(user -> sendMessageToUserChats(userId, user.getName() + " " + reason.getMessage())); } /** @@ -341,10 +354,11 @@ public enum ChatManager { * @param userId * @param message */ + @Override public void sendMessageToUserChats(UUID userId, String message) { - UserManager.instance.getUser(userId).ifPresent(user -> { + managerFactory.userManager().getUser(userId).ifPresent(user -> { List chatSessions = getChatSessions().stream() - .filter(chat -> !chat.getChatId().equals(GamesRoomManager.instance.getMainChatId())) // ignore main lobby + .filter(chat -> !chat.getChatId().equals(managerFactory.gamesRoomManager().getMainChatId())) // ignore main lobby .filter(chat -> chat.hasUser(userId)) .collect(Collectors.toList()); @@ -355,6 +369,7 @@ public enum ChatManager { }); } + @Override public void removeUser(UUID userId, DisconnectReason reason) { for (ChatSession chatSession : getChatSessions()) { if (chatSession.hasUser(userId)) { @@ -363,6 +378,7 @@ public enum ChatManager { } } + @Override public List getChatSessions() { final Lock r = lock.readLock(); r.lock(); diff --git a/Mage.Server/src/main/java/mage/server/ChatSession.java b/Mage.Server/src/main/java/mage/server/ChatSession.java index fad1424573..73ffa28fe7 100644 --- a/Mage.Server/src/main/java/mage/server/ChatSession.java +++ b/Mage.Server/src/main/java/mage/server/ChatSession.java @@ -3,6 +3,7 @@ package mage.server; import mage.game.Game; import mage.interfaces.callback.ClientCallback; import mage.interfaces.callback.ClientCallbackMethod; +import mage.server.managers.ManagerFactory; import mage.view.ChatMessage; import mage.view.ChatMessage.MessageColor; import mage.view.ChatMessage.MessageType; @@ -25,6 +26,7 @@ public class ChatSession { private static final Logger logger = Logger.getLogger(ChatSession.class); private static final DateFormat timeFormatter = DateFormat.getTimeInstance(DateFormat.SHORT); + private final ManagerFactory managerFactory; private final ReadWriteLock lock = new ReentrantReadWriteLock(); private final ConcurrentMap clients = new ConcurrentHashMap<>(); @@ -32,14 +34,15 @@ public class ChatSession { private final Date createTime; private final String info; - public ChatSession(String info) { + public ChatSession(ManagerFactory managerFactory, String info) { + this.managerFactory = managerFactory; chatId = UUID.randomUUID(); this.createTime = new Date(); this.info = info; } public void join(UUID userId) { - UserManager.instance.getUser(userId).ifPresent(user -> { + managerFactory.userManager().getUser(userId).ifPresent(user -> { if (!clients.containsKey(userId)) { String userName = user.getName(); final Lock w = lock.writeLock(); @@ -121,7 +124,7 @@ public class ChatSession { r.unlock(); } for (UUID userId : chatUserIds) { - Optional user = UserManager.instance.getUser(userId); + Optional user = managerFactory.userManager().getUser(userId); if (user.isPresent()) { user.get().fireCallback(clientCallback); } else { diff --git a/Mage.Server/src/main/java/mage/server/GmailClient.java b/Mage.Server/src/main/java/mage/server/GmailClient.java deleted file mode 100644 index a091ede4d4..0000000000 --- a/Mage.Server/src/main/java/mage/server/GmailClient.java +++ /dev/null @@ -1,91 +0,0 @@ -package mage.server; - -import com.google.api.client.auth.oauth2.Credential; -import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp; -import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver; -import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow; -import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets; -import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; -import com.google.api.client.http.HttpTransport; -import com.google.api.client.json.JsonFactory; -import com.google.api.client.json.jackson2.JacksonFactory; -import com.google.api.client.util.Base64; -import com.google.api.client.util.store.FileDataStoreFactory; -import com.google.api.services.gmail.Gmail; -import com.google.api.services.gmail.Gmail.Builder; -import com.google.api.services.gmail.GmailScopes; -import com.google.api.services.gmail.model.Message; -import java.io.ByteArrayOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.util.Collections; -import java.util.Properties; -import javax.mail.MessagingException; -import javax.mail.Session; -import javax.mail.internet.InternetAddress; -import javax.mail.internet.MimeMessage; -import mage.server.util.ConfigSettings; -import org.apache.log4j.Logger; - -public final class GmailClient { - - private static final Logger logger = Logger.getLogger(Main.class); - private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance(); - private static final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"), ".store/xmage"); - private static FileDataStoreFactory dataStoreFactory; - private static HttpTransport httpTransport; - private static Credential credential; - - public static boolean initilize() { - try { - dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR); - httpTransport = GoogleNetHttpTransport.newTrustedTransport(); - - GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new FileReader("client_secrets.json")); - if (clientSecrets.getDetails().getClientId().startsWith("Enter") - || clientSecrets.getDetails().getClientSecret().startsWith("Enter ")) { - logger.error("client_secrets.json not found"); - return false; - } - - GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder( - httpTransport, JSON_FACTORY, clientSecrets, - Collections.singleton(GmailScopes.GMAIL_COMPOSE)).setDataStoreFactory( - dataStoreFactory).build(); - - credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user"); - return true; - } catch (IOException | GeneralSecurityException ex) { - logger.error("Error initializing GmailClient", ex); - } - return false; - } - - public static boolean sendMessage(String email, String subject, String text) { - if (email.isEmpty()) { - logger.info("Email is not sent because the address is empty"); - return false; - } - try { - Gmail gmail = new Builder(httpTransport, JSON_FACTORY, credential).setApplicationName("XMage Server").build(); - - MimeMessage mimeMessage = new MimeMessage(Session.getDefaultInstance(new Properties())); - mimeMessage.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(email)); - mimeMessage.setSubject(subject); - mimeMessage.setText(text); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - mimeMessage.writeTo(baos); - Message message = new Message(); - message.setRaw(Base64.encodeBase64URLSafeString(baos.toByteArray())); - - gmail.users().messages().send(ConfigSettings.instance.getGoogleAccount() - + (ConfigSettings.instance.getGoogleAccount().endsWith("@gmail.com") ? "" : "@gmail.com"), message).execute(); - return true; - } catch (MessagingException | IOException ex) { - logger.error("Error sending message", ex); - } - return false; - } -} diff --git a/Mage.Server/src/main/java/mage/server/MageServerImpl.java b/Mage.Server/src/main/java/mage/server/MageServerImpl.java index e668311ac7..ed545b6467 100644 --- a/Mage.Server/src/main/java/mage/server/MageServerImpl.java +++ b/Mage.Server/src/main/java/mage/server/MageServerImpl.java @@ -23,15 +23,14 @@ import mage.players.PlayerType; import mage.players.net.UserData; import mage.remote.MageVersionException; import mage.server.draft.CubeFactory; -import mage.server.draft.DraftManager; -import mage.server.game.*; +import mage.server.game.GameFactory; +import mage.server.game.GamesRoom; +import mage.server.game.PlayerFactory; +import mage.server.managers.ManagerFactory; import mage.server.services.impl.FeedbackServiceImpl; import mage.server.tournament.TournamentFactory; -import mage.server.tournament.TournamentManager; -import mage.server.util.ConfigSettings; import mage.server.util.ServerMessagesUtil; import mage.server.util.SystemUtil; -import mage.server.util.ThreadExecutor; import mage.utils.*; import mage.view.*; import mage.view.ChatMessage.MessageColor; @@ -49,9 +48,10 @@ import java.util.concurrent.ExecutorService; public class MageServerImpl implements MageServer { private static final Logger logger = Logger.getLogger(MageServerImpl.class); - private static final ExecutorService callExecutor = ThreadExecutor.instance.getCallExecutor(); + private final ExecutorService callExecutor; private static final SecureRandom RANDOM = new SecureRandom(); + private final ManagerFactory managerFactory; private final String adminPassword; private final boolean testMode; private final LinkedHashMap activeAuthTokens = new LinkedHashMap() { @@ -62,15 +62,17 @@ public class MageServerImpl implements MageServer { } }; - public MageServerImpl(String adminPassword, boolean testMode) { + public MageServerImpl(ManagerFactory managerFactory, String adminPassword, boolean testMode) { + this.managerFactory = managerFactory; this.adminPassword = adminPassword; this.testMode = testMode; + this.callExecutor = managerFactory.threadExecutor().getCallExecutor(); ServerMessagesUtil.instance.getMessages(); } @Override public boolean registerUser(String sessionId, String userName, String password, String email) throws MageException { - return SessionManager.instance.registerUser(sessionId, userName, password, email); + return managerFactory.sessionManager().registerUser(sessionId, userName, password, email); } // generateAuthToken returns a uniformly distributed 6-digits string. @@ -80,7 +82,7 @@ public class MageServerImpl implements MageServer { @Override public boolean emailAuthToken(String sessionId, String email) throws MageException { - if (!ConfigSettings.instance.isAuthenticationActivated()) { + if (!managerFactory.configSettings().isAuthenticationActivated()) { sendErrorMessageToClient(sessionId, "Registration is disabled by the server config"); return false; } @@ -96,10 +98,10 @@ public class MageServerImpl implements MageServer { String text = "Use this auth token to reset " + authorizedUser.name + "'s password: " + authToken + '\n' + "It's valid until the next server restart."; boolean success; - if (!ConfigSettings.instance.getMailUser().isEmpty()) { - success = MailClient.sendMessage(email, subject, text); + if (!managerFactory.configSettings().getMailUser().isEmpty()) { + success = managerFactory.mailClient().sendMessage(email, subject, text); } else { - success = MailgunClient.sendMessage(email, subject, text); + success = managerFactory.mailgunClient().sendMessage(email, subject, text); } if (!success) { sendErrorMessageToClient(sessionId, "There was an error inside the server while emailing an auth token"); @@ -110,7 +112,7 @@ public class MageServerImpl implements MageServer { @Override public boolean resetPassword(String sessionId, String email, String authToken, String password) throws MageException { - if (!ConfigSettings.instance.isAuthenticationActivated()) { + if (!managerFactory.configSettings().isAuthenticationActivated()) { sendErrorMessageToClient(sessionId, "Registration is disabled by the server config"); return false; } @@ -139,7 +141,7 @@ public class MageServerImpl implements MageServer { logger.info("MageVersionException: userName=" + userName + ", version=" + version + " sessionId=" + sessionId); throw new MageVersionException(version, Main.getVersion()); } - return SessionManager.instance.connectUser(sessionId, userName, password, userIdStr); + return managerFactory.sessionManager().connectUser(sessionId, userName, password, userIdStr); } catch (MageException ex) { if (ex instanceof MageVersionException) { throw ex; @@ -154,7 +156,7 @@ public class MageServerImpl implements MageServer { return executeWithResult("setUserData", sessionId, new ActionWithBooleanResult() { @Override public Boolean execute() throws MageException { - return SessionManager.instance.setUserData(userName, sessionId, userData, clientVersion, userIdStr); + return managerFactory.sessionManager().setUserData(userName, sessionId, userData, clientVersion, userIdStr); } }); } @@ -168,7 +170,7 @@ public class MageServerImpl implements MageServer { if (!adminPassword.equals(this.adminPassword)) { throw new MageException("Wrong password"); } - return SessionManager.instance.connectAdmin(sessionId); + return managerFactory.sessionManager().connectAdmin(sessionId); } catch (Exception ex) { handleException(ex); } @@ -186,13 +188,13 @@ public class MageServerImpl implements MageServer { @Override public TableView execute() throws MageException { try { - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { logger.error("Session to found : " + sessionId); return null; } UUID userId = session.get().getUserId(); - Optional _user = UserManager.instance.getUser(userId); + Optional _user = managerFactory.userManager().getUser(userId); if (!_user.isPresent()) { logger.error("User for session not found. session = " + sessionId); return null; @@ -205,7 +207,7 @@ public class MageServerImpl implements MageServer { throw new MageException("No message"); } // check AI players max - String maxAiOpponents = ConfigSettings.instance.getMaxAiOpponents(); + String maxAiOpponents = managerFactory.configSettings().getMaxAiOpponents(); if (maxAiOpponents != null) { int aiPlayers = 0; for (PlayerType playerType : options.getPlayerTypes()) { @@ -241,7 +243,7 @@ public class MageServerImpl implements MageServer { user.showUserMessage("Create tournament", message); throw new MageException("No message"); } - Optional room = GamesRoomManager.instance.getRoom(roomId); + Optional room = managerFactory.gamesRoomManager().getRoom(roomId); if (!room.isPresent()) { } else { @@ -260,9 +262,9 @@ public class MageServerImpl implements MageServer { @Override public void removeTable(final String sessionId, final UUID roomId, final UUID tableId) throws MageException { execute("removeTable", sessionId, () -> { - SessionManager.instance.getSession(sessionId).ifPresent(session -> { + managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> { UUID userId = session.getUserId(); - TableManager.instance.removeTable(userId, tableId); + managerFactory.tableManager().removeTable(userId, tableId); }); }); } @@ -272,7 +274,7 @@ public class MageServerImpl implements MageServer { return executeWithResult("joinTable", sessionId, new ActionWithBooleanResult() { @Override public Boolean execute() throws MageException { - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { return false; } @@ -282,7 +284,7 @@ public class MageServerImpl implements MageServer { logger.fatal("Got no userId from sessionId" + sessionId + " tableId" + tableId); return false; } - Optional room = GamesRoomManager.instance.getRoom(roomId); + Optional room = managerFactory.gamesRoomManager().getRoom(roomId); if (!room.isPresent()) { return false; } @@ -297,20 +299,20 @@ public class MageServerImpl implements MageServer { return executeWithResult("joinTournamentTable", sessionId, new ActionWithBooleanResult() { @Override public Boolean execute() throws MageException { - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { return false; } UUID userId = session.get().getUserId(); if (logger.isTraceEnabled()) { - Optional user = UserManager.instance.getUser(userId); + Optional user = managerFactory.userManager().getUser(userId); user.ifPresent(user1 -> logger.trace("join tourn. tableId: " + tableId + ' ' + name)); } if (userId == null) { logger.fatal("Got no userId from sessionId" + sessionId + " tableId" + tableId); return false; } - Optional room = GamesRoomManager.instance.getRoom(roomId); + Optional room = managerFactory.gamesRoomManager().getRoom(roomId); if (room.isPresent()) { return room.get().joinTournamentTable(userId, tableId, name, playerType, skill, deckList, password); } @@ -325,12 +327,12 @@ public class MageServerImpl implements MageServer { return executeWithResult("submitDeck", sessionId, new ActionWithBooleanResult() { @Override public Boolean execute() throws MageException { - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { return false; } else { UUID userId = session.get().getUserId(); - boolean ret = TableManager.instance.submitDeck(userId, tableId, deckList); + boolean ret = managerFactory.tableManager().submitDeck(userId, tableId, deckList); logger.debug("Session " + sessionId + " submitted deck"); return ret; } @@ -341,13 +343,13 @@ public class MageServerImpl implements MageServer { @Override public void updateDeck(final String sessionId, final UUID tableId, final DeckCardLists deckList) throws MageException { execute("updateDeck", sessionId, () -> { - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { logger.error("Session not found : " + sessionId); } else { UUID userId = session.get().getUserId(); - TableManager.instance.updateDeck(userId, tableId, deckList); + managerFactory.tableManager().updateDeck(userId, tableId, deckList); logger.trace("Session " + sessionId + " updated deck"); } }); @@ -357,7 +359,7 @@ public class MageServerImpl implements MageServer { //FIXME: why no sessionId here??? public List getTables(UUID roomId) throws MageException { try { - Optional room = GamesRoomManager.instance.getRoom(roomId); + Optional room = managerFactory.gamesRoomManager().getRoom(roomId); if (room.isPresent()) { return room.get().getTables(); } else { @@ -373,7 +375,7 @@ public class MageServerImpl implements MageServer { //FIXME: why no sessionId here??? public List getFinishedMatches(UUID roomId) throws MageException { try { - return GamesRoomManager.instance.getRoom(roomId).map(GamesRoom::getFinished).orElse(new ArrayList<>()); + return managerFactory.gamesRoomManager().getRoom(roomId).map(GamesRoom::getFinished).orElse(new ArrayList<>()); } catch (Exception ex) { handleException(ex); } @@ -383,7 +385,7 @@ public class MageServerImpl implements MageServer { @Override public List getRoomUsers(UUID roomId) throws MageException { try { - Optional room = GamesRoomManager.instance.getRoom(roomId); + Optional room = managerFactory.gamesRoomManager().getRoom(roomId); if (room.isPresent()) { return room.get().getRoomUsersInfo(); } else { @@ -399,7 +401,7 @@ public class MageServerImpl implements MageServer { //FIXME: why no sessionId here??? public TableView getTable(UUID roomId, UUID tableId) throws MageException { try { - Optional room = GamesRoomManager.instance.getRoom(roomId); + Optional room = managerFactory.gamesRoomManager().getRoom(roomId); return room.flatMap(r -> r.getTable(tableId)).orElse(null); } catch (Exception ex) { @@ -410,22 +412,12 @@ public class MageServerImpl implements MageServer { @Override public boolean ping(String sessionId, String pingInfo) { - return SessionManager.instance.extendUserSession(sessionId, pingInfo); + return managerFactory.sessionManager().extendUserSession(sessionId, pingInfo); } - // @Override -// public void deregisterClient(final String sessionId) throws MageException { -// execute("deregisterClient", sessionId, new Action() { -// @Override -// public void execute() { -// SessionManager.instance.disconnect(sessionId, true); -// logger.debug("Client deregistered ..."); -// } -// }); -// } @Override public boolean startMatch(final String sessionId, final UUID roomId, final UUID tableId) throws MageException { - Optional controller = TableManager.instance.getController(tableId); + Optional controller = managerFactory.tableManager().getController(tableId); if (!controller.isPresent()) { logger.error("table not found : " + tableId); return false; @@ -434,30 +426,20 @@ public class MageServerImpl implements MageServer { return false; } execute("startMatch", sessionId, () -> { - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { logger.error("Session not found : " + sessionId); } else { UUID userId = session.get().getUserId(); - TableManager.instance.startMatch(userId, roomId, tableId); + managerFactory.tableManager().startMatch(userId, roomId, tableId); } }); return true; } - // @Override -// public void startChallenge(final String sessionId, final UUID roomId, final UUID tableId, final UUID challengeId) throws MageException { -// execute("startChallenge", sessionId, new Action() { -// @Override -// public void execute() { -// UUID userId = SessionManager.instance.getSession(sessionId).getUserId(); -// TableManager.instance.startChallenge(userId, roomId, tableId, challengeId); -// } -// }); -// } @Override public boolean startTournament(final String sessionId, final UUID roomId, final UUID tableId) throws MageException { - Optional controller = TableManager.instance.getController(tableId); + Optional controller = managerFactory.tableManager().getController(tableId); if (!controller.isPresent()) { logger.error("table not found : " + tableId); return false; @@ -466,12 +448,12 @@ public class MageServerImpl implements MageServer { return false; } execute("startTournament", sessionId, () -> { - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { logger.error("Session not found : " + sessionId); } else { UUID userId = session.get().getUserId(); - TableManager.instance.startTournament(userId, roomId, tableId); + managerFactory.tableManager().startTournament(userId, roomId, tableId); } }); return true; @@ -481,7 +463,7 @@ public class MageServerImpl implements MageServer { //FIXME: why no sessionId here??? public TournamentView getTournament(UUID tournamentId) throws MageException { try { - return TournamentManager.instance.getTournamentView(tournamentId); + return managerFactory.tournamentManager().getTournamentView(tournamentId); } catch (Exception ex) { handleException(ex); } @@ -493,7 +475,7 @@ public class MageServerImpl implements MageServer { public void sendChatMessage(final UUID chatId, final String userName, final String message) throws MageException { try { callExecutor.execute( - () -> ChatManager.instance.broadcast(chatId, userName, StringEscapeUtils.escapeHtml4(message), MessageColor.BLUE, true, null, ChatMessage.MessageType.TALK, null) + () -> managerFactory.chatManager().broadcast(chatId, userName, StringEscapeUtils.escapeHtml4(message), MessageColor.BLUE, true, null, ChatMessage.MessageType.TALK, null) ); } catch (Exception ex) { handleException(ex); @@ -503,10 +485,10 @@ public class MageServerImpl implements MageServer { @Override public void joinChat(final UUID chatId, final String sessionId, final String userName) throws MageException { execute("joinChat", sessionId, () -> { - SessionManager.instance.getSession(sessionId).ifPresent(session -> { + managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> { UUID userId = session.getUserId(); - ChatManager.instance.joinChat(chatId, userId); + managerFactory.chatManager().joinChat(chatId, userId); }); }); } @@ -515,9 +497,9 @@ public class MageServerImpl implements MageServer { public void leaveChat(final UUID chatId, final String sessionId) throws MageException { execute("leaveChat", sessionId, () -> { if (chatId != null) { - SessionManager.instance.getSession(sessionId).ifPresent(session -> { + managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> { UUID userId = session.getUserId(); - ChatManager.instance.leaveChat(chatId, userId); + managerFactory.chatManager().leaveChat(chatId, userId); }); } }); @@ -527,7 +509,7 @@ public class MageServerImpl implements MageServer { //FIXME: why no sessionId here??? public UUID getMainRoomId() throws MageException { try { - return GamesRoomManager.instance.getMainRoomId(); + return managerFactory.gamesRoomManager().getMainRoomId(); } catch (Exception ex) { handleException(ex); } @@ -538,7 +520,7 @@ public class MageServerImpl implements MageServer { //FIXME: why no sessionId here??? public UUID getRoomChatId(UUID roomId) throws MageException { try { - Optional room = GamesRoomManager.instance.getRoom(roomId); + Optional room = managerFactory.gamesRoomManager().getRoom(roomId); if (!room.isPresent()) { logger.error("roomId not found : " + roomId); return null; @@ -555,12 +537,12 @@ public class MageServerImpl implements MageServer { return executeWithResult("isTableOwner", sessionId, new ActionWithBooleanResult() { @Override public Boolean execute() { - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { return false; } else { UUID userId = session.get().getUserId(); - return TableManager.instance.isTableOwner(tableId, userId); + return managerFactory.tableManager().isTableOwner(tableId, userId); } } }); @@ -569,16 +551,16 @@ public class MageServerImpl implements MageServer { @Override public void swapSeats(final String sessionId, final UUID roomId, final UUID tableId, final int seatNum1, final int seatNum2) throws MageException { execute("swapSeats", sessionId, () -> { - SessionManager.instance.getSession(sessionId).ifPresent(session -> { + managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> { UUID userId = session.getUserId(); - TableManager.instance.swapSeats(tableId, userId, seatNum1, seatNum2); + managerFactory.tableManager().swapSeats(tableId, userId, seatNum1, seatNum2); }); }); } @Override public boolean leaveTable(final String sessionId, final UUID roomId, final UUID tableId) throws MageException { - Optional tableController = TableManager.instance.getController(tableId); + Optional tableController = managerFactory.tableManager().getController(tableId); if (tableController.isPresent()) { TableState tableState = tableController.get().getTableState(); if (tableState != TableState.WAITING && tableState != TableState.READY_TO_START) { @@ -586,9 +568,9 @@ public class MageServerImpl implements MageServer { return false; } execute("leaveTable", sessionId, () -> { - SessionManager.instance.getSession(sessionId).ifPresent(session -> { + managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> { UUID userId = session.getUserId(); - GamesRoomManager.instance.getRoom(roomId).ifPresent(room -> + managerFactory.gamesRoomManager().getRoom(roomId).ifPresent(room -> room.leaveTable(userId, tableId)); }); @@ -604,7 +586,7 @@ public class MageServerImpl implements MageServer { //FIXME: why no sessionId here??? public UUID getTableChatId(UUID tableId) throws MageException { try { - return TableManager.instance.getChatId(tableId).orElse(null); + return managerFactory.tableManager().getChatId(tableId).orElse(null); } catch (Exception ex) { handleException(ex); } @@ -614,9 +596,9 @@ public class MageServerImpl implements MageServer { @Override public void joinGame(final UUID gameId, final String sessionId) throws MageException { execute("joinGame", sessionId, () -> { - SessionManager.instance.getSession(sessionId).ifPresent(session -> { + managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> { UUID userId = session.getUserId(); - GameManager.instance.joinGame(gameId, userId); + managerFactory.gameManager().joinGame(gameId, userId); }); }); } @@ -624,9 +606,9 @@ public class MageServerImpl implements MageServer { @Override public void joinDraft(final UUID draftId, final String sessionId) throws MageException { execute("joinDraft", sessionId, () -> { - SessionManager.instance.getSession(sessionId).ifPresent(session -> { + managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> { UUID userId = session.getUserId(); - DraftManager.instance.joinDraft(draftId, userId); + managerFactory.draftManager().joinDraft(draftId, userId); }); }); } @@ -634,12 +616,12 @@ public class MageServerImpl implements MageServer { @Override public void joinTournament(final UUID tournamentId, final String sessionId) throws MageException { execute("joinTournament", sessionId, () -> { - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { logger.error("Session not found : " + sessionId); } else { UUID userId = session.get().getUserId(); - TournamentManager.instance.joinTournament(tournamentId, userId); + managerFactory.tournamentManager().joinTournament(tournamentId, userId); } }); } @@ -648,7 +630,7 @@ public class MageServerImpl implements MageServer { //FIXME: why no sessionId here??? public UUID getGameChatId(UUID gameId) throws MageException { try { - return GameManager.instance.getChatId(gameId).orElse(null); + return managerFactory.gameManager().getChatId(gameId).orElse(null); } catch (Exception ex) { handleException(ex); } @@ -659,7 +641,7 @@ public class MageServerImpl implements MageServer { //FIXME: why no sessionId here??? public UUID getTournamentChatId(UUID tournamentId) throws MageException { try { - return TournamentManager.instance.getChatId(tournamentId).orElse(null); + return managerFactory.tournamentManager().getChatId(tournamentId).orElse(null); } catch (Exception ex) { handleException(ex); } @@ -669,9 +651,8 @@ public class MageServerImpl implements MageServer { @Override public void sendPlayerUUID(final UUID gameId, final String sessionId, final UUID data) throws MageException { execute("sendPlayerUUID", sessionId, () -> { - Optional user = SessionManager.instance.getUser(sessionId); + Optional user = managerFactory.sessionManager().getUser(sessionId); if (user.isPresent()) { -// logger.warn("sendPlayerUUID gameId=" + gameId + " sessionId=" + sessionId + " username=" + user.getName()); user.get().sendPlayerUUID(gameId, data); } else { logger.warn("Your session expired: gameId=" + gameId + ", sessionId=" + sessionId); @@ -682,7 +663,7 @@ public class MageServerImpl implements MageServer { @Override public void sendPlayerString(final UUID gameId, final String sessionId, final String data) throws MageException { execute("sendPlayerString", sessionId, () -> { - Optional user = SessionManager.instance.getUser(sessionId); + Optional user = managerFactory.sessionManager().getUser(sessionId); if (user.isPresent()) { user.get().sendPlayerString(gameId, data); } else { @@ -694,7 +675,7 @@ public class MageServerImpl implements MageServer { @Override public void sendPlayerManaType(final UUID gameId, final UUID playerId, final String sessionId, final ManaType data) throws MageException { execute("sendPlayerManaType", sessionId, () -> { - Optional user = SessionManager.instance.getUser(sessionId); + Optional user = managerFactory.sessionManager().getUser(sessionId); if (user.isPresent()) { user.get().sendPlayerManaType(gameId, playerId, data); } else { @@ -706,7 +687,7 @@ public class MageServerImpl implements MageServer { @Override public void sendPlayerBoolean(final UUID gameId, final String sessionId, final Boolean data) throws MageException { execute("sendPlayerBoolean", sessionId, () -> { - Optional user = SessionManager.instance.getUser(sessionId); + Optional user = managerFactory.sessionManager().getUser(sessionId); if (user.isPresent()) { user.get().sendPlayerBoolean(gameId, data); } else { @@ -718,7 +699,7 @@ public class MageServerImpl implements MageServer { @Override public void sendPlayerInteger(final UUID gameId, final String sessionId, final Integer data) throws MageException { execute("sendPlayerInteger", sessionId, () -> { - Optional user = SessionManager.instance.getUser(sessionId); + Optional user = managerFactory.sessionManager().getUser(sessionId); if (user.isPresent()) { user.get().sendPlayerInteger(gameId, data); } else { @@ -735,9 +716,9 @@ public class MageServerImpl implements MageServer { @Override public void sendCardMark(final UUID draftId, final String sessionId, final UUID cardPick) throws MageException { execute("sendCardMark", sessionId, () -> { - SessionManager.instance.getSession(sessionId).ifPresent(session -> { + managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> { UUID userId = session.getUserId(); - DraftManager.instance.sendCardMark(draftId, userId, cardPick); + managerFactory.draftManager().sendCardMark(draftId, userId, cardPick); }); }); } @@ -748,9 +729,9 @@ public class MageServerImpl implements MageServer { try { callExecutor.execute( () -> { - SessionManager.instance.getSession(sessionId).ifPresent(session -> { + managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> { UUID userId = session.getUserId(); - GameManager.instance.quitMatch(gameId, userId); + managerFactory.gameManager().quitMatch(gameId, userId); }); } ); @@ -766,10 +747,10 @@ public class MageServerImpl implements MageServer { try { callExecutor.execute( () -> { - SessionManager.instance.getSession(sessionId).ifPresent(session -> { + managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> { UUID userId = session.getUserId(); - TournamentManager.instance.quit(tournamentId, userId); + managerFactory.tournamentManager().quit(tournamentId, userId); }); } ); @@ -786,14 +767,14 @@ public class MageServerImpl implements MageServer { try { callExecutor.execute( () -> { - SessionManager.instance.getSession(sessionId).ifPresent( + managerFactory.sessionManager().getSession(sessionId).ifPresent( session -> { UUID userId = session.getUserId(); - UUID tableId = DraftManager.instance.getControllerByDraftId(draftId).getTableId(); - Table table = TableManager.instance.getTable(tableId); + UUID tableId = managerFactory.draftManager().getControllerByDraftId(draftId).getTableId(); + Table table = managerFactory.tableManager().getTable(tableId); if (table.isTournament()) { UUID tournamentId = table.getTournament().getId(); - TournamentManager.instance.quit(tournamentId, userId); + managerFactory.tournamentManager().quit(tournamentId, userId); } }); } @@ -808,9 +789,9 @@ public class MageServerImpl implements MageServer { @Override public void sendPlayerAction(final PlayerAction playerAction, final UUID gameId, final String sessionId, final Object data) throws MageException { execute("sendPlayerAction", sessionId, () -> { - SessionManager.instance.getSession(sessionId).ifPresent(session -> { + managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> { UUID userId = session.getUserId(); - GameManager.instance.sendPlayerAction(playerAction, gameId, userId, data); + managerFactory.gameManager().sendPlayerAction(playerAction, gameId, userId, data); }); }); } @@ -820,14 +801,14 @@ public class MageServerImpl implements MageServer { return executeWithResult("setUserData", sessionId, new ActionWithBooleanResult() { @Override public Boolean execute() throws MageException { - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { logger.error("Session not found : " + sessionId); return false; } else { UUID userId = session.get().getUserId(); - if (GamesRoomManager.instance.getRoom(roomId).isPresent()) { - return GamesRoomManager.instance.getRoom(roomId).get().watchTable(userId, tableId); + if (managerFactory.gamesRoomManager().getRoom(roomId).isPresent()) { + return managerFactory.gamesRoomManager().getRoom(roomId).get().watchTable(userId, tableId); } else { return false; } @@ -846,10 +827,10 @@ public class MageServerImpl implements MageServer { return executeWithResult("watchGame", sessionId, new ActionWithResult() { @Override public Boolean execute() throws MageException { - return SessionManager.instance.getSession(sessionId) + return managerFactory.sessionManager().getSession(sessionId) .map(session -> { UUID userId = session.getUserId(); - return GameManager.instance.watchGame(gameId, userId); + return managerFactory.gameManager().watchGame(gameId, userId); }).orElse(false); } @@ -863,10 +844,10 @@ public class MageServerImpl implements MageServer { @Override public void stopWatching(final UUID gameId, final String sessionId) throws MageException { execute("stopWatching", sessionId, () -> { - SessionManager.instance.getSession(sessionId).ifPresent(session -> { + managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> { UUID userId = session.getUserId(); - UserManager.instance.getUser(userId).ifPresent(user -> { - GameManager.instance.stopWatching(gameId, userId); + managerFactory.userManager().getUser(userId).ifPresent(user -> { + managerFactory.gameManager().stopWatching(gameId, userId); user.removeGameWatchInfo(gameId); }); }); @@ -877,9 +858,9 @@ public class MageServerImpl implements MageServer { @Override public void replayGame(final UUID gameId, final String sessionId) throws MageException { execute("replayGame", sessionId, () -> { - SessionManager.instance.getSession(sessionId).ifPresent(session -> { + managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> { UUID userId = session.getUserId(); - ReplayManager.instance.replayGame(gameId, userId); + managerFactory.replayManager().replayGame(gameId, userId); }); }); } @@ -887,9 +868,9 @@ public class MageServerImpl implements MageServer { @Override public void startReplay(final UUID gameId, final String sessionId) throws MageException { execute("startReplay", sessionId, () -> { - SessionManager.instance.getSession(sessionId).ifPresent(session -> { + managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> { UUID userId = session.getUserId(); - ReplayManager.instance.startReplay(gameId, userId); + managerFactory.replayManager().startReplay(gameId, userId); }); }); } @@ -897,12 +878,12 @@ public class MageServerImpl implements MageServer { @Override public void stopReplay(final UUID gameId, final String sessionId) throws MageException { execute("stopReplay", sessionId, () -> { - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { logger.error("Session not found : " + sessionId); } else { UUID userId = session.get().getUserId(); - ReplayManager.instance.stopReplay(gameId, userId); + managerFactory.replayManager().stopReplay(gameId, userId); } }); } @@ -910,12 +891,12 @@ public class MageServerImpl implements MageServer { @Override public void nextPlay(final UUID gameId, final String sessionId) throws MageException { execute("nextPlay", sessionId, () -> { - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { logger.error("Session not found : " + sessionId); } else { UUID userId = session.get().getUserId(); - ReplayManager.instance.nextPlay(gameId, userId); + managerFactory.replayManager().nextPlay(gameId, userId); } }); } @@ -923,12 +904,12 @@ public class MageServerImpl implements MageServer { @Override public void previousPlay(final UUID gameId, final String sessionId) throws MageException { execute("previousPlay", sessionId, () -> { - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { logger.error("Session not found : " + sessionId); } else { UUID userId = session.get().getUserId(); - ReplayManager.instance.previousPlay(gameId, userId); + managerFactory.replayManager().previousPlay(gameId, userId); } }); } @@ -936,12 +917,12 @@ public class MageServerImpl implements MageServer { @Override public void skipForward(final UUID gameId, final String sessionId, final int moves) throws MageException { execute("skipForward", sessionId, () -> { - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { logger.error("Session not found : " + sessionId); } else { UUID userId = session.get().getUserId(); - ReplayManager.instance.skipForward(gameId, userId, moves); + managerFactory.replayManager().skipForward(gameId, userId, moves); } }); } @@ -971,9 +952,9 @@ public class MageServerImpl implements MageServer { public void cheat(final UUID gameId, final String sessionId, final UUID playerId, final DeckCardLists deckList) throws MageException { execute("cheat", sessionId, () -> { if (testMode) { - SessionManager.instance.getSession(sessionId).ifPresent(session -> { + managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> { UUID userId = session.getUserId(); - GameManager.instance.cheat(gameId, userId, playerId, deckList); + managerFactory.gameManager().cheat(gameId, userId, playerId, deckList); }); } }); @@ -985,12 +966,12 @@ public class MageServerImpl implements MageServer { @Override public Boolean execute() { if (testMode) { - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { logger.error("Session not found : " + sessionId); } else { UUID userId = session.get().getUserId(); - return GameManager.instance.cheat(gameId, userId, playerId, cardName); + return managerFactory.gameManager().cheat(gameId, userId, playerId, cardName); } } return false; @@ -1024,13 +1005,13 @@ public class MageServerImpl implements MageServer { @Override public void disconnectUser(final String sessionId, final String userSessionId) throws MageException { - execute("disconnectUser", sessionId, () -> SessionManager.instance.disconnectUser(sessionId, userSessionId)); + execute("disconnectUser", sessionId, () -> managerFactory.sessionManager().disconnectUser(sessionId, userSessionId)); } @Override public void muteUser(final String sessionId, final String userName, final long durationMinutes) throws MageException { execute("muteUser", sessionId, () -> { - UserManager.instance.getUserByName(userName).ifPresent(user -> { + managerFactory.userManager().getUserByName(userName).ifPresent(user -> { Date muteUntil = new Date(Calendar.getInstance().getTimeInMillis() + (durationMinutes * Timer.ONE_MINUTE)); user.showUserMessage("Admin info", "You were muted for chat messages until " + SystemUtil.dateFormat.format(muteUntil) + '.'); user.setChatLockedUntil(muteUntil); @@ -1042,12 +1023,12 @@ public class MageServerImpl implements MageServer { @Override public void lockUser(final String sessionId, final String userName, final long durationMinutes) throws MageException { execute("lockUser", sessionId, () -> { - UserManager.instance.getUserByName(userName).ifPresent(user -> { + managerFactory.userManager().getUserByName(userName).ifPresent(user -> { Date lockUntil = new Date(Calendar.getInstance().getTimeInMillis() + (durationMinutes * Timer.ONE_MINUTE)); user.showUserMessage("Admin info", "Your user profile was locked until " + SystemUtil.dateFormat.format(lockUntil) + '.'); user.setLockedUntil(lockUntil); if (user.isConnected()) { - SessionManager.instance.disconnectUser(sessionId, user.getSessionId()); + managerFactory.sessionManager().disconnectUser(sessionId, user.getSessionId()); } }); @@ -1058,15 +1039,15 @@ public class MageServerImpl implements MageServer { public void setActivation(final String sessionId, final String userName, boolean active) throws MageException { execute("setActivation", sessionId, () -> { AuthorizedUser authorizedUser = AuthorizedUserRepository.instance.getByName(userName); - Optional u = UserManager.instance.getUserByName(userName); + Optional u = managerFactory.userManager().getUserByName(userName); if (u.isPresent()) { User user = u.get(); user.setActive(active); if (!user.isActive() && user.isConnected()) { - SessionManager.instance.disconnectUser(sessionId, user.getSessionId()); + managerFactory.sessionManager().disconnectUser(sessionId, user.getSessionId()); } } else if (authorizedUser != null) { - User theUser = new User(userName, "localhost", authorizedUser); + User theUser = new User(managerFactory, userName, "localhost", authorizedUser); theUser.setActive(active); } @@ -1076,18 +1057,18 @@ public class MageServerImpl implements MageServer { @Override public void toggleActivation(final String sessionId, final String userName) throws MageException { execute("toggleActivation", sessionId, () - -> UserManager.instance.getUserByName(userName).ifPresent(user + -> managerFactory.userManager().getUserByName(userName).ifPresent(user -> { user.setActive(!user.isActive()); if (!user.isActive() && user.isConnected()) { - SessionManager.instance.disconnectUser(sessionId, user.getSessionId()); + managerFactory.sessionManager().disconnectUser(sessionId, user.getSessionId()); } })); } @Override public void endUserSession(final String sessionId, final String userSessionId) throws MageException { - execute("endUserSession", sessionId, () -> SessionManager.instance.endUserSession(sessionId, userSessionId)); + execute("endUserSession", sessionId, () -> managerFactory.sessionManager().endUserSession(sessionId, userSessionId)); } /** @@ -1100,9 +1081,9 @@ public class MageServerImpl implements MageServer { @Override public void removeTable(final String sessionId, final UUID tableId) throws MageException { execute("removeTable", sessionId, () -> { - SessionManager.instance.getSession(sessionId).ifPresent(session -> { + managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> { UUID userId = session.getUserId(); - TableManager.instance.removeTable(userId, tableId); + managerFactory.tableManager().removeTable(userId, tableId); }); }); } @@ -1116,7 +1097,7 @@ public class MageServerImpl implements MageServer { public void sendFeedbackMessage(final String sessionId, final String username, final String title, final String type, final String message, final String email) throws MageException { if (title != null && message != null) { execute("sendFeedbackMessage", sessionId, () - -> SessionManager.instance.getSession(sessionId).ifPresent( + -> managerFactory.sessionManager().getSession(sessionId).ifPresent( session -> FeedbackServiceImpl.instance.feedback(username, title, type, message, email, session.getHost()) )); } @@ -1126,7 +1107,7 @@ public class MageServerImpl implements MageServer { public void sendBroadcastMessage(final String sessionId, final String message) throws MageException { if (message != null) { execute("sendBroadcastMessage", sessionId, () -> { - for (User user : UserManager.instance.getUsers()) { + for (User user : managerFactory.userManager().getUsers()) { if (message.toLowerCase(Locale.ENGLISH).startsWith("warn")) { user.fireCallback(new ClientCallback(ClientCallbackMethod.SERVER_MESSAGE, null, new ChatMessage("SERVER", message, null, null, MessageColor.RED))); } else { @@ -1138,12 +1119,12 @@ public class MageServerImpl implements MageServer { } private void sendErrorMessageToClient(final String sessionId, final String message) throws MageException { - execute("sendErrorMessageToClient", sessionId, () -> SessionManager.instance.sendErrorMessageToClient(sessionId, message)); + execute("sendErrorMessageToClient", sessionId, () -> managerFactory.sessionManager().sendErrorMessageToClient(sessionId, message)); } protected void execute(final String actionName, final String sessionId, final Action action, boolean checkAdminRights) throws MageException { if (checkAdminRights) { - if (!SessionManager.instance.isAdmin(sessionId)) { + if (!managerFactory.sessionManager().isAdmin(sessionId)) { return; } } @@ -1151,11 +1132,11 @@ public class MageServerImpl implements MageServer { } protected void execute(final String actionName, final String sessionId, final Action action) throws MageException { - if (SessionManager.instance.isValidSession(sessionId)) { + if (managerFactory.sessionManager().isValidSession(sessionId)) { try { callExecutor.execute( () -> { - if (SessionManager.instance.isValidSession(sessionId)) { + if (managerFactory.sessionManager().isValidSession(sessionId)) { try { action.execute(); } catch (MageException me) { @@ -1172,7 +1153,7 @@ public class MageServerImpl implements MageServer { protected T executeWithResult(String actionName, final String sessionId, final ActionWithResult action, boolean checkAdminRights) throws MageException { if (checkAdminRights) { - if (!SessionManager.instance.isAdmin(sessionId)) { + if (!managerFactory.sessionManager().isAdmin(sessionId)) { return action.negativeResult(); } } @@ -1181,7 +1162,7 @@ public class MageServerImpl implements MageServer { //TODO: also run in threads with future task protected T executeWithResult(String actionName, final String sessionId, final ActionWithResult action) throws MageException { - if (SessionManager.instance.isValidSession(sessionId)) { + if (managerFactory.sessionManager().isValidSession(sessionId)) { try { return action.execute(); } catch (Exception ex) { @@ -1218,15 +1199,15 @@ public class MageServerImpl implements MageServer { } } - private static class ListActionWithNullNegativeResult extends ActionWithNullNegativeResult> { + private class ListActionWithNullNegativeResult extends ActionWithNullNegativeResult> { @Override public List execute() throws MageException { - return UserManager.instance.getUserInfoList(); + return managerFactory.userManager().getUserInfoList(); } } - private static class GameViewActionWithNullNegativeResult extends ActionWithNullNegativeResult { + private class GameViewActionWithNullNegativeResult extends ActionWithNullNegativeResult { private final String sessionId; private final UUID gameId; @@ -1240,18 +1221,18 @@ public class MageServerImpl implements MageServer { @Override public GameView execute() throws MageException { - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { logger.error("Session not found : " + sessionId); return null; } else { //UUID userId = session.get().getUserId(); - return GameManager.instance.getGameView(gameId, playerId); + return managerFactory.gameManager().getGameView(gameId, playerId); } } } - private static class MyActionWithBooleanResult extends ActionWithBooleanResult { + private class MyActionWithBooleanResult extends ActionWithBooleanResult { private final String sessionId; private final UUID tableId; @@ -1263,17 +1244,17 @@ public class MageServerImpl implements MageServer { @Override public Boolean execute() throws MageException { - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { return false; } else { UUID userId = session.get().getUserId(); - return TableManager.instance.watchTable(userId, tableId); + return managerFactory.tableManager().watchTable(userId, tableId); } } } - private static class DraftPickViewActionWithNullNegativeResult extends ActionWithNullNegativeResult { + private class DraftPickViewActionWithNullNegativeResult extends ActionWithNullNegativeResult { private final String sessionId; private final UUID draftId; @@ -1289,9 +1270,9 @@ public class MageServerImpl implements MageServer { @Override public DraftPickView execute() { - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (session.isPresent()) { - return DraftManager.instance.sendCardPick(draftId, session.get().getUserId(), cardPick, hiddenCards); + return managerFactory.draftManager().sendCardPick(draftId, session.get().getUserId(), cardPick, hiddenCards); } else { logger.error("Session not found sessionId: " + sessionId + " draftId:" + draftId); } @@ -1299,7 +1280,7 @@ public class MageServerImpl implements MageServer { } } - private static class MyActionWithTableViewResult extends ActionWithTableViewResult { + private class MyActionWithTableViewResult extends ActionWithTableViewResult { private final String sessionId; private final MatchOptions options; @@ -1313,12 +1294,12 @@ public class MageServerImpl implements MageServer { @Override public TableView execute() throws MageException { - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { return null; } UUID userId = session.get().getUserId(); - Optional _user = UserManager.instance.getUser(userId); + Optional _user = managerFactory.userManager().getUser(userId); if (!_user.isPresent()) { logger.error("User for session not found. session = " + sessionId); return null; @@ -1349,13 +1330,13 @@ public class MageServerImpl implements MageServer { user.showUserMessage("Create table", message); throw new MageException("No message"); } - Optional room = GamesRoomManager.instance.getRoom(roomId); + Optional room = managerFactory.gamesRoomManager().getRoom(roomId); if (room.isPresent()) { TableView table = room.get().createTable(userId, options); if (logger.isDebugEnabled()) { logger.debug("TABLE created - tableId: " + table.getTableId() + ' ' + table.getTableName()); logger.debug("- " + user.getName() + " userId: " + user.getId()); - logger.debug("- chatId: " + TableManager.instance.getChatId(table.getTableId())); + logger.debug("- chatId: " + managerFactory.tableManager().getChatId(table.getTableId())); } return table; } else { diff --git a/Mage.Server/src/main/java/mage/server/MailClient.java b/Mage.Server/src/main/java/mage/server/MailClient.java index 69e9518b77..fc830ac1ff 100644 --- a/Mage.Server/src/main/java/mage/server/MailClient.java +++ b/Mage.Server/src/main/java/mage/server/MailClient.java @@ -1,25 +1,32 @@ package mage.server; -import java.util.Properties; +import mage.server.managers.IConfigSettings; +import mage.server.managers.IMailClient; +import org.apache.log4j.Logger; + import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; -import mage.server.util.ConfigSettings; -import org.apache.log4j.Logger; +import java.util.Properties; -public final class MailClient { +public class MailClient implements IMailClient { private static final Logger logger = Logger.getLogger(Main.class); - public static boolean sendMessage(String email, String subject, String text) { + private final IConfigSettings config; + + public MailClient(IConfigSettings config) { + this.config = config; + } + + public boolean sendMessage(String email, String subject, String text) { if (email.isEmpty()) { logger.info("Email is not sent because the address is empty"); return false; } - ConfigSettings config = ConfigSettings.instance; Properties properties = System.getProperties(); properties.setProperty("mail.smtps.host", config.getMailSmtpHost()); @@ -30,7 +37,7 @@ public final class MailClient { Session session = Session.getDefaultInstance(properties); - try{ + try { MimeMessage message = new MimeMessage(session); message.setFrom(new InternetAddress(config.getMailFromAddress())); message.addRecipient(Message.RecipientType.TO, new InternetAddress(email)); @@ -44,7 +51,7 @@ public final class MailClient { trnsport.close(); return true; - }catch (MessagingException ex) { + } catch (MessagingException ex) { logger.error("Error sending message to " + email, ex); } return false; diff --git a/Mage.Server/src/main/java/mage/server/MailgunClient.java b/Mage.Server/src/main/java/mage/server/MailgunClient.java index 6cca110a0b..70264baa77 100644 --- a/Mage.Server/src/main/java/mage/server/MailgunClient.java +++ b/Mage.Server/src/main/java/mage/server/MailgunClient.java @@ -5,29 +5,37 @@ import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.WebResource; import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; import com.sun.jersey.core.util.MultivaluedMapImpl; -import javax.ws.rs.core.MediaType; -import mage.server.util.ConfigSettings; +import mage.server.managers.IConfigSettings; +import mage.server.managers.IMailClient; import org.apache.log4j.Logger; -public final class MailgunClient { +import javax.ws.rs.core.MediaType; + +public class MailgunClient implements IMailClient { private static final Logger logger = Logger.getLogger(Main.class); - public static boolean sendMessage(String email, String subject, String text) { + private final IConfigSettings config; + + public MailgunClient(IConfigSettings config) { + this.config = config; + } + + public boolean sendMessage(String email, String subject, String text) { if (email.isEmpty()) { logger.info("Email is not sent because the address is empty"); return false; } Client client = Client.create(); - client.addFilter(new HTTPBasicAuthFilter("api", ConfigSettings.instance.getMailgunApiKey())); - String domain = ConfigSettings.instance.getMailgunDomain(); + client.addFilter(new HTTPBasicAuthFilter("api", config.getMailgunApiKey())); + String domain = config.getMailgunDomain(); WebResource webResource = client.resource("https://api.mailgun.net/v3/" + domain + "/messages"); MultivaluedMapImpl formData = new MultivaluedMapImpl(); formData.add("from", "XMage '); formData.add("to", email); formData.add("subject", subject); formData.add("text", text); - ClientResponse response = webResource.type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, formData); + ClientResponse response = webResource.type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, formData); boolean succeeded = response.getStatus() == 200; if (!succeeded) { logger.error("Error sending message to " + email + ". Status code: " + response.getStatus()); diff --git a/Mage.Server/src/main/java/mage/server/Main.java b/Mage.Server/src/main/java/mage/server/Main.java index a9b617cd7c..b2721b0639 100644 --- a/Mage.Server/src/main/java/mage/server/Main.java +++ b/Mage.Server/src/main/java/mage/server/Main.java @@ -14,12 +14,11 @@ import mage.remote.Connection; import mage.server.draft.CubeFactory; import mage.server.game.GameFactory; import mage.server.game.PlayerFactory; +import mage.server.managers.IConfigSettings; +import mage.server.managers.ManagerFactory; import mage.server.record.UserStatsRepository; import mage.server.tournament.TournamentFactory; -import mage.server.util.ConfigSettings; -import mage.server.util.PluginClassLoader; -import mage.server.util.ServerMessagesUtil; -import mage.server.util.SystemUtil; +import mage.server.util.*; import mage.server.util.config.GamePlugin; import mage.server.util.config.Plugin; import mage.utils.MageVersion; @@ -70,7 +69,7 @@ public final class Main { logger.info("Starting MAGE server version " + version); logger.info("Logging level: " + logger.getEffectiveLevel()); logger.info("Default charset: " + Charset.defaultCharset()); - + final ConfigWrapper config = new ConfigWrapper(ConfigFactory.loadFromFile("config/config.xml")); String adminPassword = ""; for (String arg : args) { if (arg.startsWith(testModeArg)) { @@ -83,7 +82,7 @@ public final class Main { } } - if (ConfigSettings.instance.isAuthenticationActivated()) { + if (config.isAuthenticationActivated()) { logger.info("Check authorized user DB version ..."); if (!AuthorizedUserRepository.instance.checkAlterAndMigrateAuthorizedUser()) { logger.fatal("Failed to start server."); @@ -148,7 +147,6 @@ public final class Main { UserStatsRepository.instance.updateUserStats(); logger.info("Done."); deleteSavedGames(); - ConfigSettings config = ConfigSettings.instance; for (GamePlugin plugin : config.getGameTypes()) { GameFactory.instance.addGameType(plugin.getName(), loadGameType(plugin), loadPlugin(plugin)); } @@ -206,11 +204,12 @@ public final class Main { Connection connection = new Connection("&maxPoolSize=" + config.getMaxPoolSize()); connection.setHost(config.getServerAddress()); connection.setPort(config.getPort()); + final ManagerFactory managerFactory = new MainManagerFactory(config); try { // Parameter: serializationtype => jboss InvokerLocator serverLocator = new InvokerLocator(connection.getURI()); - if (!isAlreadyRunning(serverLocator)) { - server = new MageTransporterServer(serverLocator, new MageServerImpl(adminPassword, testMode), MageServer.class.getName(), new MageServerInvocationHandler()); + if (!isAlreadyRunning(config, serverLocator)) { + server = new MageTransporterServer(managerFactory, serverLocator, new MageServerImpl(managerFactory, adminPassword, testMode), MageServer.class.getName(), new MageServerInvocationHandler(managerFactory)); server.start(); logger.info("Started MAGE server - listening on " + connection.toString()); @@ -230,9 +229,9 @@ public final class Main { ServerMessagesUtil.instance.setStartDate(System.currentTimeMillis()); } - static boolean isAlreadyRunning(InvokerLocator serverLocator) { + static boolean isAlreadyRunning(IConfigSettings config, InvokerLocator serverLocator) { Map metadata = new HashMap<>(); - metadata.put(SocketWrapper.WRITE_TIMEOUT, String.valueOf(ConfigSettings.instance.getSocketWriteTimeout())); + metadata.put(SocketWrapper.WRITE_TIMEOUT, String.valueOf(config.getSocketWriteTimeout())); metadata.put("generalizeSocketException", "true"); try { MageServer testServer = (MageServer) TransporterClient.createTransporterClient(serverLocator.getLocatorURI(), MageServer.class, metadata); @@ -248,16 +247,22 @@ public final class Main { static class ClientConnectionListener implements ConnectionListener { + private final ManagerFactory managerFactory; + + public ClientConnectionListener(ManagerFactory managerFactory) { + this.managerFactory = managerFactory; + } + @Override public void handleConnectionException(Throwable throwable, Client client) { String sessionId = client.getSessionId(); - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { logger.trace("Session not found : " + sessionId); } else { UUID userId = session.get().getUserId(); StringBuilder sessionInfo = new StringBuilder(); - Optional user = UserManager.instance.getUser(userId); + Optional user = managerFactory.userManager().getUser(userId); if (user.isPresent()) { sessionInfo.append(user.get().getName()).append(" [").append(user.get().getGameInfo()).append(']'); } else { @@ -267,12 +272,12 @@ public final class Main { if (throwable instanceof ClientDisconnectedException) { // Seems like the random diconnects from public server land here and should not be handled as explicit disconnects // So it should be possible to reconnect to server and continue games if DisconnectReason is set to LostConnection - //SessionManager.instance.disconnect(client.getSessionId(), DisconnectReason.Disconnected); - SessionManager.instance.disconnect(client.getSessionId(), DisconnectReason.LostConnection); + //managerFactory.sessionManager().disconnect(client.getSessionId(), DisconnectReason.Disconnected); + managerFactory.sessionManager().disconnect(client.getSessionId(), DisconnectReason.LostConnection); logger.info("CLIENT DISCONNECTED - " + sessionInfo); logger.debug("Stack Trace", throwable); } else { - SessionManager.instance.disconnect(client.getSessionId(), DisconnectReason.LostConnection); + managerFactory.sessionManager().disconnect(client.getSessionId(), DisconnectReason.LostConnection); logger.info("LOST CONNECTION - " + sessionInfo); if (logger.isDebugEnabled()) { if (throwable == null) { @@ -292,11 +297,11 @@ public final class Main { protected Connector connector; - public MageTransporterServer(InvokerLocator locator, Object target, String subsystem, MageServerInvocationHandler serverInvocationHandler) throws Exception { + public MageTransporterServer(ManagerFactory managerFactory, InvokerLocator locator, Object target, String subsystem, MageServerInvocationHandler serverInvocationHandler) throws Exception { super(locator, target, subsystem); connector.addInvocationHandler("callback", serverInvocationHandler); - connector.setLeasePeriod(ConfigSettings.instance.getLeasePeriod()); - connector.addConnectionListener(new ClientConnectionListener()); + connector.setLeasePeriod(managerFactory.configSettings().getLeasePeriod()); + connector.addConnectionListener(new ClientConnectionListener(managerFactory)); } public Connector getConnector() throws Exception { @@ -313,6 +318,12 @@ public final class Main { static class MageServerInvocationHandler implements ServerInvocationHandler { + private final ManagerFactory managerFactory; + + public MageServerInvocationHandler(ManagerFactory managerFactory) { + this.managerFactory = managerFactory; + } + @Override public void setMBeanServer(MBeanServer server) { /** @@ -333,9 +344,9 @@ public final class Main { @Override public void setInvoker(ServerInvoker invoker) { - ((BisocketServerInvoker) invoker).setSecondaryBindPort(ConfigSettings.instance.getSecondaryBindPort()); - ((BisocketServerInvoker) invoker).setBacklog(ConfigSettings.instance.getBacklogSize()); - ((BisocketServerInvoker) invoker).setNumAcceptThreads(ConfigSettings.instance.getNumAcceptThreads()); + ((BisocketServerInvoker) invoker).setSecondaryBindPort(managerFactory.configSettings().getSecondaryBindPort()); + ((BisocketServerInvoker) invoker).setBacklog(managerFactory.configSettings().getBacklogSize()); + ((BisocketServerInvoker) invoker).setNumAcceptThreads(managerFactory.configSettings().getNumAcceptThreads()); } @Override @@ -344,7 +355,7 @@ public final class Main { ServerInvokerCallbackHandler handler = (ServerInvokerCallbackHandler) callbackHandler; try { String sessionId = handler.getClientSessionId(); - SessionManager.instance.createSession(sessionId, callbackHandler); + managerFactory.sessionManager().createSession(sessionId, callbackHandler); } catch (Throwable ex) { logger.fatal("", ex); } @@ -362,7 +373,7 @@ public final class Main { } else { host = "localhost"; } - Optional session = SessionManager.instance.getSession(sessionId); + Optional session = managerFactory.sessionManager().getSession(sessionId); if (!session.isPresent()) { logger.error("Session not found : " + sessionId); } else { @@ -375,7 +386,7 @@ public final class Main { public void removeListener(InvokerCallbackHandler callbackHandler) { ServerInvokerCallbackHandler handler = (ServerInvokerCallbackHandler) callbackHandler; String sessionId = handler.getClientSessionId(); - SessionManager.instance.disconnect(sessionId, DisconnectReason.Disconnected); + managerFactory.sessionManager().disconnect(sessionId, DisconnectReason.Disconnected); } } diff --git a/Mage.Server/src/main/java/mage/server/MainManagerFactory.java b/Mage.Server/src/main/java/mage/server/MainManagerFactory.java new file mode 100644 index 0000000000..cacbc635c2 --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/MainManagerFactory.java @@ -0,0 +1,118 @@ +package mage.server; + +import mage.server.draft.DraftManager; +import mage.server.game.GameManager; +import mage.server.game.GamesRoomManager; +import mage.server.game.ReplayManager; +import mage.server.managers.*; +import mage.server.tournament.TournamentManager; +import mage.server.util.ThreadExecutor; + +public class MainManagerFactory implements ManagerFactory { + + private final IConfigSettings configSettings; + private final IThreadExecutor threadExecutor; + private final IChatManager chatManager; + private final IDraftManager draftManager; + private final IGameManager gameManager; + private final IGamesRoomManager gamesRoomManager; + private final IMailClient mailClient; + private final IMailClient mailgunClient; + private final IReplayManager replayManager; + private final ISessionManager sessionManager; + private final ITableManager tableManager; + private final IUserManager userManager; + private final ITournamentManager tournamentManager; + + + public MainManagerFactory(IConfigSettings configSettings) { + this.configSettings = configSettings; + this.threadExecutor = new ThreadExecutor(configSettings); + this.mailClient = new MailClient(configSettings); + this.mailgunClient = new MailgunClient(configSettings); + this.chatManager = new ChatManager(this); + this.draftManager = new DraftManager(this); + this.gameManager = new GameManager(this); + this.replayManager = new ReplayManager(this); + this.sessionManager = new SessionManager(this); + this.tournamentManager = new TournamentManager(this); + final GamesRoomManager gamesRoomManager = new GamesRoomManager(this); + final TableManager tableManager = new TableManager(this); + final UserManager userManager = new UserManager(this); + this.gamesRoomManager = gamesRoomManager; + this.tableManager = tableManager; + this.userManager = userManager; + startThreads(gamesRoomManager, tableManager, userManager); + } + + private void startThreads(GamesRoomManager gamesRoomManager, TableManager tableManager, UserManager userManager) { + userManager.init(); + tableManager.init(); + gamesRoomManager.init(); + } + + @Override + public IChatManager chatManager() { + return chatManager; + } + + @Override + public IDraftManager draftManager() { + return draftManager; + } + + @Override + public IGameManager gameManager() { + return gameManager; + } + + @Override + public IGamesRoomManager gamesRoomManager() { + return gamesRoomManager; + } + + @Override + public IMailClient mailClient() { + return mailClient; + } + + @Override + public IMailClient mailgunClient() { + return mailgunClient; + } + + @Override + public IReplayManager replayManager() { + return replayManager; + } + + @Override + public ISessionManager sessionManager() { + return sessionManager; + } + + @Override + public ITableManager tableManager() { + return tableManager; + } + + @Override + public IUserManager userManager() { + return userManager; + } + + @Override + public IConfigSettings configSettings() { + return configSettings; + } + + @Override + public IThreadExecutor threadExecutor() { + return threadExecutor; + } + + @Override + public ITournamentManager tournamentManager() { + return tournamentManager; + } +} diff --git a/Mage.Server/src/main/java/mage/server/RoomImpl.java b/Mage.Server/src/main/java/mage/server/RoomImpl.java index d92de7b9f0..aa896a91fc 100644 --- a/Mage.Server/src/main/java/mage/server/RoomImpl.java +++ b/Mage.Server/src/main/java/mage/server/RoomImpl.java @@ -1,11 +1,10 @@ - - package mage.server; +import mage.server.managers.IChatManager; + import java.util.UUID; /** - * * @author BetaSteward_at_googlemail.com */ public abstract class RoomImpl implements Room { @@ -13,9 +12,9 @@ public abstract class RoomImpl implements Room { private final UUID chatId; private final UUID roomId; - public RoomImpl() { + public RoomImpl(IChatManager chatManager) { roomId = UUID.randomUUID(); - chatId = ChatManager.instance.createChatSession("Room " + roomId); + chatId = chatManager.createChatSession("Room " + roomId); } /** @@ -35,5 +34,4 @@ public abstract class RoomImpl implements Room { } - } diff --git a/Mage.Server/src/main/java/mage/server/Session.java b/Mage.Server/src/main/java/mage/server/Session.java index 10f0c79876..66d22cb210 100644 --- a/Mage.Server/src/main/java/mage/server/Session.java +++ b/Mage.Server/src/main/java/mage/server/Session.java @@ -7,8 +7,8 @@ import mage.interfaces.callback.ClientCallbackMethod; import mage.players.net.UserData; import mage.players.net.UserGroup; import mage.server.game.GamesRoom; -import mage.server.game.GamesRoomManager; -import mage.server.util.ConfigSettings; +import mage.server.managers.IConfigSettings; +import mage.server.managers.ManagerFactory; import mage.server.util.SystemUtil; import mage.util.RandomUtil; import org.apache.log4j.Logger; @@ -34,6 +34,7 @@ public class Session { private static final Pattern alphabetsPattern = Pattern.compile("[a-zA-Z]"); private static final Pattern digitsPattern = Pattern.compile("[0-9]"); + private final ManagerFactory managerFactory; private final String sessionId; private UUID userId; private String host; @@ -46,7 +47,8 @@ public class Session { private final ReentrantLock lock; private final ReentrantLock callBackLock; - public Session(String sessionId, InvokerCallbackHandler callbackHandler) { + public Session(ManagerFactory managerFactory, String sessionId, InvokerCallbackHandler callbackHandler) { + this.managerFactory = managerFactory; this.sessionId = sessionId; this.callbackHandler = (AsynchInvokerCallbackHandler) callbackHandler; this.isAdmin = false; @@ -56,7 +58,7 @@ public class Session { } public String registerUser(String userName, String password, String email) throws MageException { - if (!ConfigSettings.instance.isAuthenticationActivated()) { + if (!managerFactory.configSettings().isAuthenticationActivated()) { String returnMessage = "Registration is disabled by the server config"; sendErrorMessageToClient(returnMessage); return returnMessage; @@ -86,10 +88,10 @@ public class Session { boolean success; String subject = "XMage Registration Completed"; - if (!ConfigSettings.instance.getMailUser().isEmpty()) { - success = MailClient.sendMessage(email, subject, text); + if (!managerFactory.configSettings().getMailUser().isEmpty()) { + success = managerFactory.mailClient().sendMessage(email, subject, text); } else { - success = MailgunClient.sendMessage(email, subject, text); + success = managerFactory.mailgunClient().sendMessage(email, subject, text); } if (success) { String ok = "Sent a registration confirmation / initial password email to " + email + " for " + userName; @@ -109,18 +111,18 @@ public class Session { } } - private static String validateUserName(String userName) { + private String validateUserName(String userName) { if (userName.equals("Admin")) { return "User name Admin already in use"; } - ConfigSettings config = ConfigSettings.instance; + IConfigSettings config = managerFactory.configSettings(); if (userName.length() < config.getMinUserNameLength()) { return "User name may not be shorter than " + config.getMinUserNameLength() + " characters"; } if (userName.length() > config.getMaxUserNameLength()) { return "User name may not be longer than " + config.getMaxUserNameLength() + " characters"; } - Pattern invalidUserNamePattern = Pattern.compile(ConfigSettings.instance.getInvalidUserNamePattern(), Pattern.CASE_INSENSITIVE); + Pattern invalidUserNamePattern = Pattern.compile(managerFactory.configSettings().getInvalidUserNamePattern(), Pattern.CASE_INSENSITIVE); Matcher m = invalidUserNamePattern.matcher(userName); if (m.find()) { return "User name '" + userName + "' includes not allowed characters: use a-z, A-Z and 0-9"; @@ -132,8 +134,8 @@ public class Session { return null; } - private static String validatePassword(String password, String userName) { - ConfigSettings config = ConfigSettings.instance; + private String validatePassword(String password, String userName) { + IConfigSettings config = managerFactory.configSettings(); if (password.length() < config.getMinPasswordLength()) { return "Password may not be shorter than " + config.getMinPasswordLength() + " characters"; } @@ -178,7 +180,7 @@ public class Session { public String connectUserHandling(String userName, String password) throws MageException { this.isAdmin = false; AuthorizedUser authorizedUser = null; - if (ConfigSettings.instance.isAuthenticationActivated()) { + if (managerFactory.configSettings().isAuthenticationActivated()) { authorizedUser = AuthorizedUserRepository.instance.getByName(userName); String errorMsg = "Wrong username or password. In case you haven't, please register your account first."; if (authorizedUser == null) { @@ -196,7 +198,7 @@ public class Session { if (authorizedUser.lockedUntil.compareTo(Calendar.getInstance().getTime()) > 0) { return "Your profile is deactivated until " + SystemUtil.dateFormat.format(authorizedUser.lockedUntil); } else { - UserManager.instance.createUser(userName, host, authorizedUser).ifPresent(user + managerFactory.userManager().createUser(userName, host, authorizedUser).ifPresent(user -> user.setLockedUntil(null) ); @@ -204,15 +206,15 @@ public class Session { } } - Optional selectUser = UserManager.instance.createUser(userName, host, authorizedUser); + Optional selectUser = managerFactory.userManager().createUser(userName, host, authorizedUser); boolean reconnect = false; if (!selectUser.isPresent()) { // user already connected - selectUser = UserManager.instance.getUserByName(userName); + selectUser = managerFactory.userManager().getUserByName(userName); if (selectUser.isPresent()) { User user = selectUser.get(); // If authentication is not activated, check the identity using IP address. - if (ConfigSettings.instance.isAuthenticationActivated() || user.getHost().equals(host)) { + if (managerFactory.configSettings().isAuthenticationActivated() || user.getHost().equals(host)) { user.updateLastActivity(null); // minimizes possible expiration this.userId = user.getId(); if (user.getSessionId().isEmpty()) { @@ -221,7 +223,7 @@ public class Session { } else { //disconnect previous session logger.info("Disconnecting another user instance: " + userName); - SessionManager.instance.disconnect(user.getSessionId(), DisconnectReason.ConnectingOtherInstance); + managerFactory.sessionManager().disconnect(user.getSessionId(), DisconnectReason.ConnectingOtherInstance); } } else { return "User name " + userName + " already in use (or your IP address changed)"; @@ -232,18 +234,18 @@ public class Session { } } User user = selectUser.get(); - if (!UserManager.instance.connectToSession(sessionId, user.getId())) { + if (!managerFactory.userManager().connectToSession(sessionId, user.getId())) { return "Error connecting " + userName; } this.userId = user.getId(); if (reconnect) { // must be connected to receive the message - Optional room = GamesRoomManager.instance.getRoom(GamesRoomManager.instance.getMainRoomId()); + Optional room = managerFactory.gamesRoomManager().getRoom(managerFactory.gamesRoomManager().getMainRoomId()); if (!room.isPresent()) { logger.warn("main room not found"); // after server restart users try to use old rooms on reconnect return null; } - ChatManager.instance.joinChat(room.get().getChatId(), userId); - ChatManager.instance.sendReconnectMessage(userId); + managerFactory.chatManager().joinChat(room.get().getChatId(), userId); + managerFactory.chatManager().sendReconnectMessage(userId); } return null; @@ -251,12 +253,12 @@ public class Session { public void connectAdmin() { this.isAdmin = true; - User user = UserManager.instance.createUser("Admin", host, null).orElse( - UserManager.instance.getUserByName("Admin").get()); + User user = managerFactory.userManager().createUser("Admin", host, null).orElse( + managerFactory.userManager().getUserByName("Admin").get()); UserData adminUserData = UserData.getDefaultUserDataView(); adminUserData.setGroupId(UserGroup.ADMIN.getGroupId()); user.setUserData(adminUserData); - if (!UserManager.instance.connectToSession(sessionId, user.getId())) { + if (!managerFactory.userManager().connectToSession(sessionId, user.getId())) { logger.info("Error connecting Admin!"); } else { user.setUserState(User.UserState.Connected); @@ -265,7 +267,7 @@ public class Session { } public boolean setUserData(String userName, UserData userData, String clientVersion, String userIdStr) { - Optional _user = UserManager.instance.getUserByName(userName); + Optional _user = managerFactory.userManager().getUserByName(userName); _user.ifPresent(user -> { if (clientVersion != null) { user.setClientVersion(clientVersion); @@ -313,7 +315,7 @@ public class Session { // because different threads can activate this public void userLostConnection() { - Optional _user = UserManager.instance.getUser(userId); + Optional _user = managerFactory.userManager().getUser(userId); if (!_user.isPresent()) { return; //user was already disconnected by other thread } @@ -338,7 +340,7 @@ public class Session { } else { logger.error("SESSION LOCK - kill: userId " + userId); } - UserManager.instance.removeUserFromAllTablesAndChat(userId, reason); + managerFactory.userManager().removeUserFromAllTablesAndChat(userId, reason); } catch (InterruptedException ex) { logger.error("SESSION LOCK - kill: userId " + userId, ex); } finally { @@ -372,11 +374,11 @@ public class Session { logger.warn("SESSION LOCK - fireCallback - userId: " + userId + " messageId: " + call.getMessageId(), ex); } catch (HandleCallbackException ex) { this.valid = false; - UserManager.instance.getUser(userId).ifPresent(user -> { + managerFactory.userManager().getUser(userId).ifPresent(user -> { user.setUserState(User.UserState.Disconnected); logger.warn("SESSION CALLBACK EXCEPTION - " + user.getName() + " userId " + userId + " messageId: " + call.getMessageId() + " - cause: " + getBasicCause(ex).toString()); logger.trace("Stack trace:", ex); - SessionManager.instance.disconnect(sessionId, LostConnection); + managerFactory.sessionManager().disconnect(sessionId, LostConnection); }); } catch (Exception ex) { logger.warn("Unspecific exception:", ex); diff --git a/Mage.Server/src/main/java/mage/server/SessionManager.java b/Mage.Server/src/main/java/mage/server/SessionManager.java index b87dc49c9c..9fa41f13f2 100644 --- a/Mage.Server/src/main/java/mage/server/SessionManager.java +++ b/Mage.Server/src/main/java/mage/server/SessionManager.java @@ -1,8 +1,9 @@ - package mage.server; import mage.MageException; import mage.players.net.UserData; +import mage.server.managers.ISessionManager; +import mage.server.managers.ManagerFactory; import org.apache.log4j.Logger; import org.jboss.remoting.callback.InvokerCallbackHandler; @@ -13,21 +14,25 @@ import java.util.concurrent.ConcurrentHashMap; /** * @author BetaSteward_at_googlemail.com */ -public enum SessionManager { - - instance; +public class SessionManager implements ISessionManager { private static final Logger logger = Logger.getLogger(SessionManager.class); + private final ManagerFactory managerFactory; private final ConcurrentHashMap sessions = new ConcurrentHashMap<>(); + public SessionManager(ManagerFactory managerFactory) { + this.managerFactory = managerFactory; + } + + @Override public Optional getSession(@Nonnull String sessionId) { Session session = sessions.get(sessionId); if (session == null) { logger.trace("Session with sessionId " + sessionId + " is not found"); return Optional.empty(); } - if (session.getUserId() != null && !UserManager.instance.getUser(session.getUserId()).isPresent()) { + if (session.getUserId() != null && !managerFactory.userManager().getUser(session.getUserId()).isPresent()) { logger.error("User for session " + sessionId + " with userId " + session.getUserId() + " is missing. Session removed."); // can happen if user from same host signs in multiple time with multiple clients, after they disconnect with one client disconnect(sessionId, DisconnectReason.ConnectingOtherInstance, session); // direct disconnect @@ -36,11 +41,13 @@ public enum SessionManager { return Optional.of(session); } + @Override public void createSession(String sessionId, InvokerCallbackHandler callbackHandler) { - Session session = new Session(sessionId, callbackHandler); + Session session = new Session(managerFactory, sessionId, callbackHandler); sessions.put(sessionId, session); } + @Override public boolean registerUser(String sessionId, String userName, String password, String email) throws MageException { Session session = sessions.get(sessionId); if (session == null) { @@ -59,6 +66,7 @@ public enum SessionManager { return true; } + @Override public boolean connectUser(String sessionId, String userName, String password, String userIdStr) throws MageException { Session session = sessions.get(sessionId); if (session != null) { @@ -78,6 +86,7 @@ public enum SessionManager { return false; } + @Override public boolean connectAdmin(String sessionId) { Session session = sessions.get(sessionId); if (session != null) { @@ -88,17 +97,20 @@ public enum SessionManager { return false; } + @Override public boolean setUserData(String userName, String sessionId, UserData userData, String clientVersion, String userIdStr) throws MageException { - return getSession(sessionId) - .map(session -> session.setUserData(userName,userData, clientVersion, userIdStr)) - .orElse(false); + return getSession(sessionId) + .map(session -> session.setUserData(userName, userData, clientVersion, userIdStr)) + .orElse(false); } + @Override public void disconnect(String sessionId, DisconnectReason reason) { disconnect(sessionId, reason, null); } + @Override public void disconnect(String sessionId, DisconnectReason reason, Session directSession) { if (directSession == null) { // find real session to disconnects @@ -115,13 +127,13 @@ public enum SessionManager { break; case ConnectingOtherInstance: case Disconnected: // regular session end or wrong client version - UserManager.instance.disconnect(session.getUserId(), reason); + managerFactory.userManager().disconnect(session.getUserId(), reason); break; case SessionExpired: // session ends after no reconnect happens in the defined time span break; case LostConnection: // user lost connection - session expires countdown starts session.userLostConnection(); - UserManager.instance.disconnect(session.getUserId(), reason); + managerFactory.userManager().disconnect(session.getUserId(), reason); break; default: logger.trace("endSession: unexpected reason " + reason.toString() + " - sessionId: " + sessionId); @@ -141,6 +153,7 @@ public enum SessionManager { * @param sessionId * @param userSessionId */ + @Override public void disconnectUser(String sessionId, String userSessionId) { if (isAdmin(sessionId)) { getUserFromSession(sessionId).ifPresent(admin -> { @@ -159,40 +172,46 @@ public enum SessionManager { private Optional getUserFromSession(String sessionId) { return getSession(sessionId) - .flatMap(s -> UserManager.instance.getUser(s.getUserId())); + .flatMap(s -> managerFactory.userManager().getUser(s.getUserId())); } + @Override public void endUserSession(String sessionId, String userSessionId) { if (isAdmin(sessionId)) { disconnect(userSessionId, DisconnectReason.AdminDisconnect); } } + @Override public boolean isAdmin(String sessionId) { return getSession(sessionId).map(Session::isAdmin).orElse(false); } + @Override public boolean isValidSession(@Nonnull String sessionId) { return sessions.containsKey(sessionId); } + @Override public Optional getUser(@Nonnull String sessionId) { Session session = sessions.get(sessionId); if (session != null) { - return UserManager.instance.getUser(sessions.get(sessionId).getUserId()); + return managerFactory.userManager().getUser(sessions.get(sessionId).getUserId()); } logger.error(String.format("Session %s could not be found", sessionId)); return Optional.empty(); } + @Override public boolean extendUserSession(String sessionId, String pingInfo) { return getSession(sessionId) - .map(session -> UserManager.instance.extendUserSession(session.getUserId(), pingInfo)) + .map(session -> managerFactory.userManager().extendUserSession(session.getUserId(), pingInfo)) .orElse(false); } + @Override public void sendErrorMessageToClient(String sessionId, String message) { Session session = sessions.get(sessionId); if (session == null) { diff --git a/Mage.Server/src/main/java/mage/server/TableController.java b/Mage.Server/src/main/java/mage/server/TableController.java index 868fd5f4ee..db4a24eabe 100644 --- a/Mage.Server/src/main/java/mage/server/TableController.java +++ b/Mage.Server/src/main/java/mage/server/TableController.java @@ -20,16 +20,12 @@ import mage.game.tournament.TournamentOptions; import mage.game.tournament.TournamentPlayer; import mage.players.Player; import mage.players.PlayerType; -import mage.server.draft.DraftManager; import mage.server.game.GameFactory; -import mage.server.game.GameManager; import mage.server.game.PlayerFactory; +import mage.server.managers.ManagerFactory; import mage.server.record.TableRecorderImpl; import mage.server.tournament.TournamentFactory; -import mage.server.tournament.TournamentManager; -import mage.server.util.ConfigSettings; import mage.server.util.ServerMessagesUtil; -import mage.server.util.ThreadExecutor; import mage.view.ChatMessage; import org.apache.log4j.Logger; @@ -47,6 +43,7 @@ public class TableController { private static final Logger logger = Logger.getLogger(TableController.class); + private final ManagerFactory managerFactory; private final UUID userId; private final UUID chatId; private final String controllerName; @@ -58,30 +55,34 @@ public class TableController { private Tournament tournament; private ScheduledFuture futureTimeout; - protected static final ScheduledExecutorService timeoutExecutor = ThreadExecutor.instance.getTimeoutExecutor(); + protected final ScheduledExecutorService timeoutExecutor; - public TableController(UUID roomId, UUID userId, MatchOptions options) { + public TableController(ManagerFactory managerFactory, UUID roomId, UUID userId, MatchOptions options) { + this.managerFactory = managerFactory; + timeoutExecutor = managerFactory.threadExecutor().getTimeoutExecutor(); this.userId = userId; this.options = options; match = GameFactory.instance.createMatch(options.getGameType(), options); if (userId != null) { - Optional user = UserManager.instance.getUser(userId); + Optional user = managerFactory.userManager().getUser(userId); // TODO: Handle if user == null controllerName = user.map(User::getName).orElse("undefined"); } else { controllerName = "System"; } table = new Table(roomId, options.getGameType(), options.getName(), controllerName, DeckValidatorFactory.instance.createDeckValidator(options.getDeckType()), - options.getPlayerTypes(), TableRecorderImpl.instance, match, options.getBannedUsers(), options.isPlaneChase()); - chatId = ChatManager.instance.createChatSession("Match Table " + table.getId()); + options.getPlayerTypes(), new TableRecorderImpl(managerFactory.userManager()), match, options.getBannedUsers(), options.isPlaneChase()); + chatId = managerFactory.chatManager().createChatSession("Match Table " + table.getId()); init(); } - public TableController(UUID roomId, UUID userId, TournamentOptions options) { + public TableController(ManagerFactory managerFactory, UUID roomId, UUID userId, TournamentOptions options) { + this.managerFactory = managerFactory; + this.timeoutExecutor = managerFactory.threadExecutor().getTimeoutExecutor(); this.userId = userId; tournament = TournamentFactory.instance.createTournament(options.getTournamentType(), options); if (userId != null) { - Optional user = UserManager.instance.getUser(userId); + Optional user = managerFactory.userManager().getUser(userId); if (!user.isPresent()) { logger.fatal(new StringBuilder("User for userId ").append(userId).append(" could not be retrieved from UserManager").toString()); controllerName = "[unknown]"; @@ -92,8 +93,8 @@ public class TableController { controllerName = "System"; } table = new Table(roomId, options.getTournamentType(), options.getName(), controllerName, DeckValidatorFactory.instance.createDeckValidator(options.getMatchOptions().getDeckType()), - options.getPlayerTypes(), TableRecorderImpl.instance, tournament, options.getMatchOptions().getBannedUsers(), options.isPlaneChase()); - chatId = ChatManager.instance.createChatSession("Tourn. table " + table.getId()); + options.getPlayerTypes(), new TableRecorderImpl(managerFactory.userManager()), tournament, options.getMatchOptions().getBannedUsers(), options.isPlaneChase()); + chatId = managerFactory.chatManager().createChatSession("Tourn. table " + table.getId()); } private void init() { @@ -121,7 +122,7 @@ public class TableController { if (seat == null) { throw new GameException("No available seats."); } - Optional _user = UserManager.instance.getUser(userId); + Optional _user = managerFactory.userManager().getUser(userId); if (!_user.isPresent()) { logger.fatal("couldn't get user " + name + " for join tournament userId = " + userId); return false; @@ -156,7 +157,7 @@ public class TableController { user.showUserMessage("Join Table", sb.toString()); if (isOwner(userId)) { logger.debug("New table removed because owner submitted invalid deck tableId " + table.getId()); - TableManager.instance.removeTable(table.getId()); + managerFactory.tableManager().removeTable(table.getId()); } return false; } @@ -231,12 +232,12 @@ public class TableController { newTournamentPlayer.setState(oldTournamentPlayer.getState()); newTournamentPlayer.setReplacedTournamentPlayer(oldTournamentPlayer); - DraftManager.instance.getController(table.getId()).ifPresent(controller -> controller.replacePlayer(oldPlayer, newPlayer)); + managerFactory.draftManager().getController(table.getId()).ifPresent(controller -> controller.replacePlayer(oldPlayer, newPlayer)); return true; } public synchronized boolean joinTable(UUID userId, String name, PlayerType playerType, int skill, DeckCardLists deckList, String password) throws MageException { - Optional _user = UserManager.instance.getUser(userId); + Optional _user = managerFactory.userManager().getUser(userId); if (!_user.isPresent()) { logger.error("Join Table: can't find user to join " + name + " Id = " + userId); return false; @@ -274,7 +275,7 @@ public class TableController { user.showUserMessage("Join Table", sb.toString()); if (isOwner(userId)) { logger.debug("New table removed because owner submitted invalid deck tableId " + table.getId()); - TableManager.instance.removeTable(table.getId()); + managerFactory.tableManager().removeTable(table.getId()); } return false; } @@ -420,7 +421,7 @@ public class TableController { } } if (!Main.isTestMode() && !table.getValidator().validate(deck)) { - Optional _user = UserManager.instance.getUser(userId); + Optional _user = managerFactory.userManager().getUser(userId); if (!_user.isPresent()) { return false; } @@ -453,10 +454,10 @@ public class TableController { private void submitDeck(UUID userId, UUID playerId, Deck deck) { if (table.getState() == TableState.SIDEBOARDING) { match.submitDeck(playerId, deck); - UserManager.instance.getUser(userId).ifPresent(user -> user.removeSideboarding(table.getId())); + managerFactory.userManager().getUser(userId).ifPresent(user -> user.removeSideboarding(table.getId())); } else { - TournamentManager.instance.submitDeck(tournament.getId(), playerId, deck); - UserManager.instance.getUser(userId).ifPresent(user -> user.removeConstructing(playerId)); + managerFactory.tournamentManager().submitDeck(tournament.getId(), playerId, deck); + managerFactory.userManager().getUser(userId).ifPresent(user -> user.removeConstructing(playerId)); } } @@ -464,7 +465,7 @@ public class TableController { boolean validDeck = true; if (table.isTournament()) { if (tournament != null) { - validDeck = TournamentManager.instance.updateDeck(tournament.getId(), playerId, deck); + validDeck = managerFactory.tournamentManager().updateDeck(tournament.getId(), playerId, deck); } else { logger.fatal("Tournament == null table: " + table.getId() + " userId: " + userId); } @@ -478,7 +479,7 @@ public class TableController { public boolean watchTable(UUID userId) { if (table.isTournament()) { - UserManager.instance.getUser(userId).ifPresent(user -> user.ccShowTournament(table.getTournament().getId())); + managerFactory.userManager().getUser(userId).ifPresent(user -> user.ccShowTournament(table.getTournament().getId())); return true; } else { if (table.isTournamentSubTable() && !table.getTournament().getOptions().isWatchingAllowed()) { @@ -491,7 +492,7 @@ public class TableController { if (userPlayerMap.get(userId) != null) { return false; } - Optional _user = UserManager.instance.getUser(userId); + Optional _user = managerFactory.userManager().getUser(userId); if (!_user.isPresent()) { return false; } @@ -533,7 +534,7 @@ public class TableController { && (table.getState() == TableState.WAITING || table.getState() == TableState.READY_TO_START)) { // table not started yet and user is the owner, removeUserFromAllTablesAndChat the table - TableManager.instance.removeTable(table.getId()); + managerFactory.tableManager().removeTable(table.getId()); } else { UUID playerId = userPlayerMap.get(userId); if (playerId != null) { @@ -544,9 +545,9 @@ public class TableController { } else { match.quitMatch(playerId); } - Optional user = UserManager.instance.getUser(userId); + Optional user = managerFactory.userManager().getUser(userId); if (user.isPresent()) { - ChatManager.instance.broadcast(chatId, user.get().getName(), "has left the table", ChatMessage.MessageColor.BLUE, true, null, ChatMessage.MessageType.STATUS, ChatMessage.SoundToPlay.PlayerLeft); + managerFactory.chatManager().broadcast(chatId, user.get().getName(), "has left the table", ChatMessage.MessageColor.BLUE, true, null, ChatMessage.MessageType.STATUS, ChatMessage.SoundToPlay.PlayerLeft); if (!table.isTournamentSubTable()) { user.get().removeTable(playerId); } @@ -557,9 +558,9 @@ public class TableController { } else if (table.getState() != TableState.FINISHED) { if (table.isTournament()) { logger.debug("Quit tournament sub tables for userId: " + userId); - TableManager.instance.userQuitTournamentSubTables(tournament.getId(), userId); + managerFactory.tableManager().userQuitTournamentSubTables(tournament.getId(), userId); logger.debug("Quit tournament Id: " + table.getTournament().getId() + '(' + table.getTournament().getTournamentState() + ')'); - TournamentManager.instance.quit(tournament.getId(), userId); + managerFactory.tournamentManager().quit(tournament.getId(), userId); } else { MatchPlayer matchPlayer = match.getPlayer(playerId); if (matchPlayer != null && !match.hasEnded() && !matchPlayer.hasQuit()) { @@ -567,7 +568,7 @@ public class TableController { if (game != null && !game.hasEnded()) { Player player = match.getPlayer(playerId).getPlayer(); if (player != null && player.isInGame()) { - GameManager.instance.quitMatch(game.getId(), userId); + managerFactory.gameManager().quitMatch(game.getId(), userId); } match.quitMatch(playerId); } else { @@ -605,7 +606,7 @@ public class TableController { if (table.isTournamentSubTable()) { logger.info("Tourn. match started id:" + match.getId() + " tournId: " + table.getTournament().getId()); } else { - UserManager.instance.getUser(userId).ifPresent(user -> { + managerFactory.userManager().getUser(userId).ifPresent(user -> { logger.info("MATCH started [" + match.getName() + "] " + match.getId() + '(' + user.getName() + ')'); logger.debug("- " + match.getOptions().getGameType() + " - " + match.getOptions().getDeckType()); }); @@ -628,12 +629,12 @@ public class TableController { gameOptions.bannedUsers = match.getOptions().getBannedUsers(); gameOptions.planeChase = match.getOptions().isPlaneChase(); match.getGame().setGameOptions(gameOptions); - GameManager.instance.createGameSession(match.getGame(), userPlayerMap, table.getId(), choosingPlayerId, gameOptions); + managerFactory.gameManager().createGameSession(match.getGame(), userPlayerMap, table.getId(), choosingPlayerId, gameOptions); String creator = null; StringBuilder opponent = new StringBuilder(); for (Entry entry : userPlayerMap.entrySet()) { // do only for no AI players if (match.getPlayer(entry.getValue()) != null && !match.getPlayer(entry.getValue()).hasQuit()) { - Optional _user = UserManager.instance.getUser(entry.getKey()); + Optional _user = managerFactory.userManager().getUser(entry.getKey()); if (_user.isPresent()) { User user = _user.get(); user.ccGameStarted(match.getGame().getId(), entry.getValue()); @@ -670,17 +671,17 @@ public class TableController { logger.info("GAME started " + (match.getGame() != null ? match.getGame().getId() : "no Game") + " [" + match.getName() + "] " + creator + " - " + opponent.toString()); logger.debug("- matchId: " + match.getId() + " [" + match.getName() + ']'); if (match.getGame() != null) { - logger.debug("- chatId: " + GameManager.instance.getChatId(match.getGame().getId())); + logger.debug("- chatId: " + managerFactory.gameManager().getChatId(match.getGame().getId())); } } catch (Exception ex) { logger.fatal("Error starting game table: " + table.getId(), ex); if (table != null) { - TableManager.instance.removeTable(table.getId()); + managerFactory.tableManager().removeTable(table.getId()); } if (match != null) { Game game = match.getGame(); if (game != null) { - GameManager.instance.removeGame(game.getId()); + managerFactory.gameManager().removeGame(game.getId()); // game ended by error, so don't add it to ended stats } } @@ -691,9 +692,9 @@ public class TableController { try { if (userId.equals(this.userId) && table.getState() == TableState.STARTING) { tournament.setStartTime(); - TournamentManager.instance.createTournamentSession(tournament, userPlayerMap, table.getId()); + managerFactory.tournamentManager().createTournamentSession(tournament, userPlayerMap, table.getId()); for (Entry entry : userPlayerMap.entrySet()) { - UserManager.instance.getUser(entry.getKey()).ifPresent(user -> { + managerFactory.userManager().getUser(entry.getKey()).ifPresent(user -> { logger.info(new StringBuilder("User ").append(user.getName()).append(" tournament started: ").append(tournament.getId()).append(" userId: ").append(user.getId())); user.ccTournamentStarted(tournament.getId(), entry.getValue()); }); @@ -702,16 +703,16 @@ public class TableController { } } catch (Exception ex) { logger.fatal("Error starting tournament", ex); - TableManager.instance.removeTable(table.getId()); - TournamentManager.instance.quit(tournament.getId(), userId); + managerFactory.tableManager().removeTable(table.getId()); + managerFactory.tournamentManager().quit(tournament.getId(), userId); } } public void startDraft(Draft draft) { table.initDraft(); - DraftManager.instance.createDraftSession(draft, userPlayerMap, table.getId()); + managerFactory.draftManager().createDraftSession(draft, userPlayerMap, table.getId()); for (Entry entry : userPlayerMap.entrySet()) { - Optional user = UserManager.instance.getUser(entry.getKey()); + Optional user = managerFactory.userManager().getUser(entry.getKey()); if (user.isPresent()) { logger.info(new StringBuilder("User ").append(user.get().getName()).append(" draft started: ").append(draft.getId()).append(" userId: ").append(user.get().getId())); user.get().ccDraftStarted(draft.getId(), entry.getValue()); @@ -725,7 +726,7 @@ public class TableController { for (Entry entry : userPlayerMap.entrySet()) { if (entry.getValue().equals(playerId)) { - Optional user = UserManager.instance.getUser(entry.getKey()); + Optional user = managerFactory.userManager().getUser(entry.getKey()); int remaining = (int) futureTimeout.getDelay(TimeUnit.SECONDS); user.ifPresent(user1 -> user1.ccSideboard(deck, table.getId(), remaining, options.isLimited())); break; @@ -767,12 +768,12 @@ public class TableController { } UUID choosingPlayerId = match.getChooser(); match.endGame(); - if (ConfigSettings.instance.isSaveGameActivated() && !game.isSimulation()) { - if (GameManager.instance.saveGame(game.getId())) { + if (managerFactory.configSettings().isSaveGameActivated() && !game.isSimulation()) { + if (managerFactory.gameManager().saveGame(game.getId())) { match.setReplayAvailable(true); } } - GameManager.instance.removeGame(game.getId()); + managerFactory.gameManager().removeGame(game.getId()); ServerMessagesUtil.instance.incGamesEnded(); try { @@ -835,7 +836,7 @@ public class TableController { // opponent(s) left during sideboarding if (matchPlayer != null) { if (!matchPlayer.hasQuit()) { - UserManager.instance.getUser(entry.getKey()).ifPresent(user -> { + managerFactory.userManager().getUser(entry.getKey()).ifPresent(user -> { if (table.getState() == TableState.SIDEBOARDING) { StringBuilder sb = new StringBuilder(); if (table.isTournamentSubTable()) { @@ -860,7 +861,7 @@ public class TableController { } } // free resources no longer needed - match.cleanUpOnMatchEnd(ConfigSettings.instance.isSaveGameActivated(), table.isTournament()); + match.cleanUpOnMatchEnd(managerFactory.configSettings().isSaveGameActivated(), table.isTournament()); } } } @@ -932,13 +933,13 @@ public class TableController { public boolean isTournamentStillValid() { if (table.getTournament() != null) { if (table.getState() != TableState.WAITING && table.getState() != TableState.READY_TO_START && table.getState() != TableState.STARTING) { - return TournamentManager.instance.getTournamentController(table.getTournament().getId()) + return managerFactory.tournamentManager().getTournamentController(table.getTournament().getId()) .map(tc -> tc.isTournamentStillValid(table.getState())) .orElse(false); } else { // check if table creator is still a valid user, if not removeUserFromAllTablesAndChat table - return UserManager.instance.getUser(userId).isPresent(); + return managerFactory.userManager().getUser(userId).isPresent(); } } return false; @@ -1004,7 +1005,7 @@ public class TableController { || table.getState() == TableState.READY_TO_START) || !match.isDoneSideboarding() || (!matchPlayer.hasQuit() && match.getGame() != null && matchPlayer.getPlayer().isInGame())) { - Optional user = UserManager.instance.getUser(userPlayerEntry.getKey()); + Optional user = managerFactory.userManager().getUser(userPlayerEntry.getKey()); if (!user.isPresent() || !user.get().isActive()) { logger.warn("- Active user of match is missing: " + matchPlayer.getName()); logger.warn("-- matchId:" + match.getId()); @@ -1028,12 +1029,12 @@ public class TableController { void cleanUp() { if (!table.isTournamentSubTable()) { for (Map.Entry entry : userPlayerMap.entrySet()) { - UserManager.instance.getUser(entry.getKey()).ifPresent(user + managerFactory.userManager().getUser(entry.getKey()).ifPresent(user -> user.removeTable(entry.getValue())); } } - ChatManager.instance.destroyChatSession(chatId); + managerFactory.chatManager().destroyChatSession(chatId); } public synchronized TableState getTableState() { diff --git a/Mage.Server/src/main/java/mage/server/TableManager.java b/Mage.Server/src/main/java/mage/server/TableManager.java index b898241ab2..3cfa700135 100644 --- a/Mage.Server/src/main/java/mage/server/TableManager.java +++ b/Mage.Server/src/main/java/mage/server/TableManager.java @@ -14,9 +14,8 @@ import mage.game.tournament.TournamentOptions; import mage.game.tournament.TournamentPlayer; import mage.players.PlayerType; import mage.server.game.GameController; -import mage.server.game.GameManager; -import mage.server.game.GamesRoomManager; -import mage.server.util.ThreadExecutor; +import mage.server.managers.ITableManager; +import mage.server.managers.ManagerFactory; import org.apache.log4j.Logger; import java.text.DateFormat; @@ -34,11 +33,11 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author BetaSteward_at_googlemail.com */ -public enum TableManager { - instance; +public class TableManager implements ITableManager { protected final ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor(); // protected static ScheduledExecutorService expireExecutor = ThreadExecutor.getInstance().getExpireExecutor(); + private final ManagerFactory managerFactory; private final Logger logger = Logger.getLogger(TableManager.class); private final DateFormat formatter = new SimpleDateFormat("HH:mm:ss"); @@ -55,10 +54,14 @@ public enum TableManager { */ private static final int EXPIRE_CHECK_PERIOD = 10; - TableManager() { + public TableManager(ManagerFactory managerFactory) { + this.managerFactory = managerFactory; + } + + public void init() { expireExecutor.scheduleAtFixedRate(() -> { try { - ChatManager.instance.clearUserMessageStorage(); + managerFactory.chatManager().clearUserMessageStorage(); checkTableHealthState(); } catch (Exception ex) { logger.fatal("Check table health state job error:", ex); @@ -66,22 +69,25 @@ public enum TableManager { }, EXPIRE_CHECK_PERIOD, EXPIRE_CHECK_PERIOD, TimeUnit.MINUTES); } + @Override public Table createTable(UUID roomId, UUID userId, MatchOptions options) { - TableController tableController = new TableController(roomId, userId, options); + TableController tableController = new TableController(managerFactory, roomId, userId, options); putControllers(tableController.getTable().getId(), tableController); putTables(tableController.getTable().getId(), tableController.getTable()); return tableController.getTable(); } + @Override public Table createTable(UUID roomId, MatchOptions options) { - TableController tableController = new TableController(roomId, null, options); + TableController tableController = new TableController(managerFactory, roomId, null, options); putControllers(tableController.getTable().getId(), tableController); putTables(tableController.getTable().getId(), tableController.getTable()); return tableController.getTable(); } + @Override public Table createTournamentTable(UUID roomId, UUID userId, TournamentOptions options) { - TableController tableController = new TableController(roomId, userId, options); + TableController tableController = new TableController(managerFactory, roomId, userId, options); putControllers(tableController.getTable().getId(), tableController); putTables(tableController.getTable().getId(), tableController.getTable()); return tableController.getTable(); @@ -107,10 +113,12 @@ public enum TableManager { } } + @Override public Table getTable(UUID tableId) { return tables.get(tableId); } + @Override public Optional getMatch(UUID tableId) { if (controllers.containsKey(tableId)) { return Optional.of(controllers.get(tableId).getMatch()); @@ -118,6 +126,7 @@ public enum TableManager { return Optional.empty(); } + @Override public Collection getTables() { Collection
newTables = new ArrayList<>(); final Lock r = tablesLock.readLock(); @@ -130,6 +139,7 @@ public enum TableManager { return newTables; } + @Override public Collection getControllers() { Collection newControllers = new ArrayList<>(); final Lock r = controllersLock.readLock(); @@ -142,6 +152,7 @@ public enum TableManager { return newControllers; } + @Override public Optional getController(UUID tableId) { if (controllers.containsKey(tableId)) { return Optional.of(controllers.get(tableId)); @@ -149,6 +160,7 @@ public enum TableManager { return Optional.empty(); } + @Override public boolean joinTable(UUID userId, UUID tableId, String name, PlayerType playerType, int skill, DeckCardLists deckList, String password) throws MageException { if (controllers.containsKey(tableId)) { return controllers.get(tableId).joinTable(userId, name, playerType, skill, deckList, password); @@ -156,6 +168,7 @@ public enum TableManager { return false; } + @Override public boolean joinTournament(UUID userId, UUID tableId, String name, PlayerType playerType, int skill, DeckCardLists deckList, String password) throws GameException { if (controllers.containsKey(tableId)) { return controllers.get(tableId).joinTournament(userId, name, playerType, skill, deckList, password); @@ -163,11 +176,12 @@ public enum TableManager { return false; } + @Override public boolean submitDeck(UUID userId, UUID tableId, DeckCardLists deckList) throws MageException { if (controllers.containsKey(tableId)) { return controllers.get(tableId).submitDeck(userId, deckList); } - UserManager.instance.getUser(userId).ifPresent(user -> { + managerFactory.userManager().getUser(userId).ifPresent(user -> { user.removeSideboarding(tableId); user.showUserMessage("Submit deck", "Table no longer active"); @@ -176,6 +190,7 @@ public enum TableManager { return true; } + @Override public void updateDeck(UUID userId, UUID tableId, DeckCardLists deckList) throws MageException { if (controllers.containsKey(tableId)) { controllers.get(tableId).updateDeck(userId, deckList); @@ -183,6 +198,7 @@ public enum TableManager { } // removeUserFromAllTablesAndChat user from all tournament sub tables + @Override public void userQuitTournamentSubTables(UUID userId) { for (TableController controller : getControllers()) { if (controller.getTable() != null) { @@ -196,6 +212,7 @@ public enum TableManager { } // removeUserFromAllTablesAndChat user from all sub tables of a tournament + @Override public void userQuitTournamentSubTables(UUID tournamentId, UUID userId) { for (TableController controller : getControllers()) { if (controller.getTable().isTournamentSubTable() && controller.getTable().getTournament().getId().equals(tournamentId)) { @@ -206,6 +223,7 @@ public enum TableManager { } } + @Override public boolean isTableOwner(UUID tableId, UUID userId) { if (controllers.containsKey(tableId)) { return controllers.get(tableId).isOwner(userId); @@ -213,13 +231,14 @@ public enum TableManager { return false; } + @Override public boolean removeTable(UUID userId, UUID tableId) { - if (isTableOwner(tableId, userId) || UserManager.instance.isAdmin(userId)) { + if (isTableOwner(tableId, userId) || managerFactory.userManager().isAdmin(userId)) { logger.debug("Table remove request - userId: " + userId + " tableId: " + tableId); TableController tableController = controllers.get(tableId); if (tableController != null) { tableController.leaveTableAll(); - ChatManager.instance.destroyChatSession(tableController.getChatId()); + managerFactory.chatManager().destroyChatSession(tableController.getChatId()); removeTable(tableId); } return true; @@ -227,6 +246,7 @@ public enum TableManager { return false; } + @Override public void leaveTable(UUID userId, UUID tableId) { TableController tableController = controllers.get(tableId); if (tableController != null) { @@ -234,6 +254,7 @@ public enum TableManager { } } + @Override public Optional getChatId(UUID tableId) { if (controllers.containsKey(tableId)) { return Optional.of(controllers.get(tableId).getChatId()); @@ -248,11 +269,12 @@ public enum TableManager { * @param roomId * @param tableId */ + @Override public void startMatch(UUID userId, UUID roomId, UUID tableId) { if (controllers.containsKey(tableId)) { controllers.get(tableId).startMatch(userId); // chat of start dialog can be killed - ChatManager.instance.destroyChatSession(controllers.get(tableId).getChatId()); + managerFactory.chatManager().destroyChatSession(controllers.get(tableId).getChatId()); } } @@ -262,25 +284,29 @@ public enum TableManager { * @param roomId * @param tableId */ + @Override public void startTournamentSubMatch(UUID roomId, UUID tableId) { if (controllers.containsKey(tableId)) { controllers.get(tableId).startMatch(); } } + @Override public void startTournament(UUID userId, UUID roomId, UUID tableId) { if (controllers.containsKey(tableId)) { controllers.get(tableId).startTournament(userId); - ChatManager.instance.destroyChatSession(controllers.get(tableId).getChatId()); + managerFactory.chatManager().destroyChatSession(controllers.get(tableId).getChatId()); } } + @Override public void startDraft(UUID tableId, Draft draft) { if (controllers.containsKey(tableId)) { controllers.get(tableId).startDraft(draft); } } + @Override public boolean watchTable(UUID userId, UUID tableId) { if (controllers.containsKey(tableId)) { return controllers.get(tableId).watchTable(userId); @@ -288,6 +314,7 @@ public enum TableManager { return false; } + @Override public void endGame(UUID tableId) { if (controllers.containsKey(tableId)) { if (controllers.get(tableId).endGameAndStartNextGame()) { @@ -296,42 +323,49 @@ public enum TableManager { } } + @Override public void endDraft(UUID tableId, Draft draft) { if (controllers.containsKey(tableId)) { controllers.get(tableId).endDraft(draft); } } + @Override public void endTournament(UUID tableId, Tournament tournament) { if (controllers.containsKey(tableId)) { controllers.get(tableId).endTournament(tournament); } } + @Override public void swapSeats(UUID tableId, UUID userId, int seatNum1, int seatNum2) { if (controllers.containsKey(tableId) && isTableOwner(tableId, userId)) { controllers.get(tableId).swapSeats(seatNum1, seatNum2); } } + @Override public void construct(UUID tableId) { if (controllers.containsKey(tableId)) { controllers.get(tableId).construct(); } } + @Override public void initTournament(UUID tableId) { if (controllers.containsKey(tableId)) { controllers.get(tableId).initTournament(); } } + @Override public void addPlayer(UUID userId, UUID tableId, TournamentPlayer player) throws GameException { if (controllers.containsKey(tableId)) { controllers.get(tableId).addPlayer(userId, player.getPlayer(), player.getPlayerType(), player.getDeck()); } } + @Override public void removeTable(UUID tableId) { TableController tableController = controllers.get(tableId); if (tableController != null) { @@ -365,21 +399,22 @@ public enum TableManager { // If table is not finished, the table has to be removed completly because it's not a normal state (if finished it will be removed in GamesRoomImpl.Update()) if (table.getState() != TableState.FINISHED) { if (game != null) { - GameManager.instance.removeGame(game.getId()); + managerFactory.gameManager().removeGame(game.getId()); // something goes wrong, so don't add it to ended stats } - GamesRoomManager.instance.removeTable(tableId); + managerFactory.gamesRoomManager().removeTable(tableId); } } } + @Override public void debugServerState() { logger.debug("--- Server state ----------------------------------------------"); - Collection users = UserManager.instance.getUsers(); + Collection users = managerFactory.userManager().getUsers(); logger.debug("--------User: " + users.size() + " [userId | since | lock | name -----------------------"); for (User user : users) { - Optional session = SessionManager.instance.getSession(user.getSessionId()); + Optional session = managerFactory.sessionManager().getSession(user.getSessionId()); String sessionState = "N"; if (session.isPresent()) { if (session.get().isLocked()) { @@ -393,14 +428,14 @@ public enum TableManager { + " | " + sessionState + " | " + user.getName() + " (" + user.getUserState().toString() + " - " + user.getPingInfo() + ')'); } - List chatSessions = ChatManager.instance.getChatSessions(); + List chatSessions = managerFactory.chatManager().getChatSessions(); logger.debug("------- ChatSessions: " + chatSessions.size() + " ----------------------------------"); for (ChatSession chatSession : chatSessions) { logger.debug(chatSession.getChatId() + " " + formatter.format(chatSession.getCreateTime()) + ' ' + chatSession.getInfo() + ' ' + chatSession.getClients().values().toString()); } - logger.debug("------- Games: " + GameManager.instance.getNumberActiveGames() + " --------------------------------------------"); - logger.debug(" Active Game Worker: " + ThreadExecutor.instance.getActiveThreads(ThreadExecutor.instance.getGameExecutor())); - for (Entry entry : GameManager.instance.getGameController().entrySet()) { + logger.debug("------- Games: " + managerFactory.gameManager().getNumberActiveGames() + " --------------------------------------------"); + logger.debug(" Active Game Worker: " + managerFactory.threadExecutor().getActiveThreads(managerFactory.threadExecutor().getGameExecutor())); + for (Entry entry : managerFactory.gameManager().getGameController().entrySet()) { logger.debug(entry.getKey() + entry.getValue().getPlayerNameList()); } logger.debug("--- Server state END ------------------------------------------"); diff --git a/Mage.Server/src/main/java/mage/server/User.java b/Mage.Server/src/main/java/mage/server/User.java index 7cde19283f..cb0dba3047 100644 --- a/Mage.Server/src/main/java/mage/server/User.java +++ b/Mage.Server/src/main/java/mage/server/User.java @@ -10,14 +10,13 @@ import mage.interfaces.callback.ClientCallback; import mage.interfaces.callback.ClientCallbackMethod; import mage.players.net.UserData; import mage.server.draft.DraftSession; -import mage.server.game.GameManager; import mage.server.game.GameSessionPlayer; +import mage.server.managers.ManagerFactory; import mage.server.rating.GlickoRating; import mage.server.rating.GlickoRatingSystem; import mage.server.record.UserStats; import mage.server.record.UserStatsRepository; import mage.server.tournament.TournamentController; -import mage.server.tournament.TournamentManager; import mage.server.tournament.TournamentSession; import mage.server.util.ServerMessagesUtil; import mage.server.util.SystemUtil; @@ -43,6 +42,7 @@ public class User { Offline // set if the user was disconnected and expired or regularly left XMage. Removed is the user later after some time } + private final ManagerFactory managerFactory; private final UUID userId; private final String userName; private final String host; @@ -68,7 +68,8 @@ public class User { private String clientVersion; private String userIdStr; - public User(String userName, String host, AuthorizedUser authorizedUser) { + public User(ManagerFactory managerFactory, String userName, String host, AuthorizedUser authorizedUser) { + this.managerFactory = managerFactory; this.userId = UUID.randomUUID(); this.userName = userName; this.host = host; @@ -181,7 +182,7 @@ public class User { // Because watched games don't get restored after reconnection call stop watching for (Iterator iterator = watchedGames.iterator(); iterator.hasNext(); ) { UUID gameId = iterator.next(); - GameManager.instance.stopWatching(gameId, userId); + managerFactory.gameManager().stopWatching(gameId, userId); iterator.remove(); } ServerMessagesUtil.instance.incLostConnection(); @@ -227,7 +228,7 @@ public class User { public void fireCallback(final ClientCallback call) { if (isConnected()) { - SessionManager.instance.getSession(sessionId).ifPresent(session + managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> session.fireCallback(call) ); } @@ -288,27 +289,27 @@ public class User { public void sendPlayerUUID(final UUID gameId, final UUID data) { lastActivity = new Date(); - GameManager.instance.sendPlayerUUID(gameId, userId, data); + managerFactory.gameManager().sendPlayerUUID(gameId, userId, data); } public void sendPlayerString(final UUID gameId, final String data) { lastActivity = new Date(); - GameManager.instance.sendPlayerString(gameId, userId, data); + managerFactory.gameManager().sendPlayerString(gameId, userId, data); } public void sendPlayerManaType(final UUID gameId, final UUID playerId, final ManaType data) { lastActivity = new Date(); - GameManager.instance.sendPlayerManaType(gameId, playerId, userId, data); + managerFactory.gameManager().sendPlayerManaType(gameId, playerId, userId, data); } public void sendPlayerBoolean(final UUID gameId, final Boolean data) { lastActivity = new Date(); - GameManager.instance.sendPlayerBoolean(gameId, userId, data); + managerFactory.gameManager().sendPlayerBoolean(gameId, userId, data); } public void sendPlayerInteger(final UUID gameId, final Integer data) { lastActivity = new Date(); - GameManager.instance.sendPlayerInteger(gameId, userId, data); + managerFactory.gameManager().sendPlayerInteger(gameId, userId, data); } public void updateLastActivity(String pingInfo) { @@ -338,7 +339,7 @@ public class User { } for (Iterator> iterator = userTournaments.entrySet().iterator(); iterator.hasNext(); ) { Entry next = iterator.next(); - Optional tournamentController = TournamentManager.instance.getTournamentController(next.getValue()); + Optional tournamentController = managerFactory.tournamentManager().getTournamentController(next.getValue()); if (tournamentController.isPresent()) { ccTournamentStarted(next.getValue(), next.getKey()); tournamentController.get().rejoin(next.getKey()); @@ -349,7 +350,7 @@ public class User { for (Entry entry : gameSessions.entrySet()) { ccGameStarted(entry.getValue().getGameId(), entry.getKey()); entry.getValue().init(); - GameManager.instance.sendPlayerString(entry.getValue().getGameId(), userId, ""); + managerFactory.gameManager().sendPlayerString(entry.getValue().getGameId(), userId, ""); } for (Entry entry : draftSessions.entrySet()) { @@ -362,7 +363,7 @@ public class User { entry.getValue().construct(0); // TODO: Check if this is correct } for (Entry entry : sideboarding.entrySet()) { - Optional controller = TableManager.instance.getController(entry.getKey()); + Optional controller = managerFactory.tableManager().getController(entry.getKey()); if (controller.isPresent()) { ccSideboard(entry.getValue(), entry.getKey(), controller.get().getRemainingTime(), controller.get().getOptions().isLimited()); } else { @@ -427,32 +428,32 @@ public class User { draftSessions.clear(); logger.trace("REMOVE " + userName + " Tournament sessions " + userTournaments.size()); for (UUID tournamentId : userTournaments.values()) { - TournamentManager.instance.quit(tournamentId, userId); + managerFactory.tournamentManager().quit(tournamentId, userId); } userTournaments.clear(); constructing.clear(); logger.trace("REMOVE " + userName + " Tables " + tables.size()); for (Entry entry : tables.entrySet()) { logger.debug("-- leave tableId: " + entry.getValue().getId()); - TableManager.instance.leaveTable(userId, entry.getValue().getId()); + managerFactory.tableManager().leaveTable(userId, entry.getValue().getId()); } tables.clear(); sideboarding.clear(); logger.trace("REMOVE " + userName + " Game sessions: " + gameSessions.size()); for (GameSessionPlayer gameSessionPlayer : gameSessions.values()) { logger.debug("-- kill game session of gameId: " + gameSessionPlayer.getGameId()); - GameManager.instance.quitMatch(gameSessionPlayer.getGameId(), userId); + managerFactory.gameManager().quitMatch(gameSessionPlayer.getGameId(), userId); gameSessionPlayer.quitGame(); } gameSessions.clear(); logger.trace("REMOVE " + userName + " watched Games " + watchedGames.size()); for (Iterator it = watchedGames.iterator(); it.hasNext(); ) { // Iterator to prevent ConcurrentModificationException UUID gameId = it.next(); - GameManager.instance.stopWatching(gameId, userId); + managerFactory.gameManager().stopWatching(gameId, userId); } watchedGames.clear(); logger.trace("REMOVE " + userName + " Chats "); - ChatManager.instance.removeUser(userId, reason); + managerFactory.chatManager().removeUser(userId, reason); } public void setUserData(UserData userData) { @@ -788,7 +789,7 @@ public class User { if (table.getState() == TableState.FINISHED) { number++; } else { - Optional tableController = TableManager.instance.getController(table.getId()); + Optional tableController = managerFactory.tableManager().getController(table.getId()); if (!tableController.isPresent()) { logger.error("table not found : " + table.getId()); } else if (tableController.get().isUserStillActive(userId)) { diff --git a/Mage.Server/src/main/java/mage/server/UserManager.java b/Mage.Server/src/main/java/mage/server/UserManager.java index 50c41e7fc0..8d33a80b68 100644 --- a/Mage.Server/src/main/java/mage/server/UserManager.java +++ b/Mage.Server/src/main/java/mage/server/UserManager.java @@ -1,9 +1,10 @@ package mage.server; import mage.server.User.UserState; +import mage.server.managers.IUserManager; +import mage.server.managers.ManagerFactory; import mage.server.record.UserStats; import mage.server.record.UserStatsRepository; -import mage.server.util.ThreadExecutor; import mage.view.UserView; import org.apache.log4j.Logger; @@ -19,8 +20,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * * @author BetaSteward_at_googlemail.com */ -public enum UserManager { - instance; +public class UserManager implements IUserManager { 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) @@ -32,24 +32,32 @@ public enum UserManager { protected final ScheduledExecutorService userListExecutor = Executors.newSingleThreadScheduledExecutor(); private List userInfoList = new ArrayList<>(); + private final ManagerFactory managerFactory; private final ReadWriteLock lock = new ReentrantReadWriteLock(); private final ConcurrentHashMap users = new ConcurrentHashMap<>(); - private static final ExecutorService USER_EXECUTOR = ThreadExecutor.instance.getCallExecutor(); + private ExecutorService USER_EXECUTOR; - UserManager() { + // TODO externalise start of threads + public UserManager(ManagerFactory managerFactory) { + this.managerFactory = managerFactory; + } + + public void init() { + USER_EXECUTOR = managerFactory.threadExecutor().getCallExecutor(); expireExecutor.scheduleAtFixedRate(this::checkExpired, 60, 60, TimeUnit.SECONDS); userListExecutor.scheduleAtFixedRate(this::updateUserInfoList, 4, 4, TimeUnit.SECONDS); } + @Override public Optional createUser(String userName, String host, AuthorizedUser authorizedUser) { if (getUserByName(userName).isPresent()) { return Optional.empty(); //user already exists } - User user = new User(userName, host, authorizedUser); + User user = new User(managerFactory, userName, host, authorizedUser); final Lock w = lock.writeLock(); w.lock(); try { @@ -60,6 +68,7 @@ public enum UserManager { return Optional.of(user); } + @Override public Optional getUser(UUID userId) { if (!users.containsKey(userId)) { //logger.warn(String.format("User with id %s could not be found", userId), new Throwable()); // TODO: remove after session freezes fixed @@ -69,6 +78,7 @@ public enum UserManager { } } + @Override public Optional getUserByName(String userName) { final Lock r = lock.readLock(); r.lock(); @@ -81,6 +91,7 @@ public enum UserManager { } + @Override public Collection getUsers() { List userList = new ArrayList<>(); final Lock r = lock.readLock(); @@ -93,6 +104,7 @@ public enum UserManager { return userList; } + @Override public boolean connectToSession(String sessionId, UUID userId) { if (userId != null) { User user = users.get(userId); @@ -104,19 +116,19 @@ public enum UserManager { return false; } + @Override public void disconnect(UUID userId, DisconnectReason reason) { - Optional user = UserManager.instance.getUser(userId); + Optional user = getUser(userId); if (user.isPresent()) { user.get().setSessionId(""); if (reason == DisconnectReason.Disconnected) { removeUserFromAllTablesAndChat(userId, reason); user.get().setUserState(UserState.Offline); - } else { -// ChatManager.instance.sendLostConnectionMessage(userId, reason); } } } + @Override public boolean isAdmin(UUID userId) { if (userId != null) { User user = users.get(userId); @@ -127,6 +139,7 @@ public enum UserManager { return false; } + @Override public void removeUserFromAllTablesAndChat(final UUID userId, final DisconnectReason reason) { if (userId != null) { getUser(userId).ifPresent(user @@ -135,7 +148,7 @@ public enum UserManager { try { logger.info("USER REMOVE - " + user.getName() + " (" + reason.toString() + ") userId: " + userId + " [" + user.getGameInfo() + ']'); user.removeUserFromAllTables(reason); - ChatManager.instance.removeUser(user.getId(), reason); + managerFactory.chatManager().removeUser(user.getId(), reason); logger.debug("USER REMOVE END - " + user.getName()); } catch (Exception ex) { handleException(ex); @@ -146,13 +159,14 @@ public enum UserManager { } } + @Override public void informUserOpponents(final UUID userId, final String message) { if (userId != null) { getUser(userId).ifPresent(user -> USER_EXECUTOR.execute( () -> { try { - ChatManager.instance.sendMessageToUserChats(user.getId(), message); + managerFactory.chatManager().sendMessageToUserChats(user.getId(), message); } catch (Exception ex) { handleException(ex); } @@ -161,6 +175,7 @@ public enum UserManager { } } + @Override public boolean extendUserSession(UUID userId, String pingInfo) { if (userId != null) { User user = users.get(userId); @@ -245,7 +260,7 @@ public enum UserManager { private void updateUserInfoList() { try { List newUserInfoList = new ArrayList<>(); - for (User user : UserManager.instance.getUsers()) { + for (User user : getUsers()) { newUserInfoList.add(new UserView( user.getName(), user.getHost(), @@ -266,10 +281,12 @@ public enum UserManager { } } + @Override public List getUserInfoList() { return userInfoList; } + @Override public void handleException(Exception ex) { if (ex != null) { logger.fatal("User manager exception ", ex); @@ -281,6 +298,7 @@ public enum UserManager { } } + @Override public String getUserHistory(String userName) { Optional user = getUserByName(userName); if (user.isPresent()) { @@ -295,6 +313,7 @@ public enum UserManager { return "User " + userName + " not found"; } + @Override public void updateUserHistory() { USER_EXECUTOR.execute(() -> { for (String updatedUser : UserStatsRepository.instance.updateUserStats()) { diff --git a/Mage.Server/src/main/java/mage/server/draft/DraftController.java b/Mage.Server/src/main/java/mage/server/draft/DraftController.java index 24ef713bf6..2bead233f7 100644 --- a/Mage.Server/src/main/java/mage/server/draft/DraftController.java +++ b/Mage.Server/src/main/java/mage/server/draft/DraftController.java @@ -1,5 +1,3 @@ - - package mage.server.draft; import mage.MageException; @@ -9,10 +7,8 @@ import mage.game.events.Listener; import mage.game.events.PlayerQueryEvent; import mage.game.events.TableEvent; import mage.players.Player; -import mage.server.TableManager; -import mage.server.UserManager; import mage.server.game.GameController; -import mage.server.util.ThreadExecutor; +import mage.server.managers.ManagerFactory; import mage.view.DraftPickView; import org.apache.log4j.Logger; @@ -25,7 +21,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** - * * @author BetaSteward_at_googlemail.com */ public class DraftController { @@ -33,6 +28,7 @@ public class DraftController { private static final Logger logger = Logger.getLogger(GameController.class); public static final String INIT_FILE_PATH = "config" + File.separator + "init.txt"; + private final ManagerFactory managerFactory; private final ConcurrentMap draftSessions = new ConcurrentHashMap<>(); private final ConcurrentMap userPlayerMap; private final UUID draftSessionId; @@ -40,7 +36,8 @@ public class DraftController { private final UUID tableId; private final UUID markedCard; - public DraftController(Draft draft, ConcurrentHashMap userPlayerMap, UUID tableId) { + public DraftController(ManagerFactory managerFactory, Draft draft, ConcurrentHashMap userPlayerMap, UUID tableId) { + this.managerFactory = managerFactory; draftSessionId = UUID.randomUUID(); this.userPlayerMap = userPlayerMap; this.draft = draft; @@ -61,8 +58,7 @@ public class DraftController { endDraft(); break; } - } - catch (MageException ex) { + } catch (MageException ex) { logger.fatal("Table event listener error", ex); } } @@ -75,13 +71,12 @@ public class DraftController { pickCard(event.getPlayerId(), event.getMax()); break; } - } - catch (MageException ex) { + } catch (MageException ex) { logger.fatal("Table event listener error", ex); } } ); - for (DraftPlayer player: draft.getPlayers()) { + for (DraftPlayer player : draft.getPlayers()) { if (!player.getPlayer().isHuman()) { player.setJoined(); logger.debug("player " + player.getPlayer().getId() + " has joined draft " + draft.getId()); @@ -96,13 +91,13 @@ public class DraftController { public void join(UUID userId) { UUID playerId = userPlayerMap.get(userId); - DraftSession draftSession = new DraftSession(draft, userId, playerId); + DraftSession draftSession = new DraftSession(managerFactory, draft, userId, playerId); draftSessions.put(playerId, draftSession); - UserManager.instance.getUser(userId).ifPresent(user-> { - user.addDraft(playerId, draftSession); - logger.debug("User " + user.getName() + " has joined draft " + draft.getId()); - draft.getPlayer(playerId).setJoined(); - }); + managerFactory.userManager().getUser(userId).ifPresent(user -> { + user.addDraft(playerId, draftSession); + logger.debug("User " + user.getName() + " has joined draft " + draft.getId()); + draft.getPlayer(playerId).setJoined(); + }); checkStart(); } @@ -114,7 +109,7 @@ public class DraftController { } public boolean replacePlayer(Player oldPlayer, Player newPlayer) { - if (draft.replacePlayer(oldPlayer, newPlayer)) { + if (draft.replacePlayer(oldPlayer, newPlayer)) { DraftSession draftSession = draftSessions.get(oldPlayer.getId()); if (draftSession != null) { draftSession.draftOver(); // closes the draft panel of the replaced player @@ -128,12 +123,12 @@ public class DraftController { private synchronized void checkStart() { if (!draft.isStarted() && allJoined()) { draft.setStarted(); - ThreadExecutor.instance.getCallExecutor().execute(this::startDraft); + managerFactory.threadExecutor().getCallExecutor().execute(this::startDraft); } } private void startDraft() { - for (final Entry entry: draftSessions.entrySet()) { + for (final Entry entry : draftSessions.entrySet()) { if (!entry.getValue().init()) { logger.fatal("Unable to initialize client for playerId " + entry.getKey()); //TODO: generate client error message @@ -147,7 +142,7 @@ public class DraftController { if (!draft.allJoined()) { return false; } - for (DraftPlayer player: draft.getPlayers()) { + for (DraftPlayer player : draft.getPlayers()) { if (player.getPlayer().isHuman() && !draftSessions.containsKey(player.getPlayer().getId())) { return false; } @@ -160,12 +155,12 @@ public class DraftController { } private void endDraft() throws MageException { - for (final DraftSession draftSession: draftSessions.values()) { + for (final DraftSession draftSession : draftSessions.values()) { draftSession.draftOver(); draftSession.removeDraft(); } - TableManager.instance.endDraft(tableId, draft); - DraftManager.instance.removeDraft(draft.getId()); + managerFactory.tableManager().endDraft(tableId, draft); + managerFactory.draftManager().removeDraft(draft.getId()); } public void kill(UUID userId) { @@ -210,7 +205,7 @@ public class DraftController { } private synchronized void updateDraft() throws MageException { - for (final Entry entry: draftSessions.entrySet()) { + for (final Entry entry : draftSessions.entrySet()) { entry.getValue().update(); } } @@ -229,7 +224,7 @@ public class DraftController { draft.setAbort(true); try { endDraft(); - } catch(MageException ex) { + } catch (MageException ex) { } } diff --git a/Mage.Server/src/main/java/mage/server/draft/DraftManager.java b/Mage.Server/src/main/java/mage/server/draft/DraftManager.java index 3d49b6762d..0b7eef61a8 100644 --- a/Mage.Server/src/main/java/mage/server/draft/DraftManager.java +++ b/Mage.Server/src/main/java/mage/server/draft/DraftManager.java @@ -1,69 +1,83 @@ - - package mage.server.draft; +import mage.game.draft.Draft; +import mage.server.managers.IDraftManager; +import mage.server.managers.ManagerFactory; +import mage.view.DraftPickView; + import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import mage.game.draft.Draft; -import mage.view.DraftPickView; - /** - * * @author BetaSteward_at_googlemail.com */ -public enum DraftManager { - instance; +public class DraftManager implements IDraftManager { + private final ManagerFactory managerFactory; private final ConcurrentMap draftControllers = new ConcurrentHashMap<>(); + public DraftManager(ManagerFactory managerFactory) { + this.managerFactory = managerFactory; + } + + @Override public UUID createDraftSession(Draft draft, ConcurrentHashMap userPlayerMap, UUID tableId) { - DraftController draftController = new DraftController(draft, userPlayerMap, tableId); + DraftController draftController = new DraftController(managerFactory, draft, userPlayerMap, tableId); draftControllers.put(draft.getId(), draftController); return draftController.getSessionId(); } + @Override public void joinDraft(UUID draftId, UUID userId) { draftControllers.get(draftId).join(userId); } + @Override public void destroyChatSession(UUID gameId) { draftControllers.remove(gameId); } + @Override public DraftPickView sendCardPick(UUID draftId, UUID userId, UUID cardId, Set hiddenCards) { return draftControllers.get(draftId).sendCardPick(userId, cardId, hiddenCards); } + @Override public void sendCardMark(UUID draftId, UUID userId, UUID cardId) { draftControllers.get(draftId).sendCardMark(userId, cardId); } + @Override public void removeSession(UUID userId) { - for (DraftController controller: draftControllers.values()) { + for (DraftController controller : draftControllers.values()) { controller.kill(userId); } } + @Override public void kill(UUID draftId, UUID userId) { draftControllers.get(draftId).kill(userId); } + @Override public void timeout(UUID gameId, UUID userId) { draftControllers.get(gameId).timeout(userId); } + @Override public void removeDraft(UUID draftId) { draftControllers.remove(draftId); } + @Override public DraftController getControllerByDraftId(UUID draftId) { return draftControllers.get(draftId); } + @Override public Optional getController(UUID tableId) { return draftControllers.values().stream().filter(controller -> controller.getTableId().equals(tableId)).findFirst(); } diff --git a/Mage.Server/src/main/java/mage/server/draft/DraftSession.java b/Mage.Server/src/main/java/mage/server/draft/DraftSession.java index d34848fdb1..bea9c5b612 100644 --- a/Mage.Server/src/main/java/mage/server/draft/DraftSession.java +++ b/Mage.Server/src/main/java/mage/server/draft/DraftSession.java @@ -1,6 +1,15 @@ - package mage.server.draft; +import mage.game.draft.Draft; +import mage.interfaces.callback.ClientCallback; +import mage.interfaces.callback.ClientCallbackMethod; +import mage.server.User; +import mage.server.managers.ManagerFactory; +import mage.view.DraftClientMessage; +import mage.view.DraftPickView; +import mage.view.DraftView; +import org.apache.log4j.Logger; + import java.rmi.RemoteException; import java.util.Optional; import java.util.Set; @@ -8,16 +17,6 @@ import java.util.UUID; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import mage.game.draft.Draft; -import mage.interfaces.callback.ClientCallback; -import mage.interfaces.callback.ClientCallbackMethod; -import mage.server.User; -import mage.server.UserManager; -import mage.server.util.ThreadExecutor; -import mage.view.DraftClientMessage; -import mage.view.DraftPickView; -import mage.view.DraftView; -import org.apache.log4j.Logger; /** * @author BetaSteward_at_googlemail.com @@ -26,6 +25,7 @@ public class DraftSession { protected static final Logger logger = Logger.getLogger(DraftSession.class); + private final ManagerFactory managerFactory; protected final UUID userId; protected final UUID playerId; protected final Draft draft; @@ -33,9 +33,11 @@ public class DraftSession { protected UUID markedCard; private ScheduledFuture futureTimeout; - protected static final ScheduledExecutorService timeoutExecutor = ThreadExecutor.instance.getTimeoutExecutor(); + protected final ScheduledExecutorService timeoutExecutor; - public DraftSession(Draft draft, UUID userId, UUID playerId) { + public DraftSession(ManagerFactory managerFactory, Draft draft, UUID userId, UUID playerId) { + this.managerFactory = managerFactory; + this.timeoutExecutor = managerFactory.threadExecutor().getTimeoutExecutor(); this.userId = userId; this.draft = draft; this.playerId = playerId; @@ -44,12 +46,12 @@ public class DraftSession { public boolean init() { if (!killed) { - Optional user = UserManager.instance.getUser(userId); + Optional user = managerFactory.userManager().getUser(userId); if (user.isPresent()) { if (futureTimeout != null && !futureTimeout.isDone()) { int remaining = (int) futureTimeout.getDelay(TimeUnit.SECONDS); user.get().fireCallback(new ClientCallback(ClientCallbackMethod.DRAFT_INIT, draft.getId(), - new DraftClientMessage(getDraftView(), getDraftPickView(remaining)))); + new DraftClientMessage(getDraftView(), getDraftPickView(remaining)))); } return true; } @@ -59,16 +61,16 @@ public class DraftSession { public void update() { if (!killed) { - UserManager.instance + managerFactory.userManager() .getUser(userId). ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.DRAFT_UPDATE, draft.getId(), - new DraftClientMessage(getDraftView(), null)))); + new DraftClientMessage(getDraftView(), null)))); } } public void draftOver() { if (!killed) { - UserManager.instance + managerFactory.userManager() .getUser(userId) .ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.DRAFT_OVER, draft.getId()))); } @@ -77,10 +79,10 @@ public class DraftSession { public void pickCard(int timeout) { if (!killed) { setupTimeout(timeout); - UserManager.instance + managerFactory.userManager() .getUser(userId) .ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.DRAFT_PICK, draft.getId(), - new DraftClientMessage(getDraftView(), getDraftPickView(timeout))))); + new DraftClientMessage(getDraftView(), getDraftPickView(timeout))))); } } @@ -89,7 +91,7 @@ public class DraftSession { cancelTimeout(); if (seconds > 0) { futureTimeout = timeoutExecutor.schedule( - () -> DraftManager.instance.timeout(draft.getId(), userId), + () -> managerFactory.draftManager().timeout(draft.getId(), userId), seconds, TimeUnit.SECONDS ); } @@ -103,7 +105,7 @@ public class DraftSession { protected void handleRemoteException(RemoteException ex) { logger.fatal("DraftSession error ", ex); - DraftManager.instance.kill(draft.getId(), userId); + managerFactory.draftManager().kill(draft.getId(), userId); } public void setKilled() { @@ -119,7 +121,7 @@ public class DraftSession { } public void removeDraft() { - UserManager.instance.getUser(userId).ifPresent(user -> user.removeDraft(playerId)); + managerFactory.userManager().getUser(userId).ifPresent(user -> user.removeDraft(playerId)); } diff --git a/Mage.Server/src/main/java/mage/server/game/GameController.java b/Mage.Server/src/main/java/mage/server/game/GameController.java index ab3b8fcb8d..9729b238de 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -23,11 +23,11 @@ import mage.game.permanent.Permanent; import mage.game.turn.Phase; import mage.interfaces.Action; import mage.players.Player; -import mage.server.*; -import mage.server.util.ConfigSettings; +import mage.server.Main; +import mage.server.User; +import mage.server.managers.ManagerFactory; import mage.server.util.Splitter; import mage.server.util.SystemUtil; -import mage.server.util.ThreadExecutor; import mage.utils.StreamUtils; import mage.utils.timer.PriorityTimer; import mage.view.*; @@ -53,13 +53,14 @@ public class GameController implements GameCallback { private static final int GAME_TIMEOUTS_CHECK_JOINING_STATUS_EVERY_SECS = 10; // checks and inform players about joining status private static final int GAME_TIMEOUTS_CANCEL_PLAYER_GAME_JOINING_AFTER_INACTIVE_SECS = 2 * 60; // leave player from game if it don't join and inactive on server - private static final ExecutorService gameExecutor = ThreadExecutor.instance.getGameExecutor(); + private final ExecutorService gameExecutor; private static final Logger logger = Logger.getLogger(GameController.class); protected final ScheduledExecutorService joinWaitingExecutor = Executors.newSingleThreadScheduledExecutor(); private ScheduledFuture futureTimeout; - protected static final ScheduledExecutorService timeoutIdleExecutor = ThreadExecutor.instance.getTimeoutIdleExecutor(); + private final ManagerFactory managerFactory; + protected final ScheduledExecutorService timeoutIdleExecutor; private final ConcurrentMap gameSessions = new ConcurrentHashMap<>(); private final ReadWriteLock gameSessionsLock = new ReentrantReadWriteLock(); @@ -83,13 +84,16 @@ public class GameController implements GameCallback { private int turnsToRollback; private int requestsOpen; - public GameController(Game game, ConcurrentMap userPlayerMap, UUID tableId, UUID choosingPlayerId, GameOptions gameOptions) { + public GameController(ManagerFactory managerFactory, Game game, ConcurrentMap userPlayerMap, UUID tableId, UUID choosingPlayerId, GameOptions gameOptions) { + this.managerFactory = managerFactory; + gameExecutor = managerFactory.threadExecutor().getGameExecutor(); + timeoutIdleExecutor = managerFactory.threadExecutor().getTimeoutIdleExecutor(); gameSessionId = UUID.randomUUID(); this.userPlayerMap = userPlayerMap; - chatId = ChatManager.instance.createChatSession("Game " + game.getId()); + chatId = managerFactory.chatManager().createChatSession("Game " + game.getId()); this.userReqestingRollback = null; this.game = game; - this.game.setSaveGame(ConfigSettings.instance.isSaveGameActivated()); + this.game.setSaveGame(managerFactory.configSettings().isSaveGameActivated()); this.tableId = tableId; this.choosingPlayerId = choosingPlayerId; this.gameOptions = gameOptions; @@ -103,7 +107,7 @@ public class GameController implements GameCallback { for (GameSessionPlayer gameSessionPlayer : getGameSessions()) { gameSessionPlayer.cleanUp(); } - ChatManager.instance.destroyChatSession(chatId); + managerFactory.chatManager().destroyChatSession(chatId); for (PriorityTimer priorityTimer : timers.values()) { priorityTimer.cancel(); } @@ -120,11 +124,11 @@ public class GameController implements GameCallback { updateGame(); break; case INFO: - ChatManager.instance.broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, event.getGame(), MessageType.GAME, null); + managerFactory.chatManager().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, event.getGame(), MessageType.GAME, null); logger.trace(game.getId() + " " + event.getMessage()); break; case STATUS: - ChatManager.instance.broadcast(chatId, "", event.getMessage(), MessageColor.ORANGE, event.getWithTime(), event.getWithTurnInfo() ? event.getGame() : null, MessageType.GAME, null); + managerFactory.chatManager().broadcast(chatId, "", event.getMessage(), MessageColor.ORANGE, event.getWithTime(), event.getWithTurnInfo() ? event.getGame() : null, MessageType.GAME, null); logger.trace(game.getId() + " " + event.getMessage()); break; case ERROR: @@ -273,7 +277,7 @@ public class GameController implements GameCallback { logger.fatal("- userId: " + userId); return; } - Optional user = UserManager.instance.getUser(userId); + Optional user = managerFactory.userManager().getUser(userId); if (!user.isPresent()) { logger.fatal("User not found : " + userId); return; @@ -286,7 +290,7 @@ public class GameController implements GameCallback { GameSessionPlayer gameSession = gameSessions.get(playerId); String joinType; if (gameSession == null) { - gameSession = new GameSessionPlayer(game, userId, playerId); + gameSession = new GameSessionPlayer(managerFactory, game, userId, playerId); final Lock w = gameSessionsLock.writeLock(); w.lock(); try { @@ -300,7 +304,7 @@ public class GameController implements GameCallback { } user.get().addGame(playerId, gameSession); logger.debug("Player " + player.getName() + ' ' + playerId + " has " + joinType + " gameId: " + game.getId()); - ChatManager.instance.broadcast(chatId, "", game.getPlayer(playerId).getLogName() + " has " + joinType + " the game", MessageColor.ORANGE, true, game, MessageType.GAME, null); + managerFactory.chatManager().broadcast(chatId, "", game.getPlayer(playerId).getLogName() + " has " + joinType + " the game", MessageColor.ORANGE, true, game, MessageType.GAME, null); checkStart(); } @@ -335,7 +339,7 @@ public class GameController implements GameCallback { // join the game because player has not joined or was removed because of disconnect String problemPlayerFixes; user.removeConstructing(player.getId()); - GameManager.instance.joinGame(game.getId(), user.getId()); + managerFactory.gameManager().joinGame(game.getId(), user.getId()); logger.warn("Forced join of player " + player.getName() + " (" + user.getUserState() + ") to gameId: " + game.getId()); if (user.isConnected()) { // init game session, see reconnect() @@ -345,7 +349,7 @@ public class GameController implements GameCallback { logger.warn("Send forced game start event for player " + player.getName() + " in gameId: " + game.getId()); user.ccGameStarted(session.getGameId(), player.getId()); session.init(); - GameManager.instance.sendPlayerString(session.getGameId(), user.getId(), ""); + managerFactory.gameManager().sendPlayerString(session.getGameId(), user.getId(), ""); } else { problemPlayerFixes = "leave on broken game session"; logger.error("Can't find game session for forced join, leave it: player " + player.getName() + " in gameId: " + game.getId()); @@ -357,7 +361,7 @@ public class GameController implements GameCallback { player.leave(); } - ChatManager.instance.broadcast(chatId, player.getName(), user.getPingInfo() + managerFactory.chatManager().broadcast(chatId, player.getName(), user.getPingInfo() + " is forced to join the game (waiting ends after " + GAME_TIMEOUTS_CANCEL_PLAYER_GAME_JOINING_AFTER_INACTIVE_SECS + " secs, applied fixes: " + problemPlayerFixes + ")", @@ -382,7 +386,7 @@ public class GameController implements GameCallback { private Optional getUserByPlayerId(UUID playerId) { for (Map.Entry entry : userPlayerMap.entrySet()) { if (entry.getValue().equals(playerId)) { - return UserManager.instance.getUser(entry.getKey()); + return managerFactory.userManager().getUser(entry.getKey()); } } return Optional.empty(); @@ -391,7 +395,7 @@ public class GameController implements GameCallback { private void checkStart() { if (allJoined()) { joinWaitingExecutor.shutdownNow(); - ThreadExecutor.instance.getCallExecutor().execute(this::startGame); + managerFactory.threadExecutor().getCallExecutor().execute(this::startGame); } } @@ -423,14 +427,14 @@ public class GameController implements GameCallback { } if (!isAllowedToWatch(userId)) { // Dont want people on our ignore list to stalk us - UserManager.instance.getUser(userId).ifPresent(user -> { + managerFactory.userManager().getUser(userId).ifPresent(user -> { user.showUserMessage("Not allowed", "You are banned from watching this game"); - ChatManager.instance.broadcast(chatId, user.getName(), " tried to join, but is banned", MessageColor.BLUE, true, game, ChatMessage.MessageType.STATUS, null); + managerFactory.chatManager().broadcast(chatId, user.getName(), " tried to join, but is banned", MessageColor.BLUE, true, game, ChatMessage.MessageType.STATUS, null); }); return false; } - UserManager.instance.getUser(userId).ifPresent(user -> { - GameSessionWatcher gameWatcher = new GameSessionWatcher(userId, game, false); + managerFactory.userManager().getUser(userId).ifPresent(user -> { + GameSessionWatcher gameWatcher = new GameSessionWatcher(managerFactory.userManager(), userId, game, false); final Lock w = gameWatchersLock.writeLock(); w.lock(); try { @@ -440,7 +444,7 @@ public class GameController implements GameCallback { } gameWatcher.init(); user.addGameWatchInfo(game.getId()); - ChatManager.instance.broadcast(chatId, user.getName(), " has started watching", MessageColor.BLUE, true, game, ChatMessage.MessageType.STATUS, null); + managerFactory.chatManager().broadcast(chatId, user.getName(), " has started watching", MessageColor.BLUE, true, game, ChatMessage.MessageType.STATUS, null); }); return true; } @@ -453,8 +457,8 @@ public class GameController implements GameCallback { } finally { w.unlock(); } - UserManager.instance.getUser(userId).ifPresent(user -> { - ChatManager.instance.broadcast(chatId, user.getName(), " has stopped watching", MessageColor.BLUE, true, game, ChatMessage.MessageType.STATUS, null); + managerFactory.userManager().getUser(userId).ifPresent(user -> { + managerFactory.chatManager().broadcast(chatId, user.getName(), " has stopped watching", MessageColor.BLUE, true, game, ChatMessage.MessageType.STATUS, null); }); } @@ -628,7 +632,7 @@ public class GameController implements GameCallback { gameSession.requestPermissionToSeeHandCards(userIdRequester); } else { // player does not allow the request - UserManager.instance.getUser(userIdRequester).ifPresent(requester -> { + managerFactory.userManager().getUser(userIdRequester).ifPresent(requester -> { requester.showUserMessage("Request to show hand cards", "Player " + grantingPlayer.getName() + " does not allow to request to show hand cards!"); }); } @@ -640,7 +644,7 @@ public class GameController implements GameCallback { } } else { // user can already see the cards - UserManager.instance.getUser(userIdRequester).ifPresent(requester -> { + managerFactory.userManager().getUser(userIdRequester).ifPresent(requester -> { requester.showUserMessage("Request to show hand cards", "You can see already the hand cards of player " + grantingPlayer.getName() + '!'); }); @@ -653,9 +657,9 @@ public class GameController implements GameCallback { Player viewLimitedDeckPlayer = game.getPlayer(userIdRequester); if (viewLimitedDeckPlayer != null) { if (viewLimitedDeckPlayer.isHuman()) { - for (MatchPlayer p : TableManager.instance.getTable(tableId).getMatch().getPlayers()) { + for (MatchPlayer p : managerFactory.tableManager().getTable(tableId).getMatch().getPlayers()) { if (p.getPlayer().getId().equals(userIdRequester)) { - Optional u = UserManager.instance.getUser(origId); + Optional u = managerFactory.userManager().getUser(origId); if (u.isPresent() && p.getDeck() != null) { u.get().ccViewLimitedDeck(p.getDeck(), tableId, requestsOpen, true); } @@ -698,8 +702,8 @@ public class GameController implements GameCallback { if (player != null) { String sb = player.getLogName() + " has timed out (player had priority and was not active for " - + ConfigSettings.instance.getMaxSecondsIdle() + " seconds ) - Auto concede."; - ChatManager.instance.broadcast(chatId, "", sb, MessageColor.BLACK, true, game, MessageType.STATUS, null); + + managerFactory.configSettings().getMaxSecondsIdle() + " seconds ) - Auto concede."; + managerFactory.chatManager().broadcast(chatId, "", sb, MessageColor.BLACK, true, game, MessageType.STATUS, null); game.idleTimeout(playerId); } } @@ -712,7 +716,7 @@ public class GameController implements GameCallback { for (final GameSessionWatcher gameWatcher : getGameSessionWatchers()) { gameWatcher.gameOver(message); } - TableManager.instance.endGame(tableId); + managerFactory.tableManager().endGame(tableId); } public UUID getSessionId() { @@ -763,7 +767,7 @@ public class GameController implements GameCallback { } private synchronized void endGameInfo() { - Table table = TableManager.instance.getTable(tableId); + Table table = managerFactory.tableManager().getTable(tableId); if (table != null) { if (table.getMatch() != null) { for (final GameSessionPlayer gameSession : getGameSessions()) { @@ -1012,7 +1016,7 @@ public class GameController implements GameCallback { cancelTimeout(); futureTimeout = timeoutIdleExecutor.schedule( () -> idleTimeout(playerId), - Main.isTestMode() ? 3600 : ConfigSettings.instance.getMaxSecondsIdle(), + Main.isTestMode() ? 3600 : managerFactory.configSettings().getMaxSecondsIdle(), TimeUnit.SECONDS ); } @@ -1094,7 +1098,7 @@ public class GameController implements GameCallback { } public boolean isAllowedToWatch(UUID userId) { - Optional user = UserManager.instance.getUser(userId); + Optional user = managerFactory.userManager().getUser(userId); if (user.isPresent()) { return !gameOptions.bannedUsers.contains(user.get().getName()); } @@ -1208,7 +1212,7 @@ public class GameController implements GameCallback { public String getPingsInfo() { List usersInfo = new ArrayList<>(); for (Map.Entry entry : userPlayerMap.entrySet()) { - Optional user = UserManager.instance.getUser(entry.getKey()); + Optional user = managerFactory.userManager().getUser(entry.getKey()); user.ifPresent(u -> usersInfo.add("* " + u.getName() + ": " + u.getPingInfo())); } Collections.sort(usersInfo); @@ -1216,7 +1220,7 @@ public class GameController implements GameCallback { List watchersinfo = new ArrayList<>(); for (Map.Entry entry : watchers.entrySet()) { - Optional user = UserManager.instance.getUser(entry.getValue().userId); + Optional user = managerFactory.userManager().getUser(entry.getValue().userId); user.ifPresent(u -> watchersinfo.add("* " + u.getName() + ": " + u.getPingInfo())); } Collections.sort(watchersinfo); diff --git a/Mage.Server/src/main/java/mage/server/game/GameManager.java b/Mage.Server/src/main/java/mage/server/game/GameManager.java index f265090149..8c6bdcf503 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameManager.java +++ b/Mage.Server/src/main/java/mage/server/game/GameManager.java @@ -5,6 +5,8 @@ import mage.constants.ManaType; import mage.constants.PlayerAction; import mage.game.Game; import mage.game.GameOptions; +import mage.server.managers.IGameManager; +import mage.server.managers.ManagerFactory; import mage.view.GameView; import java.util.HashMap; @@ -20,14 +22,19 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author BetaSteward_at_googlemail.com */ -public enum GameManager { - instance; +public class GameManager implements IGameManager { + private final ManagerFactory managerFactory; private final ConcurrentMap gameControllers = new ConcurrentHashMap<>(); private final ReadWriteLock gameControllersLock = new ReentrantReadWriteLock(); + public GameManager(ManagerFactory managerFactory) { + this.managerFactory = managerFactory; + } + + @Override public UUID createGameSession(Game game, ConcurrentHashMap userPlayerMap, UUID tableId, UUID choosingPlayerId, GameOptions gameOptions) { - GameController gameController = new GameController(game, userPlayerMap, tableId, choosingPlayerId, gameOptions); + GameController gameController = new GameController(managerFactory, game, userPlayerMap, tableId, choosingPlayerId, gameOptions); final Lock w = gameControllersLock.writeLock(); w.lock(); try { @@ -48,6 +55,7 @@ public enum GameManager { } } + @Override public void joinGame(UUID gameId, UUID userId) { GameController gameController = getGameControllerSafe(gameId); if (gameController != null) { @@ -55,6 +63,7 @@ public enum GameManager { } } + @Override public Optional getChatId(UUID gameId) { GameController gameController = getGameControllerSafe(gameId); if (gameController != null) { @@ -63,6 +72,7 @@ public enum GameManager { return Optional.empty(); } + @Override public void sendPlayerUUID(UUID gameId, UUID userId, UUID data) { GameController gameController = getGameControllerSafe(gameId); if (gameController != null) { @@ -70,6 +80,7 @@ public enum GameManager { } } + @Override public void sendPlayerString(UUID gameId, UUID userId, String data) { GameController gameController = getGameControllerSafe(gameId); if (gameController != null) { @@ -77,6 +88,7 @@ public enum GameManager { } } + @Override public void sendPlayerManaType(UUID gameId, UUID playerId, UUID userId, ManaType data) { GameController gameController = getGameControllerSafe(gameId); if (gameController != null) { @@ -84,6 +96,7 @@ public enum GameManager { } } + @Override public void sendPlayerBoolean(UUID gameId, UUID userId, Boolean data) { GameController gameController = getGameControllerSafe(gameId); if (gameController != null) { @@ -91,6 +104,7 @@ public enum GameManager { } } + @Override public void sendPlayerInteger(UUID gameId, UUID userId, Integer data) { GameController gameController = getGameControllerSafe(gameId); if (gameController != null) { @@ -98,6 +112,7 @@ public enum GameManager { } } + @Override public void quitMatch(UUID gameId, UUID userId) { GameController gameController = getGameControllerSafe(gameId); if (gameController != null) { @@ -105,6 +120,7 @@ public enum GameManager { } } + @Override public void sendPlayerAction(PlayerAction playerAction, UUID gameId, UUID userId, Object data) { GameController gameController = getGameControllerSafe(gameId); if (gameController != null) { @@ -112,6 +128,7 @@ public enum GameManager { } } + @Override public boolean watchGame(UUID gameId, UUID userId) { GameController gameController = getGameControllerSafe(gameId); if (gameController != null) { @@ -120,6 +137,7 @@ public enum GameManager { return false; } + @Override public void stopWatching(UUID gameId, UUID userId) { GameController gameController = getGameControllerSafe(gameId); if (gameController != null) { @@ -127,6 +145,7 @@ public enum GameManager { } } + @Override public void cheat(UUID gameId, UUID userId, UUID playerId, DeckCardLists deckList) { GameController gameController = getGameControllerSafe(gameId); if (gameController != null) { @@ -134,6 +153,7 @@ public enum GameManager { } } + @Override public boolean cheat(UUID gameId, UUID userId, UUID playerId, String cardName) { GameController gameController = getGameControllerSafe(gameId); if (gameController != null) { @@ -142,6 +162,7 @@ public enum GameManager { return false; } + @Override public void removeGame(UUID gameId) { GameController gameController = getGameControllerSafe(gameId); if (gameController != null) { @@ -156,6 +177,7 @@ public enum GameManager { } } + @Override public boolean saveGame(UUID gameId) { GameController gameController = getGameControllerSafe(gameId); if (gameController != null) { @@ -164,6 +186,7 @@ public enum GameManager { return false; } + @Override public GameView getGameView(UUID gameId, UUID playerId) { GameController gameController = getGameControllerSafe(gameId); if (gameController != null) { @@ -172,10 +195,12 @@ public enum GameManager { return null; } + @Override public int getNumberActiveGames() { return getGameController().size(); } + @Override public Map getGameController() { Map newControllers = new HashMap<>(); final Lock r = gameControllersLock.readLock(); diff --git a/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java b/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java index 38e0ea9647..2c23027a03 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java +++ b/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java @@ -11,8 +11,8 @@ import mage.interfaces.callback.ClientCallback; import mage.interfaces.callback.ClientCallbackMethod; import mage.players.Player; import mage.server.User; -import mage.server.UserManager; -import mage.server.util.ThreadExecutor; +import mage.server.managers.IUserManager; +import mage.server.managers.ManagerFactory; import mage.view.*; import org.apache.log4j.Logger; @@ -28,12 +28,15 @@ public class GameSessionPlayer extends GameSessionWatcher { private static final Logger logger = Logger.getLogger(GameSessionPlayer.class); + private final IUserManager userManager; private final UUID playerId; - private static final ExecutorService callExecutor = ThreadExecutor.instance.getCallExecutor(); + private final ExecutorService callExecutor; - public GameSessionPlayer(Game game, UUID userId, UUID playerId) { - super(userId, game, true); + public GameSessionPlayer(ManagerFactory managerFactory, Game game, UUID userId, UUID playerId) { + super(managerFactory.userManager(), userId, game, true); + this.userManager = managerFactory.userManager(); + callExecutor = managerFactory.threadExecutor().getCallExecutor(); this.playerId = playerId; } @@ -44,14 +47,14 @@ public class GameSessionPlayer extends GameSessionWatcher { public void ask(final String question, final Map options) { if (!killed) { - UserManager.instance.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_ASK, game.getId(), new GameClientMessage(getGameView(), question, options))) + userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_ASK, game.getId(), new GameClientMessage(getGameView(), question, options))) ); } } public void target(final String question, final CardsView cardView, final Set targets, final boolean required, final Map options) { if (!killed) { - UserManager.instance.getUser(userId).ifPresent(user -> { + userManager.getUser(userId).ifPresent(user -> { user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_TARGET, game.getId(), new GameClientMessage(getGameView(), question, cardView, targets, required, options))); }); @@ -60,13 +63,13 @@ public class GameSessionPlayer extends GameSessionWatcher { public void select(final String message, final Map options) { if (!killed) { - UserManager.instance.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_SELECT, game.getId(), new GameClientMessage(getGameView(), message, options)))); + userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_SELECT, game.getId(), new GameClientMessage(getGameView(), message, options)))); } } public void chooseAbility(final AbilityPickerView abilities) { if (!killed) { - UserManager.instance.getUser(userId).ifPresent(user + userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_CHOOSE_ABILITY, game.getId(), abilities))); } @@ -74,7 +77,7 @@ public class GameSessionPlayer extends GameSessionWatcher { public void choosePile(final String message, final CardsView pile1, final CardsView pile2) { if (!killed) { - UserManager.instance.getUser(userId).ifPresent(user + userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_CHOOSE_PILE, game.getId(), new GameClientMessage(message, pile1, pile2)))); } @@ -82,7 +85,7 @@ public class GameSessionPlayer extends GameSessionWatcher { public void chooseChoice(final Choice choice) { if (!killed) { - UserManager.instance.getUser(userId).ifPresent(user + userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_CHOOSE_CHOICE, game.getId(), new GameClientMessage(choice)))); } @@ -90,14 +93,14 @@ public class GameSessionPlayer extends GameSessionWatcher { public void playMana(final String message, final Map options) { if (!killed) { - UserManager.instance.getUser(userId).ifPresent(user + userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_PLAY_MANA, game.getId(), new GameClientMessage(getGameView(), message, options)))); } } public void playXMana(final String message) { if (!killed) { - UserManager.instance.getUser(userId).ifPresent(user + userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_PLAY_XMANA, game.getId(), new GameClientMessage(getGameView(), message)))); } @@ -105,7 +108,7 @@ public class GameSessionPlayer extends GameSessionWatcher { public void getAmount(final String message, final int min, final int max) { if (!killed) { - UserManager.instance.getUser(userId).ifPresent(user -> { + userManager.getUser(userId).ifPresent(user -> { user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_GET_AMOUNT, game.getId(), new GameClientMessage(message, min, max))); }); } @@ -113,15 +116,15 @@ public class GameSessionPlayer extends GameSessionWatcher { public void endGameInfo(Table table) { if (!killed) { - UserManager.instance.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.END_GAME_INFO, game.getId(), getGameEndView(playerId, table)))); + userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.END_GAME_INFO, game.getId(), getGameEndView(playerId, table)))); } } public void requestPermissionToRollbackTurn(UUID requestingUserId, int numberTurns) { if (!killed) { - Optional requestingUser = UserManager.instance.getUser(requestingUserId); - Optional requestedUser = UserManager.instance.getUser(userId); + Optional requestingUser = userManager.getUser(requestingUserId); + Optional requestedUser = userManager.getUser(userId); if (requestedUser.isPresent() && requestingUser.isPresent()) { String message; switch (numberTurns) { @@ -147,8 +150,8 @@ public class GameSessionPlayer extends GameSessionWatcher { public void requestPermissionToSeeHandCards(UUID watcherId) { if (!killed) { - Optional watcher = UserManager.instance.getUser(watcherId); - Optional user = UserManager.instance.getUser(userId); + Optional watcher = userManager.getUser(watcherId); + Optional user = userManager.getUser(userId); if (user.isPresent() && watcher.isPresent()) { UserRequestMessage userRequestMessage = new UserRequestMessage( "User request", @@ -217,7 +220,7 @@ public class GameSessionPlayer extends GameSessionWatcher { } public void removeGame() { - UserManager.instance.getUser(userId).ifPresent(user -> user.removeGame(playerId)); + userManager.getUser(userId).ifPresent(user -> user.removeGame(playerId)); } diff --git a/Mage.Server/src/main/java/mage/server/game/GameSessionWatcher.java b/Mage.Server/src/main/java/mage/server/game/GameSessionWatcher.java index ebe711cfcf..5e3de9641e 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameSessionWatcher.java +++ b/Mage.Server/src/main/java/mage/server/game/GameSessionWatcher.java @@ -6,7 +6,7 @@ import mage.interfaces.callback.ClientCallback; import mage.interfaces.callback.ClientCallbackMethod; import mage.players.Player; import mage.server.User; -import mage.server.UserManager; +import mage.server.managers.IUserManager; import mage.view.GameClientMessage; import mage.view.GameEndView; import mage.view.GameView; @@ -25,12 +25,14 @@ public class GameSessionWatcher { protected static final Logger logger = Logger.getLogger(GameSessionWatcher.class); + private final IUserManager userManager; protected final UUID userId; protected final Game game; protected boolean killed = false; protected final boolean isPlayer; - public GameSessionWatcher(UUID userId, Game game, boolean isPlayer) { + public GameSessionWatcher(IUserManager userManager, UUID userId, Game game, boolean isPlayer) { + this.userManager = userManager; this.userId = userId; this.game = game; this.isPlayer = isPlayer; @@ -38,7 +40,7 @@ public class GameSessionWatcher { public boolean init() { if (!killed) { - Optional user = UserManager.instance.getUser(userId); + Optional user = userManager.getUser(userId); if (user.isPresent()) { user.get().fireCallback(new ClientCallback(ClientCallbackMethod.GAME_INIT, game.getId(), getGameView())); return true; @@ -49,28 +51,28 @@ public class GameSessionWatcher { public void update() { if (!killed) { - UserManager.instance.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_UPDATE, game.getId(), getGameView()))); + userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_UPDATE, game.getId(), getGameView()))); } } public void inform(final String message) { if (!killed) { - UserManager.instance.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_INFORM, game.getId(), new GameClientMessage(getGameView(), message)))); + userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_INFORM, game.getId(), new GameClientMessage(getGameView(), message)))); } } public void informPersonal(final String message) { if (!killed) { - UserManager.instance.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_INFORM_PERSONAL, game.getId(), new GameClientMessage(getGameView(), message)))); + userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_INFORM_PERSONAL, game.getId(), new GameClientMessage(getGameView(), message)))); } } public void gameOver(final String message) { if (!killed) { - UserManager.instance.getUser(userId).ifPresent(user -> { + userManager.getUser(userId).ifPresent(user -> { user.removeGameWatchInfo(game.getId()); user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_OVER, game.getId(), message)); }); @@ -86,7 +88,7 @@ public class GameSessionWatcher { public void gameError(final String message) { if (!killed) { - UserManager.instance.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_ERROR, game.getId(), message))); + userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_ERROR, game.getId(), message))); } } diff --git a/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java b/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java index f597cdbaf5..c69f29f69d 100644 --- a/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java +++ b/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java @@ -1,12 +1,5 @@ - package mage.server.game; -import java.io.Serializable; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; import mage.MageException; import mage.cards.decks.DeckCardLists; import mage.constants.TableState; @@ -16,18 +9,21 @@ import mage.game.match.MatchOptions; import mage.game.tournament.TournamentOptions; import mage.players.PlayerType; import mage.server.RoomImpl; -import mage.server.TableManager; import mage.server.User; -import mage.server.UserManager; -import mage.server.tournament.TournamentManager; -import mage.server.util.ConfigSettings; -import mage.server.util.ThreadExecutor; +import mage.server.managers.ManagerFactory; import mage.view.MatchView; import mage.view.RoomUsersView; import mage.view.TableView; import mage.view.UsersView; import org.apache.log4j.Logger; +import java.io.Serializable; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + /** * @author BetaSteward_at_googlemail.com */ @@ -40,9 +36,12 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { private static List matchView = new ArrayList<>(); private static List roomUsersView = new ArrayList<>(); + private final ManagerFactory managerFactory; private final ConcurrentHashMap tables = new ConcurrentHashMap<>(); - public GamesRoomImpl() { + public GamesRoomImpl(ManagerFactory managerFactory) { + super(managerFactory.chatManager()); + this.managerFactory = managerFactory; UPDATE_EXECUTOR.scheduleAtFixedRate(() -> { try { update(); @@ -71,7 +70,7 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { } else { // more since 50 matches finished since this match so removeUserFromAllTablesAndChat it if (table.isTournament()) { - TournamentManager.instance.removeTournament(table.getTournament().getId()); + managerFactory.tournamentManager().removeTournament(table.getTournament().getId()); } this.removeTable(table.getId()); } @@ -79,7 +78,7 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { tableView = tableList; matchView = matchList; List users = new ArrayList<>(); - for (User user : UserManager.instance.getUsers()) { + for (User user : managerFactory.userManager().getUsers()) { if (user.getUserState() != User.UserState.Offline && !user.getName().equals("Admin")) { try { users.add(new UsersView(user.getUserData().getFlagName(), user.getName(), @@ -108,9 +107,9 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { users.sort((one, two) -> one.getUserName().compareToIgnoreCase(two.getUserName())); List roomUserInfo = new ArrayList<>(); roomUserInfo.add(new RoomUsersView(users, - GameManager.instance.getNumberActiveGames(), - ThreadExecutor.instance.getActiveThreads(ThreadExecutor.instance.getGameExecutor()), - ConfigSettings.instance.getMaxGameThreads() + managerFactory.gameManager().getNumberActiveGames(), + managerFactory.threadExecutor().getActiveThreads(managerFactory.threadExecutor().getGameExecutor()), + managerFactory.configSettings().getMaxGameThreads() )); roomUsersView = roomUserInfo; } @@ -123,7 +122,7 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { @Override public boolean joinTable(UUID userId, UUID tableId, String name, PlayerType playerType, int skill, DeckCardLists deckList, String password) throws MageException { if (tables.containsKey(tableId)) { - return TableManager.instance.joinTable(userId, tableId, name, playerType, skill, deckList, password); + return managerFactory.tableManager().joinTable(userId, tableId, name, playerType, skill, deckList, password); } else { return false; } @@ -131,7 +130,7 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { @Override public TableView createTable(UUID userId, MatchOptions options) { - Table table = TableManager.instance.createTable(this.getRoomId(), userId, options); + Table table = managerFactory.tableManager().createTable(this.getRoomId(), userId, options); tables.put(table.getId(), table); return new TableView(table); } @@ -139,7 +138,7 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { @Override public boolean joinTournamentTable(UUID userId, UUID tableId, String name, PlayerType playerType, int skill, DeckCardLists deckList, String password) throws GameException { if (tables.containsKey(tableId)) { - return TableManager.instance.joinTournament(userId, tableId, name, playerType, skill, deckList, password); + return managerFactory.tableManager().joinTournament(userId, tableId, name, playerType, skill, deckList, password); } else { return false; } @@ -147,7 +146,7 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { @Override public TableView createTournamentTable(UUID userId, TournamentOptions options) { - Table table = TableManager.instance.createTournamentTable(this.getRoomId(), userId, options); + Table table = managerFactory.tableManager().createTournamentTable(this.getRoomId(), userId, options); tables.put(table.getId(), table); return new TableView(table); } @@ -179,12 +178,12 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { @Override public void leaveTable(UUID userId, UUID tableId) { - TableManager.instance.leaveTable(userId, tableId); + managerFactory.tableManager().leaveTable(userId, tableId); } @Override public boolean watchTable(UUID userId, UUID tableId) throws MageException { - return TableManager.instance.watchTable(userId, tableId); + return managerFactory.tableManager().watchTable(userId, tableId); } @Override diff --git a/Mage.Server/src/main/java/mage/server/game/GamesRoomManager.java b/Mage.Server/src/main/java/mage/server/game/GamesRoomManager.java index c67c834fc2..b63ab4200a 100644 --- a/Mage.Server/src/main/java/mage/server/game/GamesRoomManager.java +++ b/Mage.Server/src/main/java/mage/server/game/GamesRoomManager.java @@ -1,5 +1,7 @@ package mage.server.game; +import mage.server.managers.IGamesRoomManager; +import mage.server.managers.ManagerFactory; import org.apache.log4j.Logger; import java.util.Optional; @@ -9,36 +11,44 @@ import java.util.concurrent.ConcurrentHashMap; /** * @author BetaSteward_at_googlemail.com */ -public enum GamesRoomManager { - instance; +public class GamesRoomManager implements IGamesRoomManager { + private final ManagerFactory managerFactory; private final ConcurrentHashMap rooms = new ConcurrentHashMap<>(); - private final UUID mainRoomId; - private final UUID mainChatId; + private UUID mainRoomId; + private UUID mainChatId; private static final Logger logger = Logger.getLogger(GamesRoomManager.class); - GamesRoomManager() { - GamesRoom mainRoom = new GamesRoomImpl(); + public GamesRoomManager(ManagerFactory managerFactory) { + this.managerFactory = managerFactory; + } + + public void init() { + GamesRoom mainRoom = new GamesRoomImpl(managerFactory); mainRoomId = mainRoom.getRoomId(); mainChatId = mainRoom.getChatId(); rooms.put(mainRoomId, mainRoom); } + @Override public UUID createRoom() { - GamesRoom room = new GamesRoomImpl(); + GamesRoom room = new GamesRoomImpl(managerFactory); rooms.put(room.getRoomId(), room); return room.getRoomId(); } + @Override public UUID getMainRoomId() { return mainRoomId; } + @Override public UUID getMainChatId() { return mainChatId; } + @Override public Optional getRoom(UUID roomId) { if (rooms.containsKey(roomId)) { return Optional.of(rooms.get(roomId)); @@ -48,6 +58,7 @@ public enum GamesRoomManager { } + @Override public void removeTable(UUID tableId) { for (GamesRoom room : rooms.values()) { room.removeTable(tableId); diff --git a/Mage.Server/src/main/java/mage/server/game/ReplayManager.java b/Mage.Server/src/main/java/mage/server/game/ReplayManager.java index beb554780d..9dcbb06462 100644 --- a/Mage.Server/src/main/java/mage/server/game/ReplayManager.java +++ b/Mage.Server/src/main/java/mage/server/game/ReplayManager.java @@ -1,46 +1,56 @@ - - package mage.server.game; +import mage.server.managers.IReplayManager; +import mage.server.managers.ManagerFactory; + import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; -import mage.server.UserManager; /** - * * @author BetaSteward_at_googlemail.com */ -public enum ReplayManager { - instance; +public class ReplayManager implements IReplayManager { private final ConcurrentHashMap replaySessions = new ConcurrentHashMap<>(); + private final ManagerFactory managerFactory; - public void replayGame(UUID gameId, UUID userId) { - ReplaySession replaySession = new ReplaySession(gameId, userId); - replaySessions.put(gameId.toString() + userId.toString(), replaySession); - UserManager.instance.getUser(userId).ifPresent(user->user.ccReplayGame(gameId)); + public ReplayManager(ManagerFactory managerFactory) { + this.managerFactory = managerFactory; } + @Override + public void replayGame(UUID gameId, UUID userId) { + ReplaySession replaySession = new ReplaySession(managerFactory, gameId, userId); + replaySessions.put(gameId.toString() + userId.toString(), replaySession); + managerFactory.userManager().getUser(userId).ifPresent(user -> user.ccReplayGame(gameId)); + } + + @Override public void startReplay(UUID gameId, UUID userId) { replaySessions.get(gameId.toString() + userId.toString()).replay(); } + @Override public void stopReplay(UUID gameId, UUID userId) { replaySessions.get(gameId.toString() + userId.toString()).stop(); } + @Override public void nextPlay(UUID gameId, UUID userId) { replaySessions.get(gameId.toString() + userId.toString()).next(); } + @Override public void previousPlay(UUID gameId, UUID userId) { replaySessions.get(gameId.toString() + userId.toString()).previous(); } + @Override public void skipForward(UUID gameId, UUID userId, int moves) { replaySessions.get(gameId.toString() + userId.toString()).next(moves); } + @Override public void endReplay(UUID gameId, UUID userId) { replaySessions.remove(gameId.toString() + userId.toString()); } diff --git a/Mage.Server/src/main/java/mage/server/game/ReplaySession.java b/Mage.Server/src/main/java/mage/server/game/ReplaySession.java index bb27a7a666..ac6592cd7a 100644 --- a/Mage.Server/src/main/java/mage/server/game/ReplaySession.java +++ b/Mage.Server/src/main/java/mage/server/game/ReplaySession.java @@ -1,32 +1,32 @@ - - package mage.server.game; -import java.util.UUID; - import mage.game.Game; import mage.game.GameState; import mage.interfaces.callback.ClientCallback; import mage.interfaces.callback.ClientCallbackMethod; -import mage.server.UserManager; +import mage.server.managers.ManagerFactory; import mage.view.GameView; +import java.util.UUID; + /** * @author BetaSteward_at_googlemail.com */ public class ReplaySession implements GameCallback { + private final ManagerFactory managerFactory; private final GameReplay replay; protected final UUID userId; - ReplaySession(UUID gameId, UUID userId) { + ReplaySession(ManagerFactory managerFactory, UUID gameId, UUID userId) { + this.managerFactory = managerFactory; this.replay = new GameReplay(gameId); this.userId = userId; } public void replay() { replay.start(); - UserManager.instance.getUser(userId).ifPresent(user -> + managerFactory.userManager().getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.REPLAY_INIT, replay.getGame().getId(), new GameView(replay.next(), replay.getGame(), null, null)))); } @@ -52,17 +52,17 @@ public class ReplaySession implements GameCallback { @Override public void gameResult(final String result) { - UserManager.instance.getUser(userId).ifPresent(user -> + managerFactory.userManager().getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.REPLAY_DONE, replay.getGame().getId(), result))); - ReplayManager.instance.endReplay(replay.getGame().getId(), userId); + managerFactory.replayManager().endReplay(replay.getGame().getId(), userId); } private void updateGame(final GameState state, Game game) { if (state == null) { gameResult("game ended"); } else { - UserManager.instance.getUser(userId).ifPresent(user -> + managerFactory.userManager().getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.REPLAY_UPDATE, replay.getGame().getId(), new GameView(state, game, null, null)))); } diff --git a/Mage.Server/src/main/java/mage/server/managers/IChatManager.java b/Mage.Server/src/main/java/mage/server/managers/IChatManager.java new file mode 100644 index 0000000000..4c54375a52 --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/managers/IChatManager.java @@ -0,0 +1,36 @@ +package mage.server.managers; + +import mage.game.Game; +import mage.server.ChatSession; +import mage.server.DisconnectReason; +import mage.server.exceptions.UserNotFoundException; +import mage.view.ChatMessage; + +import java.util.List; +import java.util.UUID; + +public interface IChatManager { + UUID createChatSession(String info); + + void joinChat(UUID chatId, UUID userId); + + void clearUserMessageStorage(); + + void leaveChat(UUID chatId, UUID userId); + + void destroyChatSession(UUID chatId); + + void broadcast(UUID chatId, String userName, String message, ChatMessage.MessageColor color, boolean withTime, Game game, ChatMessage.MessageType messageType, ChatMessage.SoundToPlay soundToPlay); + + void broadcast(UUID userId, String message, ChatMessage.MessageColor color) throws UserNotFoundException; + + void sendReconnectMessage(UUID userId); + + void sendLostConnectionMessage(UUID userId, DisconnectReason reason); + + void sendMessageToUserChats(UUID userId, String message); + + void removeUser(UUID userId, DisconnectReason reason); + + List getChatSessions(); +} diff --git a/Mage.Server/src/main/java/mage/server/util/ConfigSettingsContract.java b/Mage.Server/src/main/java/mage/server/managers/IConfigSettings.java similarity index 94% rename from Mage.Server/src/main/java/mage/server/util/ConfigSettingsContract.java rename to Mage.Server/src/main/java/mage/server/managers/IConfigSettings.java index a8ded69912..4f61c6928c 100644 --- a/Mage.Server/src/main/java/mage/server/util/ConfigSettingsContract.java +++ b/Mage.Server/src/main/java/mage/server/managers/IConfigSettings.java @@ -1,11 +1,11 @@ -package mage.server.util; +package mage.server.managers; import mage.server.util.config.GamePlugin; import mage.server.util.config.Plugin; import java.util.List; -public interface ConfigSettingsContract { +public interface IConfigSettings { String getServerAddress(); String getServerName(); diff --git a/Mage.Server/src/main/java/mage/server/managers/IDraftManager.java b/Mage.Server/src/main/java/mage/server/managers/IDraftManager.java new file mode 100644 index 0000000000..75fc2ca65a --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/managers/IDraftManager.java @@ -0,0 +1,34 @@ +package mage.server.managers; + +import mage.game.draft.Draft; +import mage.server.draft.DraftController; +import mage.view.DraftPickView; + +import java.util.Optional; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public interface IDraftManager { + UUID createDraftSession(Draft draft, ConcurrentHashMap userPlayerMap, UUID tableId); + + void joinDraft(UUID draftId, UUID userId); + + void destroyChatSession(UUID gameId); + + DraftPickView sendCardPick(UUID draftId, UUID userId, UUID cardId, Set hiddenCards); + + void sendCardMark(UUID draftId, UUID userId, UUID cardId); + + void removeSession(UUID userId); + + void kill(UUID draftId, UUID userId); + + void timeout(UUID gameId, UUID userId); + + void removeDraft(UUID draftId); + + DraftController getControllerByDraftId(UUID draftId); + + Optional getController(UUID tableId); +} diff --git a/Mage.Server/src/main/java/mage/server/managers/IGameManager.java b/Mage.Server/src/main/java/mage/server/managers/IGameManager.java new file mode 100644 index 0000000000..dc40fdb8d8 --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/managers/IGameManager.java @@ -0,0 +1,54 @@ +package mage.server.managers; + +import mage.cards.decks.DeckCardLists; +import mage.constants.ManaType; +import mage.constants.PlayerAction; +import mage.game.Game; +import mage.game.GameOptions; +import mage.server.game.GameController; +import mage.view.GameView; + +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public interface IGameManager { + UUID createGameSession(Game game, ConcurrentHashMap userPlayerMap, UUID tableId, UUID choosingPlayerId, GameOptions gameOptions); + + void joinGame(UUID gameId, UUID userId); + + Optional getChatId(UUID gameId); + + void sendPlayerUUID(UUID gameId, UUID userId, UUID data); + + void sendPlayerString(UUID gameId, UUID userId, String data); + + void sendPlayerManaType(UUID gameId, UUID playerId, UUID userId, ManaType data); + + void sendPlayerBoolean(UUID gameId, UUID userId, Boolean data); + + void sendPlayerInteger(UUID gameId, UUID userId, Integer data); + + void quitMatch(UUID gameId, UUID userId); + + void sendPlayerAction(PlayerAction playerAction, UUID gameId, UUID userId, Object data); + + boolean watchGame(UUID gameId, UUID userId); + + void stopWatching(UUID gameId, UUID userId); + + void cheat(UUID gameId, UUID userId, UUID playerId, DeckCardLists deckList); + + boolean cheat(UUID gameId, UUID userId, UUID playerId, String cardName); + + void removeGame(UUID gameId); + + boolean saveGame(UUID gameId); + + GameView getGameView(UUID gameId, UUID playerId); + + int getNumberActiveGames(); + + Map getGameController(); +} diff --git a/Mage.Server/src/main/java/mage/server/managers/IGamesRoomManager.java b/Mage.Server/src/main/java/mage/server/managers/IGamesRoomManager.java new file mode 100644 index 0000000000..b68e96b0bb --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/managers/IGamesRoomManager.java @@ -0,0 +1,18 @@ +package mage.server.managers; + +import mage.server.game.GamesRoom; + +import java.util.Optional; +import java.util.UUID; + +public interface IGamesRoomManager { + UUID createRoom(); + + UUID getMainRoomId(); + + UUID getMainChatId(); + + Optional getRoom(UUID roomId); + + void removeTable(UUID tableId); +} diff --git a/Mage.Server/src/main/java/mage/server/managers/IMailClient.java b/Mage.Server/src/main/java/mage/server/managers/IMailClient.java new file mode 100644 index 0000000000..0dcf168b5c --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/managers/IMailClient.java @@ -0,0 +1,7 @@ +package mage.server.managers; + +public interface IMailClient { + + boolean sendMessage(String email, String subject, String text); + +} diff --git a/Mage.Server/src/main/java/mage/server/managers/IReplayManager.java b/Mage.Server/src/main/java/mage/server/managers/IReplayManager.java new file mode 100644 index 0000000000..540fb77192 --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/managers/IReplayManager.java @@ -0,0 +1,19 @@ +package mage.server.managers; + +import java.util.UUID; + +public interface IReplayManager { + void replayGame(UUID gameId, UUID userId); + + void startReplay(UUID gameId, UUID userId); + + void stopReplay(UUID gameId, UUID userId); + + void nextPlay(UUID gameId, UUID userId); + + void previousPlay(UUID gameId, UUID userId); + + void skipForward(UUID gameId, UUID userId, int moves); + + void endReplay(UUID gameId, UUID userId); +} diff --git a/Mage.Server/src/main/java/mage/server/managers/ISessionManager.java b/Mage.Server/src/main/java/mage/server/managers/ISessionManager.java new file mode 100644 index 0000000000..1e5fe8c731 --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/managers/ISessionManager.java @@ -0,0 +1,43 @@ +package mage.server.managers; + +import mage.MageException; +import mage.players.net.UserData; +import mage.server.DisconnectReason; +import mage.server.Session; +import mage.server.User; +import org.jboss.remoting.callback.InvokerCallbackHandler; + +import javax.annotation.Nonnull; +import java.util.Optional; + +public interface ISessionManager { + Optional getSession(@Nonnull String sessionId); + + void createSession(String sessionId, InvokerCallbackHandler callbackHandler); + + boolean registerUser(String sessionId, String userName, String password, String email) throws MageException; + + boolean connectUser(String sessionId, String userName, String password, String userIdStr) throws MageException; + + boolean connectAdmin(String sessionId); + + boolean setUserData(String userName, String sessionId, UserData userData, String clientVersion, String userIdStr) throws MageException; + + void disconnect(String sessionId, DisconnectReason reason); + + void disconnect(String sessionId, DisconnectReason reason, Session directSession); + + void disconnectUser(String sessionId, String userSessionId); + + void endUserSession(String sessionId, String userSessionId); + + boolean isAdmin(String sessionId); + + boolean isValidSession(@Nonnull String sessionId); + + Optional getUser(@Nonnull String sessionId); + + boolean extendUserSession(String sessionId, String pingInfo); + + void sendErrorMessageToClient(String sessionId, String message); +} diff --git a/Mage.Server/src/main/java/mage/server/managers/ITableManager.java b/Mage.Server/src/main/java/mage/server/managers/ITableManager.java new file mode 100644 index 0000000000..f682349208 --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/managers/ITableManager.java @@ -0,0 +1,86 @@ +package mage.server.managers; + +import mage.MageException; +import mage.cards.decks.DeckCardLists; +import mage.game.GameException; +import mage.game.Table; +import mage.game.draft.Draft; +import mage.game.match.Match; +import mage.game.match.MatchOptions; +import mage.game.tournament.Tournament; +import mage.game.tournament.TournamentOptions; +import mage.game.tournament.TournamentPlayer; +import mage.players.PlayerType; +import mage.server.TableController; + +import java.util.Collection; +import java.util.Optional; +import java.util.UUID; + +public interface ITableManager { + Table createTable(UUID roomId, UUID userId, MatchOptions options); + + Table createTable(UUID roomId, MatchOptions options); + + Table createTournamentTable(UUID roomId, UUID userId, TournamentOptions options); + + Table getTable(UUID tableId); + + Optional getMatch(UUID tableId); + + Collection
getTables(); + + Collection getControllers(); + + Optional getController(UUID tableId); + + boolean joinTable(UUID userId, UUID tableId, String name, PlayerType playerType, int skill, DeckCardLists deckList, String password) throws MageException; + + boolean joinTournament(UUID userId, UUID tableId, String name, PlayerType playerType, int skill, DeckCardLists deckList, String password) throws GameException; + + boolean submitDeck(UUID userId, UUID tableId, DeckCardLists deckList) throws MageException; + + void updateDeck(UUID userId, UUID tableId, DeckCardLists deckList) throws MageException; + + // removeUserFromAllTablesAndChat user from all tournament sub tables + void userQuitTournamentSubTables(UUID userId); + + // removeUserFromAllTablesAndChat user from all sub tables of a tournament + void userQuitTournamentSubTables(UUID tournamentId, UUID userId); + + boolean isTableOwner(UUID tableId, UUID userId); + + boolean removeTable(UUID userId, UUID tableId); + + void leaveTable(UUID userId, UUID tableId); + + Optional getChatId(UUID tableId); + + void startMatch(UUID userId, UUID roomId, UUID tableId); + + void startTournamentSubMatch(UUID roomId, UUID tableId); + + void startTournament(UUID userId, UUID roomId, UUID tableId); + + void startDraft(UUID tableId, Draft draft); + + boolean watchTable(UUID userId, UUID tableId); + + void endGame(UUID tableId); + + void endDraft(UUID tableId, Draft draft); + + void endTournament(UUID tableId, Tournament tournament); + + void swapSeats(UUID tableId, UUID userId, int seatNum1, int seatNum2); + + void construct(UUID tableId); + + void initTournament(UUID tableId); + + void addPlayer(UUID userId, UUID tableId, TournamentPlayer player) throws GameException; + + void removeTable(UUID tableId); + + void debugServerState(); +} diff --git a/Mage.Server/src/main/java/mage/server/managers/IThreadExecutor.java b/Mage.Server/src/main/java/mage/server/managers/IThreadExecutor.java new file mode 100644 index 0000000000..d268b93ae7 --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/managers/IThreadExecutor.java @@ -0,0 +1,16 @@ +package mage.server.managers; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ScheduledExecutorService; + +public interface IThreadExecutor { + int getActiveThreads(ExecutorService executerService); + + ExecutorService getCallExecutor(); + + ExecutorService getGameExecutor(); + + ScheduledExecutorService getTimeoutExecutor(); + + ScheduledExecutorService getTimeoutIdleExecutor(); +} diff --git a/Mage.Server/src/main/java/mage/server/managers/ITournamentManager.java b/Mage.Server/src/main/java/mage/server/managers/ITournamentManager.java new file mode 100644 index 0000000000..ddf1f0775a --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/managers/ITournamentManager.java @@ -0,0 +1,32 @@ +package mage.server.managers; + +import mage.cards.decks.Deck; +import mage.game.tournament.Tournament; +import mage.server.tournament.TournamentController; +import mage.view.TournamentView; + +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public interface ITournamentManager { + Optional getTournamentController(UUID tournamentId); + + void createTournamentSession(Tournament tournament, ConcurrentHashMap userPlayerMap, UUID tableId); + + void joinTournament(UUID tournamentId, UUID userId); + + void quit(UUID tournamentId, UUID userId); + + void timeout(UUID tournamentId, UUID userId); + + void submitDeck(UUID tournamentId, UUID playerId, Deck deck); + + boolean updateDeck(UUID tournamentId, UUID playerId, Deck deck); + + TournamentView getTournamentView(UUID tournamentId); + + Optional getChatId(UUID tournamentId); + + void removeTournament(UUID tournamentId); +} diff --git a/Mage.Server/src/main/java/mage/server/managers/IUserManager.java b/Mage.Server/src/main/java/mage/server/managers/IUserManager.java new file mode 100644 index 0000000000..e1f6cebd2f --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/managers/IUserManager.java @@ -0,0 +1,41 @@ +package mage.server.managers; + +import mage.server.AuthorizedUser; +import mage.server.DisconnectReason; +import mage.server.User; +import mage.view.UserView; + +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface IUserManager { + Optional createUser(String userName, String host, AuthorizedUser authorizedUser); + + Optional getUser(UUID userId); + + Optional getUserByName(String userName); + + Collection getUsers(); + + boolean connectToSession(String sessionId, UUID userId); + + void disconnect(UUID userId, DisconnectReason reason); + + boolean isAdmin(UUID userId); + + void removeUserFromAllTablesAndChat(UUID userId, DisconnectReason reason); + + void informUserOpponents(UUID userId, String message); + + boolean extendUserSession(UUID userId, String pingInfo); + + List getUserInfoList(); + + void handleException(Exception ex); + + String getUserHistory(String userName); + + void updateUserHistory(); +} diff --git a/Mage.Server/src/main/java/mage/server/managers/ManagerFactory.java b/Mage.Server/src/main/java/mage/server/managers/ManagerFactory.java new file mode 100644 index 0000000000..14d7592f05 --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/managers/ManagerFactory.java @@ -0,0 +1,29 @@ +package mage.server.managers; + +public interface ManagerFactory { + IChatManager chatManager(); + + IDraftManager draftManager(); + + IGameManager gameManager(); + + IGamesRoomManager gamesRoomManager(); + + IMailClient mailClient(); + + IMailClient mailgunClient(); + + IReplayManager replayManager(); + + ISessionManager sessionManager(); + + ITableManager tableManager(); + + IUserManager userManager(); + + IConfigSettings configSettings(); + + IThreadExecutor threadExecutor(); + + ITournamentManager tournamentManager(); +} diff --git a/Mage.Server/src/main/java/mage/server/record/TableRecorderImpl.java b/Mage.Server/src/main/java/mage/server/record/TableRecorderImpl.java index cfcc360ed3..b8ed2b5876 100644 --- a/Mage.Server/src/main/java/mage/server/record/TableRecorderImpl.java +++ b/Mage.Server/src/main/java/mage/server/record/TableRecorderImpl.java @@ -3,16 +3,20 @@ package mage.server.record; import mage.game.Table; import mage.game.Table.TableRecorder; import mage.game.result.ResultProtos.TableProto; -import mage.server.UserManager; +import mage.server.managers.IUserManager; -public enum TableRecorderImpl implements TableRecorder { +public class TableRecorderImpl implements TableRecorder { - instance; + private final IUserManager userManager; + + public TableRecorderImpl(IUserManager userManager) { + this.userManager = userManager; + } @Override public void record(Table table) { TableProto proto = table.toProto(); TableRecordRepository.instance.add(new TableRecord(proto, proto.getEndTimeMs())); - UserManager.instance.updateUserHistory(); + userManager.updateUserHistory(); } } diff --git a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java index ef63068139..a13c925f6d 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java @@ -17,14 +17,10 @@ import mage.game.tournament.Tournament; import mage.game.tournament.TournamentPairing; import mage.game.tournament.TournamentPlayer; import mage.players.PlayerType; -import mage.server.ChatManager; -import mage.server.TableManager; import mage.server.User; -import mage.server.UserManager; import mage.server.draft.DraftController; -import mage.server.draft.DraftManager; -import mage.server.game.GamesRoomManager; -import mage.server.util.ThreadExecutor; +import mage.server.managers.ITableManager; +import mage.server.managers.ManagerFactory; import mage.view.ChatMessage.MessageColor; import mage.view.ChatMessage.MessageType; import mage.view.ChatMessage.SoundToPlay; @@ -44,6 +40,7 @@ public class TournamentController { private static final Logger logger = Logger.getLogger(TournamentController.class); + private final ManagerFactory managerFactory; private final UUID chatId; private final UUID tableId; private boolean started = false; @@ -51,9 +48,10 @@ public class TournamentController { private ConcurrentMap userPlayerMap = new ConcurrentHashMap<>(); private final ConcurrentMap tournamentSessions = new ConcurrentHashMap<>(); - public TournamentController(Tournament tournament, ConcurrentMap userPlayerMap, UUID tableId) { + public TournamentController(ManagerFactory managerFactory, Tournament tournament, ConcurrentMap userPlayerMap, UUID tableId) { + this.managerFactory = managerFactory; this.userPlayerMap = userPlayerMap; - chatId = ChatManager.instance.createChatSession("Tournament " + tournament.getId()); + chatId = managerFactory.chatManager().createChatSession("Tournament " + tournament.getId()); this.tournament = tournament; this.tableId = tableId; init(); @@ -67,7 +65,7 @@ public class TournamentController { checkPlayersState(); break; case INFO: - ChatManager.instance.broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, null, MessageType.STATUS, null); + managerFactory.chatManager().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, null, MessageType.STATUS, null); logger.debug(tournament.getId() + " " + event.getMessage()); break; case START_DRAFT: @@ -122,7 +120,7 @@ public class TournamentController { if (!player.getPlayer().isHuman()) { player.setJoined(); logger.debug("player " + player.getPlayer().getId() + " has joined tournament " + tournament.getId()); - ChatManager.instance.broadcast(chatId, "", player.getPlayer().getLogName() + " has joined the tournament", MessageColor.BLACK, true, null, MessageType.STATUS, null); + managerFactory.chatManager().broadcast(chatId, "", player.getPlayer().getLogName() + " has joined the tournament", MessageColor.BLACK, true, null, MessageType.STATUS, null); } } checkStart(); @@ -132,7 +130,7 @@ public class TournamentController { UUID playerId = userPlayerMap.get(userId); if (playerId == null) { if (logger.isDebugEnabled()) { - UserManager.instance.getUser(userId).ifPresent(user + managerFactory.userManager().getUser(userId).ifPresent(user -> logger.debug(user.getName() + " shows tournament panel tournamentId: " + tournament.getId())); } @@ -143,16 +141,16 @@ public class TournamentController { return; } // first join of player - TournamentSession tournamentSession = new TournamentSession(tournament, userId, tableId, playerId); + TournamentSession tournamentSession = new TournamentSession(managerFactory, tournament, userId, tableId, playerId); tournamentSessions.put(playerId, tournamentSession); - Optional _user = UserManager.instance.getUser(userId); + Optional _user = managerFactory.userManager().getUser(userId); if (_user.isPresent()) { User user = _user.get(); user.addTournament(playerId, tournament.getId()); TournamentPlayer player = tournament.getPlayer(playerId); player.setJoined(); logger.debug("player " + player.getPlayer().getName() + " - client has joined tournament " + tournament.getId()); - ChatManager.instance.broadcast(chatId, "", player.getPlayer().getLogName() + " has joined the tournament", MessageColor.BLACK, true, null, MessageType.STATUS, null); + managerFactory.chatManager().broadcast(chatId, "", player.getPlayer().getLogName() + " has joined the tournament", MessageColor.BLACK, true, null, MessageType.STATUS, null); checkStart(); } else { logger.error("User not found userId: " + userId + " tournamentId: " + tournament.getId()); @@ -174,7 +172,7 @@ public class TournamentController { private void checkStart() { if (!started && allJoined()) { - ThreadExecutor.instance.getCallExecutor().execute(this::startTournament); + managerFactory.threadExecutor().getCallExecutor().execute(this::startTournament); } } @@ -211,15 +209,15 @@ public class TournamentController { tournamentSession.tournamentOver(); } this.tournamentSessions.clear(); - TableManager.instance.endTournament(tableId, tournament); + managerFactory.tableManager().endTournament(tableId, tournament); tournament.cleanUpOnTournamentEnd(); } private void startMatch(TournamentPairing pair, MatchOptions matchOptions) { try { - TableManager tableManager = TableManager.instance; - Table table = tableManager.createTable(GamesRoomManager.instance.getMainRoomId(), matchOptions); + ITableManager tableManager = managerFactory.tableManager(); + Table table = tableManager.createTable(managerFactory.gamesRoomManager().getMainRoomId(), matchOptions); table.setTournamentSubTable(true); table.setTournament(tournament); table.setState(TableState.WAITING); @@ -261,8 +259,8 @@ public class TournamentController { private void startMultiplayerMatch(MultiplayerRound round, MatchOptions matchOptions) { try { - TableManager tableManager = TableManager.instance; - Table table = tableManager.createTable(GamesRoomManager.instance.getMainRoomId(), matchOptions); + ITableManager tableManager = managerFactory.tableManager(); + Table table = tableManager.createTable(managerFactory.gamesRoomManager().getMainRoomId(), matchOptions); table.setTournamentSubTable(true); table.setTournament(tournament); table.setState(TableState.WAITING); @@ -287,16 +285,16 @@ public class TournamentController { } private void startDraft(Draft draft) { - TableManager.instance.startDraft(tableId, draft); + managerFactory.tableManager().startDraft(tableId, draft); } private void construct() { - TableManager.instance.construct(tableId); + managerFactory.tableManager().construct(tableId); } private void initTournament() { - if (TableManager.instance.getTable(tableId).getState() != TableState.DUELING) { - TableManager.instance.initTournament(tableId); + if (managerFactory.tableManager().getTable(tableId).getState() != TableState.DUELING) { + managerFactory.tableManager().initTournament(tableId); } } @@ -305,7 +303,7 @@ public class TournamentController { TournamentSession tournamentSession = tournamentSessions.get(playerId); tournamentSession.construct(timeout); getPlayerUserId(playerId).ifPresent(userId -> { - UserManager.instance.getUser(userId).ifPresent(user -> { + managerFactory.userManager().getUser(userId).ifPresent(user -> { user.addConstructing(playerId, tournamentSession); TournamentPlayer player = tournament.getPlayer(playerId); player.setState(TournamentPlayerState.CONSTRUCTING); @@ -319,7 +317,7 @@ public class TournamentController { TournamentPlayer player = tournament.getPlayer(playerId); if (player != null && !player.hasQuit()) { tournamentSessions.get(playerId).submitDeck(deck); - ChatManager.instance.broadcast(chatId, "", player.getPlayer().getLogName() + " has submitted their tournament deck", MessageColor.BLACK, true, null, MessageType.STATUS, SoundToPlay.PlayerSubmittedDeck); + managerFactory.chatManager().broadcast(chatId, "", player.getPlayer().getLogName() + " has submitted their tournament deck", MessageColor.BLACK, true, null, MessageType.STATUS, SoundToPlay.PlayerSubmittedDeck); } } } @@ -338,7 +336,7 @@ public class TournamentController { tournament.autoSubmit(userPlayerMap.get(userId), tournamentPlayer.generateDeck()); } else { StringBuilder sb = new StringBuilder(); - UserManager.instance.getUser(userId).ifPresent(user + managerFactory.userManager().getUser(userId).ifPresent(user -> sb.append(user.getName())); sb.append(" - no deck found for auto submit"); @@ -380,16 +378,16 @@ public class TournamentController { if (tournament.isDoneConstructing()) { info = new StringBuilder("during round ").append(tournament.getRounds().size()).toString(); // quit active matches of that tournament - TableManager.instance.userQuitTournamentSubTables(tournament.getId(), userId); + managerFactory.tableManager().userQuitTournamentSubTables(tournament.getId(), userId); status = TourneyQuitStatus.DURING_ROUND; } else if (tournamentPlayer.getState() == TournamentPlayerState.DRAFTING) { info = "during Draft phase"; if (!checkToReplaceDraftPlayerByAi(userId, tournamentPlayer)) { this.abortDraftTournament(); } else { - DraftManager.instance.getController(tableId).ifPresent(draftController -> { + managerFactory.draftManager().getController(tableId).ifPresent(draftController -> { draftController.getDraftSession(playerId).ifPresent(draftSession - -> DraftManager.instance.kill(draftSession.getDraftId(), userId)); + -> managerFactory.draftManager().kill(draftSession.getDraftId(), userId)); }); } @@ -404,7 +402,7 @@ public class TournamentController { tournamentPlayer.setQuit(info, status); tournament.quit(playerId); tournamentSession.quit(); - ChatManager.instance.broadcast(chatId, "", tournamentPlayer.getPlayer().getLogName() + " has quit the tournament", MessageColor.BLACK, true, null, MessageType.STATUS, SoundToPlay.PlayerQuitTournament); + managerFactory.chatManager().broadcast(chatId, "", tournamentPlayer.getPlayer().getLogName() + " has quit the tournament", MessageColor.BLACK, true, null, MessageType.STATUS, SoundToPlay.PlayerQuitTournament); } } @@ -417,8 +415,8 @@ public class TournamentController { } // replace player that quits with draft bot if (humans > 1) { - Optional user = UserManager.instance.getUser(userId); - TableManager.instance.getController(tableId).ifPresent(tableController -> { + Optional user = managerFactory.userManager().getUser(userId); + managerFactory.tableManager().getController(tableId).ifPresent(tableController -> { String replacePlayerName = "Draftbot"; if (user.isPresent()) { @@ -430,7 +428,7 @@ public class TournamentController { user.get().removeTable(leavingPlayer.getPlayer().getId()); user.get().removeTournament(leavingPlayer.getPlayer().getId()); } - ChatManager.instance.broadcast(chatId, "", leavingPlayer.getPlayer().getLogName() + " was replaced by draftbot", MessageColor.BLACK, true, null, MessageType.STATUS, null); + managerFactory.chatManager().broadcast(chatId, "", leavingPlayer.getPlayer().getLogName() + " was replaced by draftbot", MessageColor.BLACK, true, null, MessageType.STATUS, null); }); return true; } @@ -447,7 +445,7 @@ public class TournamentController { private void abortDraftTournament() { tournament.setAbort(true); - DraftManager.instance.getController(tableId).ifPresent(DraftController::abortDraft); + managerFactory.draftManager().getController(tableId).ifPresent(DraftController::abortDraft); } public boolean isAbort() { @@ -472,7 +470,7 @@ public class TournamentController { } public void cleanUpOnRemoveTournament() { - ChatManager.instance.destroyChatSession(chatId); + managerFactory.chatManager().destroyChatSession(chatId); } /** @@ -490,7 +488,7 @@ public class TournamentController { if (tournamentPlayer != null) { if (!tournamentPlayer.hasQuit()) { if (tournamentPlayer.getPlayer().isHuman()) { - Optional user = UserManager.instance.getUser(entry.getKey()); + Optional user = managerFactory.userManager().getUser(entry.getKey()); if (!user.isPresent()) { logger.debug("Tournament user is missing but player active -> start quit - tournamentId: " + tournament.getId() + " state: " + tableState.toString()); // active tournament player but the user is no longer online diff --git a/Mage.Server/src/main/java/mage/server/tournament/TournamentManager.java b/Mage.Server/src/main/java/mage/server/tournament/TournamentManager.java index a499842e29..4ff65f9180 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentManager.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentManager.java @@ -1,36 +1,46 @@ - package mage.server.tournament; +import mage.cards.decks.Deck; +import mage.game.tournament.Tournament; +import mage.server.managers.ITournamentManager; +import mage.server.managers.ManagerFactory; +import mage.view.TournamentView; +import org.apache.log4j.Logger; + import java.util.Optional; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import mage.cards.decks.Deck; -import mage.game.tournament.Tournament; -import mage.view.TournamentView; -import org.apache.log4j.Logger; - /** * @author BetaSteward_at_googlemail.com */ -public enum TournamentManager { - instance; +public class TournamentManager implements ITournamentManager { + + private final ManagerFactory managerFactory; private final ConcurrentMap controllers = new ConcurrentHashMap<>(); + public TournamentManager(ManagerFactory managerFactory) { + this.managerFactory = managerFactory; + } + + @Override public Optional getTournamentController(UUID tournamentId) { return Optional.ofNullable(controllers.get(tournamentId)); } + @Override public void createTournamentSession(Tournament tournament, ConcurrentHashMap userPlayerMap, UUID tableId) { - TournamentController tournamentController = new TournamentController(tournament, userPlayerMap, tableId); + TournamentController tournamentController = new TournamentController(managerFactory, tournament, userPlayerMap, tableId); controllers.put(tournament.getId(), tournamentController); } + @Override public void joinTournament(UUID tournamentId, UUID userId) { controllers.get(tournamentId).join(userId); } + @Override public void quit(UUID tournamentId, UUID userId) { TournamentController tournamentController = controllers.get(tournamentId); if (tournamentController != null) { @@ -40,18 +50,22 @@ public enum TournamentManager { } } + @Override public void timeout(UUID tournamentId, UUID userId) { controllers.get(tournamentId).timeout(userId); } + @Override public void submitDeck(UUID tournamentId, UUID playerId, Deck deck) { controllers.get(tournamentId).submitDeck(playerId, deck); } + @Override public boolean updateDeck(UUID tournamentId, UUID playerId, Deck deck) { return controllers.get(tournamentId).updateDeck(playerId, deck); } + @Override public TournamentView getTournamentView(UUID tournamentId) { TournamentController tournamentController = controllers.get(tournamentId); if (tournamentController != null) { @@ -60,6 +74,7 @@ public enum TournamentManager { return null; } + @Override public Optional getChatId(UUID tournamentId) { if (controllers.containsKey(tournamentId)) { return Optional.of(controllers.get(tournamentId).getChatId()); @@ -67,6 +82,7 @@ public enum TournamentManager { return Optional.empty(); } + @Override public void removeTournament(UUID tournamentId) { TournamentController tournamentController = controllers.get(tournamentId); if (tournamentController != null) { diff --git a/Mage.Server/src/main/java/mage/server/tournament/TournamentSession.java b/Mage.Server/src/main/java/mage/server/tournament/TournamentSession.java index 3317165991..e04c9062e2 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentSession.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentSession.java @@ -1,20 +1,19 @@ - package mage.server.tournament; +import mage.cards.decks.Deck; +import mage.game.tournament.Tournament; +import mage.interfaces.callback.ClientCallback; +import mage.interfaces.callback.ClientCallbackMethod; +import mage.server.User; +import mage.server.managers.ManagerFactory; +import mage.view.TournamentView; +import org.apache.log4j.Logger; + import java.util.Optional; import java.util.UUID; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import mage.cards.decks.Deck; -import mage.game.tournament.Tournament; -import mage.interfaces.callback.ClientCallback; -import mage.interfaces.callback.ClientCallbackMethod; -import mage.server.User; -import mage.server.UserManager; -import mage.server.util.ThreadExecutor; -import mage.view.TournamentView; -import org.apache.log4j.Logger; /** * @author BetaSteward_at_googlemail.com @@ -23,6 +22,7 @@ public class TournamentSession { protected static final Logger logger = Logger.getLogger(TournamentSession.class); + private final ManagerFactory managerFactory; protected final UUID userId; protected final UUID playerId; protected final UUID tableId; @@ -30,9 +30,11 @@ public class TournamentSession { protected boolean killed = false; private ScheduledFuture futureTimeout; - protected static final ScheduledExecutorService timeoutExecutor = ThreadExecutor.instance.getTimeoutExecutor(); + protected final ScheduledExecutorService timeoutExecutor; - public TournamentSession(Tournament tournament, UUID userId, UUID tableId, UUID playerId) { + public TournamentSession(ManagerFactory managerFactory, Tournament tournament, UUID userId, UUID tableId, UUID playerId) { + this.managerFactory = managerFactory; + this.timeoutExecutor = managerFactory.threadExecutor().getTimeoutExecutor(); this.userId = userId; this.tournament = tournament; this.playerId = playerId; @@ -41,7 +43,7 @@ public class TournamentSession { public boolean init() { if (!killed) { - Optional user = UserManager.instance.getUser(userId); + Optional user = managerFactory.userManager().getUser(userId); if (user.isPresent()) { user.get().fireCallback(new ClientCallback(ClientCallbackMethod.TOURNAMENT_INIT, tournament.getId(), getTournamentView())); return true; @@ -52,7 +54,7 @@ public class TournamentSession { public void update() { if (!killed) { - UserManager.instance.getUser(userId).ifPresent(user + managerFactory.userManager().getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.TOURNAMENT_UPDATE, tournament.getId(), getTournamentView()))); } @@ -60,7 +62,7 @@ public class TournamentSession { public void gameOver(final String message) { if (!killed) { - UserManager.instance.getUser(userId).ifPresent(user + managerFactory.userManager().getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.TOURNAMENT_OVER, tournament.getId(), message))); } @@ -69,7 +71,7 @@ public class TournamentSession { public void construct(int timeout) { if (!killed) { setupTimeout(timeout); - UserManager.instance.getUser(userId).ifPresent(user -> { + managerFactory.userManager().getUser(userId).ifPresent(user -> { int remaining = (int) futureTimeout.getDelay(TimeUnit.SECONDS); user.ccConstruct(tournament.getPlayer(playerId).getDeck(), tableId, remaining); }); @@ -102,7 +104,7 @@ public class TournamentSession { futureTimeout = timeoutExecutor.schedule( () -> { try { - TournamentManager.instance.timeout(tournament.getId(), userId); + managerFactory.tournamentManager().timeout(tournament.getId(), userId); } catch (Exception e) { logger.fatal("TournamentSession error - userId " + userId + " tId " + tournament.getId(), e); } @@ -144,7 +146,7 @@ public class TournamentSession { } private void removeTournamentForUser() { - Optional user = UserManager.instance.getUser(userId); + Optional user = managerFactory.userManager().getUser(userId); if (user.isPresent()) { user.get().removeTable(playerId); user.get().removeTournament(playerId); diff --git a/Mage.Server/src/main/java/mage/server/util/ConfigSettings.java b/Mage.Server/src/main/java/mage/server/util/ConfigSettings.java deleted file mode 100644 index e66e8f9276..0000000000 --- a/Mage.Server/src/main/java/mage/server/util/ConfigSettings.java +++ /dev/null @@ -1,161 +0,0 @@ - -package mage.server.util; - -import java.io.File; -import java.util.List; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import mage.server.util.config.Config; -import mage.server.util.config.GamePlugin; -import mage.server.util.config.Plugin; -import org.apache.log4j.Logger; - -/** - * @author BetaSteward_at_googlemail.com - */ -public enum ConfigSettings implements ConfigSettingsContract { - instance; - private final Logger logger = Logger.getLogger(ConfigSettings.class); - - private Config config; - - ConfigSettings() { - try { - JAXBContext jaxbContext = JAXBContext.newInstance("mage.server.util.config"); - Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); - config = (Config) unmarshaller.unmarshal(new File("config/config.xml")); - } catch (JAXBException ex) { - logger.fatal("ConfigSettings error", ex); - } - } - - public String getServerAddress() { - return config.getServer().getServerAddress(); - } - - public String getServerName() { - return config.getServer().getServerName(); - } - - public int getPort() { - return config.getServer().getPort().intValue(); - } - - public int getSecondaryBindPort() { - return config.getServer().getSecondaryBindPort().intValue(); - } - - public int getLeasePeriod() { - return config.getServer().getLeasePeriod().intValue(); - } - - public int getSocketWriteTimeout() { - return config.getServer().getSocketWriteTimeout().intValue(); - } - - public int getMaxPoolSize() { - return config.getServer().getMaxPoolSize().intValue(); - } - - public int getNumAcceptThreads() { - return config.getServer().getNumAcceptThreads().intValue(); - } - - public int getBacklogSize() { - return config.getServer().getBacklogSize().intValue(); - } - - public int getMaxGameThreads() { - return config.getServer().getMaxGameThreads().intValue(); - } - - public int getMaxSecondsIdle() { - return config.getServer().getMaxSecondsIdle().intValue(); - } - - public int getMinUserNameLength() { - return config.getServer().getMinUserNameLength().intValue(); - } - - public int getMaxUserNameLength() { - return config.getServer().getMaxUserNameLength().intValue(); - } - - public String getInvalidUserNamePattern() { - return config.getServer().getInvalidUserNamePattern(); - } - - public int getMinPasswordLength() { - return config.getServer().getMinPasswordLength().intValue(); - } - - public int getMaxPasswordLength() { - return config.getServer().getMaxPasswordLength().intValue(); - } - - public String getMaxAiOpponents() { - return config.getServer().getMaxAiOpponents(); - } - - public Boolean isSaveGameActivated() { - return config.getServer().isSaveGameActivated(); - } - - public Boolean isAuthenticationActivated() { - return config.getServer().isAuthenticationActivated(); - } - - public String getGoogleAccount() { - return config.getServer().getGoogleAccount(); - } - - public String getMailgunApiKey() { - return config.getServer().getMailgunApiKey(); - } - - public String getMailgunDomain() { - return config.getServer().getMailgunDomain(); - } - - public String getMailSmtpHost() { - return config.getServer().getMailSmtpHost(); - } - - public String getMailSmtpPort() { - return config.getServer().getMailSmtpPort(); - } - - public String getMailUser() { - return config.getServer().getMailUser(); - } - - public String getMailPassword() { - return config.getServer().getMailPassword(); - } - - public String getMailFromAddress() { - return config.getServer().getMailFromAddress(); - } - - public List getPlayerTypes() { - return config.getPlayerTypes().getPlayerType(); - } - - public List getGameTypes() { - return config.getGameTypes().getGameType(); - } - - public List getTournamentTypes() { - return config.getTournamentTypes().getTournamentType(); - } - - public List getDraftCubes() { - return config.getDraftCubes().getDraftCube(); - } - - public List getDeckTypes() { - return config.getDeckTypes().getDeckType(); - } - -} diff --git a/Mage.Server/src/main/java/mage/server/util/ConfigWrapper.java b/Mage.Server/src/main/java/mage/server/util/ConfigWrapper.java index 1a461a73aa..a147610b46 100644 --- a/Mage.Server/src/main/java/mage/server/util/ConfigWrapper.java +++ b/Mage.Server/src/main/java/mage/server/util/ConfigWrapper.java @@ -1,12 +1,13 @@ package mage.server.util; +import mage.server.managers.IConfigSettings; import mage.server.util.config.Config; import mage.server.util.config.GamePlugin; import mage.server.util.config.Plugin; import java.util.List; -public class ConfigWrapper implements ConfigSettingsContract { +public class ConfigWrapper implements IConfigSettings { private final Config config; diff --git a/Mage.Server/src/main/java/mage/server/util/ThreadExecutor.java b/Mage.Server/src/main/java/mage/server/util/ThreadExecutor.java index a5014ecf73..22602dde5a 100644 --- a/Mage.Server/src/main/java/mage/server/util/ThreadExecutor.java +++ b/Mage.Server/src/main/java/mage/server/util/ThreadExecutor.java @@ -1,24 +1,18 @@ - package mage.server.util; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; +import mage.server.managers.IConfigSettings; +import mage.server.managers.IThreadExecutor; + +import java.util.concurrent.*; /** - * * @author BetaSteward_at_googlemail.com */ -public enum ThreadExecutor { -instance; - private static final ExecutorService callExecutor = Executors.newCachedThreadPool(); - private static final ExecutorService userExecutor = Executors.newCachedThreadPool(); - private static final ExecutorService gameExecutor = Executors.newFixedThreadPool(ConfigSettings.instance.getMaxGameThreads()); - private static final ScheduledExecutorService timeoutExecutor = Executors.newScheduledThreadPool(4); - private static final ScheduledExecutorService timeoutIdleExecutor = Executors.newScheduledThreadPool(4); +public class ThreadExecutor implements IThreadExecutor { + private final ExecutorService callExecutor; + private final ExecutorService gameExecutor; + private final ScheduledExecutorService timeoutExecutor; + private final ScheduledExecutorService timeoutIdleExecutor; /** * noxx: what the settings below do is setting the ability to keep OS @@ -26,17 +20,20 @@ instance; * within this time period, the thread may be discarded. But anyway if new * game is created later, new OS/java thread will be created for it taking * MaxGameThreads limit into account. - * + *

* This all is done for performance reasons as creating new OS threads is * resource consuming process. */ - static { + + public ThreadExecutor(IConfigSettings config) { + callExecutor = Executors.newCachedThreadPool(); + gameExecutor = Executors.newFixedThreadPool(config.getMaxGameThreads()); + timeoutExecutor = Executors.newScheduledThreadPool(4); + timeoutIdleExecutor = Executors.newScheduledThreadPool(4); + ((ThreadPoolExecutor) callExecutor).setKeepAliveTime(60, TimeUnit.SECONDS); ((ThreadPoolExecutor) callExecutor).allowCoreThreadTimeOut(true); ((ThreadPoolExecutor) callExecutor).setThreadFactory(new XMageThreadFactory("CALL")); - ((ThreadPoolExecutor) userExecutor).setKeepAliveTime(60, TimeUnit.SECONDS); - ((ThreadPoolExecutor) userExecutor).allowCoreThreadTimeOut(true); - ((ThreadPoolExecutor) userExecutor).setThreadFactory(new XMageThreadFactory("USER")); ((ThreadPoolExecutor) gameExecutor).setKeepAliveTime(60, TimeUnit.SECONDS); ((ThreadPoolExecutor) gameExecutor).allowCoreThreadTimeOut(true); ((ThreadPoolExecutor) gameExecutor).setThreadFactory(new XMageThreadFactory("GAME")); @@ -49,6 +46,7 @@ instance; } + @Override public int getActiveThreads(ExecutorService executerService) { if (executerService instanceof ThreadPoolExecutor) { return ((ThreadPoolExecutor) executerService).getActiveCount(); @@ -56,18 +54,22 @@ instance; return -1; } + @Override public ExecutorService getCallExecutor() { return callExecutor; } + @Override public ExecutorService getGameExecutor() { return gameExecutor; } + @Override public ScheduledExecutorService getTimeoutExecutor() { return timeoutExecutor; } + @Override public ScheduledExecutorService getTimeoutIdleExecutor() { return timeoutIdleExecutor; } diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java index d5d228dd14..f008d5112d 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java @@ -14,8 +14,10 @@ import mage.players.Player; import mage.players.PlayerType; import mage.server.game.GameFactory; import mage.server.game.PlayerFactory; +import mage.server.managers.IConfigSettings; import mage.server.tournament.TournamentFactory; -import mage.server.util.ConfigSettings; +import mage.server.util.ConfigFactory; +import mage.server.util.ConfigWrapper; import mage.server.util.PluginClassLoader; import mage.server.util.config.GamePlugin; import mage.server.util.config.Plugin; @@ -100,7 +102,7 @@ public abstract class MageTestBase { public static void init() { Logger.getRootLogger().setLevel(Level.DEBUG); deleteSavedGames(); - ConfigSettings config = ConfigSettings.instance; + IConfigSettings config = new ConfigWrapper(ConfigFactory.loadFromFile("config/config.xml")); config.getGameTypes().forEach((gameType) -> { GameFactory.instance.addGameType(gameType.getName(), loadGameType(gameType), loadPlugin(gameType)); }); diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java index 1d9c9f9f02..485808af31 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java @@ -23,7 +23,9 @@ import mage.game.permanent.PermanentCard; import mage.game.tournament.TournamentType; import mage.players.Player; import mage.server.game.GameFactory; -import mage.server.util.ConfigSettings; +import mage.server.managers.IConfigSettings; +import mage.server.util.ConfigFactory; +import mage.server.util.ConfigWrapper; import mage.server.util.PluginClassLoader; import mage.server.util.config.GamePlugin; import mage.server.util.config.Plugin; @@ -114,7 +116,7 @@ public abstract class MageTestPlayerBase { logger.debug("Default charset: " + Charset.defaultCharset()); deleteSavedGames(); - ConfigSettings config = ConfigSettings.instance; + IConfigSettings config = new ConfigWrapper(ConfigFactory.loadFromFile("config/config.xml")); for (GamePlugin plugin : config.getGameTypes()) { GameFactory.instance.addGameType(plugin.getName(), loadGameType(plugin), loadPlugin(plugin)); } From e8bb8ae24b15963119880c8a7f7771c4b9478cc2 Mon Sep 17 00:00:00 2001 From: Francesco Burato Date: Fri, 30 Oct 2020 18:03:36 +0000 Subject: [PATCH 3/4] [app-wiring-refactor]: Externalise configuration path --- .../src/main/java/mage/utils/FluentBuilder.java | 2 +- Mage.Server/config/config_error.xml | 2 +- Mage.Server/src/main/java/mage/server/Main.java | 11 ++++++++++- .../src/main/java/mage/server/UserManager.java | 1 - 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Mage.Common/src/main/java/mage/utils/FluentBuilder.java b/Mage.Common/src/main/java/mage/utils/FluentBuilder.java index 3e4ab75b91..8c4174ac41 100644 --- a/Mage.Common/src/main/java/mage/utils/FluentBuilder.java +++ b/Mage.Common/src/main/java/mage/utils/FluentBuilder.java @@ -33,4 +33,4 @@ public abstract class FluentBuilder c.accept(instance)); return instance.makeValue(); } -} \ No newline at end of file +} diff --git a/Mage.Server/config/config_error.xml b/Mage.Server/config/config_error.xml index cf0b854367..51a73dee44 100644 --- a/Mage.Server/config/config_error.xml +++ b/Mage.Server/config/config_error.xml @@ -170,4 +170,4 @@ - \ No newline at end of file + diff --git a/Mage.Server/src/main/java/mage/server/Main.java b/Mage.Server/src/main/java/mage/server/Main.java index b2721b0639..49659adc4d 100644 --- a/Mage.Server/src/main/java/mage/server/Main.java +++ b/Mage.Server/src/main/java/mage/server/Main.java @@ -39,6 +39,7 @@ import java.io.IOException; import java.net.InetAddress; import java.net.MalformedURLException; import java.nio.charset.Charset; +import java.nio.file.Paths; import java.util.*; /** @@ -52,9 +53,11 @@ public final class Main { private static final String testModeArg = "-testMode="; private static final String fastDBModeArg = "-fastDbMode="; private static final String adminPasswordArg = "-adminPassword="; + private static final String configPathProp = "xmage.config.path"; private static final File pluginFolder = new File("plugins"); private static final File extensionFolder = new File("extensions"); + private static final String defaultConfigPath = Paths.get("config", "config.xml").toString(); public static final PluginClassLoader classLoader = new PluginClassLoader(); private static TransporterServer server; @@ -69,7 +72,6 @@ public final class Main { logger.info("Starting MAGE server version " + version); logger.info("Logging level: " + logger.getEffectiveLevel()); logger.info("Default charset: " + Charset.defaultCharset()); - final ConfigWrapper config = new ConfigWrapper(ConfigFactory.loadFromFile("config/config.xml")); String adminPassword = ""; for (String arg : args) { if (arg.startsWith(testModeArg)) { @@ -82,6 +84,13 @@ public final class Main { } } + final String configPath = Optional.ofNullable(System.getProperty(configPathProp)) + .orElse(defaultConfigPath); + + logger.info(String.format("Reading configuration from path=%s", configPath)); + final ConfigWrapper config = new ConfigWrapper(ConfigFactory.loadFromFile(configPath)); + + if (config.isAuthenticationActivated()) { logger.info("Check authorized user DB version ..."); if (!AuthorizedUserRepository.instance.checkAlterAndMigrateAuthorizedUser()) { diff --git a/Mage.Server/src/main/java/mage/server/UserManager.java b/Mage.Server/src/main/java/mage/server/UserManager.java index 8d33a80b68..d8e8574faa 100644 --- a/Mage.Server/src/main/java/mage/server/UserManager.java +++ b/Mage.Server/src/main/java/mage/server/UserManager.java @@ -40,7 +40,6 @@ public class UserManager implements IUserManager { private ExecutorService USER_EXECUTOR; - // TODO externalise start of threads public UserManager(ManagerFactory managerFactory) { this.managerFactory = managerFactory; } From 6e3750d50ac8573c562ff294e4b71ae00ae43e08 Mon Sep 17 00:00:00 2001 From: Francesco Burato Date: Fri, 30 Oct 2020 22:37:25 +0000 Subject: [PATCH 4/4] [app-wiring-refactor]: Apply review comments: - Add reference to original library in `FluentBuilder`. - Change `I` notation to `Impl` notation. - Move error config to test resources - Add comment with config instruction - Add config to the documentation --- .../main/java/mage/utils/FluentBuilder.java | 5 + ...{ChatManager.java => ChatManagerImpl.java} | 8 +- .../{MailClient.java => MailClientImpl.java} | 10 +- ...lgunClient.java => MailgunClientImpl.java} | 10 +- .../src/main/java/mage/server/Main.java | 9 +- .../java/mage/server/MainManagerFactory.java | 98 ++++++++++--------- .../src/main/java/mage/server/RoomImpl.java | 4 +- .../src/main/java/mage/server/Session.java | 6 +- ...onManager.java => SessionManagerImpl.java} | 8 +- .../java/mage/server/TableController.java | 2 +- ...ableManager.java => TableManagerImpl.java} | 12 +-- ...{UserManager.java => UserManagerImpl.java} | 8 +- ...raftManager.java => DraftManagerImpl.java} | 6 +- ...{GameManager.java => GameManagerImpl.java} | 6 +- .../mage/server/game/GameSessionPlayer.java | 4 +- .../mage/server/game/GameSessionWatcher.java | 6 +- ...Manager.java => GamesRoomManagerImpl.java} | 8 +- ...layManager.java => ReplayManagerImpl.java} | 6 +- .../{IChatManager.java => ChatManager.java} | 2 +- ...onfigSettings.java => ConfigSettings.java} | 2 +- .../{IDraftManager.java => DraftManager.java} | 2 +- .../{IGameManager.java => GameManager.java} | 2 +- ...RoomManager.java => GamesRoomManager.java} | 2 +- .../{IMailClient.java => MailClient.java} | 2 +- .../mage/server/managers/ManagerFactory.java | 26 ++--- ...IReplayManager.java => ReplayManager.java} | 2 +- ...essionManager.java => SessionManager.java} | 2 +- .../{ITableManager.java => TableManager.java} | 2 +- ...hreadExecutor.java => ThreadExecutor.java} | 2 +- ...entManager.java => TournamentManager.java} | 2 +- .../{IUserManager.java => UserManager.java} | 2 +- .../mage/server/record/TableRecorderImpl.java | 6 +- .../tournament/TournamentController.java | 6 +- ...anager.java => TournamentManagerImpl.java} | 8 +- .../java/mage/server/util/ConfigWrapper.java | 4 +- ...dExecutor.java => ThreadExecutorImpl.java} | 8 +- .../mage/server/util/ConfigFactoryTest.java | 4 +- .../test/resources}/config_error.xml | 0 .../test/serverside/base/MageTestBase.java | 4 +- .../serverside/base/MageTestPlayerBase.java | 4 +- readme.md | 7 ++ 41 files changed, 171 insertions(+), 146 deletions(-) rename Mage.Server/src/main/java/mage/server/{ChatManager.java => ChatManagerImpl.java} (99%) rename Mage.Server/src/main/java/mage/server/{MailClient.java => MailClientImpl.java} (89%) rename Mage.Server/src/main/java/mage/server/{MailgunClient.java => MailgunClientImpl.java} (86%) rename Mage.Server/src/main/java/mage/server/{SessionManager.java => SessionManagerImpl.java} (97%) rename Mage.Server/src/main/java/mage/server/{TableManager.java => TableManagerImpl.java} (97%) rename Mage.Server/src/main/java/mage/server/{UserManager.java => UserManagerImpl.java} (98%) rename Mage.Server/src/main/java/mage/server/draft/{DraftManager.java => DraftManagerImpl.java} (93%) rename Mage.Server/src/main/java/mage/server/game/{GameManager.java => GameManagerImpl.java} (97%) rename Mage.Server/src/main/java/mage/server/game/{GamesRoomManager.java => GamesRoomManagerImpl.java} (89%) rename Mage.Server/src/main/java/mage/server/game/{ReplayManager.java => ReplayManagerImpl.java} (91%) rename Mage.Server/src/main/java/mage/server/managers/{IChatManager.java => ChatManager.java} (97%) rename Mage.Server/src/main/java/mage/server/managers/{IConfigSettings.java => ConfigSettings.java} (97%) rename Mage.Server/src/main/java/mage/server/managers/{IDraftManager.java => DraftManager.java} (96%) rename Mage.Server/src/main/java/mage/server/managers/{IGameManager.java => GameManager.java} (98%) rename Mage.Server/src/main/java/mage/server/managers/{IGamesRoomManager.java => GamesRoomManager.java} (88%) rename Mage.Server/src/main/java/mage/server/managers/{IMailClient.java => MailClient.java} (76%) rename Mage.Server/src/main/java/mage/server/managers/{IReplayManager.java => ReplayManager.java} (92%) rename Mage.Server/src/main/java/mage/server/managers/{ISessionManager.java => SessionManager.java} (97%) rename Mage.Server/src/main/java/mage/server/managers/{ITableManager.java => TableManager.java} (98%) rename Mage.Server/src/main/java/mage/server/managers/{IThreadExecutor.java => ThreadExecutor.java} (91%) rename Mage.Server/src/main/java/mage/server/managers/{ITournamentManager.java => TournamentManager.java} (96%) rename Mage.Server/src/main/java/mage/server/managers/{IUserManager.java => UserManager.java} (96%) rename Mage.Server/src/main/java/mage/server/tournament/{TournamentManager.java => TournamentManagerImpl.java} (89%) rename Mage.Server/src/main/java/mage/server/util/{ThreadExecutor.java => ThreadExecutorImpl.java} (94%) rename Mage.Server/{config => src/test/resources}/config_error.xml (100%) diff --git a/Mage.Common/src/main/java/mage/utils/FluentBuilder.java b/Mage.Common/src/main/java/mage/utils/FluentBuilder.java index 8c4174ac41..003cd65167 100644 --- a/Mage.Common/src/main/java/mage/utils/FluentBuilder.java +++ b/Mage.Common/src/main/java/mage/utils/FluentBuilder.java @@ -4,6 +4,11 @@ import java.util.ArrayList; import java.util.function.Consumer; import java.util.function.Supplier; +/** + * A base class for fluent, immutable, composable builders. + * + * @see Builder + */ public abstract class FluentBuilder> { final ArrayList> buildSequence; diff --git a/Mage.Server/src/main/java/mage/server/ChatManager.java b/Mage.Server/src/main/java/mage/server/ChatManagerImpl.java similarity index 99% rename from Mage.Server/src/main/java/mage/server/ChatManager.java rename to Mage.Server/src/main/java/mage/server/ChatManagerImpl.java index 92b1f03af0..1bd283e03e 100644 --- a/Mage.Server/src/main/java/mage/server/ChatManager.java +++ b/Mage.Server/src/main/java/mage/server/ChatManagerImpl.java @@ -5,7 +5,7 @@ import mage.cards.repository.CardRepository; import mage.game.Game; import mage.server.exceptions.UserNotFoundException; import mage.server.game.GameController; -import mage.server.managers.IChatManager; +import mage.server.managers.ChatManager; import mage.server.managers.ManagerFactory; import mage.server.util.SystemUtil; import mage.view.ChatMessage.MessageColor; @@ -26,16 +26,16 @@ import java.util.stream.Collectors; /** * @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 userMessages = new HashMap<>(); private final ManagerFactory managerFactory; private final ConcurrentHashMap chatSessions = new ConcurrentHashMap<>(); private final ReadWriteLock lock = new ReentrantReadWriteLock(); - public ChatManager(ManagerFactory managerFactory) { + public ChatManagerImpl(ManagerFactory managerFactory) { this.managerFactory = managerFactory; } diff --git a/Mage.Server/src/main/java/mage/server/MailClient.java b/Mage.Server/src/main/java/mage/server/MailClientImpl.java similarity index 89% rename from Mage.Server/src/main/java/mage/server/MailClient.java rename to Mage.Server/src/main/java/mage/server/MailClientImpl.java index fc830ac1ff..6058fec183 100644 --- a/Mage.Server/src/main/java/mage/server/MailClient.java +++ b/Mage.Server/src/main/java/mage/server/MailClientImpl.java @@ -1,7 +1,7 @@ package mage.server; -import mage.server.managers.IConfigSettings; -import mage.server.managers.IMailClient; +import mage.server.managers.ConfigSettings; +import mage.server.managers.MailClient; import org.apache.log4j.Logger; import javax.mail.Message; @@ -12,13 +12,13 @@ import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import java.util.Properties; -public class MailClient implements IMailClient { +public class MailClientImpl implements MailClient { 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; } diff --git a/Mage.Server/src/main/java/mage/server/MailgunClient.java b/Mage.Server/src/main/java/mage/server/MailgunClientImpl.java similarity index 86% rename from Mage.Server/src/main/java/mage/server/MailgunClient.java rename to Mage.Server/src/main/java/mage/server/MailgunClientImpl.java index 70264baa77..344a77fda2 100644 --- a/Mage.Server/src/main/java/mage/server/MailgunClient.java +++ b/Mage.Server/src/main/java/mage/server/MailgunClientImpl.java @@ -5,19 +5,19 @@ import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.WebResource; import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; import com.sun.jersey.core.util.MultivaluedMapImpl; -import mage.server.managers.IConfigSettings; -import mage.server.managers.IMailClient; +import mage.server.managers.ConfigSettings; +import mage.server.managers.MailClient; import org.apache.log4j.Logger; 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 final IConfigSettings config; + private final ConfigSettings config; - public MailgunClient(IConfigSettings config) { + public MailgunClientImpl(ConfigSettings config) { this.config = config; } diff --git a/Mage.Server/src/main/java/mage/server/Main.java b/Mage.Server/src/main/java/mage/server/Main.java index 49659adc4d..c888866096 100644 --- a/Mage.Server/src/main/java/mage/server/Main.java +++ b/Mage.Server/src/main/java/mage/server/Main.java @@ -14,7 +14,7 @@ import mage.remote.Connection; import mage.server.draft.CubeFactory; import mage.server.game.GameFactory; import mage.server.game.PlayerFactory; -import mage.server.managers.IConfigSettings; +import mage.server.managers.ConfigSettings; import mage.server.managers.ManagerFactory; import mage.server.record.UserStatsRepository; import mage.server.tournament.TournamentFactory; @@ -53,6 +53,11 @@ public final class Main { private static final String testModeArg = "-testMode="; private static final String fastDBModeArg = "-fastDbMode="; 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=<path>" + */ private static final String configPathProp = "xmage.config.path"; private static final File pluginFolder = new File("plugins"); @@ -238,7 +243,7 @@ public final class Main { ServerMessagesUtil.instance.setStartDate(System.currentTimeMillis()); } - static boolean isAlreadyRunning(IConfigSettings config, InvokerLocator serverLocator) { + static boolean isAlreadyRunning(ConfigSettings config, InvokerLocator serverLocator) { Map metadata = new HashMap<>(); metadata.put(SocketWrapper.WRITE_TIMEOUT, String.valueOf(config.getSocketWriteTimeout())); metadata.put("generalizeSocketException", "true"); diff --git a/Mage.Server/src/main/java/mage/server/MainManagerFactory.java b/Mage.Server/src/main/java/mage/server/MainManagerFactory.java index cacbc635c2..753a2810f6 100644 --- a/Mage.Server/src/main/java/mage/server/MainManagerFactory.java +++ b/Mage.Server/src/main/java/mage/server/MainManagerFactory.java @@ -1,118 +1,124 @@ package mage.server; -import mage.server.draft.DraftManager; -import mage.server.game.GameManager; -import mage.server.game.GamesRoomManager; -import mage.server.game.ReplayManager; +import mage.server.draft.DraftManagerImpl; +import mage.server.game.GameManagerImpl; +import mage.server.game.GamesRoomManagerImpl; +import mage.server.game.ReplayManagerImpl; import mage.server.managers.*; -import mage.server.tournament.TournamentManager; -import mage.server.util.ThreadExecutor; +import mage.server.tournament.TournamentManagerImpl; +import mage.server.util.ThreadExecutorImpl; public class MainManagerFactory implements ManagerFactory { - private final IConfigSettings configSettings; - private final IThreadExecutor threadExecutor; - private final IChatManager chatManager; - private final IDraftManager draftManager; - private final IGameManager gameManager; - private final IGamesRoomManager gamesRoomManager; - private final IMailClient mailClient; - private final IMailClient mailgunClient; - private final IReplayManager replayManager; - private final ISessionManager sessionManager; - private final ITableManager tableManager; - private final IUserManager userManager; - private final ITournamentManager tournamentManager; + private final ConfigSettings configSettings; + private final ThreadExecutor threadExecutor; + private final ChatManager chatManager; + private final DraftManager draftManager; + private final GameManager gameManager; + private final GamesRoomManager gamesRoomManager; + private final MailClient mailClient; + private final MailClient mailgunClient; + private final ReplayManager replayManager; + private final SessionManager sessionManager; + private final TableManager tableManager; + private final UserManager userManager; + private final TournamentManager tournamentManager; - public MainManagerFactory(IConfigSettings configSettings) { + public MainManagerFactory(ConfigSettings configSettings) { this.configSettings = configSettings; - this.threadExecutor = new ThreadExecutor(configSettings); - this.mailClient = new MailClient(configSettings); - this.mailgunClient = new MailgunClient(configSettings); - this.chatManager = new ChatManager(this); - this.draftManager = new DraftManager(this); - this.gameManager = new GameManager(this); - this.replayManager = new ReplayManager(this); - this.sessionManager = new SessionManager(this); - this.tournamentManager = new TournamentManager(this); - final GamesRoomManager gamesRoomManager = new GamesRoomManager(this); - final TableManager tableManager = new TableManager(this); - final UserManager userManager = new UserManager(this); + // ThreadExecutorImpl, MailClientImpl and MailGunClient depend only on the config, so they are initialised first + this.threadExecutor = new ThreadExecutorImpl(configSettings); + this.mailClient = new MailClientImpl(configSettings); + this.mailgunClient = new MailgunClientImpl(configSettings); + // Chat, Draft, Game, Replay, Session and Tournament managers only require access to the ManagerFactory + // but do not use them in initialisation + this.chatManager = new ChatManagerImpl(this); + this.draftManager = new DraftManagerImpl(this); + this.gameManager = new GameManagerImpl(this); + this.replayManager = new ReplayManagerImpl(this); + this.sessionManager = new SessionManagerImpl(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.tableManager = tableManager; this.userManager = userManager; + // execute the initialisation block of the relevant manager (they start the executor services) startThreads(gamesRoomManager, tableManager, userManager); } - private void startThreads(GamesRoomManager gamesRoomManager, TableManager tableManager, UserManager userManager) { + private void startThreads(GamesRoomManagerImpl gamesRoomManager, TableManagerImpl tableManager, UserManagerImpl userManager) { userManager.init(); tableManager.init(); gamesRoomManager.init(); } @Override - public IChatManager chatManager() { + public ChatManager chatManager() { return chatManager; } @Override - public IDraftManager draftManager() { + public DraftManager draftManager() { return draftManager; } @Override - public IGameManager gameManager() { + public GameManager gameManager() { return gameManager; } @Override - public IGamesRoomManager gamesRoomManager() { + public GamesRoomManager gamesRoomManager() { return gamesRoomManager; } @Override - public IMailClient mailClient() { + public MailClient mailClient() { return mailClient; } @Override - public IMailClient mailgunClient() { + public MailClient mailgunClient() { return mailgunClient; } @Override - public IReplayManager replayManager() { + public ReplayManager replayManager() { return replayManager; } @Override - public ISessionManager sessionManager() { + public SessionManager sessionManager() { return sessionManager; } @Override - public ITableManager tableManager() { + public TableManager tableManager() { return tableManager; } @Override - public IUserManager userManager() { + public UserManager userManager() { return userManager; } @Override - public IConfigSettings configSettings() { + public ConfigSettings configSettings() { return configSettings; } @Override - public IThreadExecutor threadExecutor() { + public ThreadExecutor threadExecutor() { return threadExecutor; } @Override - public ITournamentManager tournamentManager() { + public TournamentManager tournamentManager() { return tournamentManager; } } diff --git a/Mage.Server/src/main/java/mage/server/RoomImpl.java b/Mage.Server/src/main/java/mage/server/RoomImpl.java index aa896a91fc..9221ee0cd3 100644 --- a/Mage.Server/src/main/java/mage/server/RoomImpl.java +++ b/Mage.Server/src/main/java/mage/server/RoomImpl.java @@ -1,6 +1,6 @@ package mage.server; -import mage.server.managers.IChatManager; +import mage.server.managers.ChatManager; import java.util.UUID; @@ -12,7 +12,7 @@ public abstract class RoomImpl implements Room { private final UUID chatId; private final UUID roomId; - public RoomImpl(IChatManager chatManager) { + public RoomImpl(ChatManager chatManager) { roomId = UUID.randomUUID(); chatId = chatManager.createChatSession("Room " + roomId); } diff --git a/Mage.Server/src/main/java/mage/server/Session.java b/Mage.Server/src/main/java/mage/server/Session.java index 66d22cb210..61d36241d5 100644 --- a/Mage.Server/src/main/java/mage/server/Session.java +++ b/Mage.Server/src/main/java/mage/server/Session.java @@ -7,7 +7,7 @@ import mage.interfaces.callback.ClientCallbackMethod; import mage.players.net.UserData; import mage.players.net.UserGroup; import mage.server.game.GamesRoom; -import mage.server.managers.IConfigSettings; +import mage.server.managers.ConfigSettings; import mage.server.managers.ManagerFactory; import mage.server.util.SystemUtil; import mage.util.RandomUtil; @@ -115,7 +115,7 @@ public class Session { if (userName.equals("Admin")) { return "User name Admin already in use"; } - IConfigSettings config = managerFactory.configSettings(); + ConfigSettings config = managerFactory.configSettings(); if (userName.length() < config.getMinUserNameLength()) { 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) { - IConfigSettings config = managerFactory.configSettings(); + ConfigSettings config = managerFactory.configSettings(); if (password.length() < config.getMinPasswordLength()) { return "Password may not be shorter than " + config.getMinPasswordLength() + " characters"; } diff --git a/Mage.Server/src/main/java/mage/server/SessionManager.java b/Mage.Server/src/main/java/mage/server/SessionManagerImpl.java similarity index 97% rename from Mage.Server/src/main/java/mage/server/SessionManager.java rename to Mage.Server/src/main/java/mage/server/SessionManagerImpl.java index 9fa41f13f2..896195a52d 100644 --- a/Mage.Server/src/main/java/mage/server/SessionManager.java +++ b/Mage.Server/src/main/java/mage/server/SessionManagerImpl.java @@ -2,7 +2,7 @@ package mage.server; import mage.MageException; import mage.players.net.UserData; -import mage.server.managers.ISessionManager; +import mage.server.managers.SessionManager; import mage.server.managers.ManagerFactory; import org.apache.log4j.Logger; import org.jboss.remoting.callback.InvokerCallbackHandler; @@ -14,14 +14,14 @@ import java.util.concurrent.ConcurrentHashMap; /** * @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 ConcurrentHashMap sessions = new ConcurrentHashMap<>(); - public SessionManager(ManagerFactory managerFactory) { + public SessionManagerImpl(ManagerFactory managerFactory) { this.managerFactory = managerFactory; } diff --git a/Mage.Server/src/main/java/mage/server/TableController.java b/Mage.Server/src/main/java/mage/server/TableController.java index db4a24eabe..ca2ce8fe04 100644 --- a/Mage.Server/src/main/java/mage/server/TableController.java +++ b/Mage.Server/src/main/java/mage/server/TableController.java @@ -84,7 +84,7 @@ public class TableController { if (userId != null) { Optional user = managerFactory.userManager().getUser(userId); 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]"; } else { controllerName = user.get().getName(); diff --git a/Mage.Server/src/main/java/mage/server/TableManager.java b/Mage.Server/src/main/java/mage/server/TableManagerImpl.java similarity index 97% rename from Mage.Server/src/main/java/mage/server/TableManager.java rename to Mage.Server/src/main/java/mage/server/TableManagerImpl.java index 3cfa700135..268c4f20fe 100644 --- a/Mage.Server/src/main/java/mage/server/TableManager.java +++ b/Mage.Server/src/main/java/mage/server/TableManagerImpl.java @@ -14,7 +14,7 @@ import mage.game.tournament.TournamentOptions; import mage.game.tournament.TournamentPlayer; import mage.players.PlayerType; import mage.server.game.GameController; -import mage.server.managers.ITableManager; +import mage.server.managers.TableManager; import mage.server.managers.ManagerFactory; import org.apache.log4j.Logger; @@ -33,12 +33,12 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author BetaSteward_at_googlemail.com */ -public class TableManager implements ITableManager { +public class TableManagerImpl implements TableManager { 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 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 ConcurrentHashMap controllers = new ConcurrentHashMap<>(); @@ -54,7 +54,7 @@ public class TableManager implements ITableManager { */ private static final int EXPIRE_CHECK_PERIOD = 10; - public TableManager(ManagerFactory managerFactory) { + public TableManagerImpl(ManagerFactory managerFactory) { this.managerFactory = managerFactory; } @@ -206,7 +206,7 @@ public class TableManager implements ITableManager { controller.leaveTable(userId); } } else { - logger.error("TableManager.userQuitTournamentSubTables table == null - userId " + userId); + logger.error("TableManagerImpl.userQuitTournamentSubTables table == null - userId " + userId); } } } diff --git a/Mage.Server/src/main/java/mage/server/UserManager.java b/Mage.Server/src/main/java/mage/server/UserManagerImpl.java similarity index 98% rename from Mage.Server/src/main/java/mage/server/UserManager.java rename to Mage.Server/src/main/java/mage/server/UserManagerImpl.java index d8e8574faa..8b1fa6ff34 100644 --- a/Mage.Server/src/main/java/mage/server/UserManager.java +++ b/Mage.Server/src/main/java/mage/server/UserManagerImpl.java @@ -1,7 +1,7 @@ package mage.server; import mage.server.User.UserState; -import mage.server.managers.IUserManager; +import mage.server.managers.UserManager; import mage.server.managers.ManagerFactory; import mage.server.record.UserStats; import mage.server.record.UserStatsRepository; @@ -20,13 +20,13 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * * @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_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 Logger logger = Logger.getLogger(UserManager.class); + private static final Logger logger = Logger.getLogger(UserManagerImpl.class); protected final ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor(); protected final ScheduledExecutorService userListExecutor = Executors.newSingleThreadScheduledExecutor(); @@ -40,7 +40,7 @@ public class UserManager implements IUserManager { private ExecutorService USER_EXECUTOR; - public UserManager(ManagerFactory managerFactory) { + public UserManagerImpl(ManagerFactory managerFactory) { this.managerFactory = managerFactory; } diff --git a/Mage.Server/src/main/java/mage/server/draft/DraftManager.java b/Mage.Server/src/main/java/mage/server/draft/DraftManagerImpl.java similarity index 93% rename from Mage.Server/src/main/java/mage/server/draft/DraftManager.java rename to Mage.Server/src/main/java/mage/server/draft/DraftManagerImpl.java index 0b7eef61a8..69127d4479 100644 --- a/Mage.Server/src/main/java/mage/server/draft/DraftManager.java +++ b/Mage.Server/src/main/java/mage/server/draft/DraftManagerImpl.java @@ -1,7 +1,7 @@ package mage.server.draft; import mage.game.draft.Draft; -import mage.server.managers.IDraftManager; +import mage.server.managers.DraftManager; import mage.server.managers.ManagerFactory; import mage.view.DraftPickView; @@ -14,12 +14,12 @@ import java.util.concurrent.ConcurrentMap; /** * @author BetaSteward_at_googlemail.com */ -public class DraftManager implements IDraftManager { +public class DraftManagerImpl implements DraftManager { private final ManagerFactory managerFactory; private final ConcurrentMap draftControllers = new ConcurrentHashMap<>(); - public DraftManager(ManagerFactory managerFactory) { + public DraftManagerImpl(ManagerFactory managerFactory) { this.managerFactory = managerFactory; } diff --git a/Mage.Server/src/main/java/mage/server/game/GameManager.java b/Mage.Server/src/main/java/mage/server/game/GameManagerImpl.java similarity index 97% rename from Mage.Server/src/main/java/mage/server/game/GameManager.java rename to Mage.Server/src/main/java/mage/server/game/GameManagerImpl.java index 8c6bdcf503..3121bfdbdb 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameManager.java +++ b/Mage.Server/src/main/java/mage/server/game/GameManagerImpl.java @@ -5,7 +5,7 @@ import mage.constants.ManaType; import mage.constants.PlayerAction; import mage.game.Game; import mage.game.GameOptions; -import mage.server.managers.IGameManager; +import mage.server.managers.GameManager; import mage.server.managers.ManagerFactory; import mage.view.GameView; @@ -22,13 +22,13 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author BetaSteward_at_googlemail.com */ -public class GameManager implements IGameManager { +public class GameManagerImpl implements GameManager { private final ManagerFactory managerFactory; private final ConcurrentMap gameControllers = new ConcurrentHashMap<>(); private final ReadWriteLock gameControllersLock = new ReentrantReadWriteLock(); - public GameManager(ManagerFactory managerFactory) { + public GameManagerImpl(ManagerFactory managerFactory) { this.managerFactory = managerFactory; } diff --git a/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java b/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java index 2c23027a03..b7f3c9aae9 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java +++ b/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java @@ -11,7 +11,7 @@ import mage.interfaces.callback.ClientCallback; import mage.interfaces.callback.ClientCallbackMethod; import mage.players.Player; import mage.server.User; -import mage.server.managers.IUserManager; +import mage.server.managers.UserManager; import mage.server.managers.ManagerFactory; import mage.view.*; import org.apache.log4j.Logger; @@ -28,7 +28,7 @@ public class GameSessionPlayer extends GameSessionWatcher { private static final Logger logger = Logger.getLogger(GameSessionPlayer.class); - private final IUserManager userManager; + private final UserManager userManager; private final UUID playerId; private final ExecutorService callExecutor; diff --git a/Mage.Server/src/main/java/mage/server/game/GameSessionWatcher.java b/Mage.Server/src/main/java/mage/server/game/GameSessionWatcher.java index 5e3de9641e..6aafddbf67 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameSessionWatcher.java +++ b/Mage.Server/src/main/java/mage/server/game/GameSessionWatcher.java @@ -6,7 +6,7 @@ import mage.interfaces.callback.ClientCallback; import mage.interfaces.callback.ClientCallbackMethod; import mage.players.Player; import mage.server.User; -import mage.server.managers.IUserManager; +import mage.server.managers.UserManager; import mage.view.GameClientMessage; import mage.view.GameEndView; import mage.view.GameView; @@ -25,13 +25,13 @@ public class GameSessionWatcher { protected static final Logger logger = Logger.getLogger(GameSessionWatcher.class); - private final IUserManager userManager; + private final UserManager userManager; protected final UUID userId; protected final Game game; protected boolean killed = false; 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.userId = userId; this.game = game; diff --git a/Mage.Server/src/main/java/mage/server/game/GamesRoomManager.java b/Mage.Server/src/main/java/mage/server/game/GamesRoomManagerImpl.java similarity index 89% rename from Mage.Server/src/main/java/mage/server/game/GamesRoomManager.java rename to Mage.Server/src/main/java/mage/server/game/GamesRoomManagerImpl.java index b63ab4200a..77ea11bc72 100644 --- a/Mage.Server/src/main/java/mage/server/game/GamesRoomManager.java +++ b/Mage.Server/src/main/java/mage/server/game/GamesRoomManagerImpl.java @@ -1,6 +1,6 @@ package mage.server.game; -import mage.server.managers.IGamesRoomManager; +import mage.server.managers.GamesRoomManager; import mage.server.managers.ManagerFactory; import org.apache.log4j.Logger; @@ -11,16 +11,16 @@ import java.util.concurrent.ConcurrentHashMap; /** * @author BetaSteward_at_googlemail.com */ -public class GamesRoomManager implements IGamesRoomManager { +public class GamesRoomManagerImpl implements GamesRoomManager { private final ManagerFactory managerFactory; private final ConcurrentHashMap rooms = new ConcurrentHashMap<>(); private UUID mainRoomId; 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; } diff --git a/Mage.Server/src/main/java/mage/server/game/ReplayManager.java b/Mage.Server/src/main/java/mage/server/game/ReplayManagerImpl.java similarity index 91% rename from Mage.Server/src/main/java/mage/server/game/ReplayManager.java rename to Mage.Server/src/main/java/mage/server/game/ReplayManagerImpl.java index 9dcbb06462..c41c554067 100644 --- a/Mage.Server/src/main/java/mage/server/game/ReplayManager.java +++ b/Mage.Server/src/main/java/mage/server/game/ReplayManagerImpl.java @@ -1,6 +1,6 @@ package mage.server.game; -import mage.server.managers.IReplayManager; +import mage.server.managers.ReplayManager; import mage.server.managers.ManagerFactory; import java.util.UUID; @@ -9,12 +9,12 @@ import java.util.concurrent.ConcurrentHashMap; /** * @author BetaSteward_at_googlemail.com */ -public class ReplayManager implements IReplayManager { +public class ReplayManagerImpl implements ReplayManager { private final ConcurrentHashMap replaySessions = new ConcurrentHashMap<>(); private final ManagerFactory managerFactory; - public ReplayManager(ManagerFactory managerFactory) { + public ReplayManagerImpl(ManagerFactory managerFactory) { this.managerFactory = managerFactory; } diff --git a/Mage.Server/src/main/java/mage/server/managers/IChatManager.java b/Mage.Server/src/main/java/mage/server/managers/ChatManager.java similarity index 97% rename from Mage.Server/src/main/java/mage/server/managers/IChatManager.java rename to Mage.Server/src/main/java/mage/server/managers/ChatManager.java index 4c54375a52..504911f7b2 100644 --- a/Mage.Server/src/main/java/mage/server/managers/IChatManager.java +++ b/Mage.Server/src/main/java/mage/server/managers/ChatManager.java @@ -9,7 +9,7 @@ import mage.view.ChatMessage; import java.util.List; import java.util.UUID; -public interface IChatManager { +public interface ChatManager { UUID createChatSession(String info); void joinChat(UUID chatId, UUID userId); diff --git a/Mage.Server/src/main/java/mage/server/managers/IConfigSettings.java b/Mage.Server/src/main/java/mage/server/managers/ConfigSettings.java similarity index 97% rename from Mage.Server/src/main/java/mage/server/managers/IConfigSettings.java rename to Mage.Server/src/main/java/mage/server/managers/ConfigSettings.java index 4f61c6928c..be6d6c6c23 100644 --- a/Mage.Server/src/main/java/mage/server/managers/IConfigSettings.java +++ b/Mage.Server/src/main/java/mage/server/managers/ConfigSettings.java @@ -5,7 +5,7 @@ import mage.server.util.config.Plugin; import java.util.List; -public interface IConfigSettings { +public interface ConfigSettings { String getServerAddress(); String getServerName(); diff --git a/Mage.Server/src/main/java/mage/server/managers/IDraftManager.java b/Mage.Server/src/main/java/mage/server/managers/DraftManager.java similarity index 96% rename from Mage.Server/src/main/java/mage/server/managers/IDraftManager.java rename to Mage.Server/src/main/java/mage/server/managers/DraftManager.java index 75fc2ca65a..d9d17a9900 100644 --- a/Mage.Server/src/main/java/mage/server/managers/IDraftManager.java +++ b/Mage.Server/src/main/java/mage/server/managers/DraftManager.java @@ -9,7 +9,7 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; -public interface IDraftManager { +public interface DraftManager { UUID createDraftSession(Draft draft, ConcurrentHashMap userPlayerMap, UUID tableId); void joinDraft(UUID draftId, UUID userId); diff --git a/Mage.Server/src/main/java/mage/server/managers/IGameManager.java b/Mage.Server/src/main/java/mage/server/managers/GameManager.java similarity index 98% rename from Mage.Server/src/main/java/mage/server/managers/IGameManager.java rename to Mage.Server/src/main/java/mage/server/managers/GameManager.java index dc40fdb8d8..4531a53742 100644 --- a/Mage.Server/src/main/java/mage/server/managers/IGameManager.java +++ b/Mage.Server/src/main/java/mage/server/managers/GameManager.java @@ -13,7 +13,7 @@ import java.util.Optional; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; -public interface IGameManager { +public interface GameManager { UUID createGameSession(Game game, ConcurrentHashMap userPlayerMap, UUID tableId, UUID choosingPlayerId, GameOptions gameOptions); void joinGame(UUID gameId, UUID userId); diff --git a/Mage.Server/src/main/java/mage/server/managers/IGamesRoomManager.java b/Mage.Server/src/main/java/mage/server/managers/GamesRoomManager.java similarity index 88% rename from Mage.Server/src/main/java/mage/server/managers/IGamesRoomManager.java rename to Mage.Server/src/main/java/mage/server/managers/GamesRoomManager.java index b68e96b0bb..e2a877358a 100644 --- a/Mage.Server/src/main/java/mage/server/managers/IGamesRoomManager.java +++ b/Mage.Server/src/main/java/mage/server/managers/GamesRoomManager.java @@ -5,7 +5,7 @@ import mage.server.game.GamesRoom; import java.util.Optional; import java.util.UUID; -public interface IGamesRoomManager { +public interface GamesRoomManager { UUID createRoom(); UUID getMainRoomId(); diff --git a/Mage.Server/src/main/java/mage/server/managers/IMailClient.java b/Mage.Server/src/main/java/mage/server/managers/MailClient.java similarity index 76% rename from Mage.Server/src/main/java/mage/server/managers/IMailClient.java rename to Mage.Server/src/main/java/mage/server/managers/MailClient.java index 0dcf168b5c..bfb125a6c9 100644 --- a/Mage.Server/src/main/java/mage/server/managers/IMailClient.java +++ b/Mage.Server/src/main/java/mage/server/managers/MailClient.java @@ -1,6 +1,6 @@ package mage.server.managers; -public interface IMailClient { +public interface MailClient { boolean sendMessage(String email, String subject, String text); diff --git a/Mage.Server/src/main/java/mage/server/managers/ManagerFactory.java b/Mage.Server/src/main/java/mage/server/managers/ManagerFactory.java index 14d7592f05..917c681f92 100644 --- a/Mage.Server/src/main/java/mage/server/managers/ManagerFactory.java +++ b/Mage.Server/src/main/java/mage/server/managers/ManagerFactory.java @@ -1,29 +1,29 @@ package mage.server.managers; 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(); } diff --git a/Mage.Server/src/main/java/mage/server/managers/IReplayManager.java b/Mage.Server/src/main/java/mage/server/managers/ReplayManager.java similarity index 92% rename from Mage.Server/src/main/java/mage/server/managers/IReplayManager.java rename to Mage.Server/src/main/java/mage/server/managers/ReplayManager.java index 540fb77192..df6148cee9 100644 --- a/Mage.Server/src/main/java/mage/server/managers/IReplayManager.java +++ b/Mage.Server/src/main/java/mage/server/managers/ReplayManager.java @@ -2,7 +2,7 @@ package mage.server.managers; import java.util.UUID; -public interface IReplayManager { +public interface ReplayManager { void replayGame(UUID gameId, UUID userId); void startReplay(UUID gameId, UUID userId); diff --git a/Mage.Server/src/main/java/mage/server/managers/ISessionManager.java b/Mage.Server/src/main/java/mage/server/managers/SessionManager.java similarity index 97% rename from Mage.Server/src/main/java/mage/server/managers/ISessionManager.java rename to Mage.Server/src/main/java/mage/server/managers/SessionManager.java index 1e5fe8c731..b5dc0d109b 100644 --- a/Mage.Server/src/main/java/mage/server/managers/ISessionManager.java +++ b/Mage.Server/src/main/java/mage/server/managers/SessionManager.java @@ -10,7 +10,7 @@ import org.jboss.remoting.callback.InvokerCallbackHandler; import javax.annotation.Nonnull; import java.util.Optional; -public interface ISessionManager { +public interface SessionManager { Optional getSession(@Nonnull String sessionId); void createSession(String sessionId, InvokerCallbackHandler callbackHandler); diff --git a/Mage.Server/src/main/java/mage/server/managers/ITableManager.java b/Mage.Server/src/main/java/mage/server/managers/TableManager.java similarity index 98% rename from Mage.Server/src/main/java/mage/server/managers/ITableManager.java rename to Mage.Server/src/main/java/mage/server/managers/TableManager.java index f682349208..7ba5d81c75 100644 --- a/Mage.Server/src/main/java/mage/server/managers/ITableManager.java +++ b/Mage.Server/src/main/java/mage/server/managers/TableManager.java @@ -17,7 +17,7 @@ import java.util.Collection; import java.util.Optional; import java.util.UUID; -public interface ITableManager { +public interface TableManager { Table createTable(UUID roomId, UUID userId, MatchOptions options); Table createTable(UUID roomId, MatchOptions options); diff --git a/Mage.Server/src/main/java/mage/server/managers/IThreadExecutor.java b/Mage.Server/src/main/java/mage/server/managers/ThreadExecutor.java similarity index 91% rename from Mage.Server/src/main/java/mage/server/managers/IThreadExecutor.java rename to Mage.Server/src/main/java/mage/server/managers/ThreadExecutor.java index d268b93ae7..46f59b5343 100644 --- a/Mage.Server/src/main/java/mage/server/managers/IThreadExecutor.java +++ b/Mage.Server/src/main/java/mage/server/managers/ThreadExecutor.java @@ -3,7 +3,7 @@ package mage.server.managers; import java.util.concurrent.ExecutorService; import java.util.concurrent.ScheduledExecutorService; -public interface IThreadExecutor { +public interface ThreadExecutor { int getActiveThreads(ExecutorService executerService); ExecutorService getCallExecutor(); diff --git a/Mage.Server/src/main/java/mage/server/managers/ITournamentManager.java b/Mage.Server/src/main/java/mage/server/managers/TournamentManager.java similarity index 96% rename from Mage.Server/src/main/java/mage/server/managers/ITournamentManager.java rename to Mage.Server/src/main/java/mage/server/managers/TournamentManager.java index ddf1f0775a..852588c264 100644 --- a/Mage.Server/src/main/java/mage/server/managers/ITournamentManager.java +++ b/Mage.Server/src/main/java/mage/server/managers/TournamentManager.java @@ -9,7 +9,7 @@ import java.util.Optional; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; -public interface ITournamentManager { +public interface TournamentManager { Optional getTournamentController(UUID tournamentId); void createTournamentSession(Tournament tournament, ConcurrentHashMap userPlayerMap, UUID tableId); diff --git a/Mage.Server/src/main/java/mage/server/managers/IUserManager.java b/Mage.Server/src/main/java/mage/server/managers/UserManager.java similarity index 96% rename from Mage.Server/src/main/java/mage/server/managers/IUserManager.java rename to Mage.Server/src/main/java/mage/server/managers/UserManager.java index e1f6cebd2f..626609ee25 100644 --- a/Mage.Server/src/main/java/mage/server/managers/IUserManager.java +++ b/Mage.Server/src/main/java/mage/server/managers/UserManager.java @@ -10,7 +10,7 @@ import java.util.List; import java.util.Optional; import java.util.UUID; -public interface IUserManager { +public interface UserManager { Optional createUser(String userName, String host, AuthorizedUser authorizedUser); Optional getUser(UUID userId); diff --git a/Mage.Server/src/main/java/mage/server/record/TableRecorderImpl.java b/Mage.Server/src/main/java/mage/server/record/TableRecorderImpl.java index b8ed2b5876..de1eaf025e 100644 --- a/Mage.Server/src/main/java/mage/server/record/TableRecorderImpl.java +++ b/Mage.Server/src/main/java/mage/server/record/TableRecorderImpl.java @@ -3,13 +3,13 @@ package mage.server.record; import mage.game.Table; import mage.game.Table.TableRecorder; import mage.game.result.ResultProtos.TableProto; -import mage.server.managers.IUserManager; +import mage.server.managers.UserManager; public class TableRecorderImpl implements TableRecorder { - private final IUserManager userManager; + private final UserManager userManager; - public TableRecorderImpl(IUserManager userManager) { + public TableRecorderImpl(UserManager userManager) { this.userManager = userManager; } diff --git a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java index a13c925f6d..094e1420b9 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java @@ -19,7 +19,7 @@ import mage.game.tournament.TournamentPlayer; import mage.players.PlayerType; import mage.server.User; import mage.server.draft.DraftController; -import mage.server.managers.ITableManager; +import mage.server.managers.TableManager; import mage.server.managers.ManagerFactory; import mage.view.ChatMessage.MessageColor; import mage.view.ChatMessage.MessageType; @@ -216,7 +216,7 @@ public class TournamentController { private void startMatch(TournamentPairing pair, MatchOptions matchOptions) { try { - ITableManager tableManager = managerFactory.tableManager(); + TableManager tableManager = managerFactory.tableManager(); Table table = tableManager.createTable(managerFactory.gamesRoomManager().getMainRoomId(), matchOptions); table.setTournamentSubTable(true); table.setTournament(tournament); @@ -259,7 +259,7 @@ public class TournamentController { private void startMultiplayerMatch(MultiplayerRound round, MatchOptions matchOptions) { try { - ITableManager tableManager = managerFactory.tableManager(); + TableManager tableManager = managerFactory.tableManager(); Table table = tableManager.createTable(managerFactory.gamesRoomManager().getMainRoomId(), matchOptions); table.setTournamentSubTable(true); table.setTournament(tournament); diff --git a/Mage.Server/src/main/java/mage/server/tournament/TournamentManager.java b/Mage.Server/src/main/java/mage/server/tournament/TournamentManagerImpl.java similarity index 89% rename from Mage.Server/src/main/java/mage/server/tournament/TournamentManager.java rename to Mage.Server/src/main/java/mage/server/tournament/TournamentManagerImpl.java index 4ff65f9180..f84ec3fcd5 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentManager.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentManagerImpl.java @@ -2,7 +2,7 @@ package mage.server.tournament; import mage.cards.decks.Deck; import mage.game.tournament.Tournament; -import mage.server.managers.ITournamentManager; +import mage.server.managers.TournamentManager; import mage.server.managers.ManagerFactory; import mage.view.TournamentView; import org.apache.log4j.Logger; @@ -15,12 +15,12 @@ import java.util.concurrent.ConcurrentMap; /** * @author BetaSteward_at_googlemail.com */ -public class TournamentManager implements ITournamentManager { +public class TournamentManagerImpl implements TournamentManager { private final ManagerFactory managerFactory; private final ConcurrentMap controllers = new ConcurrentHashMap<>(); - public TournamentManager(ManagerFactory managerFactory) { + public TournamentManagerImpl(ManagerFactory managerFactory) { this.managerFactory = managerFactory; } @@ -46,7 +46,7 @@ public class TournamentManager implements ITournamentManager { if (tournamentController != null) { tournamentController.quit(userId); } 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); } } diff --git a/Mage.Server/src/main/java/mage/server/util/ConfigWrapper.java b/Mage.Server/src/main/java/mage/server/util/ConfigWrapper.java index a147610b46..20be1a6425 100644 --- a/Mage.Server/src/main/java/mage/server/util/ConfigWrapper.java +++ b/Mage.Server/src/main/java/mage/server/util/ConfigWrapper.java @@ -1,13 +1,13 @@ 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.GamePlugin; import mage.server.util.config.Plugin; import java.util.List; -public class ConfigWrapper implements IConfigSettings { +public class ConfigWrapper implements ConfigSettings { private final Config config; diff --git a/Mage.Server/src/main/java/mage/server/util/ThreadExecutor.java b/Mage.Server/src/main/java/mage/server/util/ThreadExecutorImpl.java similarity index 94% rename from Mage.Server/src/main/java/mage/server/util/ThreadExecutor.java rename to Mage.Server/src/main/java/mage/server/util/ThreadExecutorImpl.java index 22602dde5a..85ca2f8b1e 100644 --- a/Mage.Server/src/main/java/mage/server/util/ThreadExecutor.java +++ b/Mage.Server/src/main/java/mage/server/util/ThreadExecutorImpl.java @@ -1,14 +1,14 @@ package mage.server.util; -import mage.server.managers.IConfigSettings; -import mage.server.managers.IThreadExecutor; +import mage.server.managers.ConfigSettings; +import mage.server.managers.ThreadExecutor; import java.util.concurrent.*; /** * @author BetaSteward_at_googlemail.com */ -public class ThreadExecutor implements IThreadExecutor { +public class ThreadExecutorImpl implements ThreadExecutor { private final ExecutorService callExecutor; private final ExecutorService gameExecutor; private final ScheduledExecutorService timeoutExecutor; @@ -25,7 +25,7 @@ public class ThreadExecutor implements IThreadExecutor { * resource consuming process. */ - public ThreadExecutor(IConfigSettings config) { + public ThreadExecutorImpl(ConfigSettings config) { callExecutor = Executors.newCachedThreadPool(); gameExecutor = Executors.newFixedThreadPool(config.getMaxGameThreads()); timeoutExecutor = Executors.newScheduledThreadPool(4); diff --git a/Mage.Server/src/test/java/mage/server/util/ConfigFactoryTest.java b/Mage.Server/src/test/java/mage/server/util/ConfigFactoryTest.java index aab38e713a..3563287fad 100644 --- a/Mage.Server/src/test/java/mage/server/util/ConfigFactoryTest.java +++ b/Mage.Server/src/test/java/mage/server/util/ConfigFactoryTest.java @@ -4,6 +4,8 @@ import mage.server.util.config.Config; import org.junit.jupiter.api.DisplayName; 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.assertThatExceptionOfType; @@ -22,7 +24,7 @@ public class ConfigFactoryTest { @DisplayName("should fail if config is malformed") void failOnMalformed() { assertThatExceptionOfType(ConfigurationException.class) - .isThrownBy(() -> ConfigFactory.loadFromFile("config/config_error.xml")); + .isThrownBy(() -> ConfigFactory.loadFromFile(Paths.get("src", "test", "resources", "config_error.xml").toString())); } @Test diff --git a/Mage.Server/config/config_error.xml b/Mage.Server/src/test/resources/config_error.xml similarity index 100% rename from Mage.Server/config/config_error.xml rename to Mage.Server/src/test/resources/config_error.xml diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java index f008d5112d..6e1eb646b8 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java @@ -14,7 +14,7 @@ import mage.players.Player; import mage.players.PlayerType; import mage.server.game.GameFactory; import mage.server.game.PlayerFactory; -import mage.server.managers.IConfigSettings; +import mage.server.managers.ConfigSettings; import mage.server.tournament.TournamentFactory; import mage.server.util.ConfigFactory; import mage.server.util.ConfigWrapper; @@ -102,7 +102,7 @@ public abstract class MageTestBase { public static void init() { Logger.getRootLogger().setLevel(Level.DEBUG); deleteSavedGames(); - IConfigSettings config = new ConfigWrapper(ConfigFactory.loadFromFile("config/config.xml")); + ConfigSettings config = new ConfigWrapper(ConfigFactory.loadFromFile("config/config.xml")); config.getGameTypes().forEach((gameType) -> { GameFactory.instance.addGameType(gameType.getName(), loadGameType(gameType), loadPlugin(gameType)); }); diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java index 485808af31..1d88a74644 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java @@ -23,7 +23,7 @@ import mage.game.permanent.PermanentCard; import mage.game.tournament.TournamentType; import mage.players.Player; import mage.server.game.GameFactory; -import mage.server.managers.IConfigSettings; +import mage.server.managers.ConfigSettings; import mage.server.util.ConfigFactory; import mage.server.util.ConfigWrapper; import mage.server.util.PluginClassLoader; @@ -116,7 +116,7 @@ public abstract class MageTestPlayerBase { logger.debug("Default charset: " + Charset.defaultCharset()); deleteSavedGames(); - IConfigSettings config = new ConfigWrapper(ConfigFactory.loadFromFile("config/config.xml")); + ConfigSettings config = new ConfigWrapper(ConfigFactory.loadFromFile("config/config.xml")); for (GamePlugin plugin : config.getGameTypes()) { GameFactory.instance.addGameType(plugin.getName(), loadGameType(plugin), loadPlugin(plugin)); } diff --git a/readme.md b/readme.md index a25e05cdf0..7e680f87d9 100644 --- a/readme.md +++ b/readme.md @@ -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. +### 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 Github issues page contain [popular problems and fixes](https://github.com/magefree/mage/issues?q=is%3Aissue+label%3AFAQ+):