mirror of
https://github.com/packwiz/packwiz-installer.git
synced 2025-04-19 21:16:30 +02:00
Better exception handling, progress system
This commit is contained in:
parent
905630cb2a
commit
3d28f0a674
@ -9,5 +9,24 @@ public class CLIHandler implements IUserInterface {
|
||||
|
||||
@Override
|
||||
public void show() {}
|
||||
|
||||
@Override
|
||||
public void submitProgress(InstallProgress progress) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (progress.hasProgress) {
|
||||
sb.append('(');
|
||||
sb.append(progress.progress);
|
||||
sb.append('/');
|
||||
sb.append(progress.progressTotal);
|
||||
sb.append(") ");
|
||||
}
|
||||
sb.append(progress.message);
|
||||
System.out.println(sb.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeManager(Runnable task) {
|
||||
task.run();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,11 +6,18 @@ public interface IUserInterface {
|
||||
|
||||
public void handleException(Exception e);
|
||||
|
||||
/**
|
||||
* This might not exit straight away, return after calling this!
|
||||
*/
|
||||
public default void handleExceptionAndExit(Exception e) {
|
||||
handleException(e);
|
||||
System.exit(1);
|
||||
};
|
||||
|
||||
public default void setTitle(String title) {};
|
||||
|
||||
public void submitProgress(InstallProgress progress);
|
||||
|
||||
public void executeManager(Runnable task);
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
package link.infra.packwiz.installer;
|
||||
|
||||
public class InstallProgress {
|
||||
public final String message;
|
||||
public final boolean hasProgress;
|
||||
public final int progress;
|
||||
public final int progressTotal;
|
||||
|
||||
InstallProgress(String message) {
|
||||
this.message = message;
|
||||
hasProgress = false;
|
||||
progress = 0;
|
||||
progressTotal = 0;
|
||||
}
|
||||
|
||||
InstallProgress(String message, int progress, int progressTotal) {
|
||||
this.message = message;
|
||||
hasProgress = true;
|
||||
this.progress = progress;
|
||||
this.progressTotal = progressTotal;
|
||||
}
|
||||
}
|
@ -5,6 +5,10 @@ import java.awt.Component;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
@ -14,13 +18,16 @@ import javax.swing.JPanel;
|
||||
import javax.swing.JProgressBar;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
public class InstallWindow implements IUserInterface {
|
||||
|
||||
private JFrame frmPackwizlauncher;
|
||||
private JLabel lblProgresslabel;
|
||||
private JProgressBar progressBar;
|
||||
|
||||
private String title = "Updating modpack...";
|
||||
private SwingWorkerButWithPublicPublish<Void, InstallProgress> worker;
|
||||
private AtomicBoolean aboutToCrash = new AtomicBoolean();
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
@ -52,11 +59,11 @@ public class InstallWindow implements IUserInterface {
|
||||
frmPackwizlauncher.getContentPane().add(panel, BorderLayout.CENTER);
|
||||
panel.setLayout(new BorderLayout(0, 0));
|
||||
|
||||
JProgressBar progressBar = new JProgressBar();
|
||||
progressBar.setValue(50);
|
||||
progressBar = new JProgressBar();
|
||||
progressBar.setIndeterminate(true);
|
||||
panel.add(progressBar, BorderLayout.CENTER);
|
||||
|
||||
JLabel lblProgresslabel = new JLabel("Loading...");
|
||||
lblProgresslabel = new JLabel("Loading...");
|
||||
panel.add(lblProgresslabel, BorderLayout.SOUTH);
|
||||
|
||||
JPanel panel_1 = new JPanel();
|
||||
@ -75,8 +82,13 @@ public class InstallWindow implements IUserInterface {
|
||||
JButton btnCancel = new JButton("Cancel");
|
||||
btnCancel.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
//updateManager.cleanup();
|
||||
if (worker != null) {
|
||||
worker.cancel(true);
|
||||
}
|
||||
frmPackwizlauncher.dispose();
|
||||
// TODO: show window to ask user what to do
|
||||
System.out.println("Update process cancelled by user!");
|
||||
System.exit(1);
|
||||
}
|
||||
});
|
||||
btnCancel.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||
@ -88,7 +100,23 @@ public class InstallWindow implements IUserInterface {
|
||||
|
||||
@Override
|
||||
public void handleException(Exception e) {
|
||||
JOptionPane.showMessageDialog(null, e.getMessage(), title, JOptionPane.ERROR_MESSAGE);
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
JOptionPane.showMessageDialog(null, e.getMessage(), title, JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleExceptionAndExit(Exception e) {
|
||||
// Used to prevent the done() handler of SwingWorker executing if the invokeLater hasn't happened yet
|
||||
aboutToCrash.set(true);
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
JOptionPane.showMessageDialog(null, e.getMessage(), title, JOptionPane.ERROR_MESSAGE);
|
||||
System.exit(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -103,4 +131,57 @@ public class InstallWindow implements IUserInterface {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void submitProgress(InstallProgress progress) {
|
||||
if (worker != null) {
|
||||
worker.publishPublic(progress);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeManager(Runnable task) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
worker = new SwingWorkerButWithPublicPublish<Void, InstallProgress>() {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground() throws Exception {
|
||||
task.run();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void process(List<InstallProgress> chunks) {
|
||||
// Only process last chunk
|
||||
if (chunks.size() > 0) {
|
||||
InstallProgress prog = chunks.get(chunks.size() - 1);
|
||||
if (prog.hasProgress) {
|
||||
progressBar.setIndeterminate(false);
|
||||
progressBar.setValue(prog.progress);
|
||||
progressBar.setMaximum(prog.progressTotal);
|
||||
} else {
|
||||
progressBar.setIndeterminate(true);
|
||||
progressBar.setValue(0);
|
||||
}
|
||||
lblProgresslabel.setText(prog.message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
if (aboutToCrash.get()) {
|
||||
return;
|
||||
}
|
||||
// TODO: a better way to do this?
|
||||
frmPackwizlauncher.dispose();
|
||||
System.out.println("Finished successfully!");
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
};
|
||||
worker.execute();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,10 @@
|
||||
package link.infra.packwiz.installer;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
@ -10,14 +15,39 @@ import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
|
||||
public class Main {
|
||||
|
||||
|
||||
// Actual main() is in RequiresBootstrap!
|
||||
|
||||
|
||||
public Main(String[] args) {
|
||||
// Big overarching try/catch just in case everything breaks
|
||||
try {
|
||||
this.startup(args);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
"A fatal error occurred: \n" + e.getClass().getCanonicalName() + ": " + e.getMessage(),
|
||||
"packwiz-installer", JOptionPane.ERROR_MESSAGE);
|
||||
System.exit(1);
|
||||
}
|
||||
});
|
||||
// In case the eventqueue is broken, exit after 1 minute
|
||||
try {
|
||||
Thread.sleep(60 * 1000);
|
||||
} catch (InterruptedException e1) {
|
||||
// Good, it was already called?
|
||||
return;
|
||||
}
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
protected void startup(String[] args) {
|
||||
Options options = new Options();
|
||||
addNonBootstrapOptions(options);
|
||||
addBootstrapOptions(options);
|
||||
|
||||
|
||||
CommandLineParser parser = new DefaultParser();
|
||||
CommandLine cmd = null;
|
||||
try {
|
||||
@ -32,38 +62,65 @@ public class Main {
|
||||
JOptionPane.showMessageDialog(null, e.getMessage(), "packwiz-installer", JOptionPane.ERROR_MESSAGE);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
|
||||
IUserInterface ui;
|
||||
if (cmd.hasOption("no-gui")) {
|
||||
// if "headless", GUI creation will fail anyway!
|
||||
if (cmd.hasOption("no-gui") || GraphicsEnvironment.isHeadless()) {
|
||||
ui = new CLIHandler();
|
||||
} else {
|
||||
ui = new InstallWindow();
|
||||
}
|
||||
|
||||
|
||||
String[] unparsedArgs = cmd.getArgs();
|
||||
if (unparsedArgs.length > 1) {
|
||||
ui.handleExceptionAndExit(new RuntimeException("Too many arguments specified!"));
|
||||
return;
|
||||
} else if (unparsedArgs.length < 1) {
|
||||
ui.handleExceptionAndExit(new RuntimeException("URI to install from must be specified!"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
String title = cmd.getOptionValue("title");
|
||||
if (title != null) {
|
||||
ui.setTitle(title);
|
||||
}
|
||||
|
||||
String side = cmd.getOptionValue("side");
|
||||
if (side == null) {
|
||||
side = "client";
|
||||
}
|
||||
|
||||
ui.show();
|
||||
|
||||
|
||||
UpdateManager.Options uOptions = new UpdateManager.Options();
|
||||
|
||||
String side = cmd.getOptionValue("side");
|
||||
if (side != null) {
|
||||
uOptions.side = UpdateManager.Options.Side.from(side);
|
||||
}
|
||||
|
||||
try {
|
||||
uOptions.downloadURI = new URI(unparsedArgs[0]);
|
||||
} catch (URISyntaxException e) {
|
||||
// TODO: better error message?
|
||||
ui.handleExceptionAndExit(e);
|
||||
return;
|
||||
}
|
||||
|
||||
// Start update process!
|
||||
// TODO: start in SwingWorker?
|
||||
try {
|
||||
ui.executeManager(new Runnable(){
|
||||
@Override
|
||||
public void run() {
|
||||
new UpdateManager(uOptions, ui);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
// TODO: better error message?
|
||||
ui.handleExceptionAndExit(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Called by packwiz-installer-bootstrap to set up the help command
|
||||
public static void addNonBootstrapOptions(Options options) {
|
||||
options.addOption("s", "side", true, "Side to install mods from (client/server, defaults to client)"); // TODO: implement
|
||||
options.addOption("s", "side", true, "Side to install mods from (client/server, defaults to client)");
|
||||
options.addOption(null, "title", true, "Title of the installer window");
|
||||
}
|
||||
|
||||
@ -73,7 +130,7 @@ public class Main {
|
||||
options.addOption(null, "bootstrap-update-token", true, "Github API Access Token, for private repositories");
|
||||
options.addOption(null, "bootstrap-no-update", false, "Don't update packwiz-installer");
|
||||
options.addOption(null, "bootstrap-main-jar", true, "Location of the packwiz-installer JAR file");
|
||||
options.addOption("g", "no-gui", false, "Don't display a GUI to show update progress"); // TODO: implement
|
||||
options.addOption("g", "no-gui", false, "Don't display a GUI to show update progress");
|
||||
options.addOption("h", "help", false, "Display this message"); // Implemented in packwiz-installer-bootstrap!
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,13 @@
|
||||
package link.infra.packwiz.installer;
|
||||
|
||||
import javax.swing.SwingWorker;
|
||||
|
||||
// Q: AAA WHAT HAVE YOU DONE THIS IS DISGUSTING
|
||||
// A: it just makes things easier, so i can easily have one interface for CLI/GUI
|
||||
// if someone has a better way to do this please PR it
|
||||
public abstract class SwingWorkerButWithPublicPublish<T,V> extends SwingWorker<T,V> {
|
||||
@SafeVarargs
|
||||
public final void publishPublic(V... chunks) {
|
||||
publish(chunks);
|
||||
}
|
||||
}
|
@ -3,21 +3,86 @@ package link.infra.packwiz.installer;
|
||||
import java.net.URI;
|
||||
|
||||
public class UpdateManager {
|
||||
|
||||
|
||||
public final Options opts;
|
||||
public final IUserInterface ui;
|
||||
|
||||
|
||||
public static class Options {
|
||||
public URI downloadURI;
|
||||
public String manifestFile = "packwiz.json";
|
||||
public Side side = Side.CLIENT;
|
||||
|
||||
public static enum Side {
|
||||
CLIENT("client"), SERVER("server"), BOTH("both", new Side[] { CLIENT, SERVER });
|
||||
|
||||
private final String sideName;
|
||||
private final Side[] depSides;
|
||||
|
||||
Side(String sideName) {
|
||||
this.sideName = sideName.toLowerCase();
|
||||
this.depSides = null;
|
||||
}
|
||||
|
||||
Side(String sideName, Side[] depSides) {
|
||||
this.sideName = sideName.toLowerCase();
|
||||
this.depSides = depSides;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.sideName;
|
||||
}
|
||||
|
||||
public boolean hasSide(Side tSide) {
|
||||
if (this.equals(tSide)) {
|
||||
return true;
|
||||
}
|
||||
if (this.depSides != null) {
|
||||
for (int i = 0; i < this.depSides.length; i++) {
|
||||
if (this.depSides[i].equals(tSide)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Side from(String name) {
|
||||
String lowerName = name.toLowerCase();
|
||||
for (Side side : Side.values()) {
|
||||
if (side.sideName == lowerName) {
|
||||
return side;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public UpdateManager(Options opts, IUserInterface ui) {
|
||||
this.opts = opts;
|
||||
this.ui = ui;
|
||||
this.start();
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
|
||||
|
||||
protected void start() {
|
||||
ui.submitProgress(new InstallProgress("Loading pack file..."));
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
// Big oof
|
||||
}
|
||||
ui.submitProgress(new InstallProgress("Loading metadata", 1, 2));
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
// Big oof
|
||||
}
|
||||
ui.submitProgress(new InstallProgress("Loading magic", 2, 2));
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
// Big oof
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user