feat: preparing for download and install of mode files

This commit is contained in:
lantzelot-swe 2021-12-04 22:16:41 +01:00
parent fee069f0cd
commit 33a37968f1
7 changed files with 303 additions and 190 deletions

View File

@ -46,9 +46,9 @@ import se.lantz.gui.install.VersionDownloadDialog;
import se.lantz.manager.BackupManager;
import se.lantz.manager.ExportManager;
import se.lantz.manager.ImportManager;
import se.lantz.manager.PCUAEInstallManager;
import se.lantz.manager.RestoreManager;
import se.lantz.manager.SavedStatesManager;
import se.lantz.manager.pcuae.PCUAEInstallManager;
import se.lantz.model.MainViewModel;
import se.lantz.model.data.GameListData;
import se.lantz.model.data.GameView;

View File

@ -4,7 +4,7 @@ import java.awt.Dimension;
import java.awt.Frame;
import se.lantz.gui.BaseDialog;
import se.lantz.manager.PCUAEInstallManager;
import se.lantz.manager.pcuae.PCUAEInstallManager;
public class PCUAEVersionDownloadDialog extends BaseDialog
{

View File

@ -1,4 +1,4 @@
package se.lantz.manager;
package se.lantz.manager.pcuae;
import java.awt.AWTEvent;
import java.awt.Toolkit;
@ -19,8 +19,6 @@ import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
@ -33,89 +31,75 @@ import dyorgio.runtime.out.process.CallableSerializable;
import dyorgio.runtime.run.as.root.RootExecutor;
import se.lantz.gui.MainWindow;
import se.lantz.gui.download.DownloadDialog;
import se.lantz.gui.install.PCUAEVersionDownloadDialog;
import se.lantz.util.ExceptionHandler;
public class PCUAEInstallManager implements AWTEventListener
public abstract class BaseInstallManger implements AWTEventListener
{
public static final String INSTALL_FOLDER = "./pcuae-install/";
private boolean blockEvents = false;
private ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
protected ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
private static String latestVersion = "";
private static String tagloadUrl = "";
private String downloadUrl = "";
private String pcuaeMainInstallFile = "";
private static String pcuaeLatestInInstallFolder = "";
private static String latestReleaseDescription = "";
protected volatile boolean downloadIterrupted = false;
private JMenuItem exportMenuItem;
private volatile boolean downloadIterrupted = false;
public PCUAEInstallManager(JMenuItem exportMenuItem)
public BaseInstallManger()
{
this.exportMenuItem = exportMenuItem;
Toolkit.getDefaultToolkit().addAWTEventListener(this,
AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK |
AWTEvent.MOUSE_WHEEL_EVENT_MASK |
AWTEvent.MOUSE_MOTION_EVENT_MASK);
}
public void installPCUAE()
@Override
public void eventDispatched(AWTEvent event)
{
readVersionFromInstallFolder();
if (isNewVersionAvailable())
if (blockEvents)
{
askAndStartDownload(pcuaeLatestInInstallFolder.isEmpty());
}
else
{
askToInstallExistingVersion();
if (event instanceof InputEvent)
{
((InputEvent) event).consume();
}
else if (event instanceof MouseEvent)
{
((MouseEvent) event).consume();
}
}
}
private void askAndStartDownload(boolean firstDownload)
public void switchToBusyCursor(final javax.swing.JFrame frame)
{
PCUAEVersionDownloadDialog dialog = new PCUAEVersionDownloadDialog(MainWindow.getInstance(), firstDownload);
dialog.pack();
dialog.setLocationRelativeTo(MainWindow.getInstance());
if (dialog.showDialog())
{
downloadLatestPCUAE();
}
else if (!firstDownload)
{
askToInstallExistingVersion();
}
startEventTrap(frame);
frame.getGlassPane().setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR));
}
private void askToInstallExistingVersion()
public void switchToNormalCursor(final javax.swing.JFrame frame)
{
int value = JOptionPane.showConfirmDialog(MainWindow.getInstance(),
"Do you want to install PCUAE (" + pcuaeMainInstallFile + ") now?",
"Install PCUAE",
JOptionPane.YES_NO_OPTION);
if (value == JOptionPane.YES_OPTION)
{
singleThreadExecutor.execute(() -> runAndWaitForInstallation());
}
frame.getGlassPane().setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR));
stopEventTrap(frame);
}
private boolean isNewVersionAvailable()
protected void startEventTrap(javax.swing.JFrame frame)
{
fetchLatestPCUAEVersionFromGithub();
return !pcuaeLatestInInstallFolder.equals(pcuaeMainInstallFile);
blockEvents = true;
frame.getGlassPane().setVisible(true);
}
private void readVersionFromInstallFolder()
protected void stopEventTrap(javax.swing.JFrame frame)
{
pcuaeLatestInInstallFolder = "";
blockEvents = false;
java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue();
frame.getGlassPane().setVisible(false);
}
protected String readVersionFromInstallFolder(String installFileName)
{
String latestInInstallFolder = "";
FilenameFilter filter = new FilenameFilter()
{
@Override
public boolean accept(File f, String name)
{
return name.endsWith(".exe");
return name.contains(installFileName) && name.endsWith(".exe");
}
};
File installFolder = new File(INSTALL_FOLDER);
@ -134,91 +118,18 @@ public class PCUAEInstallManager implements AWTEventListener
if (latestFile != null)
{
pcuaeLatestInInstallFolder = latestFile.getName();
latestInInstallFolder = latestFile.getName();
}
return latestInInstallFolder;
}
private void runAndWaitForInstallation()
{
switchToBusyCursor(MainWindow.getInstance());
RootExecutor rootExecutor;
try
{
rootExecutor = new RootExecutor("-Xmx64m");
// Execute privileged action without return
CallableSerializable<Integer> installCallable = new InstallCallable(pcuaeMainInstallFile);
int value = rootExecutor.call(installCallable);
//0 -> installed
//255 -> aborted
if (value == 0)
{
launchExportDialog();
}
}
catch (Exception e1)
{
ExceptionHandler.logException(e1, "Could not execute RootExecutor");
}
finally
{
SwingUtilities.invokeLater(() -> switchToNormalCursor(MainWindow.getInstance()));
}
}
private void launchExportDialog()
{
SwingUtilities.invokeLater(() -> exportMenuItem.doClick());
}
public void switchToBusyCursor(final javax.swing.JFrame frame)
{
startEventTrap(frame);
frame.getGlassPane().setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR));
}
public void switchToNormalCursor(final javax.swing.JFrame frame)
{
frame.getGlassPane().setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR));
stopEventTrap(frame);
}
private void startEventTrap(javax.swing.JFrame frame)
{
blockEvents = true;
frame.getGlassPane().setVisible(true);
}
private void stopEventTrap(javax.swing.JFrame frame)
{
blockEvents = false;
java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue();
frame.getGlassPane().setVisible(false);
}
@Override
public void eventDispatched(AWTEvent event)
{
if (blockEvents)
{
if (event instanceof InputEvent)
{
((InputEvent) event).consume();
}
else if (event instanceof MouseEvent)
{
((MouseEvent) event).consume();
}
}
}
public void fetchLatestPCUAEVersionFromGithub()
public GithubAssetInformation fetchLatestVersionFromGithub(String assetsName)
{
GithubAssetInformation githubInfo = new GithubAssetInformation();
try
{
//TODO: To get all releases, use "https://CommodoreOS@api.github.com/repos/CommodoreOS/PCUAE/releases"-
//How to handle mode packs?
//Get all releases, check which one contains the latest file with assetName (part of the name)
URL url = new URL("https://CommodoreOS@api.github.com/repos/CommodoreOS/PCUAE/releases/latest");
@ -238,57 +149,50 @@ public class PCUAEInstallManager implements AWTEventListener
reader.setLenient(true);
JsonElement root = new JsonParser().parse(reader);
JsonObject jsonObject = root.getAsJsonObject();
latestVersion = jsonObject.get("tag_name").getAsString();
tagloadUrl = jsonObject.get("html_url").getAsString();
downloadUrl = jsonObject.get("assets").getAsJsonArray().get(0).getAsJsonObject()
.get("browser_download_url").getAsString();
latestReleaseDescription = jsonObject.get("body").getAsString();
pcuaeMainInstallFile = downloadUrl.substring(downloadUrl.lastIndexOf("/") + 1);
githubInfo.setLatestVersion(jsonObject.get("tag_name").getAsString());
githubInfo.setReleaseTagUrl(jsonObject.get("html_url").getAsString());
//TODO: fix
String downloadUrl =
jsonObject.get("assets").getAsJsonArray().get(0).getAsJsonObject().get("browser_download_url").getAsString();
githubInfo.setDownloadUrl(downloadUrl);
githubInfo.setInstallFile(downloadUrl.substring(downloadUrl.lastIndexOf("/") + 1));
}
catch (IOException ex)
{
ExceptionHandler.handleException(ex, "Could not check version");
}
return githubInfo;
}
private void downloadLatestPCUAE()
protected void runAndWaitForInstallation(String fileToInstall)
{
DownloadDialog progressDialog = new DownloadDialog("Downloading PCUAE version " + latestVersion);
singleThreadExecutor.execute(() -> startDownload(progressDialog));
progressDialog.pack();
progressDialog.setLocationRelativeTo(MainWindow.getInstance());
if (progressDialog.showDialog())
switchToBusyCursor(MainWindow.getInstance());
RootExecutor rootExecutor;
try
{
pcuaeLatestInInstallFolder = pcuaeMainInstallFile;
int value =
JOptionPane.showConfirmDialog(MainWindow.getInstance(),
"Download completed, do you want to install PCUAE " + latestVersion + " now?",
"Download Complete",
JOptionPane.YES_NO_OPTION);
if (value == JOptionPane.YES_OPTION)
rootExecutor = new RootExecutor("-Xmx64m");
// Execute privileged action without return
CallableSerializable<Integer> installCallable = new InstallCallable(fileToInstall);
int value = rootExecutor.call(installCallable);
//0 -> installed
//255 -> aborted
if (value == 0)
{
singleThreadExecutor.execute(() -> runAndWaitForInstallation());
executeAfterInstallation();
}
}
else
catch (Exception e1)
{
downloadIterrupted = true;
//Make sure this executes after the downloading has been interrupted
singleThreadExecutor.execute(() -> {
try
{
Files.deleteIfExists(new File(INSTALL_FOLDER + pcuaeMainInstallFile).toPath());
}
catch (IOException e)
{
ExceptionHandler.handleException(e, "Could not delete partially downloaded file");
}
});
ExceptionHandler.logException(e1, "Could not execute RootExecutor");
}
finally
{
SwingUtilities.invokeLater(() -> switchToNormalCursor(MainWindow.getInstance()));
}
}
public void startDownload(final DownloadDialog downloadDialog)
public void startDownload(final DownloadDialog downloadDialog, GithubAssetInformation assetInfo)
{
downloadIterrupted = false;
JProgressBar progressBar = downloadDialog.getProgressBar();
@ -296,13 +200,13 @@ public class PCUAEInstallManager implements AWTEventListener
URL url;
try
{
url = new URL(downloadUrl);
url = new URL(assetInfo.getDownloadUrl());
Files.createDirectories(new File(INSTALL_FOLDER).toPath());
HttpURLConnection httpConnection = (HttpURLConnection) (url.openConnection());
long completeFileSize = httpConnection.getContentLength();
BufferedInputStream in = new BufferedInputStream(httpConnection.getInputStream());
FileOutputStream fos = new FileOutputStream(INSTALL_FOLDER + pcuaeMainInstallFile);
FileOutputStream fos = new FileOutputStream(INSTALL_FOLDER + assetInfo.getInstallFile());
BufferedOutputStream bout = new BufferedOutputStream(fos, 1024);
byte[] data = new byte[1024];
long downloadedFileSize = 0;
@ -337,23 +241,21 @@ public class PCUAEInstallManager implements AWTEventListener
}
}
public static String getLatestInInstallFolder()
protected void cleanupInterruptedDownload(String fileName)
{
return pcuaeLatestInInstallFolder;
downloadIterrupted = true;
//Make sure this executes after the downloading has been interrupted
singleThreadExecutor.execute(() -> {
try
{
Files.deleteIfExists(new File(INSTALL_FOLDER + fileName).toPath());
}
catch (IOException e)
{
ExceptionHandler.handleException(e, "Could not delete partially downloaded file");
}
});
}
public static String getLatestVersion()
{
return latestVersion;
}
public static String getDownloadUrl()
{
return tagloadUrl;
}
public static String getLatestReleaseDescription()
{
return latestReleaseDescription;
}
protected abstract void executeAfterInstallation();
}

