From 0f0ac2ab641ebbe6d74e6a8630baff1cff1c75a7 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Thu, 7 Jun 2018 10:44:10 +0200 Subject: [PATCH] Allow RS loading classes to be used with Guice - Provide OkHttpClient through Guice instead of using it from static variable - Chain the RS classes with Guice and inject ClientLoader to RuneLite class - Cleanup RS loading classes a bit Signed-off-by: Tomas Slusny --- .../java/net/runelite/client/RuneLite.java | 6 +- .../net/runelite/client/RuneLiteModule.java | 3 + .../client/rs/ClientConfigLoader.java | 85 ++++++-------- .../net/runelite/client/rs/ClientLoader.java | 106 +++++++++--------- .../rs/{RSStub.java => RSAppletStub.java} | 21 ++-- .../java/net/runelite/client/rs/RSConfig.java | 52 +++++++++ .../client/rs/ClientConfigLoaderTest.java | 18 +-- 7 files changed, 166 insertions(+), 125 deletions(-) rename runelite-client/src/main/java/net/runelite/client/rs/{RSStub.java => RSAppletStub.java} (87%) create mode 100644 runelite-client/src/main/java/net/runelite/client/rs/RSConfig.java diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLite.java b/runelite-client/src/main/java/net/runelite/client/RuneLite.java index 569b4661a1..5e215be011 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -130,6 +130,9 @@ public class RuneLite @Inject private InfoBoxManager infoBoxManager; + @Inject + private ClientLoader clientLoader; + @Inject private OverlayManager overlayManager; @@ -212,7 +215,8 @@ public class RuneLite public void start(ClientUpdateCheckMode updateMode) throws Exception { // Load RuneLite or Vanilla client - final Applet client = new ClientLoader().loadRs(updateMode); + clientLoader.setUpdateCheckMode(updateMode); + final Applet client = clientLoader.load(); final boolean isOutdated = !(client instanceof Client); diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java b/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java index 79ed0173d2..0960183ec4 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java @@ -49,6 +49,8 @@ import net.runelite.client.util.DeferredEventBus; import net.runelite.client.util.QueryRunner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import net.runelite.http.api.RuneLiteAPI; +import okhttp3.OkHttpClient; @Slf4j public class RuneLiteModule extends AbstractModule @@ -57,6 +59,7 @@ public class RuneLiteModule extends AbstractModule protected void configure() { bind(ScheduledExecutorService.class).toInstance(Executors.newSingleThreadScheduledExecutor()); + bind(OkHttpClient.class).toInstance(RuneLiteAPI.CLIENT); bind(QueryRunner.class); bind(MenuManager.class); bind(ChatMessageManager.class); diff --git a/runelite-client/src/main/java/net/runelite/client/rs/ClientConfigLoader.java b/runelite-client/src/main/java/net/runelite/client/rs/ClientConfigLoader.java index aa5b6a7d2f..9d3804ebab 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/ClientConfigLoader.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/ClientConfigLoader.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2017, Adam + * Copyright (c) 2018, Tomas Slusny * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,35 +25,39 @@ */ package net.runelite.client.rs; +import com.google.common.annotations.VisibleForTesting; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; -import java.util.HashMap; -import java.util.Map; -import net.runelite.http.api.RuneLiteAPI; -import okhttp3.HttpUrl; +import javax.inject.Inject; +import javax.inject.Singleton; +import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; -public class ClientConfigLoader +@Singleton +class ClientConfigLoader { - private static final HttpUrl CONFIG_URL = HttpUrl.parse("http://oldschool.runescape.com/jav_config.ws"); // https redirects us to rs3 + private static final String CONFIG_URL = "http://oldschool.runescape.com/jav_config.ws"; + private final OkHttpClient httpClient; - public static final String CODEBASE = "codebase"; - public static final String INITIAL_JAR = "initial_jar"; - public static final String INITIAL_CLASS = "initial_class"; - - private final Map properties = new HashMap<>(), - appletProperties = new HashMap<>(); - - public void fetch() throws IOException + @Inject + @VisibleForTesting + ClientConfigLoader(final OkHttpClient httpClient) { - Request request = new Request.Builder() + this.httpClient = httpClient; + } + + RSConfig fetch() throws IOException + { + final Request request = new Request.Builder() .url(CONFIG_URL) .build(); - try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute(); - BufferedReader in = new BufferedReader(new InputStreamReader(response.body().byteStream()))) + final RSConfig config = new RSConfig(); + + try (final Response response = httpClient.newCall(request).execute(); final BufferedReader in = new BufferedReader( + new InputStreamReader(response.body().byteStream()))) { String str; @@ -67,43 +72,25 @@ public class ClientConfigLoader String s = str.substring(0, idx); - if (s.equals("param")) + switch (s) { - str = str.substring(idx + 1); - idx = str.indexOf('='); - s = str.substring(0, idx); + case "param": + str = str.substring(idx + 1); + idx = str.indexOf('='); + s = str.substring(0, idx); - appletProperties.put(s, str.substring(idx + 1)); - } - else if (s.equals("msg")) - { - // ignore - } - else - { - properties.put(s, str.substring(idx + 1)); + config.getAppletProperties().put(s, str.substring(idx + 1)); + break; + case "msg": + // ignore + break; + default: + config.getClassLoaderProperties().put(s, str.substring(idx + 1)); + break; } } } - } - public String getProperty(String name) - { - return properties.get(name); - } - - public Map getProperties() - { - return properties; - } - - public String getAppletProperty(String name) - { - return appletProperties.get(name); - } - - public Map getAppletProperties() - { - return appletProperties; + return config; } } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java b/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java index 34125a8aca..066a1a733f 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2017, Adam + * Copyright (c) 2018, Tomas Slusny * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,31 +29,70 @@ import java.applet.Applet; import java.io.IOException; import java.net.URL; import java.net.URLClassLoader; +import javax.inject.Inject; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import net.runelite.http.api.updatecheck.UpdateCheckClient; @Slf4j public class ClientLoader { - public Applet loadRs(ClientUpdateCheckMode updateMode) - { - if (updateMode == ClientUpdateCheckMode.AUTO) - { - final UpdateCheckClient updateCheck = new UpdateCheckClient(); - updateMode = updateCheck.isOutdated() ? - ClientUpdateCheckMode.VANILLA : - ClientUpdateCheckMode.RUNELITE; - } + private final UpdateCheckClient updateCheckClient = new UpdateCheckClient(); + private final ClientConfigLoader clientConfigLoader; + @Setter + private ClientUpdateCheckMode updateCheckMode = ClientUpdateCheckMode.AUTO; + + @Inject + private ClientLoader(final ClientConfigLoader clientConfigLoader) + { + this.clientConfigLoader = clientConfigLoader; + } + + private static Applet loadRuneLite(final RSConfig config) throws ClassNotFoundException, InstantiationException, IllegalAccessException + { + // the injected client is a runtime scoped dependency + final Class clientClass = ClientLoader.class.getClassLoader().loadClass(config.getInitialClass()); + return loadFromClass(config, clientClass); + } + + private static Applet loadVanilla(final RSConfig config) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException + { + final String codebase = config.getCodeBase(); + final String initialJar = config.getInitialJar(); + final String initialClass = config.getInitialClass(); + final URL url = new URL(codebase + initialJar); + + // Must set parent classloader to null, or it will pull from + // this class's classloader first + final URLClassLoader classloader = new URLClassLoader(new URL[]{url}, null); + final Class clientClass = classloader.loadClass(initialClass); + return loadFromClass(config, clientClass); + } + + private static Applet loadFromClass(final RSConfig config, final Class clientClass) throws IllegalAccessException, InstantiationException + { + final Applet rs = (Applet) clientClass.newInstance(); + rs.setStub(new RSAppletStub(config)); + return rs; + } + + public Applet load() + { try { + final RSConfig config = clientConfigLoader.fetch(); + final ClientUpdateCheckMode updateMode = updateCheckMode == ClientUpdateCheckMode.AUTO + ? updateCheckClient.isOutdated() ? ClientUpdateCheckMode.VANILLA : ClientUpdateCheckMode.RUNELITE + : updateCheckMode; + switch (updateMode) { case RUNELITE: - return loadRuneLite(); + return loadRuneLite(config); default: case VANILLA: - return loadVanilla(); + return loadVanilla(config); case NONE: return null; } @@ -71,48 +111,4 @@ public class ClientLoader return null; } } - - private Applet loadRuneLite() throws ClassNotFoundException, IOException, InstantiationException, IllegalAccessException - { - ClientConfigLoader config = new ClientConfigLoader(); - - config.fetch(); - - String initialClass = config.getProperty(ClientConfigLoader.INITIAL_CLASS).replace(".class", ""); - - // the injected client is a runtime scoped dependency - Class clientClass = this.getClass().getClassLoader().loadClass(initialClass); - Applet rs = (Applet) clientClass.newInstance(); - - rs.setStub(new RSStub(config)); - - return rs; - } - - private Applet loadVanilla() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException - { - ClientConfigLoader config = new ClientConfigLoader(); - - config.fetch(); - - String codebase = config.getProperty(ClientConfigLoader.CODEBASE); - String initialJar = config.getProperty(ClientConfigLoader.INITIAL_JAR); - String initialClass = config.getProperty(ClientConfigLoader.INITIAL_CLASS).replace(".class", ""); - - URL url = new URL(codebase + initialJar); - - // Must set parent classloader to null, or it will pull from - // this class's classloader first - URLClassLoader classloader = new URLClassLoader(new URL[] - { - url - }, null); - - Class clientClass = classloader.loadClass(initialClass); - Applet rs = (Applet) clientClass.newInstance(); - - rs.setStub(new RSStub(config)); - - return rs; - } } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/RSStub.java b/runelite-client/src/main/java/net/runelite/client/rs/RSAppletStub.java similarity index 87% rename from runelite-client/src/main/java/net/runelite/client/rs/RSStub.java rename to runelite-client/src/main/java/net/runelite/client/rs/RSAppletStub.java index 06076879a3..a3a2a0f14a 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/RSStub.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/RSAppletStub.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2017, Adam + * Copyright (c) 2018, Tomas Slusny * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -22,22 +23,18 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - package net.runelite.client.rs; import java.applet.AppletContext; import java.applet.AppletStub; import java.net.MalformedURLException; import java.net.URL; +import lombok.RequiredArgsConstructor; -public class RSStub implements AppletStub +@RequiredArgsConstructor +class RSAppletStub implements AppletStub { - private final ClientConfigLoader config; - - public RSStub(ClientConfigLoader config) - { - this.config = config; - } + private final RSConfig config; @Override public boolean isActive() @@ -56,7 +53,7 @@ public class RSStub implements AppletStub { try { - return new URL(config.getProperty(ClientConfigLoader.CODEBASE)); + return new URL(config.getCodeBase()); } catch (MalformedURLException ex) { @@ -67,7 +64,7 @@ public class RSStub implements AppletStub @Override public String getParameter(String name) { - return config.getAppletProperty(name); + return config.getAppletProperties().get(name); } @Override @@ -79,7 +76,5 @@ public class RSStub implements AppletStub @Override public void appletResize(int width, int height) { - } - -} +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/rs/RSConfig.java b/runelite-client/src/main/java/net/runelite/client/rs/RSConfig.java new file mode 100644 index 0000000000..e0c5539323 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/rs/RSConfig.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016-2017, Adam + * Copyright (c) 2018, Tomas Slusny + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.rs; + +import java.util.HashMap; +import java.util.Map; +import lombok.Getter; + +@Getter +class RSConfig +{ + private final Map appletProperties = new HashMap<>(); + private final Map classLoaderProperties = new HashMap<>(); + + String getCodeBase() + { + return classLoaderProperties.get("codebase"); + } + + String getInitialJar() + { + return classLoaderProperties.get("initial_jar"); + } + + String getInitialClass() + { + return classLoaderProperties.get("initial_class").replace(".class", ""); + } +} diff --git a/runelite-client/src/test/java/net/runelite/client/rs/ClientConfigLoaderTest.java b/runelite-client/src/test/java/net/runelite/client/rs/ClientConfigLoaderTest.java index f602822d40..719998d407 100644 --- a/runelite-client/src/test/java/net/runelite/client/rs/ClientConfigLoaderTest.java +++ b/runelite-client/src/test/java/net/runelite/client/rs/ClientConfigLoaderTest.java @@ -26,7 +26,7 @@ package net.runelite.client.rs; import java.io.IOException; -import net.runelite.client.rs.ClientConfigLoader; +import okhttp3.OkHttpClient; import org.junit.Test; /** @@ -38,16 +38,20 @@ public class ClientConfigLoaderTest @Test public void test() throws IOException { - ClientConfigLoader loader = new ClientConfigLoader(); - loader.fetch(); + final ClientConfigLoader loader = new ClientConfigLoader(new OkHttpClient()); + final RSConfig config = loader.fetch(); - for (String key : loader.getProperties().keySet()) - System.out.println(key + ": " + loader.getProperty(key)); + for (String key : config.getClassLoaderProperties().keySet()) + { + System.out.println(key + ": " + config.getClassLoaderProperties().get(key)); + } System.out.println("Applet properties:"); - for (String key : loader.getAppletProperties().keySet()) - System.out.println(key + ": " + loader.getAppletProperty(key)); + for (String key : config.getAppletProperties().keySet()) + { + System.out.println(key + ": " + config.getAppletProperties().get(key)); + } } }