rusefi/java_console/autoupdate/src/main/java/com/rusefi/autoupdate/Autoupdate.java

246 lines
9.8 KiB
Java
Raw Normal View History

2020-06-06 19:12:48 -07:00
package com.rusefi.autoupdate;
2024-04-01 13:54:43 -07:00
import com.rusefi.core.FindFileHelper;
import com.rusefi.core.io.BundleUtil;
import com.rusefi.core.net.ConnectionAndMeta;
import com.rusefi.core.FileUtil;
import com.rusefi.core.preferences.storage.PersistentConfiguration;
import com.rusefi.core.ui.AutoupdateUtil;
import com.rusefi.core.ui.FrameHelper;
2020-06-06 19:12:48 -07:00
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.*;
2020-06-06 21:12:49 -07:00
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
2020-06-06 21:49:38 -07:00
import java.net.MalformedURLException;
import java.net.URLClassLoader;
2020-07-18 09:38:39 -07:00
import java.util.Arrays;
2020-06-06 19:12:48 -07:00
import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
public class Autoupdate {
2022-11-25 13:29:00 -08:00
private static final String LOGO_PATH = "/com/rusefi/";
private static final String LOGO = LOGO_PATH + "logo.png";
2024-04-19 20:41:31 -07:00
private static final String TITLE = "rusEFI Bundle Updater 20240401";
2020-06-06 19:12:48 -07:00
private static final String AUTOUPDATE_MODE = "autoupdate";
2020-06-06 21:49:38 -07:00
private static final String RUSEFI_CONSOLE_JAR = "rusefi_console.jar";
private static final String COM_RUSEFI_LAUNCHER = "com.rusefi.Launcher";
2020-06-06 19:12:48 -07:00
public static void main(String[] args) {
2024-04-19 20:41:31 -07:00
try {
autoupdate(args);
} catch (Throwable e) {
String stackTrace = extracted(e);
JOptionPane.showMessageDialog(null, stackTrace, "Autoupdate Error " + TITLE, JOptionPane.ERROR_MESSAGE);
}
}
private static String extracted(Throwable e) {
StringBuilder sb = new StringBuilder(e.toString());
for (StackTraceElement ste : e.getStackTrace()) {
sb.append("\n\tat ");
sb.append(ste);
}
return sb.toString();
}
private static void autoupdate(String[] args) {
String bundleFullName = BundleUtil.readBundleFullName();
if (bundleFullName == null) {
System.err.println("ERROR: Autoupdate: unable to perform without bundleFullName (parent folder name)");
System.exit(-1);
}
2024-04-19 20:41:31 -07:00
System.out.println("Handling parent folder name [" + bundleFullName + "]");
String[] bundleFullNameSplit = bundleFullName.split("\\.");
if (bundleFullNameSplit.length != 3)
throw new IllegalStateException("Unexpected parent folder name/bundleFullName [" + bundleFullName + "] exactly two dots expected");
String branchName = bundleFullNameSplit[1];
2020-10-07 16:06:31 -07:00
if (args.length > 0 && args[0].equalsIgnoreCase("release")) {
2020-10-07 17:26:56 -07:00
System.out.println("Release update requested");
downloadAndUnzipAutoupdate(bundleFullNameSplit, UpdateMode.ALWAYS, ConnectionAndMeta.BASE_URL_RELEASE);
2020-06-06 21:49:38 -07:00
} else {
2022-07-17 00:10:42 -07:00
UpdateMode mode = getMode();
if (mode != UpdateMode.NEVER) {
System.out.println("Snapshot requested");
if (branchName.equals("snapshot")) {
2024-04-19 08:24:06 -07:00
downloadAndUnzipAutoupdate(bundleFullNameSplit, mode, ConnectionAndMeta.getBaseUrl());
2022-11-01 07:25:26 -07:00
} else {
downloadAndUnzipAutoupdate(bundleFullNameSplit, mode, String.format(ConnectionAndMeta.BASE_URL_LTS, branchName));
2022-07-17 00:10:42 -07:00
}
} else {
System.out.println("Update mode: NEVER");
}
2020-06-06 19:12:48 -07:00
}
startConsole(args);
}
private static void startConsole(String[] args) {
2020-06-06 21:12:49 -07:00
try {
// we want to make sure that files are available to write so we use reflection to get lazy class initialization
2020-07-18 09:38:39 -07:00
System.out.println("Running rusEFI console with " + Arrays.toString(args));
2020-06-06 21:49:38 -07:00
// since we are overriding file we cannot just use static java classpath while launching
2020-06-16 21:35:16 -07:00
URLClassLoader jarClassLoader = AutoupdateUtil.getClassLoaderByJar(RUSEFI_CONSOLE_JAR);
2020-06-06 21:49:38 -07:00
2020-06-16 21:35:16 -07:00
Class mainClass = Class.forName(COM_RUSEFI_LAUNCHER, true, jarClassLoader);
2020-06-06 21:12:49 -07:00
Method mainMethod = mainClass.getMethod("main", args.getClass());
2020-06-06 21:27:58 -07:00
mainMethod.invoke(null, new Object[]{args});
2024-04-01 13:54:43 -07:00
} catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException | NoSuchMethodException |
MalformedURLException e) {
2020-06-06 21:12:49 -07:00
System.out.println(e);
}
2020-06-06 19:12:48 -07:00
}
private static UpdateMode getMode() {
2020-08-14 17:46:36 -07:00
String value = PersistentConfiguration.getConfig().getRoot().getProperty(AUTOUPDATE_MODE);
2020-06-06 19:12:48 -07:00
try {
return UpdateMode.valueOf(value);
} catch (Throwable e) {
return UpdateMode.ASK;
}
}
private static void downloadAndUnzipAutoupdate(String[] bundleFullNameSplit, UpdateMode mode, String baseUrl) {
2020-06-06 19:12:48 -07:00
try {
String boardName = bundleFullNameSplit[2];
2024-04-02 18:00:14 -07:00
String suffix = FindFileHelper.isObfuscated() ? "_obfuscated_public" : "";
2024-04-01 13:54:43 -07:00
String zipFileName = "rusefi_bundle_" + boardName + suffix + "_autoupdate" + ".zip";
2020-10-07 16:06:31 -07:00
ConnectionAndMeta connectionAndMeta = new ConnectionAndMeta(zipFileName).invoke(baseUrl);
2020-10-07 17:26:56 -07:00
System.out.println("Remote file " + zipFileName);
2020-06-16 21:35:16 -07:00
System.out.println("Server has " + connectionAndMeta.getCompleteFileSize() + " from " + new Date(connectionAndMeta.getLastModified()));
2020-06-06 19:12:48 -07:00
2020-06-17 19:14:22 -07:00
if (AutoupdateUtil.hasExistingFile(zipFileName, connectionAndMeta.getCompleteFileSize(), connectionAndMeta.getLastModified())) {
2020-06-06 19:12:48 -07:00
System.out.println("We already have latest update " + new Date(connectionAndMeta.getLastModified()));
return;
}
if (mode != UpdateMode.ALWAYS) {
boolean doUpdate = askUserIfUpdateIsDesired();
if (!doUpdate)
return;
}
2020-06-16 21:35:16 -07:00
// todo: user could have waited hours to respond to question above, we probably need to re-establish connection
2020-06-06 19:12:48 -07:00
long completeFileSize = connectionAndMeta.getCompleteFileSize();
long lastModified = connectionAndMeta.getLastModified();
System.out.println(Arrays.toString(bundleFullNameSplit) + " " + completeFileSize + " bytes, last modified " + new Date(lastModified));
2020-06-06 19:12:48 -07:00
2020-06-17 19:14:22 -07:00
AutoupdateUtil.downloadAutoupdateFile(zipFileName, connectionAndMeta, TITLE);
2020-06-06 19:12:48 -07:00
File file = new File(zipFileName);
file.setLastModified(lastModified);
System.out.println("Downloaded " + file.length() + " bytes");
2020-07-03 05:49:02 -07:00
FileUtil.unzip(zipFileName, new File(".."));
2022-07-17 00:10:42 -07:00
} catch (ReportedIOException e) {
// we had already reported error with a UI dialog when we had parent frame
System.err.println("Error downloading bundle: " + e);
} catch (IOException e) {
// we are here if error happened while we did not have UI frame
// todo: open frame prior to network connection and keep frame opened while uncompressing?
System.err.println("Error downloading bundle: " + e);
if (!AutoupdateUtil.runHeadless) {
JOptionPane.showMessageDialog(null, "Error downloading " + e, "Error",
2024-04-01 13:54:43 -07:00
JOptionPane.ERROR_MESSAGE);
2022-07-17 00:10:42 -07:00
}
2020-06-06 21:27:58 -07:00
}
}
2020-06-06 19:12:48 -07:00
private static boolean askUserIfUpdateIsDesired() {
CountDownLatch frameClosed = new CountDownLatch(1);
2020-06-16 21:35:16 -07:00
if (AutoupdateUtil.runHeadless) {
2020-06-07 19:21:09 -07:00
// todo: command line ask for options
return true;
}
2020-07-09 17:27:42 -07:00
return askUserIfUpdateIsDesiredWithGUI(frameClosed);
2020-06-07 19:21:09 -07:00
}
2020-07-09 17:27:42 -07:00
private static boolean askUserIfUpdateIsDesiredWithGUI(CountDownLatch frameClosed) {
AtomicBoolean doUpdate = new AtomicBoolean();
2020-06-06 19:12:48 -07:00
FrameHelper frameHelper = new FrameHelper() {
@Override
protected void onWindowClosed() {
frameClosed.countDown();
}
};
2022-11-25 13:29:00 -08:00
JFrame frame = frameHelper.getFrame();
frame.setTitle(TITLE);
ImageIcon icon = AutoupdateUtil.loadIcon(LOGO);
if (icon != null)
frame.setIconImage(icon.getImage());
2020-06-06 19:12:48 -07:00
JPanel choice = new JPanel(new BorderLayout());
choice.add(new JLabel("Do you want to update bundle to latest version?"), BorderLayout.NORTH);
JPanel middle = new JPanel(new FlowLayout());
JButton never = new JButton("Never");
never.setBackground(Color.red);
never.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
2020-08-14 17:46:36 -07:00
PersistentConfiguration.getConfig().getRoot().setProperty(AUTOUPDATE_MODE, UpdateMode.NEVER.toString());
2022-11-25 13:29:00 -08:00
frame.dispose();
2020-06-06 19:12:48 -07:00
}
});
middle.add(never);
JButton no = new JButton("No");
no.setBackground(Color.red);
no.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
2022-11-25 13:29:00 -08:00
frame.dispose();
2020-06-06 19:12:48 -07:00
}
});
middle.add(no);
JButton once = new JButton("Once");
once.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
doUpdate.set(true);
2022-11-25 13:29:00 -08:00
frame.dispose();
2020-06-06 19:12:48 -07:00
}
});
middle.add(once);
JButton always = new JButton("Always");
always.setBackground(Color.green);
always.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
2020-08-14 17:46:36 -07:00
PersistentConfiguration.getConfig().getRoot().setProperty(AUTOUPDATE_MODE, UpdateMode.ALWAYS.toString());
2020-06-06 19:12:48 -07:00
doUpdate.set(true);
2022-11-25 13:29:00 -08:00
frame.dispose();
2020-06-06 19:12:48 -07:00
}
});
middle.add(always);
choice.add(middle, BorderLayout.CENTER);
frameHelper.showFrame(choice, true);
try {
frameClosed.await();
} catch (InterruptedException e) {
// ignore
}
return doUpdate.get();
}
enum UpdateMode {
ALWAYS,
NEVER,
ASK
}
}