View File

@ -0,0 +1,54 @@
package se.lantz.manager.pcuae;
public class GithubAssetInformation
{
String latestVersion = "";
String releaseTagUrl = "";
String downloadUrl = "";
String installFile = "";
public GithubAssetInformation()
{
}
public String getLatestVersion()
{
return latestVersion;
}
public void setLatestVersion(String latestVersion)
{
this.latestVersion = latestVersion;
}
public String getReleaseTagUrl()
{
return releaseTagUrl;
}
public void setReleaseTagUrl(String releaseTagUrl)
{
this.releaseTagUrl = releaseTagUrl;
}
public String getDownloadUrl()
{
return downloadUrl;
}
public void setDownloadUrl(String downloadUrl)
{
this.downloadUrl = downloadUrl;
}
public String getInstallFile()
{
return installFile;
}
public void setInstallFile(String installFile)
{
this.installFile = installFile;
}
}

View File

@ -1,4 +1,4 @@
package se.lantz.manager;
package se.lantz.manager.pcuae;
import java.io.File;
import java.io.IOException;

View File

@ -0,0 +1,128 @@
package se.lantz.manager.pcuae;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import se.lantz.gui.MainWindow;
import se.lantz.gui.download.DownloadDialog;
import se.lantz.gui.install.PCUAEVersionDownloadDialog;
import se.lantz.util.ManagerVersionChecker;
public class PCUAEInstallManager extends BaseInstallManger
{
public static final String INSTALL_FOLDER = "./pcuae-install/";
private static final String PCUAE_INSTALL_NAME = "pcuae";
// private static final String AMIGA_MODE_INSTALL_NAME = "amiga";
// private static final String ATARI_MODE_INSTALL_NAME = "atari";
// private static final String LINUX_MODE_INSTALL_NAME = "linux";
// private static final String RETROARCH_MODE_INSTALL_NAME = "retroarch";
// private static final String VICE_MODE_INSTALL_NAME = "vice";
private static String pcuaeLatestInInstallFolder = "";
private static GithubAssetInformation gitHubReleaseInformation = new GithubAssetInformation();
private JMenuItem exportMenuItem;
public PCUAEInstallManager(JMenuItem exportMenuItem)
{
this.exportMenuItem = exportMenuItem;
}
public void installPCUAE()
{
pcuaeLatestInInstallFolder = readVersionFromInstallFolder(PCUAE_INSTALL_NAME);
if (isNewVersionAvailable())
{
askAndStartDownload(pcuaeLatestInInstallFolder.isEmpty());
}
else
{
askToInstallExistingVersion();
}
}
private void askAndStartDownload(boolean firstDownload)
{
PCUAEVersionDownloadDialog dialog = new PCUAEVersionDownloadDialog(MainWindow.getInstance(), firstDownload);
dialog.pack();
dialog.setLocationRelativeTo(MainWindow.getInstance());
if (dialog.showDialog())
{
downloadLatestPCUAE();
}
else if (!firstDownload)
{
askToInstallExistingVersion();
}
}
private void askToInstallExistingVersion()
{
int value = JOptionPane.showConfirmDialog(MainWindow.getInstance(),
"Do you want to install PCUAE (" + pcuaeLatestInInstallFolder + ") now?",
"Install PCUAE",
JOptionPane.YES_NO_OPTION);
if (value == JOptionPane.YES_OPTION)
{
singleThreadExecutor.execute(() -> runAndWaitForInstallation(pcuaeLatestInInstallFolder));
}
}
private boolean isNewVersionAvailable()
{
gitHubReleaseInformation = fetchLatestVersionFromGithub(PCUAE_INSTALL_NAME);
return ManagerVersionChecker.getIntVersion(pcuaeLatestInInstallFolder) < ManagerVersionChecker
.getIntVersion(gitHubReleaseInformation.getInstallFile());
}
@Override
protected void executeAfterInstallation()
{
SwingUtilities.invokeLater(() -> exportMenuItem.doClick());
}
private void downloadLatestPCUAE()
{
DownloadDialog progressDialog =
new DownloadDialog("Downloading PCUAE version " + gitHubReleaseInformation.getLatestVersion());
singleThreadExecutor.execute(() -> startDownload(progressDialog, gitHubReleaseInformation));
progressDialog.pack();
progressDialog.setLocationRelativeTo(MainWindow.getInstance());
if (progressDialog.showDialog())
{
pcuaeLatestInInstallFolder = gitHubReleaseInformation.getInstallFile();
int value = JOptionPane.showConfirmDialog(MainWindow.getInstance(),
"Download completed, do you want to install PCUAE " +
gitHubReleaseInformation.getLatestVersion() + " now?",
"Download Complete",
JOptionPane.YES_NO_OPTION);
if (value == JOptionPane.YES_OPTION)
{
singleThreadExecutor.execute(() -> runAndWaitForInstallation(pcuaeLatestInInstallFolder));
}
}
else
{
cleanupInterruptedDownload(gitHubReleaseInformation.getInstallFile());
}
}
public static String getLatestInInstallFolder()
{
return pcuaeLatestInInstallFolder;
}
public static String getLatestVersion()
{
return gitHubReleaseInformation.getLatestVersion();
}
public static String getDownloadUrl()
{
return gitHubReleaseInformation.getDownloadUrl();
}
}

