Files
DistMaker/src/distMaker/jre/AppLauncherUtils.java

340 lines
11 KiB
Java

package distMaker.jre;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;
import distMaker.DistUtils;
import distMaker.digest.Digest;
import distMaker.digest.DigestType;
import distMaker.digest.DigestUtils;
import distMaker.platform.PlatformUtils;
import distMaker.utils.ParseUtils;
import distMaker.utils.PlainVersion;
import distMaker.utils.Version;
import distMaker.utils.VersionUtils;
import glum.gui.GuiUtil;
import glum.io.IoUtil;
import glum.net.Credential;
import glum.net.NetUtil;
import glum.task.PartialTask;
import glum.task.Task;
import glum.util.ThreadUtil;
public class AppLauncherUtils
{
/**
* Returns a list of all the available AppLauncher releases specified at: <BR>
* {@literal <aUpdateSiteUrl>/launcher/appCatalog.txt}
*/
public static List<AppLauncherRelease> getAvailableAppLauncherReleases(Task aTask, URL aUpdateSiteUrl, Credential aCredential)
{
List<AppLauncherRelease> retList;
URL catUrl;
URLConnection connection;
InputStream inStream;
BufferedReader bufReader;
DigestType digestType;
String errMsg, strLine;
errMsg = null;
retList = new ArrayList<>();
catUrl = IoUtil.createURL(aUpdateSiteUrl.toString() + "/launcher/appCatalog.txt");
// Default to DigestType of MD5
digestType = DigestType.MD5;
inStream = null;
bufReader = null;
try
{
// Read the contents of the file
connection = catUrl.openConnection();
inStream = NetUtil.getInputStream(connection, aCredential);
bufReader = new BufferedReader(new InputStreamReader(new BufferedInputStream(inStream)));
// Read the lines
while (true)
{
strLine = bufReader.readLine();
// Bail once we are done
if (strLine == null)
break;
// Ignore comments and empty lines
if (strLine.isEmpty() == true || strLine.startsWith("#") == true)
continue;
String[] tokens;
tokens = strLine.split(",", 5);
if (tokens.length == 2 && tokens[0].equals("name") == true && tokens[1].equals("AppLauncher") == true)
; // Nothing to do - we just entered the "JRE" section
// Logic to handle the 'exit' command
else if (tokens.length >= 1 && tokens[0].equals("exit") == true)
{
// We support exit commands with 3 tokens. All others
// we will just exit.
if (tokens.length != 3)
break;
String targName = tokens[1];
String needVer = tokens[2];
if (ParseUtils.shouldExitLogic(targName, needVer) == true)
break;
}
// Logic to handle the 'digest' command
else if (tokens.length == 2 && tokens[0].equals("digest") == true)
{
DigestType tmpDigestType;
tmpDigestType = DigestType.parse(tokens[1]);
if (tmpDigestType == null)
aTask.infoAppendln("Failed to locate DigestType for: " + tokens[1]);
else
digestType = tmpDigestType;
}
// Logic to handle the 'F' command: AppLauncher File
else if (tokens.length == 5 && tokens[0].equals("F") == true)
{
String filename, digestStr, version;
long fileLen;
// Form the JreRelease
digestStr = tokens[1];
fileLen = GuiUtil.readLong(tokens[2], -1);
filename = tokens[3];
version = tokens[4];
Digest tmpDigest = new Digest(digestType, digestStr);
retList.add(new AppLauncherRelease(version, filename, tmpDigest, fileLen));
}
else
{
aTask.infoAppendln("Unreconized line: " + strLine);
}
}
}
catch(FileNotFoundException aExp)
{
errMsg = "Failed to locate resource: " + catUrl;
}
catch(IOException aExp)
{
errMsg = ThreadUtil.getStackTrace(aExp);
}
finally
{
IoUtil.forceClose(inStream);
IoUtil.forceClose(bufReader);
}
// See if we are in a valid state
if (errMsg != null)
; // Nothing to do, as an earlier error has occurred
else if (retList.size() == 0)
errMsg = "The catalog appears to be invalid.";
// Bail if there were issues
if (errMsg != null)
{
aTask.infoAppendln(errMsg);
return null;
}
return retList;
}
/**
* Utility method that checks to see if the AppLauncher will need be updated in order to support the specified JRE.
* <P>
* Returns false if the AppLauncher does NOT need be updated. Otherwise true will be returned and the version info
* will be logged to the specified aTask.
*/
public static boolean isAppLauncherUpdateNeeded(Task aTask, JreRelease aJreRelease)
{
Version currVer, nMinVer, nMaxVer;
// Bail if the installed version of AppLauncher is equal to or later than the required version
currVer = DistUtils.getAppLauncherVersion();
nMinVer = aJreRelease.getAppLauncherMinVersion();
nMaxVer = aJreRelease.getAppLauncherMaxVersion();
if (VersionUtils.isInRange(currVer, nMinVer, nMaxVer) == true)
return false;
// Log the fact that we need to update our AppLauncher
aTask.infoAppendln("Your current AppLauncher is not compatible with this release. It will need to be upgraded!");
aTask.infoAppendln("\tCurrent ver: " + currVer);
if (nMinVer != PlainVersion.AbsMin)
aTask.infoAppendln("\tMinimum ver: " + nMinVer);
if (nMaxVer != PlainVersion.AbsMax)
aTask.infoAppendln("\tMaximum ver: " + nMaxVer);
aTask.infoAppendln("");
return true;
}
/**
* Utility method that will return the AppLauncherRelease that satisfies the requirements as specified by the
* JreRelease.
* <P>
* Returns null if no AppLauncherRelease is located that can satisfy the specified JreRelease.
* <P>
* Any issues that cropped up while searching for a valid AppLauncherRelease will be logged to the specified task,
* aTask.
* <P>
* TODO: Remove the comments below
* <P>
* corresponding to the AppLauncher that we to the specified version required by this JRE.
* <P>
* Returns false on any failure.
*/
public static AppLauncherRelease updateAppLauncher(Task aTask, JreRelease aJreRelease, File aDestPath, URL updateSiteUrl, Credential aCredential)
{
// Locate the list of available AppLaunchers
List<AppLauncherRelease> availList;
availList = AppLauncherUtils.getAvailableAppLauncherReleases(aTask, updateSiteUrl, aCredential);
if (availList == null)
{
aTask.infoAppendln("The update site does not have any deployed AppLaunchers.");
aTask.infoAppendln("Please contact the update site adminstartor.");
return null;
}
if (availList.size() == 0)
{
aTask.infoAppendln("No AppLauncher releases found!");
aTask.infoAppendln("Please contact the update site adminstartor.");
return null;
}
// Retrieve the AppLauncher that is compatible from the list
Version nMinVer = aJreRelease.getAppLauncherMinVersion();
Version nMaxVer = aJreRelease.getAppLauncherMaxVersion();
AppLauncherRelease pickRelease = null;
for (AppLauncherRelease aRelease : availList)
{
Version evalVer = aRelease.getVersion();
if (VersionUtils.isInRange(evalVer, nMinVer, nMaxVer) == false)
continue;
pickRelease = aRelease;
break;
}
// Bail if no compatible release could be found
if (pickRelease == null)
{
aTask.infoAppendln("No compatible AppLauncher releases have been deployed!");
aTask.infoAppendln("Please contact the update site adminstartor.");
return null;
}
// Get stats on the release
Version pickVer = pickRelease.getVersion();
long fileLen = pickRelease.getFileLen();
// Define the path to the launcher
File launcherPath;
if (PlatformUtils.getPlatform().equals("Apple") == true)
launcherPath = new File(aDestPath.getParentFile(), "Java");
else
launcherPath = new File(aDestPath.getParentFile(), "launcher");
// Download the AppLauncher
Digest targDigest, testDigest;
MessageDigest msgDigest;
targDigest = pickRelease.getDigest();
msgDigest = DigestUtils.getDigest(targDigest.getType());
aTask.infoAppendln("Downloading AppLauncher... Version: " + pickVer);
URL srcUrl = IoUtil.createURL(updateSiteUrl.toString() + "/launcher/appLauncher-" + pickVer + ".jar");
File dstFile = new File(launcherPath, pickRelease.getFileName());
int zios_2018Feb15; // TODO: Consider refactoring this code and making it cleaner...
Task tmpTask = new PartialTask(aTask, aTask.getProgress(), 0.01);
// Task tmpTask = new PartialTask(aTask, aTask.getProgress(), (tmpFileLen * 0.75) / (releaseSizeFull + 0.00));
// Task tmpTask = new SilentTask();
if (DistUtils.downloadFile(tmpTask, srcUrl, dstFile, aCredential, fileLen, msgDigest) == false)
{
aTask.infoAppendln("Failed to download updated AppLauncher.");
aTask.infoAppendln("\tSource: " + srcUrl);
aTask.infoAppendln("\tFile: " + dstFile + "\n");
return null;
}
// Validate that the AppLauncher was downloaded successfully
testDigest = new Digest(targDigest.getType(), msgDigest.digest());
if (targDigest.equals(testDigest) == false)
{
aTask.infoAppendln("The download of the AppLauncher appears to be corrupted.");
aTask.infoAppendln("\tFile: " + dstFile);
aTask.infoAppendln("\t\tExpected " + targDigest.getDescr());
aTask.infoAppendln("\t\tReceived " + testDigest.getDescr() + "\n");
return null;
}
// Update the appLauncher.jar file
File targFile = new File(launcherPath, "appLauncher.jar");
boolean isPass;
// Back up the "original" targFile (only if a backup has not already already been made). In case
// there are multiple updates we do not want to overwrite the "real" original
boolean isOriginalBackedUp = false;
File origFile = new File(launcherPath, "appLauncher.jar.orig");
if (origFile.exists() == false)
{
isPass = targFile.renameTo(origFile);
if (isPass == false)
{
aTask.infoAppendln("Failed to rename: " + targFile + " to " + origFile);
}
else
{
isOriginalBackedUp = true;
aTask.infoAppendln("Original file has been backed up.");
aTask.infoAppendln("\t" + targFile + " ---> " + origFile);
}
}
// Update the targFile with the newly downloaded file
isPass = dstFile.renameTo(targFile);
// targFile.renameTo(origFile);
if (isPass == false)
{
aTask.infoAppendln("Failed to rename: " + dstFile + " to " + targFile);
aTask.infoAppendln("Update is being aborted");
// We need to revert to the original backup
if (isOriginalBackedUp == true)
{
isPass = origFile.renameTo(targFile);
if (isPass == false)
{
aTask.infoAppendln("Failed to revert to the orginal AppLauncher.");
aTask.infoAppendln("\t" + targFile);
aTask.infoAppendln("Update has FAILED and left application in an invalid state.\n");
}
}
return null;
}
else
{
aTask.infoAppendln("Success updating AppLauncher... ");
aTask.infoAppendln("\t" + dstFile + " ---> " + targFile + "\n");
}
return pickRelease;
}
}