package io.github.lucaseasedup.logit; import io.github.lucaseasedup.logit.command.DisabledCommandExecutor; import io.github.lucaseasedup.logit.command.LogItCommand; import io.github.lucaseasedup.logit.command.NopCommandExecutor; import io.github.lucaseasedup.logit.common.FatalReportedException; import io.github.lucaseasedup.logit.config.LocationSerializable; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.Arrays; import java.util.PropertyResourceBundle; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.logging.Level; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.configuration.serialization.ConfigurationSerialization; import org.bukkit.plugin.java.JavaPlugin; import org.mcstats.MetricsLite; public final class LogItPlugin extends JavaPlugin { /** * Internal method. Do not call directly. */ @Override public void onEnable() { try { MetricsLite metrics = new MetricsLite(this); metrics.start(); } catch (IOException ex) { } try { // Load default messages. loadMessages(getConfig().getString("locale", "en")); } catch (IOException ex) { // If messages could not be loaded, just log the failure. // They're not necessary for LogIt to work. getLogger().log(Level.WARNING, "Could not load messages.", ex); } try { loadLibraries(); } catch (FatalReportedException ex) { disable(); } getCommand("logit") .setExecutor(new LogItCommand()); getCommand("$logit-nop-command") .setExecutor(new NopCommandExecutor()); core = LogItCore.getInstance(); try { core.start(); } catch (FatalReportedException ex) { if (getConfig().getBoolean("terminateUnsafeServer", true)) { Bukkit.getServer().shutdown(); } else { disable(); } } } /** * Internal method. Do not call directly. */ @Override public void onDisable() { if (core != null) { if (core.isStarted()) { core.stop(); } core = null; } getCommand("logit") .setExecutor(new DisabledCommandExecutor()); getCommand("$logit-nop-command") .setExecutor(new DisabledCommandExecutor()); packageLocalMessages = null; userGlobalMessages = null; userLocalMessages = null; } private void enable() { getServer().getPluginManager().enablePlugin(this); } private void disable() { Bukkit.getConsoleSender().sendMessage(getMessage("pluginStopping")); getServer().getPluginManager().disablePlugin(this); } /** * Loads message files. * * <p> This method will also try to load user * global/local message files from the <i>lang</i> directory if present, * that will be transparently merged with built-in message files. * * @param suffix the locale suffix. * * @throws IOException if there was an error while reading. */ public void loadMessages(String suffix) throws IOException { if (suffix == null) throw new IllegalArgumentException(); loadPackageLocalMessages("messages_" + suffix + ".properties"); loadUserGlobalMessages("lang/messages.properties"); loadUserLocalMessages("lang/messages_" + suffix + ".properties"); } private void loadPackageLocalMessages(String entryName) throws IOException { packageLocalMessages = null; try (JarFile jarFile = new JarFile(getFile())) { JarEntry jarEntry = jarFile.getJarEntry(entryName); if (jarEntry != null) { InputStream inputStream = jarFile.getInputStream(jarEntry); try (Reader reader = new InputStreamReader(inputStream, "UTF-8")) { packageLocalMessages = new PropertyResourceBundle(reader); } } } } private void loadUserGlobalMessages(String path) throws IOException { if (path == null) throw new IllegalArgumentException(); userGlobalMessages = null; File file = new File(getDataFolder(), path); if (!file.isFile()) return; try (InputStream is = new FileInputStream(file)) { userGlobalMessages = new PropertyResourceBundle(is); } } private void loadUserLocalMessages(String path) throws IOException { if (path == null) throw new IllegalArgumentException(); userLocalMessages = null; File file = new File(getDataFolder(), path); if (!file.isFile()) return; try (InputStream is = new FileInputStream(file)) { userLocalMessages = new PropertyResourceBundle(is); } } public static String getMessage(String label) { if (label == null) throw new IllegalArgumentException(); if (getInstance() == null) return label; String message = null; try { if (getInstance().packageLocalMessages != null && getInstance().packageLocalMessages.containsKey(label)) { message = getInstance().packageLocalMessages.getString(label); } if (getInstance().userGlobalMessages != null && getInstance().userGlobalMessages.containsKey(label)) { message = getInstance().userGlobalMessages.getString(label); } if (getInstance().userLocalMessages != null && getInstance().userLocalMessages.containsKey(label)) { message = getInstance().userLocalMessages.getString(label); } } catch (ClassCastException ex) { } if (message == null) return label; return getInstance().replaceGlobalTokens( ChatColor.translateAlternateColorCodes('&', message) ); } public String replaceGlobalTokens(String message) { if (message == null) throw new IllegalArgumentException(); message = message.replace("%bukkit_version%", Bukkit.getBukkitVersion()); message = message.replace("%logit_version%", LogItPlugin.getInstance().getDescription().getVersion()); message = message.replace("%server_id%", Bukkit.getServerId()); message = message.replace("%server_ip%", Bukkit.getIp()); message = message.replace("%server_motd%", Bukkit.getMotd()); message = message.replace("%server_name%", Bukkit.getServerName()); return message; } public void loadLibraries() throws FatalReportedException { File dir = new File(getDataFolder(), "lib"); if (!dir.isDirectory()) return; File[] files = dir.listFiles(); for (File file : files) { if (!file.isFile()) continue; if (!file.getName().endsWith(".jar")) continue; loadLibrary(file.getName()); } } private void loadLibrary(String filename) throws FatalReportedException { if (isLibraryLoaded(filename)) return; try { File file = new File(getDataFolder(), "lib/" + filename); if (!file.exists()) throw new FileNotFoundException(); URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader(); URL url = file.toURI().toURL(); if (!Arrays.asList(classLoader.getURLs()).contains(url)) { Method addUrlMethod = URLClassLoader.class.getDeclaredMethod( "addURL", new Class[]{URL.class} ); addUrlMethod.setAccessible(true); addUrlMethod.invoke(classLoader, new Object[]{url}); } } catch (FileNotFoundException | MalformedURLException ex) { getLogger().log(Level.SEVERE, "Library " + filename + " was not found"); disable(); FatalReportedException.throwNew(ex); } catch (ReflectiveOperationException ex) { getLogger().log(Level.SEVERE, "Could not load library " + filename, ex); disable(); FatalReportedException.throwNew(ex); } } public boolean isLibraryLoaded(String filename) { File file = new File(getDataFolder(), "lib/" + filename); URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader(); URL url; try { url = file.toURI().toURL(); } catch (MalformedURLException ex) { return false; } return Arrays.asList(classLoader.getURLs()).contains(url); } public static String getCraftBukkitVersion() { String packageName = Bukkit.getServer() .getClass().getPackage().getName(); String[] packageParts = packageName.split("\\."); return packageParts[packageParts.length - 1]; } /* package */ static LogItPlugin getInstance() { if (instance == null) { instance = (LogItPlugin) Bukkit.getPluginManager().getPlugin("LogIt"); } return instance; } static { ConfigurationSerialization.registerClass(LocationSerializable.class); } public static final String PACKAGE = "io.github.lucaseasedup.logit"; private static LogItPlugin instance = null; private PropertyResourceBundle packageLocalMessages; private PropertyResourceBundle userGlobalMessages; private PropertyResourceBundle userLocalMessages; private LogItCore core; }