View File

@ -15,10 +15,15 @@ import java.nio.file.StandardCopyOption;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
@ -29,6 +34,7 @@ import se.lantz.gui.download.DownloadDialog;
public class ManagerVersionChecker
{
private static final Logger logger = LoggerFactory.getLogger(FileManager.class);
public static final String TEMP_FOLDER = "./temp/";
private static String latestVersion = "";
private static String tagloadUrl = "";
@ -178,8 +184,31 @@ public class ManagerVersionChecker
public static boolean isNewVersionAvailable()
{
//Ignore all versions that starts with 1
return !latestVersion.startsWith("1") && !FileManager.getPcuVersionFromManifest().equals(latestVersion);
logger.debug("Manifest version=" + FileManager.getPcuVersionFromManifest());
//Ignore versions starting with 1, the comparison does not work well with that.
//Once 2.x is available it will be calculated correctly
if (latestVersion.startsWith("1"))
{
return false;
}
return getIntVersion(FileManager.getPcuVersionFromManifest()) < getIntVersion(latestVersion);
}
public static int getIntVersion(String versionString)
{
//Regular expression to match digits in a string
String regex = "\\d+";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(versionString);
String numbers = "";
while(matcher.find()) {
numbers = numbers + matcher.group();
}
if (numbers.isEmpty())
{
return 0;
}
return Integer.parseInt(numbers);
}
public static String getLatestVersion()