diff --git a/.github/workflows/build-tsplugin-body.yaml b/.github/workflows/build-tsplugin-body.yaml index e9db327678..125b765135 100644 --- a/.github/workflows/build-tsplugin-body.yaml +++ b/.github/workflows/build-tsplugin-body.yaml @@ -17,7 +17,7 @@ jobs: - name: Test Compiler run: javac -version - - name: Install Coverage Tools + - name: Install Tools run: sudo apt-get install ncftp - name: Build TS plugin body diff --git a/java_console/autoupdate/src/com/rusefi/autoupdate/Autoupdate.java b/java_console/autoupdate/src/com/rusefi/autoupdate/Autoupdate.java index beaf893588..f8eed2ba2d 100644 --- a/java_console/autoupdate/src/com/rusefi/autoupdate/Autoupdate.java +++ b/java_console/autoupdate/src/com/rusefi/autoupdate/Autoupdate.java @@ -10,12 +10,10 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.HttpURLConnection; import java.net.MalformedURLException; -import java.net.URL; import java.net.URLClassLoader; import java.util.Date; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -25,11 +23,8 @@ public class Autoupdate { private static final String TITLE = "rusEFI Bundle Updater 20200607"; private static final String BUNDLE_NAME_FILE = "../bundle_name.ini"; private static final String AUTOUPDATE_MODE = "autoupdate"; - private static final int BUFFER_SIZE = 32 * 1024; - private static final int STEPS = 1000; private static final String RUSEFI_CONSOLE_JAR = "rusefi_console.jar"; private static final String COM_RUSEFI_LAUNCHER = "com.rusefi.Launcher"; - private static final boolean runHeadless = Boolean.getBoolean("run_headless") || GraphicsEnvironment.isHeadless(); public static void main(String[] args) { UpdateMode mode = getMode(); @@ -50,12 +45,9 @@ public class Autoupdate { // we want to make sure that files are available to write so we use reflection to get lazy class initialization System.out.println("Running rusEFI console"); // since we are overriding file we cannot just use static java classpath while launching - URLClassLoader child = new URLClassLoader( - new URL[]{new File(RUSEFI_CONSOLE_JAR).toURI().toURL()}, - Autoupdate.class.getClassLoader() - ); + URLClassLoader jarClassLoader = AutoupdateUtil.getClassLoaderByJar(RUSEFI_CONSOLE_JAR); - Class mainClass = Class.forName(COM_RUSEFI_LAUNCHER, true, child); + Class mainClass = Class.forName(COM_RUSEFI_LAUNCHER, true, jarClassLoader); Method mainMethod = mainClass.getMethod("main", args.getClass()); mainMethod.invoke(null, new Object[]{args}); } catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | MalformedURLException e) { @@ -75,8 +67,8 @@ public class Autoupdate { private static void handleBundle(String bundleFullName, UpdateMode mode) { try { String zipFileName = bundleFullName + "_autoupdate" + ".zip"; - ConnectionAndMeta connectionAndMeta = new ConnectionAndMeta(zipFileName).invoke(); - System.out.println("Server has " + connectionAndMeta.completeFileSize + " from " + new Date(connectionAndMeta.getLastModified())); + AutoupdateUtil.ConnectionAndMeta connectionAndMeta = new AutoupdateUtil.ConnectionAndMeta(zipFileName).invoke(); + System.out.println("Server has " + connectionAndMeta.getCompleteFileSize() + " from " + new Date(connectionAndMeta.getLastModified())); if (hasExistingFile(zipFileName, connectionAndMeta.getCompleteFileSize(), connectionAndMeta.getLastModified())) { System.out.println("We already have latest update " + new Date(connectionAndMeta.getLastModified())); @@ -89,13 +81,14 @@ public class Autoupdate { return; } + // todo: user could have waited hours to respond to question above, we probably need to re-establish connection HttpURLConnection httpConnection = connectionAndMeta.getHttpConnection(); long completeFileSize = connectionAndMeta.getCompleteFileSize(); long lastModified = connectionAndMeta.getLastModified(); System.out.println(bundleFullName + " " + completeFileSize + " bytes, last modified " + new Date(lastModified)); - downloadAutoupdateFile(zipFileName, httpConnection, completeFileSize); + AutoupdateUtil.downloadAutoupdateFile(zipFileName, httpConnection, completeFileSize, TITLE); File file = new File(zipFileName); file.setLastModified(lastModified); @@ -107,59 +100,11 @@ public class Autoupdate { } } - private static void downloadAutoupdateFile(String zipFileName, HttpURLConnection httpConnection, long completeFileSize) throws IOException { - BufferedInputStream in = new BufferedInputStream(httpConnection.getInputStream()); - FileOutputStream fos = new FileOutputStream(zipFileName); - BufferedOutputStream bout = new BufferedOutputStream(fos, BUFFER_SIZE); - byte[] data = new byte[BUFFER_SIZE]; - long downloadedFileSize = 0; - int newDataSize; - - int printedPercentage = 0; - - FrameHelper frameHelper = null; - final AtomicReference jProgressBarAtomicReference = new AtomicReference<>(); - if (!runHeadless) { - frameHelper = new FrameHelper(); - JProgressBar jProgressBar = new JProgressBar(); - - frameHelper.getFrame().setTitle(TITLE); - jProgressBar.setMaximum(STEPS); - jProgressBarAtomicReference.set(jProgressBar); - frameHelper.showFrame(jProgressBar, true); - } - - while ((newDataSize = in.read(data, 0, BUFFER_SIZE)) >= 0) { - downloadedFileSize += newDataSize; - - // calculate progress - final int currentProgress = (int) ((((double) downloadedFileSize) / ((double) completeFileSize)) * STEPS); - - int currentPercentage = (int) (100L * downloadedFileSize / completeFileSize); - if (currentPercentage > printedPercentage + 5) { - System.out.println("Downloaded " + currentPercentage + "%"); - printedPercentage = currentPercentage; - } - - if (!runHeadless) { - SwingUtilities.invokeLater(() -> jProgressBarAtomicReference.get().setValue(currentProgress)); - } - - bout.write(data, 0, newDataSize); - } - bout.close(); - in.close(); - - if (!runHeadless) { - frameHelper.getFrame().dispose(); - } - } - private static boolean askUserIfUpdateIsDesired() { AtomicBoolean doUpdate = new AtomicBoolean(); CountDownLatch frameClosed = new CountDownLatch(1); - if (runHeadless) { + if (AutoupdateUtil.runHeadless) { // todo: command line ask for options return true; } @@ -303,34 +248,4 @@ public class Autoupdate { ASK } - private static class ConnectionAndMeta { - private String zipFileName; - private HttpURLConnection httpConnection; - private long completeFileSize; - private long lastModified; - - public ConnectionAndMeta(String zipFileName) { - this.zipFileName = zipFileName; - } - - public HttpURLConnection getHttpConnection() { - return httpConnection; - } - - public long getCompleteFileSize() { - return completeFileSize; - } - - public long getLastModified() { - return lastModified; - } - - public ConnectionAndMeta invoke() throws IOException { - URL url = new URL("https://rusefi.com/build_server/autoupdate/" + zipFileName); - httpConnection = (HttpURLConnection) url.openConnection(); - completeFileSize = httpConnection.getContentLength(); - lastModified = httpConnection.getLastModified(); - return this; - } - } } diff --git a/java_console/autoupdate/src/com/rusefi/autoupdate/AutoupdateUtil.java b/java_console/autoupdate/src/com/rusefi/autoupdate/AutoupdateUtil.java new file mode 100644 index 0000000000..bf0d257e79 --- /dev/null +++ b/java_console/autoupdate/src/com/rusefi/autoupdate/AutoupdateUtil.java @@ -0,0 +1,109 @@ +package com.rusefi.autoupdate; + +import com.rusefi.ui.util.FrameHelper; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.*; +import java.io.*; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicReference; + +public class AutoupdateUtil { + public static final boolean runHeadless = Boolean.getBoolean("run_headless") || GraphicsEnvironment.isHeadless(); + + private static final int BUFFER_SIZE = 32 * 1024; + private static final int STEPS = 1000; + + public static void downloadAutoupdateFile(String zipFileName, HttpURLConnection httpConnection, long completeFileSize, String title) throws IOException { + Objects.requireNonNull(httpConnection, "httpConnection"); + BufferedInputStream in = new BufferedInputStream(httpConnection.getInputStream()); + FileOutputStream fos = new FileOutputStream(zipFileName); + BufferedOutputStream bout = new BufferedOutputStream(fos, BUFFER_SIZE); + byte[] data = new byte[BUFFER_SIZE]; + long downloadedFileSize = 0; + int newDataSize; + + int printedPercentage = 0; + + FrameHelper frameHelper = null; + final AtomicReference jProgressBarAtomicReference = new AtomicReference<>(); + if (!runHeadless) { + frameHelper = new FrameHelper(); + JProgressBar jProgressBar = new JProgressBar(); + + frameHelper.getFrame().setTitle(title); + jProgressBar.setMaximum(STEPS); + jProgressBarAtomicReference.set(jProgressBar); + frameHelper.showFrame(jProgressBar, true); + } + + while ((newDataSize = in.read(data, 0, BUFFER_SIZE)) >= 0) { + downloadedFileSize += newDataSize; + + // calculate progress + final int currentProgress = (int) ((((double) downloadedFileSize) / ((double) completeFileSize)) * STEPS); + + int currentPercentage = (int) (100L * downloadedFileSize / completeFileSize); + if (currentPercentage > printedPercentage + 5) { + System.out.println("Downloaded " + currentPercentage + "%"); + printedPercentage = currentPercentage; + } + + if (!runHeadless) { + SwingUtilities.invokeLater(() -> jProgressBarAtomicReference.get().setValue(currentProgress)); + } + + bout.write(data, 0, newDataSize); + } + bout.close(); + in.close(); + + if (!runHeadless) { + frameHelper.getFrame().dispose(); + } + } + + @NotNull + public static URLClassLoader getClassLoaderByJar(String jar) throws MalformedURLException { + return new URLClassLoader( + new URL[]{new File(jar).toURI().toURL()}, + AutoupdateUtil.class.getClassLoader() + ); + } + + public static class ConnectionAndMeta { + private String zipFileName; + private HttpURLConnection httpConnection; + private long completeFileSize; + private long lastModified; + + public ConnectionAndMeta(String zipFileName) { + this.zipFileName = zipFileName; + } + + public HttpURLConnection getHttpConnection() { + return httpConnection; + } + + public long getCompleteFileSize() { + return completeFileSize; + } + + public long getLastModified() { + return lastModified; + } + + public ConnectionAndMeta invoke() throws IOException { + URL url = new URL("https://rusefi.com/build_server/autoupdate/" + zipFileName); + httpConnection = (HttpURLConnection) url.openConnection(); + completeFileSize = httpConnection.getContentLength(); + lastModified = httpConnection.getLastModified(); + return this; + } + } +} diff --git a/java_tools/ts_plugin/src/com/rusefi/ts_plugin/PluginEntry.java b/java_tools/ts_plugin/src/com/rusefi/ts_plugin/PluginEntry.java index 61393d8398..f714b5dda9 100644 --- a/java_tools/ts_plugin/src/com/rusefi/ts_plugin/PluginEntry.java +++ b/java_tools/ts_plugin/src/com/rusefi/ts_plugin/PluginEntry.java @@ -18,12 +18,13 @@ import java.io.IOException; import java.util.Map; import java.util.TreeMap; +/** + * TsPlugin launcher creates an instance of this class via reflection. + */ public class PluginEntry implements TsPluginBody { private final AuthTokenPanel tokenPanel = new AuthTokenPanel(); private final JComponent content = new JPanel(); - private ControllerAccess controllerAccess; - public PluginEntry() { content.add(tokenPanel.getContent()); @@ -31,12 +32,16 @@ public class PluginEntry implements TsPluginBody { upload.addActionListener(new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { - Msq tune = writeCurrentTune(controllerAccess); + Msq tune = writeCurrentTune(ControllerAccess.getInstance()); Online.uploadTune(tune, tokenPanel, content); } }); content.add(upload); + } + @Override + public JComponent getContent() { + return content; } public void close() { @@ -68,7 +73,6 @@ public class PluginEntry implements TsPluginBody { return ControllerAccess.getInstance().getEcuConfigurationNames()[0]; } - private static String toString(double scalarValue, int decimalPlaces) { // todo: start using decimalPlaces parameter! return Double.toString(scalarValue); diff --git a/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/Sandbox.java b/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/Sandbox.java index 90f23f615c..73a206e42a 100644 --- a/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/Sandbox.java +++ b/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/Sandbox.java @@ -1,7 +1,5 @@ package com.rusefi.ts_plugin; -import com.rusefi.ts_plugin.TsPluginLauncher; - import javax.swing.*; public class Sandbox { diff --git a/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/TsPluginBody.java b/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/TsPluginBody.java index d9c7a2c7b4..9d16ed1e0c 100644 --- a/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/TsPluginBody.java +++ b/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/TsPluginBody.java @@ -1,5 +1,9 @@ package com.rusefi.ts_plugin; +import javax.swing.*; + public interface TsPluginBody { + JComponent getContent(); + void close(); } diff --git a/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/TsPluginLauncher.java b/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/TsPluginLauncher.java index 8541c58466..e0bb31a135 100644 --- a/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/TsPluginLauncher.java +++ b/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/TsPluginLauncher.java @@ -10,11 +10,13 @@ import javax.swing.*; * by the way TS installs stuff into %user%\.efianalytics\TunerStudio\plugins folder */ public class TsPluginLauncher implements ApplicationPlugin { - private static final String VERSION = "alpha2020"; + + public static final String VERSION = "alpha2020"; private final JPanel content = new JPanel(new VerticalFlowLayout()); public TsPluginLauncher() { content.add(new JLabel("" + VERSION)); + content.add(new Updater().getContent()); } @Override diff --git a/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/Updater.java b/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/Updater.java new file mode 100644 index 0000000000..ce42374577 --- /dev/null +++ b/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/Updater.java @@ -0,0 +1,71 @@ +package com.rusefi.ts_plugin; + +import com.rusefi.autoupdate.AutoupdateUtil; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.io.IOException; +import java.net.URLClassLoader; + +public class Updater { + private static final String PLUGIN_BODY_JAR = "rusefi_plugin_body.jar"; + private static final String TITLE = "rusEFI plugin installer " + TsPluginLauncher.VERSION; + + private final JPanel content = new JPanel(); + + public Updater() { + JButton download = new JButton("Download"); + + download.addActionListener(new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + new Thread(() -> startDownload(download)).start(); + + + } + }); + + content.add(download); + } + + private void startDownload(JButton download) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + download.setEnabled(false); + } + }); + + try { + AutoupdateUtil.ConnectionAndMeta connectionAndMeta = new AutoupdateUtil.ConnectionAndMeta(PLUGIN_BODY_JAR).invoke(); + + AutoupdateUtil.downloadAutoupdateFile(PLUGIN_BODY_JAR, connectionAndMeta.getHttpConnection(), connectionAndMeta.getCompleteFileSize(), + TITLE); + + URLClassLoader jarClassLoader = AutoupdateUtil.getClassLoaderByJar(PLUGIN_BODY_JAR); + + Class clazz = Class.forName("com.rusefi.ts_plugin.PluginEntry", true, jarClassLoader); + TsPluginBody instance = (TsPluginBody) clazz.newInstance(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + replaceWith(instance); + } + }); + + } catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e) { + download.setEnabled(true); + + } + + } + + private void replaceWith(TsPluginBody instance) { + content.removeAll(); + content.add(instance.getContent()); + } + + public JPanel getContent() { + return content; + } +} diff --git a/java_tools/ts_plugin_launcher/ts_plugin_launcher.iml b/java_tools/ts_plugin_launcher/ts_plugin_launcher.iml index a3a4e1a20b..de860a0204 100644 --- a/java_tools/ts_plugin_launcher/ts_plugin_launcher.iml +++ b/java_tools/ts_plugin_launcher/ts_plugin_launcher.iml @@ -8,5 +8,6 @@ + \ No newline at end of file