Ver Fonte

Adding Database Installer

Adding game and login server configurations using fluent API.
Zoey76 há 6 anos atrás
pai
commit
8d6a72da93
34 ficheiros alterados com 1344 adições e 56 exclusões
  1. 2 0
      README.md
  2. 21 5
      pom.xml
  3. 4 3
      src/main/java/com/l2jserver/cli/L2JServerCLI.java
  4. 37 0
      src/main/java/com/l2jserver/cli/command/AbstractCommand.java
  5. 1 1
      src/main/java/com/l2jserver/cli/command/AccountCommand.java
  6. 1 1
      src/main/java/com/l2jserver/cli/command/BuildCommand.java
  7. 3 5
      src/main/java/com/l2jserver/cli/command/CodeCommand.java
  8. 40 0
      src/main/java/com/l2jserver/cli/command/DatabaseCommand.java
  9. 1 1
      src/main/java/com/l2jserver/cli/command/DeployCommand.java
  10. 1 1
      src/main/java/com/l2jserver/cli/command/QuitCommand.java
  11. 3 2
      src/main/java/com/l2jserver/cli/command/account/AccountCreateCommand.java
  12. 3 13
      src/main/java/com/l2jserver/cli/command/account/AccountDeleteCommand.java
  13. 4 4
      src/main/java/com/l2jserver/cli/command/account/AccountListCommand.java
  14. 4 3
      src/main/java/com/l2jserver/cli/command/account/AccountUpdateCommand.java
  15. 162 0
      src/main/java/com/l2jserver/cli/command/database/DatabaseInstallCommand.java
  16. 63 0
      src/main/java/com/l2jserver/cli/config/Configs.java
  17. 46 0
      src/main/java/com/l2jserver/cli/config/DatabaseConfiguration.java
  18. 27 0
      src/main/java/com/l2jserver/cli/config/GameServerConfiguration.java
  19. 27 0
      src/main/java/com/l2jserver/cli/config/LoginServerConfiguration.java
  20. 96 0
      src/main/java/com/l2jserver/cli/config/impl/DatabaseConfigurationImpl.java
  21. 42 0
      src/main/java/com/l2jserver/cli/config/impl/GameServerConfigurationImpl.java
  22. 42 0
      src/main/java/com/l2jserver/cli/config/impl/LoginServerConfigurationImpl.java
  23. 222 5
      src/main/java/com/l2jserver/cli/dao/AbstractDAO.java
  24. 112 0
      src/main/java/com/l2jserver/cli/dao/AbstractDatabaseDAO.java
  25. 22 12
      src/main/java/com/l2jserver/cli/dao/AccountDAO.java
  26. 41 0
      src/main/java/com/l2jserver/cli/dao/GameServerDatabaseDAO.java
  27. 41 0
      src/main/java/com/l2jserver/cli/dao/LoginServerDatabaseDAO.java
  28. 28 0
      src/main/java/com/l2jserver/cli/model/DatabaseInstallType.java
  29. 28 0
      src/main/java/com/l2jserver/cli/model/ServerType.java
  30. 46 0
      src/main/java/com/l2jserver/cli/util/FileWriterStdout.java
  31. 37 0
      src/main/java/com/l2jserver/cli/util/SQLFilter.java
  32. 13 0
      src/main/resources/config.properties
  33. 115 0
      src/main/resources/sql/cleanup/gs_cleanup.sql
  34. 9 0
      src/main/resources/sql/cleanup/ls_cleanup.sql

+ 2 - 0
README.md

@@ -7,6 +7,8 @@ Existing commands
 - code: gets the source code from the repository
 - build: builds the source code
 - deploy: deploys the built source code
+- database
+  - install: installs the database
 - account
   - create: creates an account
   - update: updates an account

+ 21 - 5
pom.xml

@@ -11,6 +11,12 @@
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<!-- Dependencies -->
 		<picocli.version>3.9.3</picocli.version>
+		<jgit.version>5.2.1.201812262042-r</jgit.version>
+		<slf4j.version>1.7.25</slf4j.version>
+		<log4j.version>2.11.1</log4j.version>
+		<mysql-connector-java.version>8.0.15</mysql-connector-java.version>
+		<commons-configuration2.version>2.4</commons-configuration2.version>
+		<commons-beanutils.version>1.9.3</commons-beanutils.version>
 	</properties>
 	<dependencies>
 		<dependency>
@@ -21,27 +27,37 @@
 		<dependency>
 			<groupId>org.eclipse.jgit</groupId>
 			<artifactId>org.eclipse.jgit</artifactId>
-			<version>5.2.1.201812262042-r</version>
+			<version>${jgit.version}</version>
 		</dependency>
 		<dependency>
 			<groupId>org.slf4j</groupId>
 			<artifactId>slf4j-api</artifactId>
-			<version>1.7.25</version>
+			<version>${slf4j.version}</version>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.logging.log4j</groupId>
 			<artifactId>log4j-slf4j-impl</artifactId>
-			<version>2.11.1</version>
+			<version>${log4j.version}</version>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.logging.log4j</groupId>
 			<artifactId>log4j-core</artifactId>
-			<version>2.11.1</version>
+			<version>${log4j.version}</version>
 		</dependency>
 		<dependency>
 			<groupId>mysql</groupId>
 			<artifactId>mysql-connector-java</artifactId>
