installation/removal/updating/running extensions from store

This commit is contained in:
sirjonasxx 2021-08-18 04:32:51 +02:00
parent 3ccd67b1c4
commit 41dc3b7119
5 changed files with 213 additions and 81 deletions

View File

@ -21,6 +21,7 @@ public class ExecutionInfo {
extensionTypeToExecutionCommand.put("*.py3", new String[]{"python3", "{path}"});
extensionTypeToExecutionCommand.put("*.sh", new String[]{"{path}"});
extensionTypeToExecutionCommand.put("*.exe", new String[]{"{path}"});
extensionTypeToExecutionCommand.put("*.js", new String[]{"node", "{path}"});
String[] extraArgs = {"-p", "{port}", "-f", "{filename}", "-c", "{cookie}"};
for(String type : extensionTypeToExecutionCommand.keySet()) {

View File

@ -2,6 +2,7 @@ package gearth.services.extension_handler.extensions.implementations.network.exe
import gearth.Main;
import gearth.services.extension_handler.extensions.implementations.network.authentication.Authenticator;
import gearth.services.internal_extensions.extensionstore.tools.StoreExtensionTools;
import java.io.BufferedReader;
import java.io.File;
@ -72,7 +73,7 @@ public class NormalExtensionRunner implements ExtensionRunner {
newPath
);
addExecPermission(newPath.toString());
// addExecPermission(newPath.toString());
tryRunExtension(newPath.toString(), port);
} catch (IOException e) {
@ -84,7 +85,15 @@ public class NormalExtensionRunner implements ExtensionRunner {
public void tryRunExtension(String path, int port) {
try {
if (new File(path).isDirectory()) {
// this extension is installed from the extension store and requires
// different behavior
StoreExtensionTools.executeExtension(path, port);
return;
}
String filename = Paths.get(path).getFileName().toString();
String[] execCommand = ExecutionInfo.getExecutionCommand(getFileExtension(path));
execCommand = Arrays.copyOf(execCommand, execCommand.length);
String cookie = Authenticator.generateCookieForExtension(filename);
@ -99,66 +108,74 @@ public class NormalExtensionRunner implements ExtensionRunner {
// Process proc = Runtime.getRuntime().exec(execCommand);
Process proc = pb.start();
if (Main.hasFlag(ExtensionRunner.SHOW_EXTENSIONS_LOG)) {
String sep = "" + System.lineSeparator();
synchronized (System.out) {
System.out.println(path + sep + "Launching" + sep + "----------" + sep);
}
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(proc.getInputStream()));
new Thread(() -> {
try {
String line;
while((line = stdInput.readLine()) != null) {
synchronized (System.out) {
System.out.println(path + sep + "Output" + sep + line + sep + "----------" + sep);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
BufferedReader stdError = new BufferedReader(new
InputStreamReader(proc.getErrorStream()));
new Thread(() -> {
try {
String line;
while((line = stdError.readLine()) != null) {
synchronized (System.out) {
System.out.println(path + sep + "Error" + sep + line + sep + "----------" + sep);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
maybeLogExtension(path, proc);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void maybeLogExtension(String path, Process proc) {
if (Main.hasFlag(ExtensionRunner.SHOW_EXTENSIONS_LOG)) {
String sep = "" + System.lineSeparator();
synchronized (System.out) {
System.out.println(path + sep + "Launching" + sep + "----------" + sep);
}
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(proc.getInputStream()));
new Thread(() -> {
try {
String line;
while((line = stdInput.readLine()) != null) {
synchronized (System.out) {
System.out.println(path + sep + "Output" + sep + line + sep + "----------" + sep);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
BufferedReader stdError = new BufferedReader(new
InputStreamReader(proc.getErrorStream()));
new Thread(() -> {
try {
String line;
while((line = stdError.readLine()) != null) {
synchronized (System.out) {
System.out.println(path + sep + "Error" + sep + line + sep + "----------" + sep);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
@Override
public void uninstallExtension(String filename) {
try {
Files.delete(Paths.get(
JARPATH,
ExecutionInfo.EXTENSIONSDIRECTORY,
filename
));
Path path = Paths.get(JARPATH, ExecutionInfo.EXTENSIONSDIRECTORY, filename);
if (new File(path.toString()).isDirectory()) {
// is installed through extension store
StoreExtensionTools.removeExtension(path.toString());
}
else {
Files.delete(path);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void addExecPermission(String path) {
//not needed at first sight
}
// private void addExecPermission(String path) {
// //not needed at first sight
// }
private String getFileExtension(String path) {
String name = Paths.get(path).getFileName().toString();

View File

@ -1,6 +1,5 @@
package gearth.services.internal_extensions.extensionstore.repository;
import gearth.services.internal_extensions.extensionstore.repository.models.StoreConfig;
import gearth.services.internal_extensions.extensionstore.repository.models.StoreData;
import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
@ -8,7 +7,6 @@ import org.json.JSONObject;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
public class StoreFetch {
@ -42,7 +40,7 @@ public class StoreFetch {
public static void main(String[] args) {
// get("1.4.1");
// fetch("1.4.1");
}
}

View File

@ -127,12 +127,12 @@ public class StoreExtension {
}
public static class Commands {
private final String defaultCommand;
private final String linux;
private final String windows;
private final String mac;
private final List<String> defaultCommand;
private final List<String> linux;
private final List<String> windows;
private final List<String> mac;
public Commands(String defaultCommand, String linux, String windows, String mac) {
public Commands(List<String> defaultCommand, List<String> linux, List<String> windows, List<String> mac) {
this.defaultCommand = defaultCommand;
this.linux = linux;
this.windows = windows;
@ -140,25 +140,29 @@ public class StoreExtension {
}
public Commands(JSONObject object) {
this.defaultCommand = object.getString("default");
this.linux = object.has("linux") ? object.getString("linux") : null;
this.windows = object.has("windows") ? object.getString("windows") : null;
this.mac = object.has("mac") ? object.getString("mac") : null;
this.defaultCommand = object.getJSONArray("default").toList().stream()
.map(s -> (String)s).collect(Collectors.toList());
this.linux = object.has("linux") ?object.getJSONArray("linux").toList().stream()
.map(s -> (String)s).collect(Collectors.toList()) : null;
this.windows = object.has("windows") ? object.getJSONArray("windows").toList().stream()
.map(s -> (String)s).collect(Collectors.toList()) : null;
this.mac = object.has("mac") ? object.getJSONArray("mac").toList().stream()
.map(s -> (String)s).collect(Collectors.toList()) : null;
}
public String getDefault() {
public List<String> getDefault() {
return defaultCommand;
}
public String getLinux() {
public List<String> getLinux() {
return linux;
}
public String getWindows() {
public List<String> getWindows() {
return windows;
}
public String getMac() {
public List<String> getMac() {
return mac;
}
}

View File

@ -1,21 +1,29 @@
package gearth.services.internal_extensions.extensionstore.tools;
import gearth.misc.OSValidator;
import gearth.services.extension_handler.extensions.implementations.network.authentication.Authenticator;
import gearth.services.extension_handler.extensions.implementations.network.executer.ExecutionInfo;
import gearth.services.extension_handler.extensions.implementations.network.executer.NormalExtensionRunner;
import gearth.services.internal_extensions.extensionstore.repository.StoreFetch;
import gearth.services.internal_extensions.extensionstore.repository.StoreRepository;
import gearth.services.internal_extensions.extensionstore.repository.models.StoreExtension;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@ -29,32 +37,71 @@ public class StoreExtensionTools {
}
public static void executeExtension(String folderName) {
public static void executeExtension(String extensionPath, int port) {
try {
String installedExtensionId = Paths.get(extensionPath).getFileName().toString();
String commandPath = Paths.get(extensionPath, "command.txt").toString();
String cookie = Authenticator.generateCookieForExtension(installedExtensionId);
List<String> command = new JSONArray(FileUtils.readFileToString(new File(commandPath), "UTF-8"))
.toList().stream().map(o -> (String)o).map(s -> s
.replace("{port}", port+"")
.replace("{filename}", installedExtensionId)
.replace("{cookie}", cookie))
.collect(Collectors.toList());
ProcessBuilder pb = new ProcessBuilder(command);
pb.directory(new File(Paths.get(extensionPath, "extension").toString()));
Process p = pb.start();
NormalExtensionRunner.maybeLogExtension(extensionPath, p);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void unzipInto(InputStream inputStream, File directory) throws IOException {
byte[] buffer = new byte[1024];
inputStream = new BufferedInputStream(inputStream);
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
for (ZipEntry entry = null; (entry = zipInputStream.getNextEntry()) != null;) {
ZipEntry entry = zipInputStream.getNextEntry();
while (entry != null) {
File file = new File(Paths.get(directory.getPath(), entry.getName()).toString());
if (entry.isDirectory()) {
file.mkdirs();
if (!file.isDirectory() && !file.mkdirs()) {
throw new IOException("Failed to create directory " + file);
}
}
else {
FileUtils.copyInputStreamToFile(inputStream, file);
// StreamUtil.write(pathBuilder, inputStream, false);
File parent = file.getParentFile();
if (!parent.isDirectory() && !parent.mkdirs()) {
throw new IOException("Failed to create directory " + parent);
}
// write file content
FileOutputStream fos = new FileOutputStream(file);
int len;
while ((len = zipInputStream.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
}
entry = zipInputStream.getNextEntry();
}
zipInputStream.closeEntry();
zipInputStream.close();
}
public static void installExtension(String name, StoreRepository storeRepository, InstallExtListener listener) {
new Thread(() -> {
String downloadUrl = String.format("https://github.com/sirjonasxx/G-ExtensionStore/raw/repo/%s/store/extensions/%s/extension.zip", storeRepository.getRepoVersion(), name);
@ -73,9 +120,20 @@ public class StoreExtensionTools {
try {
URL url = new URL(downloadUrl);
InputStream inputStream = url.openStream();
unzipInto(inputStream, extensionPath);
// todo command file
try {
unzipInto(inputStream, extensionPath);
File commandFile = new File(Paths.get(path, "command.txt").toString());
List<String> command = OSValidator.isMac() ? ext.getCommands().getMac() : (OSValidator.isUnix() ? ext.getCommands().getLinux() :
(OSValidator.isWindows() ? ext.getCommands().getWindows() : ext.getCommands().getDefault()));
command = command == null ? ext.getCommands().getDefault() : command;
FileUtils.writeStringToFile(commandFile, new JSONArray(command).toString(), "UTF-8");
listener.success(path);
} catch (IOException e) {
listener.fail("Error while unzipping");
}
} catch (MalformedURLException e) {
listener.fail("Invalid extension URL");
@ -84,7 +142,7 @@ public class StoreExtensionTools {
}
}
else {
listener.fail("Something went wrong creating the extension directory");
listener.fail("Something went wrong creating the extension directory, does the extension already exist?");
}
}
else {
@ -95,13 +153,67 @@ public class StoreExtensionTools {
}
public static void removeExtension(String folderName) {
public static void removeExtension(String extensionPath) throws IOException {
FileUtils.deleteDirectory(new File(extensionPath));
}
public static void updateExtension() {
public static void updateExtension(String name, StoreRepository storeRepository, InstallExtListener listener) {
// remove old occurences
String path = Paths.get(NormalExtensionRunner.JARPATH, ExecutionInfo.EXTENSIONSDIRECTORY).toString();
File extensionsDir = new File(path);
try {
File[] existingExtensions = extensionsDir.listFiles();
if (existingExtensions != null) {
for (File extension : existingExtensions) {
if (extension.isDirectory()) {
// installed through extensions store
if (extension.getName().contains("_")) {
List<String> parts = new ArrayList<>(Arrays.asList(extension.getName().split("_")));
parts.remove(path.length() - 1);
String extensionName = String.join("_", parts);
if (name.equals(extensionName)) {
removeExtension(extension.getPath());
}
}
}
}
}
} catch (Exception e) {
listener.fail("Something went wrong with uninstalling the extension");
return;
}
installExtension(name, storeRepository, listener);
}
public static void main(String[] args) {
StoreFetch.fetch("1.4.1", new StoreFetch.StoreFetchListener() {
@Override
public void success(StoreRepository storeRepository) {
installExtension("G-BuildTools", storeRepository, new InstallExtListener() {
@Override
public void success(String installationFolder) {
System.out.println(String.format("Installed in: %s", installationFolder));
}
@Override
public void fail(String reason) {
System.out.println(reason);
}
});
}
@Override
public void fail(String reason) {
System.out.println("failed fetching repository");
}
});
}