public Connection getConnection() { try { if (sqlite) { // To avoid concurrency problem with SQLite, we will just use one connection. Cf : // constructor above for SQLite synchronized (SQLiteConn) { SQLiteConn = DriverManager.getConnection( "jdbc:sqlite:" + BAT.getInstance().getDataFolder().getAbsolutePath() + File.separator + "bat_database.db"); return SQLiteConn; } } return ds.getConnection(); } catch (final SQLException e) { BAT.getInstance() .getLogger() .severe( "BAT can't etablish connection with the database. Please report this and include the following lines :"); if (e.getCause() instanceof CommunicationsException) { BAT.getInstance().getLogger().severe(e.getCause().getMessage()); } if (BAT.getInstance().getConfiguration().isDebugMode()) { e.printStackTrace(); } return null; } }
/** Constructor used for SQLite */ public DataSourceHandler() { /* * As SQLite supports concurrency pretty badly (locked database which causes problem), we're gonna get a connection from the DriverManager each time * we need to acces to the database. In the contrary of BoneCP with mysql in which we saved connection to optimize perfomance, it's not necessary with SQLite. * FYI, here are the results of test : execute 1000 insert request using SQLite, with or without using the same connection : * - Using the same connection it took : 22820 ms * - Getting another connection each time (DriverManager.getConnection), it took : 24186 ms * The difference is only 1366 ms for 1000 request, that means on average additional 1.3 ms, which is insignificant as we are executing almost every query async. * To the people who read that, all these calculations can seem a little overrated, but I really like to improve perfomance at the most and I'm pretty curious :p */ sqlite = true; try { SQLiteConn = DriverManager.getConnection( "jdbc:sqlite:" + BAT.getInstance().getDataFolder().getAbsolutePath() + File.separator + "bat_database.db"); SQLiteConn.close(); } catch (SQLException e) { BAT.getInstance() .getLogger() .severe( "BAT encounters a problem during the initialization of the sqlite database connection."); if (e.getMessage() != null) { BAT.getInstance().getLogger().severe("Error message : " + e.getMessage()); } } }
@Override public void onCommand(CommandSender sender, String[] args, boolean confirmedCmd) throws IllegalArgumentException { final ProxiedPlayer target = ProxyServer.getInstance().getPlayer(args[0]); final String reason = Utils.getFinalArg(args, 1); if(target == null){ if(!confirmedCmd && Core.getPlayerIP(args[0]).equals("0.0.0.0")){ mustConfirmCommand(sender, getName() + " " + Joiner.on(' ').join(args), _("operationUnknownPlayer", new String[] {args[0]})); return; } } if(sender instanceof ProxiedPlayer){ checkArgument(PermissionManager.canExecuteAction(Action.WARN , sender, ((ProxiedPlayer)sender).getServer().getInfo().getName()), _("noPerm")); } checkArgument(comment.hasLastcommentCooledDown(args[0]), _("cooldownUnfinished")); comment.insertComment(args[0], reason, Type.WARNING, sender.getName()); if(target != null){ target.sendMessage(__("wasWarnedNotif", new String[] {reason})); } BAT.broadcast(_("warnBroadcast", new String[]{args[0], sender.getName(), reason}), Action.WARN_BROADCAST.getPermission()); return; }
// Useful methods public static String handleException(final SQLException e) { BAT.getInstance() .getLogger() .severe( "BAT encounters a problem with the database. Please report this and include the following lines :"); e.printStackTrace(); return "An error related to the database occured. Please check the log."; }
/** * Constructor used for MySQL * * @param host * @param port * @param database * @param username * @param password * @throws SQLException */ public DataSourceHandler( final String host, final String port, final String database, final String username, final String password) throws SQLException { // Check database's informations and init connection this.host = Preconditions.checkNotNull(host); this.port = Preconditions.checkNotNull(port); this.database = Preconditions.checkNotNull(database); this.username = Preconditions.checkNotNull(username); this.password = Preconditions.checkNotNull(password); BAT.getInstance().getLogger().config("Initialization of HikariCP in progress ..."); BasicConfigurator.configure(new NullAppender()); ds = new HikariDataSource(); ds.setJdbcUrl( "jdbc:mysql://" + this.host + ":" + this.port + "/" + this.database + "?useLegacyDatetimeCode=false&serverTimezone=" + TimeZone.getDefault().getID()); ds.setUsername(this.username); ds.setPassword(this.password); ds.addDataSourceProperty("cachePrepStmts", "true"); ds.setMaximumPoolSize(8); try { final Connection conn = ds.getConnection(); int intOffset = Calendar.getInstance().getTimeZone().getOffset(Calendar.getInstance().getTimeInMillis()) / 1000; String offset = String.format("%02d:%02d", Math.abs(intOffset / 3600), Math.abs((intOffset / 60) % 60)); offset = (intOffset >= 0 ? "+" : "-") + offset; conn.createStatement().executeQuery("SET time_zone='" + offset + "';"); conn.close(); BAT.getInstance().getLogger().config("BoneCP is loaded !"); } catch (final SQLException e) { BAT.getInstance() .getLogger() .severe( "BAT encounters a problem during the initialization of the database connection." + " Please check your logins and database configuration."); if (e.getCause() instanceof CommunicationsException) { BAT.getInstance().getLogger().severe(e.getCause().getMessage()); } if (BAT.getInstance().getConfiguration().isDebugMode()) { BAT.getInstance().getLogger().log(Level.SEVERE, e.getMessage(), e); } throw e; } sqlite = false; }
/** Starts a new async task and pump the inputstream */ public void pump() { ProxyServer.getInstance() .getScheduler() .runAsync( BAT.getInstance(), new Runnable() { @Override public void run() { try { pumpedLines = CharStreams.readLines(reader); reader.close(); } catch (final IOException e) { BAT.getInstance() .getLogger() .severe( "BAT encounter an error while reading the stream of subprocess. Please report this :"); e.printStackTrace(); } } }); }
@Override public void onCommand(final CommandSender sender, final String[] args, final boolean confirmedCmd) throws IllegalArgumentException { if (args[0].equals("help")) { try { FormatUtils.showFormattedHelp(BAT.getInstance().getModules().getModule("comment").getCommands(), sender, "COMMENT"); } catch (final InvalidModuleException e) { e.printStackTrace(); } return; } if(args.length < 2){ throw new IllegalArgumentException(); } if(!confirmedCmd && Core.getPlayerIP(args[0]).equals("0.0.0.0")){ mustConfirmCommand(sender, "bat " + getName() + " " + Joiner.on(' ').join(args), _("operationUnknownPlayer", new String[] {args[0]})); return; } checkArgument(comment.hasLastcommentCooledDown(args[0]), _("cooldownUnfinished")); comment.insertComment(args[0], Utils.getFinalArg(args, 1), Type.NOTE, sender.getName()); sender.sendMessage(__("commentAdded")); }
@Override public void onCommand(final CommandSender sender, final String[] args, final boolean confirmedCmd) throws IllegalArgumentException { sender.sendMessage(BAT.__(comment.clearComments(args[0], ((args.length == 2) ? Integer.parseInt(args[1]) : -1) ))); }
/** * Generate a backup of the BAT data in mysql database. * * @param path * @param onComplete * @throws RuntimeException if MySQL is not used or if the creation of the backup file failed */ public void generateMysqlBackup(final Callback<String> onComplete) throws RuntimeException { ProxyServer.getInstance() .getScheduler() .runAsync( BAT.getInstance(), new Runnable() { @Override public void run() { try { Process testProcess = Runtime.getRuntime().exec("mysqldump --help"); new StreamPumper(testProcess.getErrorStream()).pump(); new StreamPumper(testProcess.getInputStream()).pump(); int returnValue = testProcess.waitFor(); if (returnValue != 0) { throw new Exception(); } } catch (final Exception e) { onComplete.done( "The backup can't be achieved because mysqldump is nowhere to be found.", null); return; } final File backupDirectory = new File( BAT.getInstance().getDataFolder().getAbsolutePath() + File.separator + "databaseBackups"); backupDirectory.mkdir(); File backupFile = new File( backupDirectory.getAbsolutePath() + File.separator + "backup" + new SimpleDateFormat("dd-MMM-yyyy_HH'h'mm") .format(Calendar.getInstance().getTime()) + ".sql"); for (int i = 0; ; i++) { if (!backupFile.exists()) { break; } else { if (i == 0) { backupFile = new File(backupFile.getAbsolutePath().replace(".sql", "#" + i + ".sql")); } else { backupFile = new File( backupFile .getAbsolutePath() .replaceAll("#\\d+\\.sql$", "#" + i + ".sql")); } } } String backupCmd = "mysqldump -u {user} -p --add-drop-database -r {path} {database} {tables}"; final String tables = Joiner.on(' ') .join( Arrays.asList( SQLQueries.Ban.table, SQLQueries.Mute.table, SQLQueries.Watch.table, SQLQueries.Kick.table, SQLQueries.Comments.table, SQLQueries.Core.table)); String backupPath = backupFile.getAbsolutePath(); if (backupPath.contains(" ")) { backupPath = "\"" + backupPath + "\""; } backupCmd = backupCmd .replace("{user}", username) .replace("{database}", database) .replace("{path}", backupPath) .replace("{tables}", tables); if (password.equals("")) { backupCmd = backupCmd.replace("-p", ""); } else { backupCmd = backupCmd.replace("-p", "--password="******"\\") ? "\\\\" : File.separator)); final String fileName = splittedPath[splittedPath.length - 1]; onComplete.done( format("The backup file (%s) has been sucessfully generated.", fileName), null); } else { onComplete.done( "An error happens during the creation of the mysql backup. Please check the logs", null); BAT.getInstance() .getLogger() .severe( "An error happens during the creation of the mysql backup. Please report :"); for (final String message : errorPumper.getLines()) { BAT.getInstance().getLogger().severe(message); } } } catch (final Exception e) { onComplete.done("An error happens during the creation of the mysql backup.", e); e.printStackTrace(); } } }); }