/** * This file is part of Craftconomy3. * * Copyright (c) 2011-2016, Greatman <http://github.com/greatman/> * * Craftconomy3 is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Craftconomy3 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Craftconomy3. If not, see <http://www.gnu.org/licenses/>. */ package com.greatmancode.craftconomy3.utils; import com.greatmancode.craftconomy3.Cause; import com.greatmancode.craftconomy3.Common; import com.greatmancode.craftconomy3.LogInfo; import com.greatmancode.craftconomy3.account.Account; import com.greatmancode.craftconomy3.currency.Currency; import com.greatmancode.craftconomy3.storage.StorageEngine; import com.greatmancode.craftconomy3.storage.sql.H2Engine; import com.greatmancode.craftconomy3.storage.sql.MySQLEngine; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import java.io.*; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.*; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.UUID; import java.util.logging.Level; public class OldFormatConverter { private HikariDataSource db; private String tablePrefix; public void run() throws SQLException, IOException, ParseException { String dbType = Common.getInstance().getMainConfig().getString("System.Database.Type"); HikariConfig config = new HikariConfig(); if (dbType.equalsIgnoreCase("mysql")) { config.setMaximumPoolSize(10); config.setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource"); config.addDataSourceProperty("serverName", Common.getInstance().getMainConfig().getString("System.Database.Address")); config.addDataSourceProperty("port", Common.getInstance().getMainConfig().getString("System.Database.Port")); config.addDataSourceProperty("databaseName", Common.getInstance().getMainConfig().getString("System.Database.Db")); config.addDataSourceProperty("user", Common.getInstance().getMainConfig().getString("System.Database.Username")); config.addDataSourceProperty("password", Common.getInstance().getMainConfig().getString("System.Database.Password")); config.addDataSourceProperty("autoDeserialize", true); config.setConnectionTimeout(5000); db = new HikariDataSource(config); } else if (dbType.equalsIgnoreCase("sqlite")) { config.setDriverClassName("org.sqlite.JDBC"); config.setJdbcUrl("jdbc:sqlite:"+ Common.getInstance().getServerCaller().getDataFolder() + File.separator + "database.db"); config.setConnectionTestQuery("SELECT 1"); db = new HikariDataSource(config); } else { Common.getInstance().sendConsoleMessage(Level.SEVERE, "Unknown database type for old format converter!"); return; } Connection connection = db.getConnection(); this.tablePrefix = Common.getInstance().getMainConfig().getString("System.Database.Prefix"); File accountFile = new File(Common.getInstance().getServerCaller().getDataFolder(), "accounts.json"); Common.getInstance().sendConsoleMessage(Level.INFO, "Doing a backup in a xml file before doing the conversion."); //Document setup JSONObject mainObject = new JSONObject(); Common.getInstance().sendConsoleMessage(Level.INFO, "Saving currency table"); //Currencies PreparedStatement statement = connection.prepareStatement("SELECT * FROM " + tablePrefix + "currency"); ResultSet set = statement.executeQuery(); JSONArray array = new JSONArray(); while (set.next()) { JSONObject entry = new JSONObject(); entry.put("id", set.getInt("id")); entry.put("name", set.getString("name")); entry.put("plural", set.getString("plural")); entry.put("minor", set.getString("minor")); entry.put("minorPlural", set.getString("minorPlural")); entry.put("sign", set.getString("sign")); entry.put("status", set.getBoolean("status")); array.add(entry); } statement.close(); mainObject.put("currencies", array); //World groups Common.getInstance().sendConsoleMessage(Level.INFO, "Saving world group table"); array = new JSONArray(); statement = connection.prepareStatement("SELECT * FROM " + tablePrefix + "worldgroup"); set = statement.executeQuery(); while (set.next()) { JSONObject entry = new JSONObject(); entry.put("groupName", set.getString("groupName")); entry.put("worldList", set.getString("worldList")); array.add(entry); } statement.close(); mainObject.put("worldgroups", array); //Exchange table Common.getInstance().sendConsoleMessage(Level.INFO, "Saving exchange table"); array = new JSONArray(); statement = connection.prepareStatement("SELECT * FROM " + tablePrefix + "exchange"); set = statement.executeQuery(); while (set.next()) { JSONObject entry = new JSONObject(); entry.put("from_currency_id", set.getInt("from_currency_id")); entry.put("to_currency_id", set.getInt("to_currency_id")); entry.put("amount", set.getDouble("amount")); array.add(entry); } statement.close(); mainObject.put("exchanges", array); //config table Common.getInstance().sendConsoleMessage(Level.INFO, "Saving config table"); array = new JSONArray(); statement = connection.prepareStatement("SELECT * FROM " + tablePrefix + "config"); set = statement.executeQuery(); while (set.next()) { JSONObject entry = new JSONObject(); entry.put("name", set.getString("name")); entry.put("value", set.getString("value")); array.add(entry); } statement.close(); mainObject.put("configs", array); //account table Common.getInstance().sendConsoleMessage(Level.INFO, "Saving account table"); array = new JSONArray(); statement = connection.prepareStatement("SELECT * FROM " + tablePrefix + "account"); set = statement.executeQuery(); while (set.next()) { JSONObject entry = new JSONObject(); entry.put("name", set.getString("name")); entry.put("infiniteMoney", set.getBoolean("infiniteMoney")); entry.put("ignoreACL", set.getBoolean("ignoreACL")); entry.put("uuid", set.getString("uuid")); JSONArray balanceArray = new JSONArray(); PreparedStatement internalStatement = connection.prepareStatement("SELECT * FROM " + tablePrefix + "balance WHERE username_id=?"); internalStatement.setInt(1, set.getInt("id")); ResultSet internalSet = internalStatement.executeQuery(); while (internalSet.next()) { JSONObject object = new JSONObject(); object.put("currency_id", internalSet.getInt("currency_id")); object.put("worldName", internalSet.getString("worldName")); object.put("balance", internalSet.getDouble("balance")); balanceArray.add(object); } internalStatement.close(); entry.put("balances", balanceArray); internalStatement = connection.prepareStatement("SELECT * FROM " + tablePrefix +"log WHERE username_id=?"); internalStatement.setInt(1, set.getInt("id")); internalSet = internalStatement.executeQuery(); JSONArray logArray = new JSONArray(); while(internalSet.next()) { JSONObject object = new JSONObject(); object.put("type", getObject(internalSet.getBlob("type" )).toString()); object.put("cause", getObject(internalSet.getBlob("cause")).toString()); object.put("timestamp", internalSet.getTimestamp("timestamp").getTime()); object.put("causeReason", internalSet.getString("causeReason")); object.put("currencyName", internalSet.getString("currencyName")); object.put("worldName", internalSet.getString("worldName")); object.put("amount", internalSet.getDouble("amount")); logArray.add(object); } internalStatement.close(); entry.put("logs", logArray); internalStatement = connection.prepareStatement("SELECT * FROM " + tablePrefix +"acl WHERE account_id=?"); internalStatement.setInt(1, set.getInt("id")); internalSet = internalStatement.executeQuery(); JSONArray aclArray = new JSONArray(); while(internalSet.next()) { JSONObject object = new JSONObject(); object.put("playerName", internalSet.getString("playerName")); object.put("deposit", internalSet.getBoolean("deposit")); object.put("withdraw", internalSet.getBoolean("withdraw")); object.put("acl", internalSet.getBoolean("acl")); object.put("balance", internalSet.getBoolean("balance")); object.put("owner", internalSet.getBoolean("owner")); aclArray.add(object); } internalStatement.close(); entry.put("acls", aclArray); array.add(entry); } statement.close(); mainObject.put("accounts", array); Common.getInstance().sendConsoleMessage(Level.INFO, "Writing json file"); FileWriter writer = new FileWriter(accountFile); writer.write(mainObject.toJSONString()); writer.flush(); writer.close(); Common.getInstance().sendConsoleMessage(Level.INFO, "File written! Dropping all tables"); //The backup is now saved. Let's drop everything statement = connection.prepareStatement("DROP TABLE " + tablePrefix + "config"); statement.execute(); statement.close(); statement = connection.prepareStatement("DROP TABLE " + tablePrefix + "acl"); statement.execute(); statement.close(); statement = connection.prepareStatement("DROP TABLE " + tablePrefix + "balance"); statement.execute(); statement.close(); statement = connection.prepareStatement("DROP TABLE " + tablePrefix + "log"); statement.execute(); statement.close(); statement = connection.prepareStatement("DROP TABLE " + tablePrefix + "worldgroup"); statement.execute(); statement.close(); statement = connection.prepareStatement("DROP TABLE " + tablePrefix + "exchange"); statement.execute(); statement.close(); statement = connection.prepareStatement("DROP TABLE " + tablePrefix + "account"); statement.execute(); statement.close(); statement = connection.prepareStatement("DROP TABLE " + tablePrefix + "currency"); statement.execute(); statement.close(); statement = connection.prepareStatement("DROP TABLE " + tablePrefix + "payday"); statement.execute(); statement.close(); connection.close(); step2(); } public void step2() throws SQLException, IOException, ParseException { Common.getInstance().sendConsoleMessage(Level.INFO, "Converting step 2: Inserting the data back in all the new tables"); Common.getInstance().sendConsoleMessage(Level.INFO, "Creating the new tables"); String dbType = Common.getInstance().getMainConfig().getString("System.Database.Type"); if (dbType.equals("sqlite")) { Common.getInstance().sendConsoleMessage(Level.INFO, "You are using SQLite! This is now deprecated. Selecting H2 instead."); Common.getInstance().getMainConfig().setValue("System.Database.Type", "h2"); dbType = "h2"; } StorageEngine engine = null; HikariConfig config = new HikariConfig(); if (dbType.equalsIgnoreCase("mysql")) { engine = new MySQLEngine(); } else if (dbType.equalsIgnoreCase("h2")) { engine = new H2Engine(); } else { throw new UnsupportedOperationException("Unknown database!"); } engine.disableAutoCommit(); Common.getInstance().sendConsoleMessage(Level.INFO, "Loading backup json file"); File accountFile = new File(Common.getInstance().getServerCaller().getDataFolder(), "accounts.json"); System.out.println(accountFile.exists()); JSONObject jsonObject = (JSONObject) new JSONParser().parse(new FileReader(accountFile)); Map<Integer, String> currenciesMap = new HashMap<>(); Common.getInstance().sendConsoleMessage(Level.INFO,"Saving currencies"); //Create the currency table JSONArray currencyArray = (JSONArray) jsonObject.get("currencies"); Iterator<JSONObject> iterator = currencyArray.iterator(); while (iterator.hasNext()) { JSONObject obj = iterator.next(); currenciesMap.put(((Long) obj.get("id")).intValue(), (String)obj.get("name")); Currency currency = new Currency((String)obj.get("name"), (String)obj.get("plural"), (String)obj.get("minor"), (String)obj.get("minorPlural"), (String)obj.get("sign")); try { Class clazz = currency.getClass(); Method setDefault = clazz.getDeclaredMethod("setDefault", boolean.class); setDefault.setAccessible(true); setDefault.invoke(currency, (boolean) obj.get("status")); } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); } engine.saveCurrency("", currency); } Common.getInstance().sendConsoleMessage(Level.INFO, "Saving world groups..."); JSONArray worldgroup = (JSONArray) jsonObject.get("worldgroups"); iterator = worldgroup.iterator(); while (iterator.hasNext()) { JSONObject obj = iterator.next(); engine.saveWorldGroup((String)obj.get("groupName"), (String)obj.get("worldList")); } Common.getInstance().sendConsoleMessage(Level.INFO, "Saving Exchange rates"); JSONArray exchangeArray = (JSONArray) jsonObject.get("exchanges"); iterator = exchangeArray.iterator(); while (iterator.hasNext()) { JSONObject obj = iterator.next(); int id_from = ((Long) obj.get("from_currency_id")).intValue(); int id_to = ((Long) obj.get("to_currency_id")).intValue(); engine.setExchangeRate(engine.getCurrency(currenciesMap.get(id_from)), engine.getCurrency(currenciesMap.get(id_to)), (double)obj.get("amount")); } Common.getInstance().sendConsoleMessage(Level.INFO, "Saving configs"); JSONArray configArray = (JSONArray) jsonObject.get("configs"); iterator = configArray.iterator(); while (iterator.hasNext()) { JSONObject obj = iterator.next(); if (!obj.get("name").equals("dbVersion")) { engine.setConfigEntry((String)obj.get("name"), (String)obj.get("value")); } } Common.getInstance().sendConsoleMessage(Level.INFO, "Saving accounts. This may take a long time."); boolean log = false; if (Common.getInstance().getMainConfig().getBoolean("System.Logging.Enabled")) { Common.getInstance().getMainConfig().setValue("System.Logging.Enabled", false); log = true; } JSONArray accounts = (JSONArray) jsonObject.get("accounts"); iterator = accounts.iterator(); while (iterator.hasNext()) { JSONObject obj = iterator.next(); String name = (String) obj.get("name"); Account account = null; if (name.startsWith("bank:")) { account = engine.getAccount(name.split(":")[1], true, false); } else { account = engine.getAccount(name, false, false); } engine.setIgnoreACL(account, (Boolean) obj.get("ignoreACL")); engine.setInfiniteMoney(account, (Boolean) obj.get("infiniteMoney")); if (obj.get("uuid") != null) { engine.updateUUID(account.getAccountName(), UUID.fromString((String) obj.get("uuid"))); } JSONArray balances = (JSONArray) obj.get("balances"); Iterator<JSONObject> internalIterator = balances.iterator(); while (internalIterator.hasNext()) { JSONObject internalObj = internalIterator.next(); Currency currency = engine.getCurrency(currenciesMap.get(((Long) internalObj.get("currency_id")).intValue())); if (currency != null) { engine.setBalance(account, (double)internalObj.get("balance"), currency, (String)internalObj.get("worldName")); } } JSONArray logs = (JSONArray) obj.get("logs"); internalIterator = logs.iterator(); while (internalIterator.hasNext()) { JSONObject internalObj = internalIterator.next(); engine.saveLog(LogInfo.valueOf((String) internalObj.get("type")), Cause.valueOf((String) internalObj.get("cause")),(String)internalObj.get("causeReason"),account, (double)internalObj.get("amount"),engine.getCurrency((String) internalObj.get("currencyName")),(String)internalObj.get("worldName"), new Timestamp((long)internalObj.get("timestamp"))); } JSONArray acls = (JSONArray) obj.get("acls"); internalIterator = acls.iterator(); while (internalIterator.hasNext()) { JSONObject internalObj = internalIterator.next(); engine.saveACL(account, (String)internalObj.get("playerName"), (boolean)internalObj.get("deposit"), (boolean)internalObj.get("withdraw"), (boolean) internalObj.get("acl"), (boolean) internalObj.get("balance"), (boolean) internalObj.get("owner")); } } engine.commit(); engine.enableAutoCommit(); if (log) { Common.getInstance().getMainConfig().setValue("System.Logging.Enabled", true); } Common.getInstance().sendConsoleMessage(Level.INFO, "Converting done!"); } private Object getObject(Blob blob) throws SQLException { try { ObjectInputStream is = null; is = new ObjectInputStream(blob.getBinaryStream()); Object o = null; try { return is.readObject(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { try { is.close(); } catch (Exception ignored) { } } } catch ( IOException e ) { e.printStackTrace(); } return null; } }