From 6d3ab146acec60ebfe39734065aa8fa1768525bf Mon Sep 17 00:00:00 2001 From: JKetelaar Date: Sat, 9 Jan 2016 21:30:26 +0100 Subject: [PATCH] [FEATURE] Finished local server loading --- .../parabot/core/desc/ServerProviderInfo.java | 24 +++- .../core/parsers/servers/LocalServers.java | 33 ++++- .../environment/api/utils/FileUtil.java | 23 +++ .../executers/LocalPublicServerExecuter.java | 134 ++++++++++++++++++ 4 files changed, 210 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/parabot/environment/servers/executers/LocalPublicServerExecuter.java diff --git a/src/main/java/org/parabot/core/desc/ServerProviderInfo.java b/src/main/java/org/parabot/core/desc/ServerProviderInfo.java index d6cd609..ba20206 100644 --- a/src/main/java/org/parabot/core/desc/ServerProviderInfo.java +++ b/src/main/java/org/parabot/core/desc/ServerProviderInfo.java @@ -16,6 +16,7 @@ import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.Properties; +import java.util.zip.CRC32; /** * Gets the information for the selected server provider @@ -53,13 +54,32 @@ public class ServerProviderInfo { } } - public ServerProviderInfo(){ + public ServerProviderInfo(String clientJar, String hooks, String name, String clientClass, int bankTabs){ + this.properties = new Properties(); + this.settings = new HashMap<>(); + try { BufferedReader br = WebUtil.getReader(new URL(Configuration.GET_SERVER_SETTINGS)); JSONObject settings = (JSONObject) WebUtil.getJsonParser().parse(br); + parseSettings(settings); } catch (ParseException | IOException e) { e.printStackTrace(); } + + this.properties.setProperty("client_jar", clientJar); + this.properties.setProperty("hooks", hooks); + this.properties.setProperty("name", name); + this.properties.setProperty("client_class", clientClass); + this.properties.setProperty("provider_crc32", String.valueOf(getCRC32(name, "provider"))); + this.properties.setProperty("client_crc32", String.valueOf(getCRC32(name, "client"))); + this.properties.setProperty("bank_tabs", String.valueOf(bankTabs)); + } + + private long getCRC32(String name, String type){ + CRC32 crc = new CRC32(); + name += "-" + type; + crc.update(name.getBytes()); + return crc.getValue(); } private void parseSettings(JSONObject object){ @@ -107,7 +127,7 @@ public class ServerProviderInfo { } public long getCRC32() { - return Long.parseLong(properties.getProperty("provider_crc32")); + return Long.parseLong(properties.getProperty("provider_crc32")); } public long getClientCRC32() { diff --git a/src/main/java/org/parabot/core/parsers/servers/LocalServers.java b/src/main/java/org/parabot/core/parsers/servers/LocalServers.java index 8010046..a1dc8a6 100644 --- a/src/main/java/org/parabot/core/parsers/servers/LocalServers.java +++ b/src/main/java/org/parabot/core/parsers/servers/LocalServers.java @@ -5,22 +5,37 @@ import java.io.FileReader; import java.io.FilenameFilter; import java.io.IOException; import java.lang.reflect.Constructor; +import java.net.URL; import java.util.ArrayList; +import java.util.Collections; +import java.util.Objects; import org.json.simple.JSONObject; import org.json.simple.parser.ParseException; +import org.parabot.core.Configuration; +import org.parabot.core.Context; +import org.parabot.core.Core; import org.parabot.core.Directories; +import org.parabot.core.build.BuildPath; import org.parabot.core.classpath.ClassPath; import org.parabot.core.desc.ServerDescription; +import org.parabot.core.desc.ServerProviderInfo; +import org.parabot.core.ui.components.VerboseLoader; +import org.parabot.core.ui.utils.UILog; import org.parabot.environment.api.utils.WebUtil; import org.parabot.environment.servers.ServerManifest; +import org.parabot.environment.servers.ServerProvider; +import org.parabot.environment.servers.executers.LocalPublicServerExecuter; import org.parabot.environment.servers.executers.LocalServerExecuter; +import org.parabot.environment.servers.executers.PublicServerExecuter; import org.parabot.environment.servers.loader.ServerLoader; +import javax.swing.*; + /** * Parses local server providers located in the servers directory * - * @author Everel + * @author Everel, JKetelaar */ public class LocalServers extends ServerParser { @@ -31,7 +46,7 @@ public class LocalServers extends ServerParser { basePath.parseJarFiles(false); basePath.addClasses(Directories.getServerPath()); - final ArrayList classPaths = new ArrayList(); + final ArrayList classPaths = new ArrayList<>(); classPaths.add(basePath); for (final ClassPath classPath : basePath.getJarFiles()) { classPaths.add(classPath); @@ -75,12 +90,26 @@ public class LocalServers extends ServerParser { try { JSONObject object = (JSONObject) WebUtil.getJsonParser().parse(new FileReader(file)); String name = (String) object.get("name"); + String author = (String) object.get("author"); + double version = (Double) object.get("version"); String clientClass = (String) object.get("client-class"); + Object bank; + int bankTabs = 0; + if ((bank = object.get("bank")) != null){ + bankTabs = (int) bank; + } JSONObject locations = (JSONObject) object.get("locations"); String server = (String) locations.get("server"); + String provider = (String) locations.get("provider"); String hooks = (String) locations.get("hooks"); + ServerProviderInfo serverProviderInfo = new ServerProviderInfo(server, hooks, name, clientClass, bankTabs); + + System.out.println(server); + ServerDescription desc = new ServerDescription(name, + author, version); + SERVER_CACHE.put(desc, new LocalPublicServerExecuter(name, serverProviderInfo, server, provider)); } catch (IOException | ParseException e) { e.printStackTrace(); } diff --git a/src/main/java/org/parabot/environment/api/utils/FileUtil.java b/src/main/java/org/parabot/environment/api/utils/FileUtil.java index 6d0b914..ba7ea9c 100644 --- a/src/main/java/org/parabot/environment/api/utils/FileUtil.java +++ b/src/main/java/org/parabot/environment/api/utils/FileUtil.java @@ -2,7 +2,9 @@ package org.parabot.environment.api.utils; import java.io.File; import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; +import java.nio.channels.FileChannel; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -65,4 +67,25 @@ public class FileUtil { return null; } + + public static void copyFile(File sourceFile, File destFile) + throws IOException { + if (!sourceFile.exists()) { + return; + } + if (!destFile.exists()) { + destFile.createNewFile(); + } + FileChannel source = null; + FileChannel destination = null; + source = new FileInputStream(sourceFile).getChannel(); + destination = new FileOutputStream(destFile).getChannel(); + if (source != null) { + destination.transferFrom(source, 0, source.size()); + } + if (source != null) { + source.close(); + } + destination.close(); + } } diff --git a/src/main/java/org/parabot/environment/servers/executers/LocalPublicServerExecuter.java b/src/main/java/org/parabot/environment/servers/executers/LocalPublicServerExecuter.java new file mode 100644 index 0000000..912745c --- /dev/null +++ b/src/main/java/org/parabot/environment/servers/executers/LocalPublicServerExecuter.java @@ -0,0 +1,134 @@ +package org.parabot.environment.servers.executers; + +import org.parabot.core.Configuration; +import org.parabot.core.Context; +import org.parabot.core.Core; +import org.parabot.core.Directories; +import org.parabot.core.build.BuildPath; +import org.parabot.core.classpath.ClassPath; +import org.parabot.core.desc.ServerProviderInfo; +import org.parabot.core.forum.AccountManager; +import org.parabot.core.forum.AccountManagerAccess; +import org.parabot.core.ui.components.VerboseLoader; +import org.parabot.core.ui.utils.UILog; +import org.parabot.environment.api.utils.FileUtil; +import org.parabot.environment.api.utils.WebUtil; +import org.parabot.environment.servers.ServerProvider; +import org.parabot.environment.servers.loader.ServerLoader; + +import javax.swing.*; +import java.io.File; +import java.lang.reflect.Constructor; +import java.net.URL; + +/** + * + * Fetches a server provider from the local config file + * + * @author JKetelaar + * + */ +public class LocalPublicServerExecuter extends ServerExecuter { + private String serverName; + private String serverUrl; + private String providerUrl; + private ServerProviderInfo serverProviderInfo; + + public LocalPublicServerExecuter(final String serverName, final ServerProviderInfo serverProviderInfo, String serverUrl, String providerUrl) { + this.serverName = serverName; + this.serverUrl = serverUrl; + this.providerUrl = providerUrl; + this.serverProviderInfo = serverProviderInfo; + } + + @Override + public void run() { + try { + final File destination = new File(Directories.getCachePath(), + serverProviderInfo.getCRC32() + ".jar"); + + Core.verbose("Downloading: " + providerUrl + " ..."); + + if(destination.exists()) { + Core.verbose("Found cached server provider [CRC32: " + serverProviderInfo.getCRC32() + "]"); + } else { + File local; + if ((local = new File(providerUrl)).exists()){ + FileUtil.copyFile(local, destination); + Core.verbose("Server provider copied..."); + }else { + WebUtil.downloadFile(new URL(providerUrl), destination, VerboseLoader.get()); + Core.verbose("Server provider downloaded..."); + } + } + + final File clientDestination = new File(Directories.getCachePath(), + serverProviderInfo.getClientCRC32() + ".jar"); + + Core.verbose("Downloading: " + serverUrl + " ..."); + + if(clientDestination.exists()) { + Core.verbose("Found cached client [CRC32: " + serverProviderInfo.getClientCRC32() + "]"); + } else { + File local; + if ((local = new File(serverUrl)).exists()){ + FileUtil.copyFile(local, clientDestination); + Core.verbose("Server client copied..."); + }else { + WebUtil.downloadFile(new URL(serverUrl), clientDestination, VerboseLoader.get()); + Core.verbose("Server client downloaded..."); + } + } + + final ClassPath classPath = new ClassPath(); + classPath.addJar(destination); + + BuildPath.add(destination.toURI().toURL()); + + ServerLoader serverLoader = new ServerLoader(classPath); + final String[] classNames = serverLoader.getServerClassNames(); + if (classNames.length == 0) { + UILog.log( + "Error", + "Failed to load server provider, error: [No provider found in jar file.]", + JOptionPane.ERROR_MESSAGE); + return; + } else if (classNames.length > 1) { + UILog.log( + "Error", + "Failed to load server provider, error: [Multiple providers found in jar file.]"); + return; + } + + final String className = classNames[0]; + try { + final Class providerClass = serverLoader + .loadClass(className); + final Constructor con = providerClass.getConstructor(); + final ServerProvider serverProvider = (ServerProvider) con + .newInstance(); + Context.getInstance(serverProvider).setProviderInfo(serverProviderInfo); + super.finalize(serverProvider, this.serverName); + } catch (NoClassDefFoundError | ClassNotFoundException ignored) { + UILog.log( + "Error", + "Failed to load server provider, error: [This server provider is not compatible with this version of parabot]", + JOptionPane.ERROR_MESSAGE); + } catch (Throwable t) { + t.printStackTrace(); + UILog.log( + "Error", + "Failed to load server provider.", + JOptionPane.ERROR_MESSAGE); + } + + } catch (Exception e) { + e.printStackTrace(); + UILog.log( + "Error", + "Failed to load server provider, post the stacktrace/error on the parabot forums.", + JOptionPane.ERROR_MESSAGE); + } + + } +}