-			<version>8.0.15</version>
+			<version>${mysql-connector-java.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.commons</groupId>
+			<artifactId>commons-configuration2</artifactId>
+			<version>${commons-configuration2.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>commons-beanutils</groupId>
+			<artifactId>commons-beanutils</artifactId>
+			<version>${commons-beanutils.version}</version>
 		</dependency>
 	</dependencies>
 </project>

+ 4 - 3
src/main/java/com/l2jserver/cli/L2JServerCLI.java

@@ -25,6 +25,7 @@ import java.util.concurrent.Callable;
 import com.l2jserver.cli.command.AccountCommand;
 import com.l2jserver.cli.command.BuildCommand;
 import com.l2jserver.cli.command.CodeCommand;
+import com.l2jserver.cli.command.DatabaseCommand;
 import com.l2jserver.cli.command.DeployCommand;
 import com.l2jserver.cli.command.QuitCommand;
 
@@ -35,10 +36,11 @@ import picocli.CommandLine.Command;
  * L2J Server CLI.
  * @author Zoey76
  */
-@Command(name = "l2j", version = "1.0", subcommands = { //
+@Command(name = "", version = "1.0", subcommands = { //
 	CodeCommand.class, //
 	BuildCommand.class, //
 	DeployCommand.class, //
+	DatabaseCommand.class, //
 	AccountCommand.class, //
 	QuitCommand.class //
 })
@@ -53,8 +55,7 @@ public class L2JServerCLI implements Callable<Void> {
 				final String[] args = br.readLine().split(" ");
 				CommandLine.call(new L2JServerCLI(), args);
 			}
-		}
-		catch (Exception ex) {
+		} catch (Exception ex) {
 			ex.printStackTrace();
 		}
 		return null;

+ 37 - 0
src/main/java/com/l2jserver/cli/command/AbstractCommand.java

@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.cli.command;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+
+/**
+ * Abstract command.
+ * @author Zoey76
+ */
+public abstract class AbstractCommand implements Runnable {
+	protected static final String YES = "y";
+	
+	protected static final FilterInputStream FILTER_INPUT_STREAM = new FilterInputStream(System.in) {
+		@Override
+		public void close() throws IOException {
+			// Do not close it.
+		}
+	};
+}

+ 1 - 1
src/main/java/com/l2jserver/cli/command/AccountCommand.java

@@ -36,7 +36,7 @@ import picocli.CommandLine.Command;
 	AccountListCommand.class, //
 	AccountDeleteCommand.class //
 })
-public class AccountCommand implements Runnable {
+public class AccountCommand extends AbstractCommand {
 	
 	@Override
 	public void run() {

+ 1 - 1
src/main/java/com/l2jserver/cli/command/BuildCommand.java

@@ -25,7 +25,7 @@ import picocli.CommandLine.Command;
  * @author Zoey76
  */
 @Command(name = "build")
-public class BuildCommand implements Runnable {
+public class BuildCommand extends AbstractCommand {
 	
 	@Override
 	public void run() {

+ 3 - 5
src/main/java/com/l2jserver/cli/command/CodeCommand.java

@@ -35,7 +35,7 @@ import picocli.CommandLine.Option;
  * @author Zoey76
  */
 @Command(name = "code")
-public class CodeCommand implements Runnable {
+public class CodeCommand extends AbstractCommand {
 	
 	private static final Logger LOG = LoggerFactory.getLogger(CodeCommand.class);
 	
@@ -79,8 +79,7 @@ public class CodeCommand implements Runnable {
 					break;
 				}
 			}
-		}
-		catch (Exception ex) {
+		} catch (Exception ex) {
 			LOG.error("Unable to get the code!", ex);
 		}
 	}
@@ -92,8 +91,7 @@ public class CodeCommand implements Runnable {
 				.setDirectory(directory) //
 				.setProgressMonitor(LOGGER_PROGRESS_MONITOR) //
 				.call();
-		}
-		catch (Exception ex) {
+		} catch (Exception ex) {
 			LOG.error("Unable to get the code!", ex);
 		}
 	}

+ 40 - 0
src/main/java/com/l2jserver/cli/command/DatabaseCommand.java

@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.cli.command;
+
+import com.l2jserver.cli.command.database.DatabaseInstallCommand;
+
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+
+/**
+ * Database command.
+ * @author Zoey76
+ */
+@Command(name = "database", subcommands = { //
+	DatabaseInstallCommand.class
+})
+public class DatabaseCommand extends AbstractCommand {
+	
+	@Override
+	public void run() {
+		System.err.println("Please invoke a subcommand");
+		new CommandLine(new DatabaseCommand()).usage(System.out);
+	}
+}

+ 1 - 1
src/main/java/com/l2jserver/cli/command/DeployCommand.java

@@ -25,7 +25,7 @@ import picocli.CommandLine.Command;
  * @author Zoey76
  */
 @Command(name = "deploy")
-public class DeployCommand implements Runnable {
+public class DeployCommand extends AbstractCommand {
 	
 	@Override
 	public void run() {

+ 1 - 1
src/main/java/com/l2jserver/cli/command/QuitCommand.java

@@ -25,7 +25,7 @@ import picocli.CommandLine.Command;
  * @author Zoey76
  */
 @Command(name = "quit")
-public class QuitCommand implements Runnable {
+public class QuitCommand extends AbstractCommand {
 	
 	@Override
 	public void run() {

+ 3 - 2
src/main/java/com/l2jserver/cli/command/account/AccountCreateCommand.java

@@ -18,6 +18,7 @@
  */
 package com.l2jserver.cli.command.account;
 
+import com.l2jserver.cli.command.AbstractCommand;
 import com.l2jserver.cli.dao.AccountDAO;
 
 import picocli.CommandLine.Command;
@@ -28,7 +29,7 @@ import picocli.CommandLine.Option;
  * @author Zoey76
  */
 @Command(name = "create")
-public class AccountCreateCommand implements Runnable {
+public class AccountCreateCommand extends AbstractCommand {
 	
 	@Option(names = {
 		"-u",
@@ -52,6 +53,6 @@ public class AccountCreateCommand implements Runnable {
 	public void run() {
 		System.out.println("Creating account " + username + "...");
 		
-		AccountDAO.upsert(username, password, accessLevel);
+		AccountDAO.getInstance().upsert(username, password, accessLevel);
 	}
 }

+ 3 - 13
src/main/java/com/l2jserver/cli/command/account/AccountDeleteCommand.java

@@ -18,10 +18,9 @@
  */
 package com.l2jserver.cli.command.account;
 
-import java.io.FilterInputStream;
-import java.io.IOException;
 import java.util.Scanner;
 
+import com.l2jserver.cli.command.AbstractCommand;
 import com.l2jserver.cli.dao.AccountDAO;
 
 import picocli.CommandLine.Command;
@@ -32,16 +31,7 @@ import picocli.CommandLine.Option;
  * @author Zoey76
  */
 @Command(name = "delete")
-public class AccountDeleteCommand implements Runnable {
-	
-	private static final String YES = "y";
-	
-	private static final FilterInputStream FILTER_INPUT_STREAM = new FilterInputStream(System.in) {
-		@Override
-		public void close() throws IOException {
-			// Do not close it.
-		}
-	};
+public class AccountDeleteCommand extends AbstractCommand {
 	
 	@Option(names = {
 		"-u",
@@ -57,7 +47,7 @@ public class AccountDeleteCommand implements Runnable {
 		System.out.print("Do you really want to delete this account? y/N: ");
 		try (var s = new Scanner(FILTER_INPUT_STREAM)) {
 			if (YES.equalsIgnoreCase(s.next())) {
-				final var deleted = AccountDAO.delete(username);
+				final var deleted = AccountDAO.getInstance().delete(username);
 				if (deleted) {
 					System.out.println("Account " + username + " has been deleted.");
 				} else {

+ 4 - 4
src/main/java/com/l2jserver/cli/command/account/AccountListCommand.java

@@ -18,8 +18,8 @@
  */
 package com.l2jserver.cli.command.account;
 
-import static com.l2jserver.cli.dao.AccountDAO.listAccounts;
-
+import com.l2jserver.cli.command.AbstractCommand;
+import com.l2jserver.cli.dao.AccountDAO;
 import com.l2jserver.cli.model.AccountListType;
 
 import picocli.CommandLine.Command;
@@ -30,7 +30,7 @@ import picocli.CommandLine.Option;
  * @author Zoey76
  */
 @Command(name = "list")
-public class AccountListCommand implements Runnable {
+public class AccountListCommand extends AbstractCommand {
 	
 	@Option(names = {
 		"-t",
@@ -42,6 +42,6 @@ public class AccountListCommand implements Runnable {
 	public void run() {
 		System.out.println("Listing " + accountListType.name().toLowerCase() + " accounts...");
 		
-		listAccounts(accountListType).entrySet().forEach(a -> System.out.println(a.getKey() + " (" + a.getValue() + ")"));
+		AccountDAO.getInstance().listAccounts(accountListType).entrySet().forEach(a -> System.out.println(a.getKey() + " (" + a.getValue() + ")"));
 	}
 }

+ 4 - 3
src/main/java/com/l2jserver/cli/command/account/AccountUpdateCommand.java

@@ -18,6 +18,7 @@
  */
 package com.l2jserver.cli.command.account;
 
+import com.l2jserver.cli.command.AbstractCommand;
 import com.l2jserver.cli.dao.AccountDAO;
 
 import picocli.CommandLine.Command;
@@ -28,7 +29,7 @@ import picocli.CommandLine.Option;
  * @author Zoey76
  */
 @Command(name = "update")
-public class AccountUpdateCommand implements Runnable {
+public class AccountUpdateCommand extends AbstractCommand {
 	
 	@Option(names = {
 		"-u",
@@ -53,7 +54,7 @@ public class AccountUpdateCommand implements Runnable {
 		System.out.println("Updating account " + username + " (" + accessLevel + ")");
 		
 		if (password != null && accessLevel != null) {
-			final var createdUpdated = AccountDAO.upsert(username, password, accessLevel);
+			final var createdUpdated = AccountDAO.getInstance().upsert(username, password, accessLevel);
 			if (createdUpdated) {
 				System.out.println("Account " + username + " has been created or updated.");
 			}
@@ -61,7 +62,7 @@ public class AccountUpdateCommand implements Runnable {
 		}
 		
 		if (accessLevel != null) {
-			final var updated = AccountDAO.changeAccountLevel(username, accessLevel);
+			final var updated = AccountDAO.getInstance().changeAccountLevel(username, accessLevel);
 			if (updated) {
 				System.out.println("Account " + username + " has been updated.");
 			} else {

+ 162 - 0
src/main/java/com/l2jserver/cli/command/database/DatabaseInstallCommand.java

@@ -0,0 +1,162 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.cli.command.database;
+
+import java.io.File;
+import java.util.Scanner;
+
+import com.l2jserver.cli.command.AbstractCommand;
+import com.l2jserver.cli.config.Configs;
+import com.l2jserver.cli.config.DatabaseConfiguration;
+import com.l2jserver.cli.dao.AbstractDatabaseDAO;
+import com.l2jserver.cli.dao.GameServerDatabaseDAO;
+import com.l2jserver.cli.dao.LoginServerDatabaseDAO;
+import com.l2jserver.cli.model.DatabaseInstallType;
+import com.l2jserver.cli.model.ServerType;
+
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
+
+/**
+ * Database install command.
+ * @author Zoey76
+ */
+@Command(name = "install")
+public class DatabaseInstallCommand extends AbstractCommand {
+	
+	@Option(names = {
+		"-l",
+		"--location"
+	}, required = true, description = "Files location")
+	private String path;
+	
+	@Option(names = {
+		"-h",
+		"--host"
+	}, description = "Database host")
+	private String host;
+	
+	@Option(names = {
+		"-p",
+		"--port"
+	}, description = "Database port")
+	private Integer port;
+	
+	@Option(names = {
+		"-u",
+		"--user"
+	}, description = "Database user")
+	private String user;
+	
+	@Option(names = {
+		"-pw",
+		"--password"
+	}, description = "Database password")
+	private String password;
+	
+	@Option(names = {
+		"-d",
+		"--db"
+	}, description = "Database name")
+	private String database;
+	
+	@Option(names = {
+		"-m",
+		"--mode"
+	}, required = true, description = "Database installation mode")
+	private DatabaseInstallType mode;
+	
+	@Option(names = {
+		"-t",
+		"--type"
+	}, required = true, description = "Server Type")
+	private ServerType serverType;
+	
+	@Override
+	public void run() {
+		// Validate files exists
+		final var sqlPath = new File(path);
+		if (!sqlPath.exists()) {
+			System.err.println("The path does not exist!");
+			return;
+		}
+		
+		final AbstractDatabaseDAO databaseDAO = databaseDAO();
+		
+		databaseDAO.ensureDatabaseUsage();
+		
+		databaseDAO.createDump();
+		
+		databaseDAO.updates(mode, sqlPath);
+		
+		databaseDAO.basic(sqlPath);
+		
+		System.out.print("Install custom tables? (y/N): ");
+		try (var s = new Scanner(FILTER_INPUT_STREAM)) {
+			if (YES.equalsIgnoreCase(s.next())) {
+				databaseDAO.custom(sqlPath);
+			}
+		}
+		
+		System.out.print("Install mod tables? (y/N): ");
+		try (var s = new Scanner(FILTER_INPUT_STREAM)) {
+			if (YES.equalsIgnoreCase(s.next())) {
+				databaseDAO.mods(sqlPath);
+			}
+		}
+		
+		System.out.println("Database installation complete.");
+	}
+	
+	private AbstractDatabaseDAO databaseDAO() {
+		switch (serverType) {
+			case GAME: {
+				overrideConfigs(Configs.gameServer().db());
+				return new GameServerDatabaseDAO();
+			}
+			default:
+			case LOGIN: {
+				overrideConfigs(Configs.loginServer().db());
+				return new LoginServerDatabaseDAO();
+			}
+		}
+	}
+	
+	private void overrideConfigs(DatabaseConfiguration databaseConfiguration) {
+		if (host != null) {
+			databaseConfiguration.withHost(host);
+		}
+		
+		if (port != null) {
+			databaseConfiguration.withPort(port);
+		}
+		
+		if (user != null) {
+			databaseConfiguration.withUser(user);
+		}
+		
+		if (password != null) {
+			databaseConfiguration.withPassword(password);
+		}
+		
+		if (database != null) {
+			databaseConfiguration.withName(database);
+		}
+	}
+}

+ 63 - 0
src/main/java/com/l2jserver/cli/config/Configs.java

@@ -0,0 +1,63 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.cli.config;
+
+import java.io.File;
+
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.builder.fluent.Configurations;
+
+import com.l2jserver.cli.config.impl.GameServerConfigurationImpl;
+import com.l2jserver.cli.config.impl.LoginServerConfigurationImpl;
+
+/**
+ * Configs.
+ * @author Zoey76
+ */
+public enum Configs {
+	INSTANCE;
+	
+	private Configuration config;
+	
+	private GameServerConfiguration gameServerConfig;
+	
+	private LoginServerConfiguration loginServerConfiguration;
+	
+	Configs() {
+		final var configs = new Configurations();
+		try {
+			config = configs.properties(new File("config.properties"));
+			
+			gameServerConfig = new GameServerConfigurationImpl(config);
+			
+			loginServerConfiguration = new LoginServerConfigurationImpl(config);
+		} catch (Exception ex) {
+			System.err.println("There has been an error loading configs!");
+			ex.printStackTrace();
+		}
+	}
+	
+	public static GameServerConfiguration gameServer() {
+		return INSTANCE.gameServerConfig;
+	}
+	
+	public static LoginServerConfiguration loginServer() {
+		return INSTANCE.loginServerConfiguration;
+	}
+}

+ 46 - 0
src/main/java/com/l2jserver/cli/config/DatabaseConfiguration.java

@@ -0,0 +1,46 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.cli.config;
+
+/**
+ * Database configuration interface.
+ * @author Zoey76
+ */
+public interface DatabaseConfiguration {
+	
+	String name();
+	
+	String host();
+	
+	int port();
+	
+	String user();
+	
+	String password();
+	
+	DatabaseConfiguration withName(String name);
+	
+	DatabaseConfiguration withHost(String host);
+	
+	DatabaseConfiguration withPort(int port);
+	
+	DatabaseConfiguration withUser(String user);
+	
+	DatabaseConfiguration withPassword(String password);
+}

+ 27 - 0
src/main/java/com/l2jserver/cli/config/GameServerConfiguration.java

@@ -0,0 +1,27 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.cli.config;
+
+/**
+ * Game Server configuration interface.
+ * @author Zoey76
+ */
+public interface GameServerConfiguration {
+	DatabaseConfiguration db();
+}

+ 27 - 0
src/main/java/com/l2jserver/cli/config/LoginServerConfiguration.java

@@ -0,0 +1,27 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.cli.config;
+
+/**
+ * Login Server configuration interface.
+ * @author Zoey76
+ */
+public interface LoginServerConfiguration {
+	DatabaseConfiguration db();
+}

+ 96 - 0
src/main/java/com/l2jserver/cli/config/impl/DatabaseConfigurationImpl.java

@@ -0,0 +1,96 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.cli.config.impl;
+
+import org.apache.commons.configuration2.Configuration;
+
+import com.l2jserver.cli.config.DatabaseConfiguration;
+
+/**
+ * Database configuration implementation.
+ * @author Zoey76
+ */
+public class DatabaseConfigurationImpl implements DatabaseConfiguration {
+	
+	private static final String PREFIX = ".db.";
+	
+	private String section;
+	
+	private Configuration config;
+	
+	public DatabaseConfigurationImpl(String section, Configuration config) {
+		this.config = config;
+		this.section = section;
+	}
+	
+	@Override
+	public String name() {
+		return config.getString(section + PREFIX + "name");
+	}
+	
+	@Override
+	public String host() {
+		return config.getString(section + PREFIX + "host");
+	}
+	
+	@Override
+	public int port() {
+		return config.getInt(section + PREFIX + "port");
+	}
+	
+	@Override
+	public String user() {
+		return config.getString(section + PREFIX + "user");
+	}
+	
+	@Override
+	public String password() {
+		return config.getString(section + PREFIX + "password");
+	}
+	
+	@Override
+	public DatabaseConfiguration withName(String name) {
+		config.setProperty(section + PREFIX + "name", name);
+		return this;
+	}
+	
+	@Override
+	public DatabaseConfiguration withHost(String host) {
+		config.setProperty(section + PREFIX + "host", host);
+		return this;
+	}
+	
+	@Override
+	public DatabaseConfiguration withPort(int port) {
+		config.setProperty(section + PREFIX + "port", port);
+		return this;
+	}
+	
+	@Override
+	public DatabaseConfiguration withUser(String user) {
+		config.setProperty(section + PREFIX + "user", user);
+		return this;
+	}
+	
+	@Override
+	public DatabaseConfiguration withPassword(String password) {
+		config.setProperty(section + PREFIX + "password", password);
+		return this;
+	}
+}

+ 42 - 0
src/main/java/com/l2jserver/cli/config/impl/GameServerConfigurationImpl.java

@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.cli.config.impl;
+
+import org.apache.commons.configuration2.Configuration;
+
+import com.l2jserver.cli.config.DatabaseConfiguration;
+import com.l2jserver.cli.config.GameServerConfiguration;
+
+/**
+ * Game Server configuration implementation.
+ * @author Zoey76
+ */
+public class GameServerConfigurationImpl implements GameServerConfiguration {
+	
+	private DatabaseConfiguration databaseConfiguration;
+	
+	public GameServerConfigurationImpl(Configuration config) {
+		databaseConfiguration = new DatabaseConfigurationImpl("gs", config);
+	}
+	
+	@Override
+	public DatabaseConfiguration db() {
+		return databaseConfiguration;
+	}
+}

+ 42 - 0
src/main/java/com/l2jserver/cli/config/impl/LoginServerConfigurationImpl.java

@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.cli.config.impl;
+
+import org.apache.commons.configuration2.Configuration;
+
+import com.l2jserver.cli.config.DatabaseConfiguration;
+import com.l2jserver.cli.config.LoginServerConfiguration;
+
+/**
+ * Login Server configuration implementation.
+ * @author Zoey76
+ */
+public class LoginServerConfigurationImpl implements LoginServerConfiguration {
+	
+	private DatabaseConfiguration databaseConfiguration;
+	
+	public LoginServerConfigurationImpl(Configuration config) {
+		databaseConfiguration = new DatabaseConfigurationImpl("ls", config);
+	}
+	
+	@Override
+	public DatabaseConfiguration db() {
+		return databaseConfiguration;
+	}
+}

+ 222 - 5
src/main/java/com/l2jserver/cli/dao/AbstractDAO.java

@@ -18,9 +18,22 @@
  */
 package com.l2jserver.cli.dao;
 
+import java.io.File;
+import java.io.FileWriter;
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.SQLException;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Properties;
+import java.util.Scanner;
+
+import com.l2jserver.cli.util.FileWriterStdout;
+import com.l2jserver.cli.util.SQLFilter;
 
 /**
  * Abstract DAO.
@@ -28,13 +41,217 @@ import java.sql.SQLException;
  */
 class AbstractDAO {
 	
-	private static final String URL = "jdbc:mysql://localhost/l2jls?useSSL=false&serverTimezone=UTC";
+	private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss");
+	
+	private final String host;
+	
+	private final int port;
+	
+	private final String database;
 	
-	private static String username = "root";
+	private final Properties info;
+	
+	AbstractDAO(String host, int port, String database, String username, String password) {
+		this.host = host;
+		this.port = port;
+		this.database = database;
+		info = new Properties();
+		info.put("user", username);
+		info.put("password", password);
+		info.put("useSSL", "false");
+		info.put("serverTimezone", "UTC");
+		info.put("allowPublicKeyRetrieval", "true");
+	}
+	
+	public String getDatabase() {
+		return database;
+	}
 	
-	private static String password = "toor";
+	protected Connection getConnection() throws SQLException {
+		final String url = String.format("jdbc:mysql://%s:%s/%s", host, port, database);
+		return DriverManager.getConnection(url, info);
+	}
+	
+	public void ensureDatabaseUsage() {
+		final String url = String.format("jdbc:mysql://%s:%s", host, port);
+		try (var con = DriverManager.getConnection(url, info); //
+			var s = con.createStatement()) {
+			s.execute("CREATE DATABASE IF NOT EXISTS `" + database + "`");
+			s.execute("USE `" + database + "`");
+		} catch (Exception ex) {
+			System.err.println("There has been an error ensuring database " + database + " usage!");
+			ex.printStackTrace();
+		}
+	}
+	
+	public void executeSQLScript(File file) {
+		String line = "";
+		try (var con = getConnection(); //
+			var stmt = con.createStatement(); //
+			var scn = new Scanner(file)) {
+			var sb = new StringBuilder();
+			while (scn.hasNextLine()) {
+				line = scn.nextLine();
+				if (line.startsWith("--")) {
+					continue;
+				}
+				
+				if (line.contains("--")) {
+					line = line.split("--")[0];
+				}
+				
+				line = line.trim();
+				if (!line.isEmpty()) {
+					sb.append(line + System.getProperty("line.separator"));
+				}
+				
+				if (line.endsWith(";")) {
+					stmt.execute(sb.toString());
+					sb = new StringBuilder();
+				}
+			}
+		} catch (Exception ex) {
+			System.err.println("There has been an error executing file " + file.getName() + "!");
+			ex.printStackTrace();
+		}
+	}
+	
+	public void executeDirectoryOfSQLScripts(File dir, boolean skipErrors) {
+		final var files = dir.listFiles(new SQLFilter());
+		if (files != null) {
+			Arrays.sort(files);
+			for (var file : files) {
+				if (skipErrors) {
+					try {
+						executeSQLScript(file);
+					} catch (Throwable t) {
+					}
+				} else {
+					executeSQLScript(file);
+				}
+			}
+		}
+	}
 	
-	public static Connection getConnection() throws SQLException {
-		return DriverManager.getConnection(URL, username, password);
+	public void createDump() {
+		try (var con = getConnection(); //
+			var s = con.createStatement(); //
+			var rset = s.executeQuery("SHOW TABLES")) {
+			final var fileName = database + "_dump_" + DATE_TIME_FORMATTER.format(LocalDateTime.now()) + ".sql";
+			var dump = new File("dumps", fileName);
+			new File("dumps").mkdir();
+			dump.createNewFile();
+			
+			if (rset.last()) {
+				rset.beforeFirst();
+			}
+			
+			try (var fileWriter = new FileWriter(dump);
+				var fws = new FileWriterStdout(fileWriter)) {
+				while (rset.next()) {
+					fws.println("CREATE TABLE `" + rset.getString(1) + "`");
+					fws.println("(");
+					try (var desc = con.createStatement();
+						var dset = desc.executeQuery("DESC " + rset.getString(1))) {
+						final var keys = new HashMap<String, List<String>>();
+						var isFirst = true;
+						while (dset.next()) {
+							if (!isFirst) {
+								fws.println(",");
+							}
+							fws.print("\t`" + dset.getString(1) + "`");
+							fws.print(" " + dset.getString(2));
+							if (dset.getString(3).equals("NO")) {
+								fws.print(" NOT NULL");
+							}
+							if (!dset.getString(4).isEmpty()) {
+								if (!keys.containsKey(dset.getString(4))) {
+									keys.put(dset.getString(4), new ArrayList<String>());
+								}
+								keys.get(dset.getString(4)).add(dset.getString(1));
+							}
+							if (dset.getString(5) != null) {
+								fws.print(" DEFAULT '" + dset.getString(5) + "'");
+							}
+							if (!dset.getString(6).isEmpty()) {
+								fws.print(" " + dset.getString(6));
+							}
+							isFirst = false;
+						}
+						if (keys.containsKey("PRI")) {
+							fws.println(",");
+							fws.print("\tPRIMARY KEY (");
+							isFirst = true;
+							for (String key : keys.get("PRI")) {
+								if (!isFirst) {
+									fws.print(", ");
+								}
+								fws.print("`" + key + "`");
+								isFirst = false;
+							}
+							fws.print(")");
+						}
+						if (keys.containsKey("MUL")) {
+							fws.println(",");
+							isFirst = true;
+							for (String key : keys.get("MUL")) {
+								if (!isFirst) {
+									fws.println(", ");
+								}
+								fws.print("\tKEY `key_" + key + "` (`" + key + "`)");
+								isFirst = false;
+							}
+						}
+						fws.println();
+						fws.println(");");
+						fws.flush();
+					}
+					
+					try (var desc = con.createStatement();
+						var dset = desc.executeQuery("SELECT * FROM " + rset.getString(1))) {
+						boolean isFirst = true;
+						int cnt = 0;
+						while (dset.next()) {
+							if ((cnt % 100) == 0) {
+								fws.println("INSERT INTO `" + rset.getString(1) + "` VALUES ");
+							} else {
+								fws.println(",");
+							}
+							
+							fws.print("\t(");
+							boolean isInFirst = true;
+							for (int i = 1; i <= dset.getMetaData().getColumnCount(); i++) {
+								if (!isInFirst) {
+									fws.print(", ");
+								}
+								
+								if (dset.getString(i) == null) {
+									fws.print("NULL");
+								} else {
+									fws.print("'" + dset.getString(i).replace("\'", "\\\'") + "'");
+								}
+								isInFirst = false;
+							}
+							fws.print(")");
+							isFirst = false;
+							
+							if ((cnt % 100) == 99) {
+								fws.println(";");
+							}
+							cnt++;
+						}
+						if (!isFirst && ((cnt % 100) != 0)) {
+							fws.println(";");
+						}
+						fws.println();
+						fws.flush();
+					}
+				}
+				fws.flush();
+			}
+		} catch (Exception ex) {
+			System.err.println("There has been an error creating a database backup for " + database + "!");
+			ex.printStackTrace();
+		}
 	}
 }

+ 112 - 0
src/main/java/com/l2jserver/cli/dao/AbstractDatabaseDAO.java

@@ -0,0 +1,112 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.cli.dao;
+
+import java.io.File;
+import java.util.prefs.Preferences;
+
+import com.l2jserver.cli.model.DatabaseInstallType;
+import com.l2jserver.cli.util.SQLFilter;
+
+/**
+ * Database DAO.
+ * @author Zoey76
+ */
+public abstract class AbstractDatabaseDAO extends AbstractDAO {
+	
+	AbstractDatabaseDAO(String host, int port, String database, String username, String password) {
+		super(host, port, database, username, password);
+	}
+	
+	public void mods(File sqlPath) {
+		final var modsPath = new File(sqlPath, "mods");
+		if (modsPath.exists()) {
+			System.out.println("Installing mod tables...");
+			runSQLFiles(modsPath.listFiles(new SQLFilter()));
+		}
+	}
+	
+	public void custom(File sqlPath) {
+		final var customPath = new File(sqlPath, "custom");
+		if (customPath.exists()) {
+			System.out.println("Installing custom tables...");
+			runSQLFiles(customPath.listFiles(new SQLFilter()));
+		}
+	}
+	
+	public void basic(File sqlPath) {
+		System.out.println("Installing basic SQL scripts...");
+		runSQLFiles(sqlPath.listFiles(new SQLFilter()));
+	}
+	
+	public abstract void updates(DatabaseInstallType mode, File sqlPath);
+	
+	protected void updates(DatabaseInstallType mode, String cleanup, File sqlPath) {
+		final var userPreferences = Preferences.userRoot();
+		final var updatePath = new File(sqlPath, "updates");
+		final var updatePreferences = getDatabase() + "_update";
+		
+		switch (mode) {
+			case FULL: {
+				System.out.println("Executing cleanup script...");
+				
+				runSQLFiles(new File(ClassLoader.getSystemResource(cleanup).getFile()));
+				
+				if (updatePath.exists()) {
+					final var sb = new StringBuilder();
+					for (var sqlFile : updatePath.listFiles(new SQLFilter())) {
+						sb.append(sqlFile.getName() + ';');
+					}
+					userPreferences.put(updatePreferences, sb.toString());
+				}
+				break;
+			}
+			case UPDATE: {
+				System.out.println("Installing update SQL scripts...");
+				final var updated = userPreferences.get(updatePreferences, "");
+				for (var sqlFile : updatePath.listFiles(new SQLFilter())) {
+					if (!updated.contains(sqlFile.getName())) {
+						try {
+							System.out.println("Installing " + sqlFile.getName() + "...");
+							executeSQLScript(sqlFile);
+						} catch (Exception ex) {
+							System.err.println("There has been an error executing SQL update!");
+							ex.printStackTrace();
+							return;
+						}
+						userPreferences.put(updatePreferences, updated + sqlFile.getName() + ";");
+					}
+				}
+				break;
+			}
+		}
+	}
+	
+	private void runSQLFiles(File... sqlFiles) {
+		for (var sqlFile : sqlFiles) {
+			try {
+				System.out.println("Running " + sqlFile.getName() + "...");
+				executeSQLScript(sqlFile);
+			} catch (Exception ex) {
+				System.err.println("There has been an error executing SQL file " + sqlFile.getName() + "!");
+				ex.printStackTrace();
+			}
+		}
+	}
+}

+ 22 - 12
src/main/java/com/l2jserver/cli/dao/AccountDAO.java

@@ -18,6 +18,7 @@
  */
 package com.l2jserver.cli.dao;
 
+import static com.l2jserver.cli.config.Configs.loginServer;
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 import java.security.MessageDigest;
@@ -48,7 +49,11 @@ public class AccountDAO extends AbstractDAO {
 	
 	private static final String ALGORITHM = "SHA";
 	
-	public static boolean upsert(String username, String password, int accessLevel) {
+	private AccountDAO() {
+		super(loginServer().db().host(), loginServer().db().port(), loginServer().db().name(), loginServer().db().user(), loginServer().db().password());
+	}
+	
+	public boolean upsert(String username, String password, int accessLevel) {
 		try (var con = getConnection(); //
 			var ps = con.prepareStatement(REPLACE_ACCOUNT)) {
 			final var md = MessageDigest.getInstance(ALGORITHM);
@@ -58,27 +63,25 @@ public class AccountDAO extends AbstractDAO {
 			ps.setString(2, Base64.getEncoder().encodeToString(newPassword));
 			ps.setInt(3, accessLevel);
 			return ps.executeUpdate() > 0;
-		}
-		catch (Exception ex) {
+		} catch (Exception ex) {
 			System.out.println("There was error while creating/updating account " + username + "!");
 		}
 		return false;
 	}
 	
-	public static boolean changeAccountLevel(String username, int accesslevel) {
+	public boolean changeAccountLevel(String username, int accesslevel) {
 		try (var con = getConnection(); //
 			var ps = con.prepareStatement(UPDATE_ACCOUNT_LEVEL)) {
 			ps.setInt(1, accesslevel);
 			ps.setString(2, username);
 			return ps.executeUpdate() > 0;
-		}
-		catch (Exception ex) {
+		} catch (Exception ex) {
 			System.out.println("There was error while updating account " + username + " level!");
 		}
 		return false;
 	}
 	
-	public static Map<String, Integer> listAccounts(AccountListType accountListType) {
+	public Map<String, Integer> listAccounts(AccountListType accountListType) {
 		final var result = new HashMap<String, Integer>();
 		try (var con = getConnection(); //
 			var st = con.createStatement(); //
@@ -86,22 +89,29 @@ public class AccountDAO extends AbstractDAO {
 			while (rs.next()) {
 				result.put(rs.getString("login"), rs.getInt("accessLevel"));
 			}
-		}
-		catch (Exception ex) {
+		} catch (Exception ex) {
 			System.out.println("There was error while listing " + accountListType.name().toLowerCase() + " accounts!");
+			ex.printStackTrace();
 		}
 		return result;
 	}
 	
-	public static boolean delete(String username) {
+	public boolean delete(String username) {
 		try (var con = getConnection(); //
 			var ps = con.prepareStatement(DELETE_ACCOUNT)) {
 			ps.setString(1, username);
 			return ps.executeUpdate() > 0;
-		}
-		catch (Exception ex) {
+		} catch (Exception ex) {
 			System.out.println("There was error while deleting account " + username + "!");
 		}
 		return false;
 	}
+	
+	public static AccountDAO getInstance() {
+		return SingletonHolder.INSTANCE;
+	}
+	
+	private static class SingletonHolder {
+		protected static final AccountDAO INSTANCE = new AccountDAO();
+	}
 }

+ 41 - 0
src/main/java/com/l2jserver/cli/dao/GameServerDatabaseDAO.java

@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.cli.dao;
+
+import static com.l2jserver.cli.config.Configs.gameServer;
+
+import java.io.File;
+
+import com.l2jserver.cli.model.DatabaseInstallType;
+
+/**
+ * Game Server Database DAO.
+ * @author Zoey76
+ */
+public class GameServerDatabaseDAO extends AbstractDatabaseDAO {
+	
+	public GameServerDatabaseDAO() {
+		super(gameServer().db().host(), gameServer().db().port(), gameServer().db().name(), gameServer().db().user(), gameServer().db().password());
+	}
+	
+	@Override
+	public void updates(DatabaseInstallType mode, File sqlPath) {
+		this.updates(mode, "sql/cleanup/gs_cleanup.sql", sqlPath);
+	}
+}

+ 41 - 0
src/main/java/com/l2jserver/cli/dao/LoginServerDatabaseDAO.java

@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.cli.dao;
+
+import static com.l2jserver.cli.config.Configs.loginServer;
+
+import java.io.File;
+
+import com.l2jserver.cli.model.DatabaseInstallType;
+
+/**
+ * Login Server Database DAO.
+ * @author Zoey76
+ */
+public class LoginServerDatabaseDAO extends AbstractDatabaseDAO {
+	
+	public LoginServerDatabaseDAO() {
+		super(loginServer().db().host(), loginServer().db().port(), loginServer().db().name(), loginServer().db().user(), loginServer().db().password());
+	}
+	
+	@Override
+	public void updates(DatabaseInstallType mode, File sqlPath) {
+		this.updates(mode, "sql/cleanup/ls_cleanup.sql", sqlPath);
+	}
+}

+ 28 - 0
src/main/java/com/l2jserver/cli/model/DatabaseInstallType.java

@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.cli.model;
+
+/**
+ * Database Install type.
+ * @author Zoey76
+ */
+public enum DatabaseInstallType {
+	FULL,
+	UPDATE
+}

+ 28 - 0
src/main/java/com/l2jserver/cli/model/ServerType.java

@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.cli.model;
+
+/**
+ * Server type.
+ * @author Zoey76
+ */
+public enum ServerType {
+	GAME,
+	LOGIN
+}

+ 46 - 0
src/main/java/com/l2jserver/cli/util/FileWriterStdout.java

@@ -0,0 +1,46 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.cli.util;
+
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.io.IOException;
+
+/**
+ * File writer.
+ * @author mrTJO
+ * @author Zoey76
+ */
+public class FileWriterStdout extends BufferedWriter {
+	public FileWriterStdout(FileWriter fileWriter) {
+		super(fileWriter);
+	}
+	
+	public void println() throws IOException {
+		append(System.lineSeparator());
+	}
+	
+	public void println(String line) throws IOException {
+		append(line + System.lineSeparator());
+	}
+	
+	public void print(String text) throws IOException {
+		append(text);
+	}
+}

+ 37 - 0
src/main/java/com/l2jserver/cli/util/SQLFilter.java

@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.cli.util;
+
+import java.io.File;
+import java.io.FileFilter;
+
+/**
+ * Specialized {@link FileFilter} class.<br>
+ * Accepts <b>files</b> ending with ".sql" only.
+ * @author Zoey76
+ */
+public class SQLFilter implements FileFilter {
+	@Override
+	public boolean accept(File f) {
+		if ((f == null) || !f.isFile()) {
+			return false;
+		}
+		return f.getName().toLowerCase().endsWith(".sql");
+	}
+}

+ 13 - 0
src/main/resources/config.properties

@@ -0,0 +1,13 @@
+# Game Server
+gs.db.name=l2jgs
+gs.db.host=127.0.0.1
+gs.db.port=3306
+gs.db.user=root
+gs.db.password=toor
+
+# Login Server
+ls.db.name=l2jls
+ls.db.host=127.0.0.1
+ls.db.port=3306
+ls.db.user=root
+ls.db.password=toor

+ 115 - 0
src/main/resources/sql/cleanup/gs_cleanup.sql

@@ -0,0 +1,115 @@
+-- These queries are meant to delete any game server table you may have from previous L2J installations.
+--
+-- Queries that create these tables and/or populate them apropiately are available in L2J DataPack.
+
+DROP TABLE IF EXISTS 
+account_gsdata,
+airships,
+announcements,
+auction,
+auction_bid,
+auction_watch,
+bbs_favorites,
+bot_reported_char_data,
+buylists,
+castle,
+castle_doorupgrade,
+castle_functions,
+castle_manor_procure,
+castle_manor_production,
+castle_siege_guards,
+castle_trapupgrade,
+character_contacts,
+character_friends,
+character_hennas,
+character_instance_time,
+character_item_reuse_save,
+character_macroses,
+character_offline_trade,
+character_offline_trade_items,
+character_pet_skills_save,
+character_premium_items,
+character_quest_global_data,
+character_quests,
+character_raid_points,
+character_recipebook,
+character_recipeshoplist,
+character_reco_bonus,
+character_shortcuts,
+character_skills,
+character_skills_save,
+character_subclasses,
+character_summon_skills_save,
+character_summons,
+character_tpbookmark,
+character_ui_actions,
+character_ui_categories,
+character_variables,
+characters,
+clan_data,
+clan_notices,
+clan_privs,
+clan_skills,
+clan_subpledges,
+clan_wars,
+clanhall,
+clanhall_functions,
+clanhall_siege_attackers,
+clanhall_siege_guards,
+crests,
+cursed_weapons,
+dimensional_rift,
+fort,
+fort_doorupgrade,
+fort_functions,
+fort_siege_guards,
+fort_spawnlist,
+fortsiege_clans,
+forums,
+four_sepulchers_spawnlist,
+games,
+global_tasks,
+global_variables,
+grandboss_data,
+grandboss_list,
+herb_droplist_groups,
+heroes,
+heroes_diary,
+item_attributes,
+item_auction,
+item_auction_bid,
+item_elementals,
+items,
+itemsonground,
+locations,
+merchant_lease,
+messages,
+mods_wedding,
+npc_buffer,
+olympiad_data,
+olympiad_fights,
+olympiad_nobles,
+olympiad_nobles_eom,
+petition_feedback,
+pets,
+pets_skills,
+posts,
+punishments,
+quest_global_data,
+raidboss_spawnlist,
+rainbowsprings_attacker_list,
+random_spawn,
+random_spawn_loc,
+seven_signs,
+seven_signs_festival,
+seven_signs_status,
+siegable_clanhall,
+siegable_hall_flagwar_attackers,
+siegable_hall_flagwar_attackers_members,
+siege_clans,
+spawnlist,
+teleport,
+territories,
+territory_registrations,
+territory_spawnlist,
+topic;

+ 9 - 0
src/main/resources/sql/cleanup/ls_cleanup.sql

@@ -0,0 +1,9 @@
+-- These queries are meant to delete any login server table you may have from previous L2J installations.
+--
+-- Queries that create these tables and/or populate them apropiately are available in L2J DataPack.
+
+DROP TABLE IF EXISTS
+account_data,
+accounts,
+accounts_ipauth,
+gameservers;