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 <slusnucky@gmail.com>
This commit is contained in:
Tomas Slusny
2018-06-07 10:44:10 +02:00
parent dcbccbb01b
commit 0f0ac2ab64
7 changed files with 166 additions and 125 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
* 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<String, String> 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<String, String> getProperties()
{
return properties;
}
public String getAppletProperty(String name)
{
return appletProperties.get(name);
}
public Map<String, String> getAppletProperties()
{
return appletProperties;
return config;
}
}

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
* 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;
}
}

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
* 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)
{
}
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
* 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<String, String> appletProperties = new HashMap<>();
private final Map<String, String> 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", "");
}
}

View File

@@ -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));
}
}
}