project(externals): Make the external manager more robust
This commit is contained in:
@@ -88,10 +88,9 @@ import org.pf4j.DependencyResolver;
|
||||
import org.pf4j.PluginDependency;
|
||||
import org.pf4j.PluginRuntimeException;
|
||||
import org.pf4j.PluginWrapper;
|
||||
import org.pf4j.update.DefaultUpdateRepository;
|
||||
import org.pf4j.update.PluginInfo;
|
||||
import org.pf4j.update.UpdateManager;
|
||||
import org.pf4j.update.UpdateRepository;
|
||||
import org.pf4j.update.VerifyException;
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
@Slf4j
|
||||
@@ -107,7 +106,7 @@ public class OPRSExternalPluginManager
|
||||
@Getter(AccessLevel.PUBLIC)
|
||||
private org.pf4j.PluginManager externalPluginManager;
|
||||
@Getter(AccessLevel.PUBLIC)
|
||||
private final List<UpdateRepository> repositories = new ArrayList<>();
|
||||
private final List<OPRSUpdateRepository> repositories = new ArrayList<>();
|
||||
@Inject
|
||||
private OpenOSRSConfig openOSRSConfig;
|
||||
@Inject
|
||||
@@ -124,7 +123,7 @@ public class OPRSExternalPluginManager
|
||||
@Inject
|
||||
private Groups groups;
|
||||
@Getter(AccessLevel.PUBLIC)
|
||||
private UpdateManager updateManager;
|
||||
private OPRSUpdateManager updateManager;
|
||||
@Inject
|
||||
@Named("safeMode")
|
||||
private boolean safeMode;
|
||||
@@ -160,7 +159,7 @@ public class OPRSExternalPluginManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that {@link UpdateManager#addRepository} checks if the repo exists, however it throws an exception which is bad
|
||||
* Note that {@link OPRSUpdateManager#addRepository} checks if the repo exists, however it throws an exception which is bad
|
||||
*/
|
||||
public boolean doesRepoExist(String id)
|
||||
{
|
||||
@@ -192,17 +191,17 @@ public class OPRSExternalPluginManager
|
||||
|
||||
public static boolean testRepository(URL url, String pluginsJson)
|
||||
{
|
||||
final List<UpdateRepository> repositories = new ArrayList<>();
|
||||
final List<OPRSUpdateRepository> repositories = new ArrayList<>();
|
||||
if (pluginsJson != null)
|
||||
{
|
||||
repositories.add(new DefaultUpdateRepository("repository-testing", url, pluginsJson));
|
||||
repositories.add(new OPRSUpdateRepository("repository-testing", url, pluginsJson));
|
||||
}
|
||||
else
|
||||
{
|
||||
repositories.add(new DefaultUpdateRepository("repository-testing", url));
|
||||
repositories.add(new OPRSUpdateRepository("repository-testing", url));
|
||||
}
|
||||
DefaultPluginManager testPluginManager = new DefaultPluginManager(EXTERNALPLUGIN_DIR.toPath());
|
||||
UpdateManager updateManager = new UpdateManager(testPluginManager, repositories);
|
||||
OPRSUpdateManager updateManager = new OPRSUpdateManager(testPluginManager, repositories);
|
||||
|
||||
return updateManager.getPlugins().size() <= 0;
|
||||
}
|
||||
@@ -258,7 +257,7 @@ public class OPRSExternalPluginManager
|
||||
loadOldFormat();
|
||||
}
|
||||
|
||||
updateManager = new UpdateManager(externalPluginManager, repositories);
|
||||
updateManager = new OPRSUpdateManager(externalPluginManager, repositories);
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
@@ -310,11 +309,11 @@ public class OPRSExternalPluginManager
|
||||
|
||||
if (pluginJson == null)
|
||||
{
|
||||
repositories.add(new DefaultUpdateRepository(id, new URL(url)));
|
||||
repositories.add(new OPRSUpdateRepository(id, new URL(url)));
|
||||
}
|
||||
else
|
||||
{
|
||||
repositories.add(new DefaultUpdateRepository(id, new URL(url), pluginJson));
|
||||
repositories.add(new OPRSUpdateRepository(id, new URL(url), pluginJson));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -340,7 +339,7 @@ public class OPRSExternalPluginManager
|
||||
String id = keyval.substring(0, keyval.lastIndexOf(":https"));
|
||||
String url = keyval.substring(keyval.lastIndexOf("https"));
|
||||
|
||||
DefaultUpdateRepository defaultRepo = new DefaultUpdateRepository(id, new URL(url));
|
||||
OPRSUpdateRepository defaultRepo = new OPRSUpdateRepository(id, new URL(url));
|
||||
repositories.add(defaultRepo);
|
||||
log.debug("Added Repo: {}", defaultRepo.getUrl());
|
||||
}
|
||||
@@ -355,7 +354,7 @@ public class OPRSExternalPluginManager
|
||||
openOSRSConfig.setExternalRepositories(DEFAULT_PLUGIN_REPOS);
|
||||
}
|
||||
|
||||
updateManager = new UpdateManager(externalPluginManager, repositories);
|
||||
updateManager = new OPRSUpdateManager(externalPluginManager, repositories);
|
||||
}
|
||||
|
||||
public void addGHRepository(String owner, String name)
|
||||
@@ -377,15 +376,15 @@ public class OPRSExternalPluginManager
|
||||
|
||||
public void addRepository(String key, URL url, String pluginsJson)
|
||||
{
|
||||
DefaultUpdateRepository respository;
|
||||
OPRSUpdateRepository respository;
|
||||
|
||||
if (pluginsJson != null)
|
||||
{
|
||||
respository = new DefaultUpdateRepository(key, url, pluginsJson);
|
||||
respository = new OPRSUpdateRepository(key, url, pluginsJson);
|
||||
}
|
||||
else
|
||||
{
|
||||
respository = new DefaultUpdateRepository(key, url);
|
||||
respository = new OPRSUpdateRepository(key, url);
|
||||
}
|
||||
|
||||
updateManager.addRepository(respository);
|
||||
@@ -1030,10 +1029,18 @@ public class OPRSExternalPluginManager
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
catch (VerifyException ex)
|
||||
{
|
||||
// This should never happen but can crash the client
|
||||
log.error("Cannot update plugin '{}', the SHA512 hash mismatches! {}", plugin.id, ex.getMessage());
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
catch (PluginRuntimeException ex)
|
||||
{
|
||||
// This should never happen but can crash the client
|
||||
log.warn("Cannot update plugin '{}', the user probably has another client open", plugin.id);
|
||||
log.error(String.valueOf(ex));
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
@@ -1181,8 +1188,6 @@ public class OPRSExternalPluginManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Mostly stolen from {@link java.net.URLStreamHandler#toExternalForm(URL)}
|
||||
*
|
||||
* @param url URL to encode
|
||||
* @return URL, with path, query and ref encoded
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,463 @@
|
||||
package net.runelite.client.plugins;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.pf4j.PluginManager;
|
||||
import org.pf4j.PluginRuntimeException;
|
||||
import org.pf4j.PluginState;
|
||||
import org.pf4j.PluginWrapper;
|
||||
import org.pf4j.VersionManager;
|
||||
import org.pf4j.update.DefaultUpdateRepository;
|
||||
import org.pf4j.update.FileDownloader;
|
||||
import org.pf4j.update.FileVerifier;
|
||||
import org.pf4j.update.PluginInfo;
|
||||
import org.pf4j.update.SimpleFileDownloader;
|
||||
import org.pf4j.update.UpdateManager;
|
||||
import org.pf4j.update.verifier.CompoundVerifier;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class OPRSUpdateManager
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(UpdateManager.class);
|
||||
|
||||
private final PluginManager pluginManager;
|
||||
private final VersionManager versionManager;
|
||||
private final String systemVersion;
|
||||
private final Path repositoriesJson;
|
||||
|
||||
// cache last plugin release per plugin id (the key)
|
||||
private final Map<String, PluginInfo.PluginRelease> lastPluginRelease = new HashMap<>();
|
||||
|
||||
protected List<OPRSUpdateRepository> repositories;
|
||||
|
||||
public OPRSUpdateManager(PluginManager pluginManager)
|
||||
{
|
||||
this.pluginManager = pluginManager;
|
||||
|
||||
versionManager = pluginManager.getVersionManager();
|
||||
systemVersion = pluginManager.getSystemVersion();
|
||||
repositoriesJson = Paths.get("repositories.json");
|
||||
}
|
||||
|
||||
public OPRSUpdateManager(PluginManager pluginManager, List<OPRSUpdateRepository> repos)
|
||||
{
|
||||
this(pluginManager);
|
||||
|
||||
repositories = repos == null ? new ArrayList<>() : repos;
|
||||
}
|
||||
|
||||
public List<PluginInfo> getAvailablePlugins()
|
||||
{
|
||||
List<PluginInfo> availablePlugins = new ArrayList<>();
|
||||
for (PluginInfo plugin : getPlugins())
|
||||
{
|
||||
if (pluginManager.getPlugin(plugin.id) == null)
|
||||
{
|
||||
availablePlugins.add(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
return availablePlugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of plugins that are newer versions of already installed plugins.
|
||||
*
|
||||
* @return list of plugins that have updates
|
||||
*/
|
||||
public List<PluginInfo> getUpdates()
|
||||
{
|
||||
List<PluginInfo> updates = new ArrayList<>();
|
||||
for (PluginWrapper installed : pluginManager.getPlugins())
|
||||
{
|
||||
String pluginId = installed.getPluginId();
|
||||
if (hasPluginUpdate(pluginId))
|
||||
{
|
||||
updates.add(getPluginsMap().get(pluginId));
|
||||
}
|
||||
}
|
||||
|
||||
return updates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if Update Repositories has newer versions of some of the installed plugins.
|
||||
*
|
||||
* @return true if updates exist
|
||||
*/
|
||||
public boolean hasUpdates()
|
||||
{
|
||||
return getUpdates().size() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of plugins from all repos.
|
||||
*
|
||||
* @return List of plugin info
|
||||
*/
|
||||
public List<PluginInfo> getPlugins()
|
||||
{
|
||||
List<PluginInfo> list = new ArrayList<>(getPluginsMap().values());
|
||||
Collections.sort(list);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a map of all plugins from all repos where key is plugin id.
|
||||
*
|
||||
* @return List of plugin info
|
||||
*/
|
||||
public Map<String, PluginInfo> getPluginsMap()
|
||||
{
|
||||
Map<String, PluginInfo> pluginsMap = new HashMap<>();
|
||||
for (OPRSUpdateRepository repository : getRepositories())
|
||||
{
|
||||
pluginsMap.putAll(repository.getPlugins());
|
||||
}
|
||||
|
||||
return pluginsMap;
|
||||
}
|
||||
|
||||
public List<OPRSUpdateRepository> getRepositories()
|
||||
{
|
||||
if (repositories == null && repositoriesJson != null)
|
||||
{
|
||||
refresh();
|
||||
}
|
||||
|
||||
return repositories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add one {@link DefaultUpdateRepository}.
|
||||
*
|
||||
* @param id of repo
|
||||
* @param url of repo
|
||||
*/
|
||||
public void addRepository(String id, URL url)
|
||||
{
|
||||
for (OPRSUpdateRepository ur : repositories)
|
||||
{
|
||||
if (ur.getId().equals(id))
|
||||
{
|
||||
throw new RuntimeException("Repository with id " + id + " already exists");
|
||||
}
|
||||
}
|
||||
repositories.add(new OPRSUpdateRepository(id, url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a repo that was created by client.
|
||||
*
|
||||
* @param newRepo the new UpdateRepository to add to the list
|
||||
*/
|
||||
public void addRepository(OPRSUpdateRepository newRepo)
|
||||
{
|
||||
for (OPRSUpdateRepository ur : repositories)
|
||||
{
|
||||
if (ur.getId().equals(newRepo.getId()))
|
||||
{
|
||||
throw new RuntimeException("Repository with id " + newRepo.getId() + " already exists");
|
||||
}
|
||||
}
|
||||
newRepo.refresh();
|
||||
repositories.add(newRepo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a repository by id.
|
||||
*
|
||||
* @param id of repository to remove
|
||||
*/
|
||||
public void removeRepository(String id)
|
||||
{
|
||||
for (OPRSUpdateRepository repo : getRepositories())
|
||||
{
|
||||
if (id.equals(repo.getId()))
|
||||
{
|
||||
repositories.remove(repo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
log.warn("Repository with id " + id + " not found, doing nothing");
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes all repositories, so they are forced to refresh list of plugins.
|
||||
*/
|
||||
public synchronized void refresh()
|
||||
{
|
||||
if (repositoriesJson != null && Files.exists(repositoriesJson))
|
||||
{
|
||||
initRepositoriesFromJson();
|
||||
}
|
||||
for (OPRSUpdateRepository updateRepository : repositories)
|
||||
{
|
||||
updateRepository.refresh();
|
||||
}
|
||||
lastPluginRelease.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs a plugin by id and version.
|
||||
*
|
||||
* @param id the id of plugin to install
|
||||
* @param version the version of plugin to install, on SemVer format, or null for latest
|
||||
* @return true if installation successful and plugin started
|
||||
* @throws PluginRuntimeException if plugin does not exist in repos or problems during
|
||||
*/
|
||||
public synchronized boolean installPlugin(String id, String version)
|
||||
{
|
||||
// Download to temporary location
|
||||
Path downloaded = downloadPlugin(id, version);
|
||||
|
||||
Path pluginsRoot = pluginManager.getPluginsRoot();
|
||||
Path file = pluginsRoot.resolve(downloaded.getFileName());
|
||||
try
|
||||
{
|
||||
Files.move(downloaded, file, REPLACE_EXISTING);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new PluginRuntimeException(e, "Failed to write file '{}' to plugins folder", file);
|
||||
}
|
||||
|
||||
String pluginId = pluginManager.loadPlugin(file);
|
||||
PluginState state = pluginManager.startPlugin(pluginId);
|
||||
|
||||
return PluginState.STARTED.equals(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads a plugin with given coordinates, runs all {@link FileVerifier}s
|
||||
* and returns a path to the downloaded file.
|
||||
*
|
||||
* @param id of plugin
|
||||
* @param version of plugin or null to download latest
|
||||
* @return Path to file which will reside in a temporary folder in the system default temp area
|
||||
* @throws PluginRuntimeException if download failed
|
||||
*/
|
||||
protected Path downloadPlugin(String id, String version)
|
||||
{
|
||||
try
|
||||
{
|
||||
PluginInfo.PluginRelease release = findReleaseForPlugin(id, version);
|
||||
Path downloaded = getFileDownloader(id).downloadFile(new URL(release.url));
|
||||
getFileVerifier(id).verify(new FileVerifier.Context(id, release), downloaded);
|
||||
return downloaded;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new PluginRuntimeException(e, "Error during download of plugin {}", id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the {@link FileDownloader} to use for this repository.
|
||||
*
|
||||
* @param pluginId the plugin we wish to download
|
||||
* @return FileDownloader instance
|
||||
*/
|
||||
protected FileDownloader getFileDownloader(String pluginId)
|
||||
{
|
||||
for (OPRSUpdateRepository ur : repositories)
|
||||
{
|
||||
if (ur.getPlugin(pluginId) != null && ur.getFileDownloader() != null)
|
||||
{
|
||||
return ur.getFileDownloader();
|
||||
}
|
||||
}
|
||||
|
||||
return new SimpleFileDownloader();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a file verifier to use for this plugin. First tries to use custom verifier
|
||||
* configured for the repository, then fallback to the default {@link CompoundVerifier}
|
||||
*
|
||||
* @param pluginId the plugin we wish to download
|
||||
* @return FileVerifier instance
|
||||
*/
|
||||
protected FileVerifier getFileVerifier(String pluginId)
|
||||
{
|
||||
for (OPRSUpdateRepository ur : repositories)
|
||||
{
|
||||
if (ur.getPlugin(pluginId) != null && ur.getFileVerifier() != null)
|
||||
{
|
||||
return ur.getFileVerifier();
|
||||
}
|
||||
}
|
||||
|
||||
return new CompoundVerifier();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves Release from id and version.
|
||||
*
|
||||
* @param id of plugin
|
||||
* @param version of plugin or null to locate latest version
|
||||
* @return PluginRelease for downloading
|
||||
* @throws PluginRuntimeException if id or version does not exist
|
||||
*/
|
||||
protected PluginInfo.PluginRelease findReleaseForPlugin(String id, String version)
|
||||
{
|
||||
PluginInfo pluginInfo = getPluginsMap().get(id);
|
||||
if (pluginInfo == null)
|
||||
{
|
||||
log.info("Plugin with id {} does not exist in any repository", id);
|
||||
throw new PluginRuntimeException("Plugin with id {} not found in any repository", id);
|
||||
}
|
||||
|
||||
if (version == null)
|
||||
{
|
||||
return getLastPluginRelease(id);
|
||||
}
|
||||
|
||||
for (PluginInfo.PluginRelease release : pluginInfo.releases)
|
||||
{
|
||||
if (versionManager.compareVersions(version, release.version) == 0 && release.url != null)
|
||||
{
|
||||
return release;
|
||||
}
|
||||
}
|
||||
|
||||
throw new PluginRuntimeException("Plugin {} with version @{} does not exist in the repository", id, version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a plugin id to given version or to latest version if {@code version == null}.
|
||||
*
|
||||
* @param id the id of plugin to update
|
||||
* @param version the version to update to, on SemVer format, or null for latest
|
||||
* @return true if update successful
|
||||
* @throws PluginRuntimeException in case the given version is not available, plugin id not already installed etc
|
||||
*/
|
||||
public boolean updatePlugin(String id, String version)
|
||||
{
|
||||
if (pluginManager.getPlugin(id) == null)
|
||||
{
|
||||
throw new PluginRuntimeException("Plugin {} cannot be updated since it is not installed", id);
|
||||
}
|
||||
|
||||
PluginInfo pluginInfo = getPluginsMap().get(id);
|
||||
if (pluginInfo == null)
|
||||
{
|
||||
throw new PluginRuntimeException("Plugin {} does not exist in any repository", id);
|
||||
}
|
||||
|
||||
if (!hasPluginUpdate(id))
|
||||
{
|
||||
log.warn("Plugin {} does not have an update available which is compatible with system version {}", id, systemVersion);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Download to temp folder
|
||||
Path downloaded = downloadPlugin(id, version);
|
||||
|
||||
if (!pluginManager.deletePlugin(id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Path pluginsRoot = pluginManager.getPluginsRoot();
|
||||
Path file = pluginsRoot.resolve(downloaded.getFileName());
|
||||
try
|
||||
{
|
||||
Files.move(downloaded, file, REPLACE_EXISTING);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new PluginRuntimeException("Failed to write plugin file {} to plugin folder", file);
|
||||
}
|
||||
|
||||
String newPluginId = pluginManager.loadPlugin(file);
|
||||
PluginState state = pluginManager.startPlugin(newPluginId);
|
||||
|
||||
return PluginState.STARTED.equals(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last release version of this plugin for given system version, regardless of release date.
|
||||
*
|
||||
* @return PluginRelease which has the highest version number
|
||||
*/
|
||||
public PluginInfo.PluginRelease getLastPluginRelease(String id)
|
||||
{
|
||||
PluginInfo pluginInfo = getPluginsMap().get(id);
|
||||
if (pluginInfo == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!lastPluginRelease.containsKey(id))
|
||||
{
|
||||
for (PluginInfo.PluginRelease release : pluginInfo.releases)
|
||||
{
|
||||
if (systemVersion.equals("0.0.0") || versionManager.checkVersionConstraint(systemVersion, release.requires))
|
||||
{
|
||||
if (lastPluginRelease.get(id) == null)
|
||||
{
|
||||
lastPluginRelease.put(id, release);
|
||||
}
|
||||
else if (versionManager.compareVersions(release.version, lastPluginRelease.get(id).version) > 0)
|
||||
{
|
||||
lastPluginRelease.put(id, release);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lastPluginRelease.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds whether the newer version of the plugin.
|
||||
*
|
||||
* @return true if there is a newer version available which is compatible with system
|
||||
*/
|
||||
public boolean hasPluginUpdate(String id)
|
||||
{
|
||||
PluginInfo pluginInfo = getPluginsMap().get(id);
|
||||
if (pluginInfo == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
String installedVersion = pluginManager.getPlugin(id).getDescriptor().getVersion();
|
||||
PluginInfo.PluginRelease last = getLastPluginRelease(id);
|
||||
|
||||
return last != null && versionManager.compareVersions(last.version, installedVersion) > 0;
|
||||
}
|
||||
|
||||
protected synchronized void initRepositoriesFromJson()
|
||||
{
|
||||
log.debug("Read repositories from '{}'", repositoriesJson);
|
||||
try (FileReader reader = new FileReader(repositoriesJson.toFile()))
|
||||
{
|
||||
Gson gson = new GsonBuilder().create();
|
||||
OPRSUpdateRepository[] items = gson.fromJson(reader, OPRSUpdateRepository[].class);
|
||||
repositories = Arrays.asList(items);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
repositories = Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package net.runelite.client.plugins;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.pf4j.update.DefaultUpdateRepository;
|
||||
import org.pf4j.update.FileDownloader;
|
||||
import org.pf4j.update.FileVerifier;
|
||||
import org.pf4j.update.PluginInfo;
|
||||
import org.pf4j.update.SimpleFileDownloader;
|
||||
import org.pf4j.update.UpdateRepository;
|
||||
import org.pf4j.update.util.LenientDateTypeAdapter;
|
||||
import org.pf4j.update.verifier.CompoundVerifier;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class OPRSUpdateRepository implements UpdateRepository
|
||||
{
|
||||
|
||||
private static final String DEFAULT_PLUGINS_JSON_FILENAME = "plugins.json";
|
||||
private static final Logger log = LoggerFactory.getLogger(DefaultUpdateRepository.class);
|
||||
|
||||
private final String id;
|
||||
private final URL url;
|
||||
private String pluginsJsonFileName;
|
||||
|
||||
private Map<String, PluginInfo> plugins;
|
||||
|
||||
public OPRSUpdateRepository(String id, URL url)
|
||||
{
|
||||
this(id, url, DEFAULT_PLUGINS_JSON_FILENAME);
|
||||
}
|
||||
|
||||
public OPRSUpdateRepository(String id, URL url, String pluginsJsonFileName)
|
||||
{
|
||||
this.id = id;
|
||||
this.url = url;
|
||||
this.pluginsJsonFileName = pluginsJsonFileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getUrl()
|
||||
{
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, PluginInfo> getPlugins()
|
||||
{
|
||||
if (plugins == null)
|
||||
{
|
||||
initPlugins();
|
||||
}
|
||||
|
||||
return plugins;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginInfo getPlugin(String id)
|
||||
{
|
||||
return getPlugins().get(id);
|
||||
}
|
||||
|
||||
private void initPlugins()
|
||||
{
|
||||
Reader pluginsJsonReader;
|
||||
try
|
||||
{
|
||||
URL pluginsUrl = new URL(getUrl(), getPluginsJsonFileName());
|
||||
log.debug("Read plugins of '{}' repository from '{}'", id, pluginsUrl);
|
||||
pluginsJsonReader = new InputStreamReader(pluginsUrl.openStream());
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
log.error("{}{} could not be loaded (file missing)", getUrl(), getPluginsJsonFileName());
|
||||
plugins = Collections.emptyMap();
|
||||
return;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error(e.getMessage(), e);
|
||||
plugins = Collections.emptyMap();
|
||||
return;
|
||||
}
|
||||
|
||||
Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new LenientDateTypeAdapter()).create();
|
||||
PluginInfo[] items;
|
||||
try
|
||||
{
|
||||
items = gson.fromJson(pluginsJsonReader, PluginInfo[].class);
|
||||
}
|
||||
catch (IllegalStateException | JsonSyntaxException ex)
|
||||
{
|
||||
items = new PluginInfo[]{};
|
||||
}
|
||||
plugins = new HashMap<>(items.length);
|
||||
for (PluginInfo p : items)
|
||||
{
|
||||
for (PluginInfo.PluginRelease r : p.releases)
|
||||
{
|
||||
try
|
||||
{
|
||||
r.url = new URL(getUrl(), r.url).toString();
|
||||
if (r.date.getTime() == 0)
|
||||
{
|
||||
log.warn("Illegal release date when parsing {}@{}, setting to epoch", p.id, r.version);
|
||||
}
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
log.warn("Skipping release {} of plugin {} due to failure to build valid absolute URL. Url was {}{}", r.version, p.id, getUrl(), r.url);
|
||||
}
|
||||
}
|
||||
p.setRepositoryId(getId());
|
||||
plugins.put(p.id, p);
|
||||
}
|
||||
log.debug("Found {} plugins in repository '{}'", plugins.size(), id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Causes {@code plugins.json} to be read again to look for new updates from repositories.
|
||||
*/
|
||||
@Override
|
||||
public void refresh()
|
||||
{
|
||||
plugins = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileDownloader getFileDownloader()
|
||||
{
|
||||
return new SimpleFileDownloader();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a file verifier to execute on the downloaded file for it to be claimed valid.
|
||||
* May be a CompoundVerifier in order to chain several verifiers.
|
||||
*
|
||||
* @return list of {@link FileVerifier}s
|
||||
*/
|
||||
@Override
|
||||
public FileVerifier getFileVerifier()
|
||||
{
|
||||
return new CompoundVerifier();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the plugins json file name. Returns {@code plugins.json} if null.
|
||||
*
|
||||
* @return the plugins json file name
|
||||
*/
|
||||
public String getPluginsJsonFileName()
|
||||
{
|
||||
if (pluginsJsonFileName == null)
|
||||
{
|
||||
pluginsJsonFileName = DEFAULT_PLUGINS_JSON_FILENAME;
|
||||
}
|
||||
|
||||
return pluginsJsonFileName;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import net.runelite.client.plugins.OPRSExternalPluginManager;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.openosrs.client.events.OPRSPluginChanged;
|
||||
import com.openosrs.client.events.OPRSRepositoryChanged;
|
||||
import net.runelite.client.plugins.OPRSUpdateManager;
|
||||
import net.runelite.client.plugins.OPRSUpdateRepository;
|
||||
import net.runelite.client.util.DeferredDocumentChangedListener;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
@@ -46,8 +48,6 @@ import net.runelite.client.util.ImageUtil;
|
||||
import net.runelite.client.util.SwingUtil;
|
||||
import org.pf4j.VersionManager;
|
||||
import org.pf4j.update.PluginInfo;
|
||||
import org.pf4j.update.UpdateManager;
|
||||
import org.pf4j.update.UpdateRepository;
|
||||
import org.pf4j.update.VerifyException;
|
||||
|
||||
@Slf4j
|
||||
@@ -84,7 +84,7 @@ public class PluginsPanel extends JPanel
|
||||
|
||||
private final OPRSExternalPluginManager externalPluginManager;
|
||||
private final VersionManager versionManager;
|
||||
private final UpdateManager updateManager;
|
||||
private final OPRSUpdateManager updateManager;
|
||||
|
||||
private final IconTextField searchBar = new IconTextField();
|
||||
private final JPanel filterwrapper = new JPanel(new BorderLayout(0, 10));
|
||||
@@ -167,7 +167,7 @@ public class PluginsPanel extends JPanel
|
||||
{
|
||||
List<String> repositories = new ArrayList<>();
|
||||
repositories.add("All");
|
||||
for (UpdateRepository updateRepository : this.updateManager.getRepositories())
|
||||
for (OPRSUpdateRepository updateRepository : this.updateManager.getRepositories())
|
||||
{
|
||||
repositories.add(updateRepository.getUrl().toString().replace("https://raw.githubusercontent.com/", "").replace("/master/", ""));
|
||||
}
|
||||
@@ -366,7 +366,7 @@ public class PluginsPanel extends JPanel
|
||||
{
|
||||
boolean filtered = true;
|
||||
String filter = String.valueOf(filterComboBox.getSelectedItem());
|
||||
for (UpdateRepository updateRepository : updateManager.getRepositories())
|
||||
for (OPRSUpdateRepository updateRepository : updateManager.getRepositories())
|
||||
{
|
||||
if (filter.equals(updateRepository.getUrl().toString().replace("https://raw.githubusercontent.com/", "").replace("/master/", "")) &&
|
||||
pluginInfo.getRepositoryId().equals(updateRepository.getId()))
|
||||
@@ -424,7 +424,7 @@ public class PluginsPanel extends JPanel
|
||||
{
|
||||
boolean filtered = true;
|
||||
String filter = String.valueOf(filterComboBox.getSelectedItem());
|
||||
for (UpdateRepository updateRepository : updateManager.getRepositories())
|
||||
for (OPRSUpdateRepository updateRepository : updateManager.getRepositories())
|
||||
{
|
||||
if (filter.equals(updateRepository.getUrl().toString().replace("https://raw.githubusercontent.com/", "").replace("/master/", "")) &&
|
||||
pluginInfo.getRepositoryId().equals(updateRepository.getId()))
|
||||
|
||||
@@ -16,12 +16,12 @@ import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import net.runelite.client.plugins.OPRSUpdateRepository;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
import net.runelite.client.util.LinkBrowser;
|
||||
import org.pf4j.update.PluginInfo;
|
||||
import org.pf4j.update.UpdateRepository;
|
||||
|
||||
public class RepositoryBox extends JPanel
|
||||
{
|
||||
@@ -53,7 +53,7 @@ public class RepositoryBox extends JPanel
|
||||
DISCORD_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(discordImg, 0.53f));
|
||||
}
|
||||
|
||||
RepositoryBox(OPRSExternalPluginManager externalPluginManager, UpdateRepository updateRepository)
|
||||
RepositoryBox(OPRSExternalPluginManager externalPluginManager, OPRSUpdateRepository updateRepository)
|
||||
{
|
||||
setLayout(new BorderLayout());
|
||||
setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
|
||||
@@ -10,8 +10,8 @@ import javax.swing.JPanel;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.plugins.OPRSUpdateRepository;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import org.pf4j.update.UpdateRepository;
|
||||
|
||||
public class RepositoryPanel extends JPanel
|
||||
{
|
||||
@@ -45,7 +45,7 @@ public class RepositoryPanel extends JPanel
|
||||
c.gridy = 0;
|
||||
c.insets = new Insets(5, 0, 0, 0);
|
||||
|
||||
for (UpdateRepository repository : externalPluginManager.getRepositories())
|
||||
for (OPRSUpdateRepository repository : externalPluginManager.getRepositories())
|
||||
{
|
||||
final RepositoryBox p = new RepositoryBox(externalPluginManager, repository);
|
||||
add(p, c);
|
||||
|
||||
Reference in New Issue
Block a user