mirror of
https://github.com/JHUAPL/DistMaker.git
synced 2026-01-09 14:37:54 -05:00
Added support for configurable digest
Changed -jreRelease to -jreVersion Added preliminary support for JRE updating Code cleanup / refactoring
This commit is contained in:
BIN
lib/commons-compress-1.10-sources.jar
Normal file
BIN
lib/commons-compress-1.10-sources.jar
Normal file
Binary file not shown.
BIN
lib/commons-compress-1.10.jar
Normal file
BIN
lib/commons-compress-1.10.jar
Normal file
Binary file not shown.
@@ -20,7 +20,7 @@ def buildRelease(args, buildPath):
|
||||
# Retrieve vars of interest
|
||||
appName = args.name
|
||||
version = args.version
|
||||
jreRelease = args.jreRelease
|
||||
jreRelease = args.jreVersion
|
||||
platformStr = 'apple'
|
||||
|
||||
# Check our system environment before proceeding
|
||||
@@ -384,6 +384,7 @@ def buildPListInfoStatic(destFile, args):
|
||||
tupList.append(('CFBundlePackageType', 'APPL'))
|
||||
tupList.append(('CFBundleSignature', '????'))
|
||||
tupList.append(('CFBundleVersion', args.version))
|
||||
tupList.append(('NSHighResolutionCapable', 'true'))
|
||||
tupList.append(('NSHumanReadableCopyright', ''))
|
||||
jrePath = 'jre' + args.jreRelease
|
||||
tupList.append(('JVMRuntime', jrePath))
|
||||
|
||||
@@ -39,11 +39,23 @@ class FancyArgumentParser(argparse.ArgumentParser):
|
||||
# yield arg
|
||||
|
||||
|
||||
def buildCatalogFile(deltaPath):
|
||||
|
||||
# Build the delta md5sum catalog
|
||||
def buildCatalogFile(args, deltaPath):
|
||||
# Build the delta catalog
|
||||
records = []
|
||||
|
||||
# Record the digest used
|
||||
digestType = args.digest
|
||||
record = ('digest', digestType)
|
||||
records.append(record)
|
||||
|
||||
# Record the JRE required
|
||||
jreVersion = args.jreVersion
|
||||
if jreVersion == None:
|
||||
jreVersion = jreUtils.getDefaultJrVersion()
|
||||
if jreVersion != None:
|
||||
record = ('jre', jreVersion)
|
||||
records.append(record)
|
||||
|
||||
snipLen = len(deltaPath) + 1
|
||||
# for root, dirNames, fileNames in os.walk(deltaPath, onerror=failTracker.recordError):
|
||||
for root, dirNames, fileNames in os.walk(deltaPath):
|
||||
@@ -73,22 +85,20 @@ def buildCatalogFile(deltaPath):
|
||||
elif os.path.isfile(fullPath) == True:
|
||||
# Gather the various stats of the specified file
|
||||
stat = os.stat(fullPath)
|
||||
md5sum = miscUtils.computeMd5ForFile(fullPath)
|
||||
digestVal = miscUtils.computeDigestForFile(fullPath, digestType)
|
||||
relPath = fullPath[snipLen:]
|
||||
record = ('F', md5sum, str(stat.st_size), relPath)
|
||||
record = ('F', digestVal, str(stat.st_size), relPath)
|
||||
records.append(record)
|
||||
else:
|
||||
print("Undefined node. Full path: " + fullPath + "\n")
|
||||
|
||||
|
||||
# Save the records to the catalog file
|
||||
dstPath = os.path.join(deltaPath, "catalog.txt")
|
||||
f = open(dstPath, 'wb')
|
||||
for aRecord in records:
|
||||
if len(aRecord) == 2:
|
||||
f.write(aRecord[0] + ',' + aRecord[1] + '\n')
|
||||
else:
|
||||
f.write(aRecord[0] + ',' + aRecord[1] + ',' + aRecord[2] + ',' + aRecord[3] + '\n')
|
||||
f.write(','.join(aRecord) + '\n')
|
||||
|
||||
f.write('exit\n')
|
||||
f.close()
|
||||
|
||||
def checkForRequiredApplications():
|
||||
@@ -166,7 +176,7 @@ if __name__ == "__main__":
|
||||
parser.add_argument('-appArgs', help='Application arguments. Note that this argument must ALWAYS be the last specified!', nargs=argparse.REMAINDER, default=[])
|
||||
parser.add_argument('-dataCode', '-dc', help='A list of supporting folders for the application.', nargs='+', default=[])
|
||||
parser.add_argument('-javaCode', '-jc', help='A folder which contains the Java build.')
|
||||
parser.add_argument('-jreRelease', help='JRE release to utilize. Note there should be a corresponding folder in ~/jre/<platform>/', default=None)
|
||||
parser.add_argument('-jreVersion', help='JRE version to utilize. This should be a value like 1.7 or 1.8 or 1.8.34. Note there should be corresponding tar.gz JREs for each platform in the folder ~/jre/', default=None)
|
||||
parser.add_argument('-jvmArgs', help='JVM arguments.', nargs='+', default=[])
|
||||
parser.add_argument('-classPath', help='Class path listing of jar files relative to javaCode. Leave blank for auto determination.', nargs='+', default=[])
|
||||
parser.add_argument('-debug', help='Turn on debug options for built applications.', action='store_true', default=False)
|
||||
@@ -174,7 +184,8 @@ if __name__ == "__main__":
|
||||
parser.add_argument('-bgFile', help='Background file used for apple dmg file.')
|
||||
parser.add_argument('-iconFile', help='PNG file used for linux/windows icon.')
|
||||
parser.add_argument('-icnsFile', help='Icon file used for apple build.')
|
||||
parser.add_argument('-forceSingleInstance', help='Force the application to have only one instance..', default=False)
|
||||
parser.add_argument('-forceSingleInstance', help='Force the application to have only one instance.', default=False)
|
||||
parser.add_argument('-digest', help='Digest used to ensure integrity of application upgrades. Default: sha256', choices=['md5', 'sha256', 'sha512'], default='sha256')
|
||||
# parser.add_argument('-bundleId', help='Apple specific id descriptor.')
|
||||
|
||||
# Intercept any request for a help message and bail
|
||||
@@ -265,8 +276,8 @@ if __name__ == "__main__":
|
||||
dstPath = os.path.join(buildPath, "delta/app.cfg")
|
||||
miscUtils.buildAppLauncherConfig(dstPath, args)
|
||||
|
||||
# Build the delta md5sum catalog
|
||||
buildCatalogFile(deltaPath)
|
||||
# Build the delta catalog
|
||||
buildCatalogFile(args, deltaPath)
|
||||
|
||||
# Build the Apple release
|
||||
appleUtils.buildRelease(args, buildPath)
|
||||
@@ -278,6 +289,6 @@ if __name__ == "__main__":
|
||||
windowsUtils.buildRelease(args, buildPath)
|
||||
|
||||
# Copy over the deploy script
|
||||
srcPath = os.path.join(miscUtils.getInstallRoot(), "deployDist.py")
|
||||
srcPath = os.path.join(miscUtils.getInstallRoot(), "deployAppDist.py")
|
||||
shutil.copy(srcPath, buildPath)
|
||||
|
||||
|
||||
@@ -28,15 +28,15 @@ def getDistInfo(distPath):
|
||||
exeMode = line;
|
||||
elif exeMode == '-name' and len(line) > 0:
|
||||
appName = line
|
||||
elif exeMode == '-version' and len(line) > 0:
|
||||
elif exeMode == '-version' and len(line) > 0:
|
||||
version = line
|
||||
elif exeMode == '-buildDate' and len(line) > 0:
|
||||
elif exeMode == '-buildDate' and len(line) > 0:
|
||||
buildDate = line
|
||||
f.close()
|
||||
|
||||
if appName == None or version == None or buildDate == None:
|
||||
print('Distribution corresponding to the folder: ' + distPath + ' does not appear to be valid!')
|
||||
print('The configuration file, ' + cfgFile+ ', is not valid.')
|
||||
print('The configuration file, ' + cfgFile + ', is not valid.')
|
||||
print('Release will not be made for app ' + appName)
|
||||
exit()
|
||||
|
||||
@@ -150,7 +150,7 @@ if __name__ == "__main__":
|
||||
# Logic to capture Ctrl-C and bail
|
||||
signal.signal(signal.SIGINT, handleSignal)
|
||||
|
||||
# Retrive the location of the scriptPath
|
||||
# Retrieve the location of the scriptPath
|
||||
scriptPath = os.path.realpath(__file__)
|
||||
scriptPath = os.path.dirname(scriptPath)
|
||||
|
||||
0
script/deployJreDist.py
Executable file
0
script/deployJreDist.py
Executable file
@@ -9,7 +9,7 @@ import tempfile
|
||||
import miscUtils
|
||||
|
||||
# Globals
|
||||
# The global variable defaultJreRelease is a hint for which (tar.gz) JRE release to
|
||||
# The global variable defaultJreVersion is a hint for which (tar.gz) JRE release to
|
||||
# default to. Note if this variable is not specified then the latest JRE release
|
||||
# located in the appropriate <installPath>/jre directory will be utilized.
|
||||
#
|
||||
@@ -19,16 +19,16 @@ import miscUtils
|
||||
# where VERSION is something like: 8u73
|
||||
# For example the Linux JRE 1.8.73 tar.gz release would be:
|
||||
# <installpath>/jre/jre-8u73-linux-x64.tar.gz
|
||||
defaultJreRelease = '1.8'
|
||||
defaultJreVersion = '1.8'
|
||||
|
||||
|
||||
def getDefaultJreRelease(aPlatform):
|
||||
"""Utility method to locate the default JRE to utilize. The returned value will be a string such as 1.8.73"""
|
||||
# Return the default if it is hard wired (and is available)
|
||||
if 'defaultJreRelease' in globals():
|
||||
jreTarGzFile = getJreTarGzFile(aPlatform, defaultJreRelease)
|
||||
if 'defaultJreVersion' in globals():
|
||||
jreTarGzFile = getJreTarGzFile(aPlatform, defaultJreVersion)
|
||||
if jreTarGzFile == None:
|
||||
print('[WARNING] The specified default JRE for the ' + aPlatform.capitalize() + ' platform is: ' + defaultJreRelease + '. However this JRE is not installed! <---')
|
||||
print('[WARNING] The specified default JRE for the ' + aPlatform.capitalize() + ' platform is: ' + defaultJreVersion + '. However this JRE is not installed! <---')
|
||||
else:
|
||||
return '1.' + '.'.join(getJreTarGzVersion(jreTarGzFile))
|
||||
|
||||
@@ -38,6 +38,14 @@ def getDefaultJreRelease(aPlatform):
|
||||
return '1.' + '.'.join(getJreTarGzVersion(jreTarGzFile))
|
||||
|
||||
|
||||
def getDefaultJreVersion():
|
||||
"""Returns the default JRE version. This will return None if a default JRE version has not been specified
|
||||
and one can not be determined."""
|
||||
if 'defaultJreVersion' in globals():
|
||||
return defaultJreVersion;
|
||||
return None
|
||||
|
||||
|
||||
def doesJreVersionMatch(aRequestVer, aEvaluateVer):
|
||||
"""Returns true if aEvaluateVer is a match for the requested version. Note that aEvaluateVer is considered
|
||||
a match if each (available) component corresponds to the component in a aRequestVer. aRequestVer must
|
||||
@@ -125,7 +133,7 @@ def getJreTarGzVersion(aFile):
|
||||
"""Returns the version corresponding to the passed in JRE tar.gz file.
|
||||
The returned value will be a list consisting of the (major, minor) components of the version.
|
||||
|
||||
The file naming convenition is expected to be:
|
||||
The file naming convention is expected to be:
|
||||
jre-<A>u<B>-*.tar.gz
|
||||
where:
|
||||
A ---> The major version
|
||||
@@ -159,7 +167,7 @@ def unpackAndRenameToStandard(aJreTarGzFile, aDestPath):
|
||||
if os.path.isdir(aDestPath) == False:
|
||||
os.makedirs(aDestPath)
|
||||
|
||||
# Unpack to a tempory folder at aDestPath
|
||||
# Unpack to a temporary folder at aDestPath
|
||||
tmpPath = tempfile.mkdtemp(dir=aDestPath)
|
||||
subprocess.check_call(["tar", "-xf", aJreTarGzFile, "-C", tmpPath], stderr=subprocess.STDOUT)
|
||||
|
||||
@@ -174,6 +182,6 @@ def unpackAndRenameToStandard(aJreTarGzFile, aDestPath):
|
||||
targPath = os.path.join(aDestPath, jreBasePath)
|
||||
os.rename(fileList[0], targPath)
|
||||
|
||||
# Remove the the tempory path
|
||||
# Remove the the temporary path
|
||||
os.rmdir(tmpPath)
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ def buildRelease(args, buildPath):
|
||||
# Retrieve vars of interest
|
||||
appName = args.name
|
||||
version = args.version
|
||||
jreRelease = args.jreRelease
|
||||
jreRelease = args.jreVersion
|
||||
platformStr = 'linux'
|
||||
|
||||
# Check our system environment before proceeding
|
||||
@@ -122,6 +122,13 @@ def buildBashScript(destFile, args, jreTarGzFile):
|
||||
f.write('# mutations to this script while it is running\n')
|
||||
f.write('{ # Do not remove this bracket! \n\n')
|
||||
|
||||
f.write('# Define where the Java executable is located\n')
|
||||
if jreTarGzFile == None:
|
||||
f.write('javaExe=java\n\n')
|
||||
else:
|
||||
jrePath = jreUtils.getBasePathForJreTarGzFile(jreTarGzFile)
|
||||
f.write('javaExe=../' + jrePath + '/bin/java\n\n')
|
||||
|
||||
f.write('# Define the maximum memory to allow the application to utilize\n')
|
||||
if maxMem == None:
|
||||
f.write('#maxMem=512m # Uncomment out this line to change from defaults.\n\n')
|
||||
@@ -142,10 +149,7 @@ def buildBashScript(destFile, args, jreTarGzFile):
|
||||
f.write(' xmxStr=\'-Xmx\'$maxMem\n')
|
||||
f.write('fi\n\n')
|
||||
|
||||
exeCmd = 'java ' + jvmArgsStr + '$xmxStr '
|
||||
if jreTarGzFile != None:
|
||||
jrePath = jreUtils.getBasePathForJreTarGzFile(jreTarGzFile)
|
||||
exeCmd = '../' + jrePath + '/bin/java ' + jvmArgsStr + '$xmxStr '
|
||||
exeCmd = '$javaExe ' + jvmArgsStr + '$xmxStr '
|
||||
exeCmd = exeCmd + '-Djava.system.class.loader=appLauncher.RootClassLoader -cp ../launcher/appLauncher.jar appLauncher.AppLauncher $*'
|
||||
f.write('# Run the application\n')
|
||||
f.write(exeCmd + '\n\n')
|
||||
|
||||
@@ -19,16 +19,25 @@ def checkRoot():
|
||||
|
||||
|
||||
# Source: http://stackoverflow.com/questions/1131220/get-md5-hash-of-a-files-without-open-it-in-python
|
||||
def computeMd5ForFile(evalFile, block_size=2**20):
|
||||
def computeDigestForFile(evalFile, digest, block_size=2**20):
|
||||
# Select the proper hash algorithm
|
||||
if digest == 'md5':
|
||||
hash = hashlib.md5()
|
||||
elif digest == 'sha256':
|
||||
hash = hashlib.sha256()
|
||||
elif digest == 'sha512':
|
||||
hash = hashlib.sha512()
|
||||
else:
|
||||
raise Exception('Unrecognized hash function: ' + digest);
|
||||
|
||||
f = open(evalFile, 'rb')
|
||||
md5 = hashlib.md5()
|
||||
while True:
|
||||
data = f.read(block_size)
|
||||
if not data:
|
||||
break
|
||||
md5.update(data)
|
||||
hash.update(data)
|
||||
f.close()
|
||||
return md5.hexdigest()
|
||||
return hash.hexdigest()
|
||||
|
||||
|
||||
def getInstallRoot():
|
||||
|
||||
@@ -17,7 +17,7 @@ def buildRelease(args, buildPath):
|
||||
# Retrieve vars of interest
|
||||
appName = args.name
|
||||
version = args.version
|
||||
jreRelease = args.jreRelease
|
||||
jreRelease = args.jreVersion
|
||||
platformStr = 'windows'
|
||||
|
||||
# Check our system environment before proceeding
|
||||
|
||||
@@ -10,33 +10,31 @@ import glum.task.*;
|
||||
import glum.unit.DateUnit;
|
||||
import glum.util.ThreadUtil;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.*;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.nio.file.Files;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.*;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
|
||||
import distMaker.digest.Digest;
|
||||
import distMaker.digest.DigestUtils;
|
||||
import distMaker.gui.PickReleasePanel;
|
||||
import distMaker.node.FileNode;
|
||||
import distMaker.node.Node;
|
||||
import distMaker.jre.*;
|
||||
import distMaker.node.*;
|
||||
import distMaker.platform.AppleUtils;
|
||||
import distMaker.platform.PlatformUtils;
|
||||
|
||||
public class DistMakerEngine
|
||||
{
|
||||
// State vars
|
||||
private URL updateSiteUrl;
|
||||
private Release currRelease;
|
||||
private AppRelease currRelease;
|
||||
private Credential refCredential;
|
||||
|
||||
// Gui vars
|
||||
@@ -52,10 +50,8 @@ public class DistMakerEngine
|
||||
refCredential = null;
|
||||
|
||||
parentFrame = aParentFrame;
|
||||
msgPanel = new MessagePanel(parentFrame);
|
||||
msgPanel.setSize(700, 400);
|
||||
promptPanel = new PromptPanel(parentFrame);
|
||||
promptPanel.setSize(500, 300);
|
||||
msgPanel = new MessagePanel(parentFrame, "Untitled", 700, 400);
|
||||
promptPanel = new PromptPanel(parentFrame, "Untitled", 500, 300);
|
||||
|
||||
initialize();
|
||||
}
|
||||
@@ -109,38 +105,39 @@ public class DistMakerEngine
|
||||
* <LI>running from a developers environment (Ex: Eclipse IDE)
|
||||
* <LI>If the software application was not properly packaged (or has become corrupt) with DistMaker.
|
||||
*/
|
||||
public Release getCurrentRelease()
|
||||
public AppRelease getCurrentRelease()
|
||||
{
|
||||
return currRelease;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public UpdateStatus isUpToDate()
|
||||
{
|
||||
LoggingTask task = new LoggingTask();
|
||||
String appName = currRelease.getName();
|
||||
List<Release> unsortedReleaseList = DistUtils.getAvailableReleases(task, updateSiteUrl, appName, refCredential);
|
||||
LoggingTask task = new LoggingTask();
|
||||
String appName = currRelease.getName();
|
||||
List<AppRelease> unsortedReleaseList = DistUtils.getAvailableAppReleases(task, updateSiteUrl, appName, refCredential);
|
||||
|
||||
if (unsortedReleaseList == null) {
|
||||
// The update check failed, so return a status of false with a message about the problem
|
||||
String msg = Joiner.on("; ").join(task.getMessages());
|
||||
return new UpdateStatus(msg);
|
||||
}
|
||||
// Sort the items, and isolate the newest item
|
||||
LinkedList<Release> fullList = new LinkedList<>(unsortedReleaseList);
|
||||
Collections.sort(fullList);
|
||||
Release newestRelease = fullList.removeLast();
|
||||
if (unsortedReleaseList == null)
|
||||
{
|
||||
// The update check failed, so return a status of false with a message about the problem
|
||||
String msg = Joiner.on("; ").join(task.getMessages());
|
||||
return new UpdateStatus(msg);
|
||||
}
|
||||
// Sort the items, and isolate the newest item
|
||||
LinkedList<AppRelease> fullList = new LinkedList<>(unsortedReleaseList);
|
||||
Collections.sort(fullList);
|
||||
AppRelease newestRelease = fullList.removeLast();
|
||||
|
||||
// The check succeeded, so return wether or not the app is up to date.
|
||||
return new UpdateStatus(newestRelease.equals(currRelease));
|
||||
// The check succeeded, so return whether or not the app is up to date.
|
||||
return new UpdateStatus(newestRelease.equals(currRelease));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets in the credentials used to access the update site. If either argument is null, then the credentials will be
|
||||
* cleared out.
|
||||
* Sets in the credentials used to access the update site. If either argument is null, then the credentials will be cleared out.
|
||||
*/
|
||||
public void setCredentials(String aUsername, char[] aPassword)
|
||||
{
|
||||
@@ -214,7 +211,7 @@ public class DistMakerEngine
|
||||
}
|
||||
|
||||
}
|
||||
catch (IOException aExp)
|
||||
catch(IOException aExp)
|
||||
{
|
||||
aExp.printStackTrace();
|
||||
}
|
||||
@@ -226,7 +223,7 @@ public class DistMakerEngine
|
||||
if (appName == null || verName == null)
|
||||
{
|
||||
displayNotice(null);
|
||||
System.out.println("Failed to properly parse DistMaker config file: " + cfgFile);
|
||||
System.err.println("Failed to properly parse DistMaker config file: " + cfgFile);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -237,7 +234,7 @@ public class DistMakerEngine
|
||||
if (buildStr != null)
|
||||
buildTime = dateUnit.parseString(buildStr, 0);
|
||||
|
||||
currRelease = new Release(appName, verName, buildTime);
|
||||
currRelease = new AppRelease(appName, verName, buildTime);
|
||||
|
||||
// Notify the user, if the application has been successfully updated
|
||||
markSystemFullyStarted();
|
||||
@@ -255,8 +252,8 @@ public class DistMakerEngine
|
||||
@SuppressWarnings("unused")
|
||||
private void checkForUpdatesWorker(FullTaskPanel aTask, UpdateCheckListener listener)
|
||||
{
|
||||
List<Release> fullList;
|
||||
Release chosenItem;
|
||||
List<AppRelease> fullList;
|
||||
AppRelease chosenItem;
|
||||
File installPath, deltaPath;
|
||||
String appName;
|
||||
boolean isPass;
|
||||
@@ -271,7 +268,7 @@ public class DistMakerEngine
|
||||
|
||||
// Retrieve the list of available releases
|
||||
aTask.infoAppendln("Checking for updates...\n");
|
||||
fullList = DistUtils.getAvailableReleases(aTask, updateSiteUrl, appName, refCredential);
|
||||
fullList = DistUtils.getAvailableAppReleases(aTask, updateSiteUrl, appName, refCredential);
|
||||
if (fullList == null)
|
||||
{
|
||||
aTask.abort();
|
||||
@@ -281,21 +278,23 @@ public class DistMakerEngine
|
||||
// a successful test has been done, so notify the listener
|
||||
listener.checkForNewVersionsPerformed();
|
||||
|
||||
// In case there is only the current version, don't show the update selection panel.
|
||||
// Just show a short message that everything is up to date, and abort.
|
||||
// (This check used to be in the getAvailableReleases() call above, but I needed
|
||||
// that to not throw an error for the case of only one release, so I moved that
|
||||
// check here.)
|
||||
if (fullList.size() == 1) {
|
||||
if (fullList.get(0).equals(currRelease)) {
|
||||
// There is only one release out there, and its the same
|
||||
// as the one being run, so there is nothing to update.
|
||||
String msg = "There are no updates of " + appName + ". Only one release has been made.";
|
||||
aTask.infoAppendln(msg);
|
||||
aTask.abort();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// In case there is only the current version, don't show the update selection panel.
|
||||
// Just show a short message that everything is up to date, and abort.
|
||||
// (This check used to be in the getAvailableReleases() call above, but I needed
|
||||
// that to not throw an error for the case of only one release, so I moved that
|
||||
// check here.)
|
||||
if (fullList.size() == 1)
|
||||
{
|
||||
if (fullList.get(0).equals(currRelease))
|
||||
{
|
||||
// There is only one release out there, and its the same
|
||||
// as the one being run, so there is nothing to update.
|
||||
String msg = "There are no updates of " + appName + ". Only one release has been made.";
|
||||
aTask.infoAppendln(msg);
|
||||
aTask.abort();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide the taskPanel
|
||||
aTask.setVisible(false);
|
||||
@@ -309,7 +308,7 @@ public class DistMakerEngine
|
||||
aFuncRunnable = new FunctionRunnable(this, "queryUserForInput", aTask, deltaPath, fullList);
|
||||
SwingUtilities.invokeAndWait(aFuncRunnable);
|
||||
}
|
||||
catch (Exception aExp)
|
||||
catch(Exception aExp)
|
||||
{
|
||||
aExp.printStackTrace();
|
||||
}
|
||||
@@ -382,14 +381,15 @@ public class DistMakerEngine
|
||||
* <P>
|
||||
* Returns true if the release was downloaded properly.
|
||||
*/
|
||||
private boolean downloadRelease(Task aTask, Release aRelease, File destPath)
|
||||
private boolean downloadRelease(Task aTask, AppRelease aRelease, File destPath)
|
||||
{
|
||||
Map<String, Node> staleMap, updateMap;
|
||||
AppCatalog staleCat, updateCat;
|
||||
Node staleNode, updateNode;
|
||||
URL catUrl, staleUrl, updateUrl;
|
||||
File catalogFile;
|
||||
Task mainTask, tmpTask;
|
||||
long nodeFileLen;
|
||||
double progressVal;
|
||||
long tmpFileLen;
|
||||
boolean isPass;
|
||||
|
||||
try
|
||||
@@ -397,7 +397,7 @@ public class DistMakerEngine
|
||||
staleUrl = DistUtils.getAppPath().toURI().toURL();
|
||||
updateUrl = IoUtil.createURL(updateSiteUrl.toString() + "/" + aRelease.getName() + "/" + aRelease.getVersion() + "/delta");
|
||||
}
|
||||
catch (MalformedURLException aExp)
|
||||
catch(MalformedURLException aExp)
|
||||
{
|
||||
aTask.infoAppendln(ThreadUtil.getStackTrace(aExp));
|
||||
aExp.printStackTrace();
|
||||
@@ -407,51 +407,182 @@ public class DistMakerEngine
|
||||
// Download the update catalog to the (local) delta location (Progress -> [0% - 1%])
|
||||
catUrl = IoUtil.createURL(updateUrl.toString() + "/catalog.txt");
|
||||
catalogFile = new File(destPath, "catalog.txt");
|
||||
if (DistUtils.downloadFile(new PartialTask(aTask, 0.00, 0.01), catUrl, catalogFile, refCredential, -1L) == false)
|
||||
if (DistUtils.downloadFile(new PartialTask(aTask, 0.00, 0.01), catUrl, catalogFile, refCredential, -1L, null) == false)
|
||||
return false;
|
||||
|
||||
// Load the map of stale nodes
|
||||
// Load the stale catalog
|
||||
catalogFile = new File(DistUtils.getAppPath(), "catalog.txt");
|
||||
staleMap = DistUtils.readCatalog(aTask, catalogFile, staleUrl);
|
||||
if (staleMap == null)
|
||||
staleCat = DistUtils.readAppCatalog(aTask, catalogFile, staleUrl);
|
||||
if (staleCat == null)
|
||||
return false;
|
||||
|
||||
// Load the map of update nodes
|
||||
// Load the update catalog
|
||||
catalogFile = new File(destPath, "catalog.txt");
|
||||
updateMap = DistUtils.readCatalog(aTask, catalogFile, updateUrl);
|
||||
if (updateMap == null)
|
||||
updateCat = DistUtils.readAppCatalog(aTask, catalogFile, updateUrl);
|
||||
if (updateCat == null)
|
||||
return false;
|
||||
|
||||
// Determine the total number of bytes to be transferred
|
||||
// Determine the total number of bytes to be transferred and set up the mainTask
|
||||
long releaseSizeFull = 0L, releaseSizeCurr = 0L;
|
||||
for (Node aNode : updateMap.values())
|
||||
for (Node aNode : updateCat.getAllNodesList())
|
||||
{
|
||||
if (aNode instanceof FileNode)
|
||||
releaseSizeFull += ((FileNode)aNode).getFileLen();
|
||||
}
|
||||
|
||||
// Download the individual files (Progress -> [1% - 95%])
|
||||
double progressVal = 0.00;
|
||||
// Set up the mainTask for downloading of remote content (Progress -> [1% - 95%])
|
||||
mainTask = new PartialTask(aTask, 0.01, 0.94);
|
||||
mainTask.infoAppendln("Downloading release: " + aRelease.getVersion() + " Nodes: " + updateMap.size());
|
||||
for (String aFileName : updateMap.keySet())
|
||||
|
||||
// Ensure our JRE version is sufficient for this release
|
||||
JreVersion currJreVer = DistUtils.getJreVersion();
|
||||
JreVersion targJreVer = updateCat.getJreVersion();
|
||||
if (targJreVer != null && JreVersion.getBetterVersion(targJreVer, currJreVer) != currJreVer)
|
||||
{
|
||||
List<JreRelease> jreList;
|
||||
|
||||
aTask.infoAppendln("Your current JRE is too old. It will need to be updated!");
|
||||
aTask.infoAppendln("\tCurrent JRE: " + currJreVer.getLabel());
|
||||
aTask.infoAppendln("\tMinimun JRE: " + targJreVer.getLabel() + "\n");
|
||||
|
||||
// Get list of all available JREs
|
||||
jreList = JreUtils.getAvailableJreReleases(aTask, updateSiteUrl, refCredential);
|
||||
if (jreList == null)
|
||||
{
|
||||
aTask.infoAppendln("The update site has not had any JREs deployed.");
|
||||
aTask.infoAppendln("Please contact the update site adminstartor.");
|
||||
return false;
|
||||
}
|
||||
if (jreList.size() == 0)
|
||||
{
|
||||
aTask.infoAppendln("No JRE releases found!");
|
||||
aTask.infoAppendln("Please contact the update site adminstartor.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve the latest appropriate JreRelease
|
||||
String platform = DistUtils.getPlatform();
|
||||
jreList = JreUtils.getMatchingPlatforms(jreList, platform);
|
||||
if (jreList.size() == 0)
|
||||
{
|
||||
aTask.infoAppendln("There are no JRE releases available for the platform: " + platform + "!");
|
||||
return false;
|
||||
}
|
||||
|
||||
JreRelease pickJre = jreList.get(0);
|
||||
JreVersion pickJreVer = pickJre.getVersion();
|
||||
|
||||
if (JreVersion.getBetterVersion(pickJreVer, targJreVer) == currJreVer)
|
||||
{
|
||||
aTask.infoAppendln("The latest available JRE on the update site is not recent enought!");
|
||||
aTask.infoAppendln("Minimun required JRE: " + targJreVer.getLabel());
|
||||
aTask.infoAppendln("Latest available JRE: " + pickJreVer.getLabel());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update the number of bytes to be retrieved to take into account the JRE which we will be downloading
|
||||
// and form the appropriate tmpTask
|
||||
tmpFileLen = pickJre.getFileLen();
|
||||
releaseSizeFull += tmpFileLen;
|
||||
tmpTask = new PartialTask(mainTask, mainTask.getProgress(), tmpFileLen / (releaseSizeFull + 0.00));
|
||||
|
||||
// Download the JRE
|
||||
Digest targDigest, testDigest;
|
||||
targDigest = pickJre.getDigest();
|
||||
MessageDigest msgDigest;
|
||||
msgDigest = DigestUtils.getDigest(targDigest.getType());
|
||||
mainTask.infoAppendln("Downloading JRE... Version: " + pickJre.getVersion().getLabel());
|
||||
URL srcUrl = IoUtil.createURL(updateSiteUrl.toString() + "/jre/" + pickJre.getFileName());
|
||||
File dstFile = new File(new File(destPath, "jre"), pickJre.getFileName());
|
||||
DistUtils.downloadFile(tmpTask, srcUrl, dstFile, refCredential, tmpFileLen, msgDigest);
|
||||
|
||||
// Validate that the JRE was downloaded successfully
|
||||
testDigest = new Digest(targDigest.getType(), msgDigest.digest());
|
||||
if (targDigest.equals(testDigest) == false)
|
||||
{
|
||||
aTask.infoAppendln("The download of the JRE appears to be corrupted.");
|
||||
aTask.infoAppendln("\tFile: " + dstFile);
|
||||
aTask.infoAppendln("\t\tExpected " + targDigest.getDescr());
|
||||
aTask.infoAppendln("\t\tRecieved " + testDigest.getDescr() + "\n");
|
||||
return false;
|
||||
}
|
||||
releaseSizeCurr += tmpFileLen;
|
||||
progressVal = releaseSizeCurr / (releaseSizeFull + 0.00);
|
||||
mainTask.setProgress(progressVal);
|
||||
|
||||
// TODO: Unpack the JRE at the proper location and then delete it
|
||||
File jrePath = PlatformUtils.getJreLocation(pickJre);
|
||||
try
|
||||
{
|
||||
int finish_me_and_clean_me;
|
||||
// Files.createTempDirectory(dstFile, prefix, attrs)
|
||||
// Files.createTempDir();
|
||||
|
||||
|
||||
File unpackPath;
|
||||
unpackPath = new File(destPath, "jre/unpack");
|
||||
unpackPath.mkdirs();
|
||||
MiscUtils.unTar(dstFile, unpackPath);
|
||||
|
||||
File[] fileArr;
|
||||
fileArr = unpackPath.listFiles();
|
||||
if (fileArr.length != 1 && fileArr[0].isDirectory() == false)
|
||||
throw new Exception("Expected only one (top level) folder to be unpacked. Items extracted: " + fileArr.length + " Path: " + unpackPath);
|
||||
|
||||
File jreUnpackedPath;
|
||||
jreUnpackedPath = fileArr[0];
|
||||
|
||||
// Moved the unpacked file to the "standardized" jrePath
|
||||
jreUnpackedPath.renameTo(jrePath);
|
||||
// MiscUtils.unTar(dstFile, jrePath);
|
||||
|
||||
// TODO: Remove the unpacked folder...
|
||||
}
|
||||
catch(Exception aExp)
|
||||
{
|
||||
aTask.infoAppendln("Failed to untar archive. The update has been aborted.");
|
||||
aTask.infoAppendln("\tTar File: " + dstFile);
|
||||
aTask.infoAppendln("\tDestination: " + jrePath);
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Update the launch script or launch config file to point to the proper JRE
|
||||
if (PlatformUtils.setJreLocation(jrePath) == false)
|
||||
{
|
||||
aTask.infoAppendln("Failed to update the configuration to point to the updated JRE!");
|
||||
aTask.infoAppendln("\tCurrent JRE: " + currJreVer.getLabel());
|
||||
aTask.infoAppendln("\t Chosen JRE: " + pickJreVer.getLabel());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
// TODO: Eventually remove the old JRE - perhaps from the app launcher
|
||||
}
|
||||
|
||||
// Download the individual application files
|
||||
mainTask.infoAppendln("Downloading release: " + aRelease.getVersion() + " Nodes: " + updateCat.getAllNodesList().size());
|
||||
for (Node aNode : updateCat.getAllNodesList())
|
||||
{
|
||||
// Bail if we have been aborted
|
||||
if (mainTask.isActive() == false)
|
||||
return false;
|
||||
|
||||
updateNode = updateMap.get(aFileName);
|
||||
staleNode = staleMap.get(aFileName);
|
||||
nodeFileLen = 0L;
|
||||
updateNode = aNode;
|
||||
staleNode = staleCat.getNode(updateNode.getFileName());
|
||||
tmpFileLen = 0L;
|
||||
if (updateNode instanceof FileNode)
|
||||
nodeFileLen = ((FileNode)updateNode).getFileLen();
|
||||
tmpTask = new PartialTask(mainTask, mainTask.getProgress(), nodeFileLen / (releaseSizeFull + 0.00));
|
||||
tmpFileLen = ((FileNode)updateNode).getFileLen();
|
||||
tmpTask = new PartialTask(mainTask, mainTask.getProgress(), tmpFileLen / (releaseSizeFull + 0.00));
|
||||
|
||||
// Attempt to use the local copy
|
||||
isPass = false;
|
||||
if (staleNode != null && updateNode.areContentsEqual(staleNode) == true)
|
||||
{
|
||||
isPass = staleNode.transferContentTo(tmpTask, refCredential, destPath);
|
||||
// Note we pass the SilentTask since
|
||||
// - This should be fairly fast since this should result in a local disk copy
|
||||
// - This may fail, (but the failuer is recoverable and this serves just as an optimization)
|
||||
// isPass = staleNode.transferContentTo(tmpTask, refCredential, destPath);
|
||||
isPass = staleNode.transferContentTo(new SilentTask(), refCredential, destPath);
|
||||
if (isPass == true)
|
||||
mainTask.infoAppendln("\t(L) " + staleNode.getFileName());
|
||||
}
|
||||
@@ -475,7 +606,7 @@ public class DistMakerEngine
|
||||
}
|
||||
|
||||
// Update the progress
|
||||
releaseSizeCurr += nodeFileLen;
|
||||
releaseSizeCurr += tmpFileLen;
|
||||
progressVal = releaseSizeCurr / (releaseSizeFull + 0.00);
|
||||
mainTask.setProgress(progressVal);
|
||||
}
|
||||
@@ -487,8 +618,7 @@ public class DistMakerEngine
|
||||
}
|
||||
|
||||
/**
|
||||
* Notification that the corresponding application has been fully initialized. This helper method will notify the
|
||||
* user on the status of any update.
|
||||
* Notification that the corresponding application has been fully initialized. This helper method will notify the user on the status of any update.
|
||||
*/
|
||||
private void markSystemFullyStarted()
|
||||
{
|
||||
@@ -528,9 +658,9 @@ public class DistMakerEngine
|
||||
* This method will be called via reflection.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void queryUserForInput(Task aTask, File deltaPath, List<Release> fullList)
|
||||
private void queryUserForInput(Task aTask, File deltaPath, List<AppRelease> fullList)
|
||||
{
|
||||
Release chosenItem;
|
||||
AppRelease chosenItem;
|
||||
|
||||
// Query the user, if the wish to destroy the old update
|
||||
if (deltaPath.isDirectory() == true)
|
||||
@@ -567,7 +697,7 @@ public class DistMakerEngine
|
||||
/**
|
||||
* Helper method to update platform specific configuration files
|
||||
*/
|
||||
private boolean updatePlatformConfigFiles(Task aTask, Release aRelease)
|
||||
private boolean updatePlatformConfigFiles(Task aTask, AppRelease aRelease)
|
||||
{
|
||||
File installPath, pFile;
|
||||
String errMsg;
|
||||
|
||||
@@ -12,8 +12,13 @@ import glum.util.ThreadUtil;
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.security.DigestInputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.*;
|
||||
|
||||
import distMaker.digest.Digest;
|
||||
import distMaker.digest.DigestType;
|
||||
import distMaker.jre.JreVersion;
|
||||
import distMaker.node.*;
|
||||
|
||||
public class DistUtils
|
||||
@@ -59,6 +64,35 @@ public class DistUtils
|
||||
return jarPath.getParentFile().getParentFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JreVersion for the JRE which we are running on.
|
||||
*/
|
||||
public static JreVersion getJreVersion()
|
||||
{
|
||||
String jreVer;
|
||||
|
||||
jreVer = System.getProperty("java.version");
|
||||
return new JreVersion(jreVer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the platform (Apple, Linux, or Windows) on which the current JRE is running on.
|
||||
*/
|
||||
public static String getPlatform()
|
||||
{
|
||||
String osName;
|
||||
|
||||
osName = System.getProperty("os.name").toUpperCase();
|
||||
if (osName.startsWith("LINUX") == true)
|
||||
return "Linux";
|
||||
if (osName.startsWith("MAC OS X") == true)
|
||||
return "Apple";
|
||||
if (osName.startsWith("WINDOWS") == true)
|
||||
return "Windows";
|
||||
|
||||
return System.getProperty("os.name");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the code associated with the update.
|
||||
*/
|
||||
@@ -86,12 +120,11 @@ public class DistUtils
|
||||
/**
|
||||
* Downloads the specified file from srcUrl to destFile. Returns true on success
|
||||
* <P>
|
||||
* Note the passed in task's progress will be updated from 0% to 100% at file download completion, If the specified
|
||||
* file size is invalid (aFileSize <= 0) or the download turns out to be bigger than the specified size then there
|
||||
* will be no progress update while the file is being downloaded - only at completion.
|
||||
* Note the passed in task's progress will be updated from 0% to 100% at file download completion, If the specified file size is invalid (aFileSize <= 0) or
|
||||
* the download turns out to be bigger than the specified size then there will be no progress update while the file is being downloaded - only at completion.
|
||||
*/
|
||||
@SuppressWarnings("resource")
|
||||
public static boolean downloadFile(Task aTask, URL aUrl, File aFile, Credential aCredential, long aFileSize)
|
||||
public static boolean downloadFile(Task aTask, URL aUrl, File aFile, Credential aCredential, long aFileSize, MessageDigest aDigest)
|
||||
{
|
||||
URLConnection connection;
|
||||
InputStream inStream;
|
||||
@@ -122,6 +155,8 @@ public class DistUtils
|
||||
|
||||
// Open the input/output streams
|
||||
inStream = NetUtil.getInputStream(connection, aCredential);
|
||||
if (aDigest != null)
|
||||
inStream = new DigestInputStream(inStream, aDigest);
|
||||
outStream = new FileOutputStream(aFile);
|
||||
|
||||
// Copy the bytes from the instream to the outstream
|
||||
@@ -162,7 +197,7 @@ public class DistUtils
|
||||
// Mark aTask's progress as complete since the file was downloaded.
|
||||
aTask.setProgress(1.0);
|
||||
}
|
||||
catch (IOException aExp)
|
||||
catch(IOException aExp)
|
||||
{
|
||||
errMsg = getErrorCodeMessage(aUrl, connection, aExp);
|
||||
aTask.infoAppendln(errMsg);
|
||||
@@ -180,9 +215,9 @@ public class DistUtils
|
||||
/**
|
||||
* Returns the list of available releases.
|
||||
*/
|
||||
public static List<Release> getAvailableReleases(Task aTask, URL aUpdateUrl, String appName, Credential aCredential)
|
||||
public static List<AppRelease> getAvailableAppReleases(Task aTask, URL aUpdateUrl, String appName, Credential aCredential)
|
||||
{
|
||||
List<Release> fullList;
|
||||
List<AppRelease> fullList;
|
||||
URL catUrl;
|
||||
URLConnection connection;
|
||||
InputStream inStream;
|
||||
@@ -232,13 +267,17 @@ public class DistUtils
|
||||
dateUnit = new DateUnit("", "yyyyMMMdd HH:mm:ss");
|
||||
buildTime = dateUnit.parseString(tokens[1], 0);
|
||||
|
||||
fullList.add(new Release(appName, verName, buildTime));
|
||||
fullList.add(new AppRelease(appName, verName, buildTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException aExp)
|
||||
catch(IOException aExp)
|
||||
{
|
||||
// Friendly error message
|
||||
errMsg = getErrorCodeMessage(aUpdateUrl, connection, aExp);
|
||||
|
||||
// Add the stack trace
|
||||
errMsg += "\n\n" + ThreadUtil.getStackTrace(aExp);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -248,7 +287,7 @@ public class DistUtils
|
||||
|
||||
// See if we are in a valid state
|
||||
if (errMsg != null)
|
||||
; // Nothing to do, as an earlier error has occured
|
||||
; // Nothing to do, as an earlier error has occurred
|
||||
else if (fullList.size() == 0)
|
||||
errMsg = "The update URL appears to be invalid.";
|
||||
|
||||
@@ -271,9 +310,6 @@ public class DistUtils
|
||||
Result result;
|
||||
String errMsg;
|
||||
|
||||
// Dump the stack trace
|
||||
aExp.printStackTrace();
|
||||
|
||||
// Form a user friendly exception
|
||||
errMsg = "The update site, " + aUpdateUrl + ", is not available.\n\t";
|
||||
|
||||
@@ -311,9 +347,8 @@ public class DistUtils
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to determine if the specified path is fully writable by this process. This is done by making sure
|
||||
* that all folders and child folders are writable by the current process. Note after this method is called, all
|
||||
* folders will have the write permission bit set.
|
||||
* Utility method to determine if the specified path is fully writable by this process. This is done by making sure that all folders and child folders are
|
||||
* writable by the current process. Note after this method is called, all folders will have the write permission bit set.
|
||||
*/
|
||||
public static boolean isFullyWriteable(File aPath)
|
||||
{
|
||||
@@ -343,31 +378,33 @@ public class DistUtils
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of Nodes which describe the full content of an update specified in <aUpdateUrl>/catalog.txt
|
||||
* Returns the AppCatalog which describe the full content of an update specified in <aUpdateUrl>/catalog.txt
|
||||
*/
|
||||
public static Map<String, Node> readCatalog(Task aTask, File catalogFile, URL aUpdateUrl)
|
||||
public static AppCatalog readAppCatalog(Task aTask, File aCatalogFile, URL aUpdateUrl)
|
||||
{
|
||||
Map<String, Node> retMap;
|
||||
List<Node> nodeList;
|
||||
JreVersion jreVersion;
|
||||
InputStream inStream;
|
||||
BufferedReader bufReader;
|
||||
String errMsg;
|
||||
DigestType digestType;
|
||||
String errMsg, strLine;
|
||||
|
||||
errMsg = null;
|
||||
retMap = new LinkedHashMap<>();
|
||||
nodeList = new ArrayList<>();
|
||||
jreVersion = null;
|
||||
|
||||
// Default to DigestType of MD5
|
||||
digestType = DigestType.MD5;
|
||||
|
||||
inStream = null;
|
||||
bufReader = null;
|
||||
try
|
||||
{
|
||||
String[] tokens;
|
||||
String strLine, filename, md5sum;
|
||||
long fileLen;
|
||||
|
||||
// Read the contents of the file
|
||||
inStream = new FileInputStream(catalogFile);
|
||||
inStream = new FileInputStream(aCatalogFile);
|
||||
bufReader = new BufferedReader(new InputStreamReader(new BufferedInputStream(inStream)));
|
||||
|
||||
// Read the lines
|
||||
while (true)
|
||||
{
|
||||
strLine = bufReader.readLine();
|
||||
@@ -379,17 +416,47 @@ public class DistUtils
|
||||
tokens = strLine.split(",", 4);
|
||||
if (strLine.isEmpty() == true || strLine.startsWith("#") == true)
|
||||
; // Nothing to do
|
||||
else if (tokens.length >= 1 && tokens[0].equals("exit") == true)
|
||||
break; // Bail once we get the 'exit' command
|
||||
else if (tokens.length == 2 && tokens[0].equals("P") == true)
|
||||
{
|
||||
String filename;
|
||||
|
||||
// Form the PathNode
|
||||
filename = tokens[1];
|
||||
retMap.put(filename, new PathNode(aUpdateUrl, filename));
|
||||
nodeList.add(new PathNode(aUpdateUrl, filename));
|
||||
}
|
||||
else if (tokens.length == 4 && tokens[0].equals("F") == true)
|
||||
{
|
||||
md5sum = tokens[1];
|
||||
String filename, digestStr;
|
||||
long fileLen;
|
||||
|
||||
// Form the FileNode
|
||||
digestStr = tokens[1];
|
||||
fileLen = GuiUtil.readLong(tokens[2], -1);
|
||||
filename = tokens[3];
|
||||
retMap.put(filename, new FileNode(aUpdateUrl, filename, md5sum, fileLen));
|
||||
nodeList.add(new FileNode(aUpdateUrl, filename, new Digest(digestType, digestStr), fileLen));
|
||||
}
|
||||
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;
|
||||
}
|
||||
else if (tokens.length == 2 && tokens[0].equals("jre") == true)
|
||||
{
|
||||
if (jreVersion != null)
|
||||
{
|
||||
aTask.infoAppendln("JRE version has already been specified. Current ver: " + jreVersion.getLabel() + " Requested ver: " + tokens[1]
|
||||
+ ". Skipping...");
|
||||
continue;
|
||||
}
|
||||
|
||||
jreVersion = new JreVersion(tokens[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -397,7 +464,7 @@ public class DistUtils
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException aExp)
|
||||
catch(IOException aExp)
|
||||
{
|
||||
errMsg = ThreadUtil.getStackTrace(aExp);
|
||||
}
|
||||
@@ -410,7 +477,7 @@ public class DistUtils
|
||||
// See if we are in a valid state
|
||||
if (errMsg != null)
|
||||
; // Nothing to do, as an earlier error has occurred
|
||||
else if (retMap.size() == 0)
|
||||
else if (nodeList.size() == 0)
|
||||
errMsg = "The catalog appears to be invalid.";
|
||||
|
||||
// Bail if there were issues
|
||||
@@ -420,12 +487,11 @@ public class DistUtils
|
||||
return null;
|
||||
}
|
||||
|
||||
return retMap;
|
||||
return new AppCatalog(jreVersion, nodeList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to switch the DistMaker library into debug mode. You should never call this method unless you are
|
||||
* modifying the DistMaker library.
|
||||
* Utility method to switch the DistMaker library into debug mode. You should never call this method unless you are modifying the DistMaker library.
|
||||
* <P>
|
||||
* This functionality only exists to allow rapid development of DistMaker
|
||||
*/
|
||||
|
||||
72
src/distMaker/MiscUtils.java
Normal file
72
src/distMaker/MiscUtils.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package distMaker;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.attribute.PosixFilePermission;
|
||||
import java.nio.file.attribute.PosixFilePermissions;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Collection of generic utility methods that should be migrated to another library.
|
||||
*/
|
||||
public class MiscUtils
|
||||
{
|
||||
public static void unTar(final File inputFile, final File aDestPath) throws Exception
|
||||
{
|
||||
throw new Exception("Incomplete...");
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to convert a Unix base-10 mode into the equivalent string.
|
||||
* <P>
|
||||
* Example: 493 -> 'rwxr-xr-x'
|
||||
* <P>
|
||||
* The returned string will always be of length 9
|
||||
*/
|
||||
public static String convertUnixModeToStr(int aMode)
|
||||
{
|
||||
char permArr[] = {'r', 'w', 'x', 'r', 'w', 'x', 'r', 'w', 'x'};
|
||||
|
||||
for (int c1 = 8; c1 >= 0; c1--)
|
||||
{
|
||||
if (((aMode >> c1) & 0x01) != 1)
|
||||
permArr[8 - c1] = '-';
|
||||
}
|
||||
|
||||
return new String(permArr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to convert a Unix base-10 mode into the Set<PosixFilePermission>.
|
||||
* <P>
|
||||
* Example: 493 -> 'rwxr-xr-x'
|
||||
* <P>
|
||||
* The returned string will always be of length 9
|
||||
*/
|
||||
public static Set<PosixFilePermission> convertUnixModeToPFP(int aMode)
|
||||
{
|
||||
return PosixFilePermissions.fromString(convertUnixModeToStr(aMode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to output the specified strings to aFile
|
||||
*/
|
||||
public static boolean writeDoc(File aFile, List<String> strList)
|
||||
{
|
||||
// Output the strList
|
||||
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(aFile)));)
|
||||
{
|
||||
// Write the lines
|
||||
for (String aStr : strList)
|
||||
bw.write(aStr + '\n');
|
||||
}
|
||||
catch(Exception aExp)
|
||||
{
|
||||
aExp.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,36 +2,36 @@ package distMaker;
|
||||
|
||||
public class UpdateStatus
|
||||
{
|
||||
private final boolean isUpToDate;
|
||||
private final boolean errorDeterminingState;
|
||||
private final String errorMessage;
|
||||
private final boolean isUpToDate;
|
||||
private final boolean errorDeterminingState;
|
||||
private final String errorMessage;
|
||||
|
||||
public UpdateStatus(boolean isUpToDate)
|
||||
{
|
||||
this.isUpToDate = isUpToDate;
|
||||
this.errorDeterminingState = false;;
|
||||
this.errorMessage = "";
|
||||
}
|
||||
public UpdateStatus(boolean isUpToDate)
|
||||
{
|
||||
this.isUpToDate = isUpToDate;
|
||||
this.errorDeterminingState = false;
|
||||
this.errorMessage = "";
|
||||
}
|
||||
|
||||
public UpdateStatus(String errorMessage)
|
||||
{
|
||||
this.isUpToDate = false;
|
||||
this.errorDeterminingState = true;
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
public UpdateStatus(String errorMessage)
|
||||
{
|
||||
this.isUpToDate = false;
|
||||
this.errorDeterminingState = true;
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public boolean isUpToDate()
|
||||
{
|
||||
return isUpToDate;
|
||||
}
|
||||
public boolean isUpToDate()
|
||||
{
|
||||
return isUpToDate;
|
||||
}
|
||||
|
||||
public boolean isErrorDeterminingState()
|
||||
{
|
||||
return errorDeterminingState;
|
||||
}
|
||||
public boolean isErrorDeterminingState()
|
||||
{
|
||||
return errorDeterminingState;
|
||||
}
|
||||
|
||||
public String getErrorMessage()
|
||||
{
|
||||
return errorMessage;
|
||||
}
|
||||
public String getErrorMessage()
|
||||
{
|
||||
return errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
83
src/distMaker/digest/Digest.java
Normal file
83
src/distMaker/digest/Digest.java
Normal file
@@ -0,0 +1,83 @@
|
||||
package distMaker.digest;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class Digest
|
||||
{
|
||||
private final DigestType digestType;
|
||||
private final byte[] digestValueArr;
|
||||
|
||||
public Digest(DigestType aDigestType, byte[] aDigestValueArr)
|
||||
{
|
||||
digestType = aDigestType;
|
||||
digestValueArr = Arrays.copyOf(aDigestValueArr, aDigestValueArr.length);
|
||||
}
|
||||
|
||||
public Digest(DigestType aDigestType, String aHexStr)
|
||||
{
|
||||
digestType = aDigestType;
|
||||
digestValueArr = DigestUtils.hexStr2ByteArr(aHexStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a user friendly description (string) of this digest result.
|
||||
* <P>
|
||||
* The result will be DigestType:hexDigestValue
|
||||
*/
|
||||
public String getDescr()
|
||||
{
|
||||
return "" + digestType + ":" + getValueAsString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the DigestType associated with this Digest.
|
||||
*/
|
||||
public DigestType getType()
|
||||
{
|
||||
return digestType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual digest (as a string) associated with this Digest.
|
||||
*/
|
||||
public byte[] getValue()
|
||||
{
|
||||
return Arrays.copyOf(digestValueArr, digestValueArr.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual digest (as a string) associated with this Digest.
|
||||
*/
|
||||
public String getValueAsString()
|
||||
{
|
||||
return DigestUtils.byteArr2HexStr(digestValueArr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((digestType == null) ? 0 : digestType.hashCode());
|
||||
result = prime * result + Arrays.hashCode(digestValueArr);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Digest other = (Digest)obj;
|
||||
if (digestType != other.digestType)
|
||||
return false;
|
||||
if (!Arrays.equals(digestValueArr, other.digestValueArr))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
46
src/distMaker/digest/DigestType.java
Normal file
46
src/distMaker/digest/DigestType.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package distMaker.digest;
|
||||
|
||||
public enum DigestType
|
||||
{
|
||||
// Weak digest - but very fast
|
||||
MD5("MD5"),
|
||||
|
||||
// Fairly strong digest type (with good performance on 32 bit machines)
|
||||
SHA256("SHA-256"),
|
||||
|
||||
// Very strong digest type
|
||||
SHA512("SHA-512");
|
||||
|
||||
// State vars
|
||||
private String algName;
|
||||
|
||||
private DigestType(String aAlgName)
|
||||
{
|
||||
algName = aAlgName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the official digest algorithm name.
|
||||
*
|
||||
* @see http://docs.oracle.com/javase/1.5.0/docs/guide/security/CryptoSpec.html#AppA
|
||||
*/
|
||||
public String getAlgName()
|
||||
{
|
||||
return algName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding DigestType.
|
||||
*/
|
||||
public static DigestType parse(String aStr)
|
||||
{
|
||||
if (aStr.equalsIgnoreCase("MD5") == true)
|
||||
return MD5;
|
||||
if (aStr.equalsIgnoreCase("SHA256") == true)
|
||||
return SHA256;
|
||||
if (aStr.equalsIgnoreCase("SHA512") == true)
|
||||
return SHA512;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
68
src/distMaker/digest/DigestUtils.java
Normal file
68
src/distMaker/digest/DigestUtils.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package distMaker.digest;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
|
||||
|
||||
/**
|
||||
* Collection of utility methods to ease working with the MessageDigest and associated classes.
|
||||
*/
|
||||
public class DigestUtils
|
||||
{
|
||||
/**
|
||||
* Utility method that will throw a RuntimeExcepption if the specified digest function is not found.
|
||||
* <P>
|
||||
* Algorithm should be MD5, SHA-256, SHA-512, ...
|
||||
* <P>
|
||||
* See: http://docs.oracle.com/javase/1.8.0/docs/guide/security/CryptoSpec.html#AppA
|
||||
*/
|
||||
public static MessageDigest getDigest(String aAlgorithm)
|
||||
{
|
||||
MessageDigest retDigest;
|
||||
|
||||
try
|
||||
{
|
||||
retDigest = MessageDigest.getInstance(aAlgorithm);
|
||||
}
|
||||
catch(NoSuchAlgorithmException aExp)
|
||||
{
|
||||
throw new RuntimeException("Digest not found. Digest algorith not found: " + aAlgorithm);
|
||||
}
|
||||
|
||||
return retDigest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that will throw a RuntimeExcepption if the specified digest function is not found.
|
||||
* <P>
|
||||
* See: http://docs.oracle.com/javase/1.8.0/docs/guide/security/CryptoSpec.html#AppA
|
||||
*/
|
||||
public static MessageDigest getDigest(DigestType aDigestType)
|
||||
{
|
||||
return getDigest(aDigestType.getAlgName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that returns the hex string corresponding to the byte array.
|
||||
*/
|
||||
public static String byteArr2HexStr(byte[] aByteArr)
|
||||
{
|
||||
String retStr;
|
||||
|
||||
retStr = (new HexBinaryAdapter()).marshal(aByteArr).toLowerCase();
|
||||
return retStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that returns a byte array corresponding to the hex string.
|
||||
*/
|
||||
public static byte[] hexStr2ByteArr(String aHexStr)
|
||||
{
|
||||
byte[] retArr;
|
||||
|
||||
retArr = (new HexBinaryAdapter()).unmarshal(aHexStr);
|
||||
return retArr;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import javax.swing.event.ListSelectionListener;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import distMaker.platform.MemUtils;
|
||||
|
||||
import distMaker.platform.PlatformUtils;
|
||||
import static distMaker.platform.MemUtils.KB_SIZE;
|
||||
import static distMaker.platform.MemUtils.MB_SIZE;
|
||||
import static distMaker.platform.MemUtils.GB_SIZE;
|
||||
@@ -48,11 +48,11 @@ public class MemoryConfigPanel extends GlassPanel implements ActionListener, Zio
|
||||
private long targMemSize;
|
||||
|
||||
/**
|
||||
* Constructor where the developer specifies the max heap memory. Be careful about using this method, as if a value
|
||||
* is specified too large, then the program may become non operational on the next run.
|
||||
* Constructor where the developer specifies the max heap memory. Be careful about using this method, as if a value is specified too large, then the program
|
||||
* may become non operational on the next run.
|
||||
* <P>
|
||||
* Should the program become non operational then the end user would have to manually configure the config/script
|
||||
* files by hand or a reinstall would be required.
|
||||
* Should the program become non operational then the end user would have to manually configure the config/script files by hand or a reinstall would be
|
||||
* required.
|
||||
*/
|
||||
public MemoryConfigPanel(Component aParent, long aMaxMemSize)
|
||||
{
|
||||
@@ -74,8 +74,8 @@ public class MemoryConfigPanel extends GlassPanel implements ActionListener, Zio
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor where the DistMaker framework attempts to determine the appropriate maxMexSize. Should, the DistMaker
|
||||
* framework fail to determine the installed system memory, then 4GB will be assumed as the installed system memory.
|
||||
* Constructor where the DistMaker framework attempts to determine the appropriate maxMexSize. Should, the DistMaker framework fail to determine the
|
||||
* installed system memory, then 4GB will be assumed as the installed system memory.
|
||||
*/
|
||||
public MemoryConfigPanel(Component aParent)
|
||||
{
|
||||
@@ -124,7 +124,7 @@ public class MemoryConfigPanel extends GlassPanel implements ActionListener, Zio
|
||||
targMemSize = roundToMB(targMemSize);
|
||||
|
||||
// Bail if we are not able to set the DistMaker max heap memory
|
||||
if (MemUtils.setMaxHeapMem(warnPanel, targMemSize) == false)
|
||||
if (PlatformUtils.setMaxHeapMem(warnPanel, targMemSize) == false)
|
||||
return;
|
||||
|
||||
// Update our state vars
|
||||
@@ -242,8 +242,7 @@ public class MemoryConfigPanel extends GlassPanel implements ActionListener, Zio
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to round (floor) values to the nearest megabyte. The returned value is guaranteed to be at least 1
|
||||
* megabyte.
|
||||
* Utility method to round (floor) values to the nearest megabyte. The returned value is guaranteed to be at least 1 megabyte.
|
||||
* <P>
|
||||
* The input value, aSize, should be specified in bytes, and the returned value will be specified in bytes.
|
||||
*/
|
||||
|
||||
@@ -25,7 +25,7 @@ import javax.swing.event.ListSelectionListener;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import distMaker.LookUp;
|
||||
import distMaker.Release;
|
||||
import distMaker.node.AppRelease;
|
||||
|
||||
public class PickReleasePanel extends GlassPanel implements ActionListener, ZioRaw, ListSelectionListener
|
||||
{
|
||||
@@ -34,19 +34,19 @@ public class PickReleasePanel extends GlassPanel implements ActionListener, ZioR
|
||||
// GUI vars
|
||||
private JLabel titleL;
|
||||
private JRadioButton newestRB, olderRB;
|
||||
private ItemListPanel<Release> listPanel;
|
||||
private ItemListPanel<AppRelease> listPanel;
|
||||
private QueryTableCellRenderer col0Renderer, col1Renderer;
|
||||
private JButton abortB, proceedB;
|
||||
private JTextArea infoTA, warnTA;
|
||||
private Font smallFont;
|
||||
|
||||
// State vars
|
||||
private StaticItemProcessor<Release> myItemProcessor;
|
||||
private Release chosenItem;
|
||||
private Release installedItem;
|
||||
private Release newestItem;
|
||||
private StaticItemProcessor<AppRelease> myItemProcessor;
|
||||
private AppRelease chosenItem;
|
||||
private AppRelease installedItem;
|
||||
private AppRelease newestItem;
|
||||
|
||||
public PickReleasePanel(Component aParent, Release aInstalledItem)
|
||||
public PickReleasePanel(Component aParent, AppRelease aInstalledItem)
|
||||
{
|
||||
super(aParent);
|
||||
|
||||
@@ -67,7 +67,7 @@ public class PickReleasePanel extends GlassPanel implements ActionListener, ZioR
|
||||
/**
|
||||
* Returns the Release selected by the user. This will be null if the user aborted the action.
|
||||
*/
|
||||
public Release getChosenItem()
|
||||
public AppRelease getChosenItem()
|
||||
{
|
||||
return chosenItem;
|
||||
}
|
||||
@@ -75,7 +75,7 @@ public class PickReleasePanel extends GlassPanel implements ActionListener, ZioR
|
||||
/**
|
||||
* Sets in the configuration of available versions
|
||||
*/
|
||||
public void setConfiguration(List<Release> itemList)
|
||||
public void setConfiguration(List<AppRelease> itemList)
|
||||
{
|
||||
DateUnit dateUnit;
|
||||
// String currBuildStr;
|
||||
@@ -84,7 +84,7 @@ public class PickReleasePanel extends GlassPanel implements ActionListener, ZioR
|
||||
String appName, infoMsg;
|
||||
|
||||
// Sort the items, and isolate the newest item
|
||||
LinkedList<Release> linkedList;
|
||||
LinkedList<AppRelease> linkedList;
|
||||
linkedList = new LinkedList<>(itemList);
|
||||
Collections.sort(linkedList);
|
||||
Collections.reverse(linkedList); // reverse the list to show most recent versions on top
|
||||
@@ -210,7 +210,7 @@ public class PickReleasePanel extends GlassPanel implements ActionListener, ZioR
|
||||
private JPanel buildItemListTablePanel()
|
||||
{
|
||||
QueryComposer<LookUp> aComposer;
|
||||
QueryItemHandler<Release> aItemHandler;
|
||||
QueryItemHandler<AppRelease> aItemHandler;
|
||||
DateUnit dateUnit;
|
||||
|
||||
dateUnit = new DateUnit("", "yyyyMMMdd HH:mm");
|
||||
@@ -225,10 +225,10 @@ public class PickReleasePanel extends GlassPanel implements ActionListener, ZioR
|
||||
aComposer.setRenderer(LookUp.Version, col0Renderer);
|
||||
aComposer.setRenderer(LookUp.BuildTime, col1Renderer);
|
||||
|
||||
aItemHandler = new QueryItemHandler<Release>(aComposer);
|
||||
myItemProcessor = new StaticItemProcessor<Release>();
|
||||
aItemHandler = new QueryItemHandler<AppRelease>(aComposer);
|
||||
myItemProcessor = new StaticItemProcessor<AppRelease>();
|
||||
|
||||
listPanel = new ItemListPanel<Release>(aItemHandler, myItemProcessor, false, false);
|
||||
listPanel = new ItemListPanel<AppRelease>(aItemHandler, myItemProcessor, false, false);
|
||||
listPanel.setSortingEnabled(false);
|
||||
listPanel.addListSelectionListener(this);
|
||||
return listPanel;
|
||||
@@ -239,7 +239,7 @@ public class PickReleasePanel extends GlassPanel implements ActionListener, ZioR
|
||||
*/
|
||||
private void updateGui()
|
||||
{
|
||||
Release pickItem;
|
||||
AppRelease pickItem;
|
||||
String warnMsg;
|
||||
boolean isEnabled;
|
||||
|
||||
|
||||
102
src/distMaker/jre/JreRelease.java
Normal file
102
src/distMaker/jre/JreRelease.java
Normal file
@@ -0,0 +1,102 @@
|
||||
package distMaker.jre;
|
||||
|
||||
import distMaker.digest.Digest;
|
||||
|
||||
/**
|
||||
* Immutable class that describes a JRE Release.
|
||||
* <P>
|
||||
* The reference fileName should be a compressed (tar.gz) JRE.
|
||||
*/
|
||||
public class JreRelease implements Comparable<JreRelease>
|
||||
{
|
||||
private String platform;
|
||||
private JreVersion version;
|
||||
private Digest digest;
|
||||
private String fileName;
|
||||
private long fileLen;
|
||||
|
||||
public JreRelease(String aPlatform, String aVersion, String aFileName, Digest aDigest, long aFileLen)
|
||||
{
|
||||
platform = aPlatform;
|
||||
version = new JreVersion(aVersion);
|
||||
fileName = aFileName;
|
||||
digest = aDigest;
|
||||
fileLen = aFileLen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Digest associated with the JRE (tar.gz) file.
|
||||
*/
|
||||
public Digest getDigest()
|
||||
{
|
||||
return digest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of the JRE corresponding to this release.
|
||||
*/
|
||||
public JreVersion getVersion()
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the specified platform matches our platform.
|
||||
*/
|
||||
public boolean isPlatformMatch(String aPlatform)
|
||||
{
|
||||
String platformStr;
|
||||
|
||||
// Consider this JreRelease a match if our platform is contained within aPlatform
|
||||
platformStr = platform.toUpperCase();
|
||||
if (aPlatform.toUpperCase().contains(platformStr) == true)
|
||||
return true;
|
||||
|
||||
// If our platform == APPLE - then check to see if aPlatform mathes against 'MACOSX'
|
||||
if (platformStr.equals("APPLE") == true && aPlatform.toUpperCase().contains("MACOSX") == true)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of the associated file
|
||||
*/
|
||||
public long getFileLen()
|
||||
{
|
||||
return fileLen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the filename of this (tar.gz) JRE release.
|
||||
*/
|
||||
public String getFileName()
|
||||
{
|
||||
return fileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(JreRelease aItem)
|
||||
{
|
||||
int cmpVal;
|
||||
|
||||
cmpVal = platform.compareTo(aItem.platform);
|
||||
if (cmpVal != 0)
|
||||
return cmpVal;
|
||||
|
||||
cmpVal = version.compareTo(aItem.version);
|
||||
if (cmpVal != 0)
|
||||
return cmpVal;
|
||||
|
||||
cmpVal = fileName.compareTo(aItem.fileName);
|
||||
if (cmpVal != 0)
|
||||
return cmpVal;
|
||||
|
||||
cmpVal = Long.compare(fileLen, aItem.fileLen);
|
||||
if (cmpVal != 0)
|
||||
return cmpVal;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
149
src/distMaker/jre/JreUtils.java
Normal file
149
src/distMaker/jre/JreUtils.java
Normal file
@@ -0,0 +1,149 @@
|
||||
package distMaker.jre;
|
||||
|
||||
import glum.gui.GuiUtil;
|
||||
import glum.io.IoUtil;
|
||||
import glum.net.Credential;
|
||||
import glum.net.NetUtil;
|
||||
import glum.task.Task;
|
||||
import glum.util.ThreadUtil;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.*;
|
||||
|
||||
import distMaker.digest.Digest;
|
||||
import distMaker.digest.DigestType;
|
||||
|
||||
public class JreUtils
|
||||
{
|
||||
/**
|
||||
* Returns a list of all the available JRE releases specified in <aUpdateSiteUrl>/jre/jreCatalog.txt
|
||||
*/
|
||||
public static List<JreRelease> getAvailableJreReleases(Task aTask, URL aUpdateSiteUrl, Credential aCredential)
|
||||
{
|
||||
List<JreRelease> retList;
|
||||
URL catUrl;
|
||||
URLConnection connection;
|
||||
InputStream inStream;
|
||||
BufferedReader bufReader;
|
||||
DigestType digestType;
|
||||
String errMsg, strLine;
|
||||
|
||||
errMsg = null;
|
||||
retList = new ArrayList<>();
|
||||
catUrl = IoUtil.createURL(aUpdateSiteUrl.toString() + "/jre/jreCatalog.txt");
|
||||
|
||||
// Default to DigestType of MD5
|
||||
digestType = DigestType.MD5;
|
||||
|
||||
inStream = null;
|
||||
bufReader = null;
|
||||
try
|
||||
{
|
||||
String[] tokens;
|
||||
|
||||
// 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;
|
||||
|
||||
tokens = strLine.split(",", 4);
|
||||
if (strLine.isEmpty() == true || strLine.startsWith("#") == true)
|
||||
; // Nothing to do
|
||||
else if (tokens.length >= 1 && tokens[0].equals("exit") == true)
|
||||
break; // Bail once we get the 'exit' 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;
|
||||
}
|
||||
else if (tokens.length == 6 && tokens[0].equals("jre") == true)
|
||||
{
|
||||
String platform, version, filename, digestStr;
|
||||
long fileLen;
|
||||
|
||||
// Form the JreRelease
|
||||
digestStr = tokens[1];
|
||||
platform = tokens[2];
|
||||
version = tokens[3];
|
||||
fileLen = GuiUtil.readLong(tokens[4], -1);
|
||||
filename = tokens[5];
|
||||
retList.add(new JreRelease(platform, version, filename, new Digest(digestType, digestStr), 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 returns a list of matching JREs. The list will be sorted in order from newest to oldest. All returned JREs will have a platform that
|
||||
* matches aPlatform.
|
||||
*/
|
||||
public static List<JreRelease> getMatchingPlatforms(List<JreRelease> aJreList, String aPlatform)
|
||||
{
|
||||
List<JreRelease> retList;
|
||||
|
||||
// Grab all JREs with a matching platforms
|
||||
retList = new ArrayList<>();
|
||||
for (JreRelease aRelease : aJreList)
|
||||
{
|
||||
if (aRelease.isPlatformMatch(aPlatform) == false)
|
||||
continue;
|
||||
|
||||
retList.add(aRelease);
|
||||
}
|
||||
|
||||
// Sort the platforms, but reverse the order so that the newest version is first
|
||||
Collections.sort(retList);
|
||||
Collections.reverse(retList);
|
||||
|
||||
return retList;
|
||||
}
|
||||
|
||||
}
|
||||
82
src/distMaker/jre/JreVersion.java
Normal file
82
src/distMaker/jre/JreVersion.java
Normal file
@@ -0,0 +1,82 @@
|
||||
package distMaker.jre;
|
||||
|
||||
import glum.gui.GuiUtil;
|
||||
|
||||
public class JreVersion implements Comparable<JreVersion>
|
||||
{
|
||||
private String version;
|
||||
|
||||
public JreVersion(String aVersion)
|
||||
{
|
||||
version = aVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of the JRE as a string.
|
||||
*/
|
||||
public String getLabel()
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that returns the better version.
|
||||
* <P>
|
||||
* The better version is defined as the later version (and the more specific version).
|
||||
* <P>
|
||||
* Returns null if the better version can not be determined
|
||||
*/
|
||||
public static JreVersion getBetterVersion(JreVersion verA, JreVersion verB)
|
||||
{
|
||||
JreVersion defaultVer;
|
||||
String[] tokenA, tokenB;
|
||||
int valA, valB, idxCnt;
|
||||
|
||||
tokenA = verA.getLabel().split("[._]");
|
||||
tokenB = verB.getLabel().split("[._]");
|
||||
|
||||
// Default return JreVersion is verA or the version that is more specific
|
||||
defaultVer = verA;
|
||||
if (tokenA.length < tokenB.length)
|
||||
defaultVer = verB;
|
||||
|
||||
// Set the idxCnt to the less specific JreVersion
|
||||
idxCnt = tokenA.length;
|
||||
if (tokenB.length < tokenA.length)
|
||||
idxCnt = tokenB.length;
|
||||
|
||||
// Compare each component of the version string. Each component should be separated by '.'
|
||||
// Assume each component is an integer where larger values correspond to later versions
|
||||
for (int c1 = 0; c1 < idxCnt; c1++)
|
||||
{
|
||||
valA = GuiUtil.readInt(tokenA[c1], -1);
|
||||
valB = GuiUtil.readInt(tokenB[c1], -1);
|
||||
if (valA == -1 && valB == -1)
|
||||
return null;
|
||||
|
||||
if (valB == -1 || valA > valB)
|
||||
return verA;
|
||||
if (valA == -1 || valB > valA)
|
||||
return verB;
|
||||
}
|
||||
|
||||
// Defaults to verA
|
||||
return defaultVer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(JreVersion aItem)
|
||||
{
|
||||
JreVersion tmpVer;
|
||||
|
||||
// Note the natural ordering is from oldest version to most recent version
|
||||
tmpVer = JreVersion.getBetterVersion(this, aItem);
|
||||
if (tmpVer == aItem)
|
||||
return -1;
|
||||
if (tmpVer == this)
|
||||
return +1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
68
src/distMaker/node/AppCatalog.java
Normal file
68
src/distMaker/node/AppCatalog.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package distMaker.node;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import distMaker.jre.JreVersion;
|
||||
|
||||
/**
|
||||
* Object that describes the structure (files, folders, and JRE version) of a Java application.
|
||||
*/
|
||||
public class AppCatalog
|
||||
{
|
||||
/** The minimum JRE version required. */
|
||||
private JreVersion jreVersion;
|
||||
|
||||
/** A mapping of filename to to corresponding Node */
|
||||
private ImmutableMap<String, Node> nodeMap;
|
||||
|
||||
public AppCatalog(JreVersion aJreVersion, List<Node> aNodeList)
|
||||
{
|
||||
jreVersion = aJreVersion;
|
||||
nodeMap = ImmutableMap.copyOf(formNameMap(aNodeList));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum JreVersion required.
|
||||
*/
|
||||
public JreVersion getJreVersion()
|
||||
{
|
||||
return jreVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Node corresponding to the specified name.
|
||||
*/
|
||||
public Node getNode(String aName)
|
||||
{
|
||||
return nodeMap.get(aName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full list of Nodes
|
||||
*/
|
||||
public ImmutableList<Node> getAllNodesList()
|
||||
{
|
||||
return nodeMap.values().asList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to form the map used to quickly locate a Node with the corresponding filename.
|
||||
* <P>
|
||||
* TODO: This should be renamed formNameMap to formDigestMap<BR>
|
||||
* TODO: This should probably be a mapping of Digest to Node rather than filename to Node
|
||||
*/
|
||||
public Map<String, Node> formNameMap(List<Node> aNodeList)
|
||||
{
|
||||
Map<String, Node> retMap;
|
||||
|
||||
retMap = new LinkedHashMap<>();
|
||||
for (Node aNode : aNodeList)
|
||||
retMap.put(aNode.getFileName(), aNode);
|
||||
|
||||
return retMap;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,17 +1,18 @@
|
||||
package distMaker;
|
||||
package distMaker.node;
|
||||
|
||||
import distMaker.LookUp;
|
||||
import glum.database.QueryItem;
|
||||
|
||||
/**
|
||||
* Immutable object that has information relevant to the packaged software.
|
||||
*/
|
||||
public class Release implements Comparable<Release>, QueryItem<LookUp>
|
||||
public class AppRelease implements Comparable<AppRelease>, QueryItem<LookUp>
|
||||
{
|
||||
private final String appName;
|
||||
private final String version;
|
||||
private final long buildTime;
|
||||
|
||||
public Release(String aAppName, String aVersion, long aBuildTime)
|
||||
public AppRelease(String aAppName, String aVersion, long aBuildTime)
|
||||
{
|
||||
appName = aAppName;
|
||||
version = aVersion;
|
||||
@@ -43,7 +44,7 @@ public class Release implements Comparable<Release>, QueryItem<LookUp>
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Release o)
|
||||
public int compareTo(AppRelease o)
|
||||
{
|
||||
if (buildTime < o.buildTime)
|
||||
return -1;
|
||||
@@ -95,7 +96,7 @@ public class Release implements Comparable<Release>, QueryItem<LookUp>
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Release other = (Release)obj;
|
||||
AppRelease other = (AppRelease)obj;
|
||||
if (appName == null)
|
||||
{
|
||||
if (other.appName != null)
|
||||
@@ -6,21 +6,27 @@ import glum.task.Task;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
import distMaker.DistUtils;
|
||||
import distMaker.digest.Digest;
|
||||
import distMaker.digest.DigestUtils;
|
||||
|
||||
/**
|
||||
* Immutable node describing a File.
|
||||
*/
|
||||
public class FileNode implements Node
|
||||
{
|
||||
protected URL rootUrl;
|
||||
protected String md5sum;
|
||||
protected String fileName;
|
||||
protected long fileLen;
|
||||
private final URL rootUrl;
|
||||
private final Digest digest;
|
||||
private final String fileName;
|
||||
private final long fileLen;
|
||||
|
||||
public FileNode(URL aRootUrl, String aFileName, String aMd5sum, long aFileLen)
|
||||
public FileNode(URL aRootUrl, String aFileName, Digest aDigest, long aFileLen)
|
||||
{
|
||||
rootUrl = aRootUrl;
|
||||
fileName = aFileName;
|
||||
md5sum = aMd5sum;
|
||||
digest = aDigest;
|
||||
fileLen = aFileLen;
|
||||
}
|
||||
|
||||
@@ -33,7 +39,7 @@ public class FileNode implements Node
|
||||
return false;
|
||||
|
||||
fNode = (FileNode)aNode;
|
||||
if (fNode.md5sum.equals(md5sum) == false)
|
||||
if (fNode.digest.equals(digest) == false)
|
||||
return false;
|
||||
if (fNode.fileName.equals(fileName) == false)
|
||||
return false;
|
||||
@@ -62,6 +68,8 @@ public class FileNode implements Node
|
||||
{
|
||||
URL srcUrl;
|
||||
File dstFile;
|
||||
Digest tmpDigest;
|
||||
boolean isPass;
|
||||
|
||||
// Determine the source URL to copy the contents from
|
||||
srcUrl = IoUtil.createURL(rootUrl.toString() + "/" + fileName);
|
||||
@@ -69,6 +77,23 @@ public class FileNode implements Node
|
||||
// Determine the file to transfer the contents to
|
||||
dstFile = new File(dstPath, fileName);
|
||||
|
||||
return DistUtils.downloadFile(aTask, srcUrl, dstFile, aCredential, fileLen);
|
||||
// Download the file
|
||||
MessageDigest msgDigest = DigestUtils.getDigest(digest.getType());
|
||||
isPass = DistUtils.downloadFile(aTask, srcUrl, dstFile, aCredential, fileLen, msgDigest);
|
||||
if (isPass == false)
|
||||
return false;
|
||||
|
||||
// Validate that the file was downloaded successfully
|
||||
tmpDigest = new Digest(digest.getType(), msgDigest.digest());
|
||||
if (digest.equals(tmpDigest) == false)
|
||||
{
|
||||
aTask.infoAppendln("\nThe download of the application appears to be corrupted.");
|
||||
aTask.infoAppendln("\tFile: " + fileName);
|
||||
aTask.infoAppendln("\t\tExpected " + digest.getDescr());
|
||||
aTask.infoAppendln("\t\tRecieved " + tmpDigest.getDescr() + "\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,12 +8,15 @@ import java.net.URL;
|
||||
|
||||
public class PathNode implements Node
|
||||
{
|
||||
protected URL rootUrl;
|
||||
protected String fileName;
|
||||
// private final URL rootUrl;
|
||||
private final String fileName;
|
||||
|
||||
/**
|
||||
* Immutable node describing a File.
|
||||
*/
|
||||
public PathNode(URL aRootUrl, String aFileName)
|
||||
{
|
||||
rootUrl = aRootUrl;
|
||||
// rootUrl = aRootUrl;
|
||||
fileName = aFileName;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package distMaker.platform;
|
||||
|
||||
import glum.io.IoUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
@@ -13,11 +11,47 @@ import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.w3c.dom.*;
|
||||
|
||||
import distMaker.DistUtils;
|
||||
|
||||
/**
|
||||
* Utility class which contains a set of methods to interact with an Apple Info.plist file.
|
||||
*/
|
||||
public class AppleUtils
|
||||
{
|
||||
/**
|
||||
* Utility method to update the JRE to reflect the specified path.
|
||||
* <P>
|
||||
* TODO: Complete this comment and method.
|
||||
*/
|
||||
public static boolean updateJrePath(File aPath)
|
||||
{
|
||||
int zios_finish;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plist file used to configure apple applications.
|
||||
* <P>
|
||||
* Two locations will be searched.... TODO: Add more details of those locations.
|
||||
*/
|
||||
private static File getPlistFile()
|
||||
{
|
||||
File installPath;
|
||||
File pFile;
|
||||
|
||||
// Get the top level install path
|
||||
installPath = DistUtils.getAppPath().getParentFile();
|
||||
|
||||
// Attempt to locate the pList file
|
||||
pFile = new File(installPath, "Info.plist");
|
||||
if (pFile.isFile() == false)
|
||||
pFile = new File(installPath.getParentFile(), "Info.plist");
|
||||
if (pFile.isFile() == false)
|
||||
pFile = null;
|
||||
|
||||
return pFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update the specified max memory (-Xmx) value in the plist file (aFile) to the specified maxMemVal.
|
||||
* <P>
|
||||
@@ -26,7 +60,21 @@ public class AppleUtils
|
||||
*
|
||||
* @return Returns null on success or an error message describing the issue.
|
||||
*/
|
||||
public static String updateMaxMem(File aFile, long numBytes)
|
||||
public static String updateMaxMem(long numBytes)
|
||||
{
|
||||
// Utilize the system pList file and delegate.
|
||||
return updateMaxMem(numBytes, getPlistFile());
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update the specified max memory (-Xmx) value in the plist file (aFile) to the specified maxMemVal.
|
||||
* <P>
|
||||
* In order for this method to succeed there must be a valid JVMOptions section followed by an array of string elements of JVM arguments. The array element
|
||||
* may be empty but must be specified.
|
||||
*
|
||||
* @return Returns null on success or an error message describing the issue.
|
||||
*/
|
||||
public static String updateMaxMem(long numBytes, File pFile)
|
||||
{
|
||||
Document doc;
|
||||
Element docElement;
|
||||
@@ -37,22 +85,32 @@ public class AppleUtils
|
||||
String tagStr, valStr, currKeyVal;
|
||||
int zios_Clean;
|
||||
|
||||
// Bail if we failed to locate the pList file.
|
||||
if (pFile == null)
|
||||
return "The plist file could not be located.";
|
||||
// Bail if the plist file is not a regular file.
|
||||
if (pFile.isFile() == false)
|
||||
return "The plist file does not appear to be a regular file: " + pFile;
|
||||
// Bail if the plist file is not writeable.
|
||||
if (pFile.setWritable(true) == false)
|
||||
return "The plist file is not writeable: " + pFile;
|
||||
|
||||
// Load the XML document via the javax.xml.parsers.* package
|
||||
try
|
||||
{
|
||||
doc = loadDoc(aFile);
|
||||
doc = loadDoc(pFile);
|
||||
docElement = doc.getDocumentElement();
|
||||
}
|
||||
catch(Exception aExp)
|
||||
{
|
||||
aExp.printStackTrace();
|
||||
return "Failed to parse XML document. File: " + aFile;
|
||||
return "Failed to parse XML document. File: " + pFile;
|
||||
}
|
||||
|
||||
// Locate the <dict> element
|
||||
dictList = docElement.getElementsByTagName("dict");
|
||||
if (dictList.getLength() == 0)
|
||||
return "No <dict> element found!";
|
||||
return "No <dict> element found! File: " + pFile;
|
||||
|
||||
arrE = null;
|
||||
currKeyVal = null;
|
||||
@@ -90,7 +148,7 @@ public class AppleUtils
|
||||
|
||||
// Bail if we failed to locate the array element
|
||||
if (arrE == null)
|
||||
return "Failed to locate the element <array> following the element: <key>JVMOptions</key>";
|
||||
return "Failed to locate the element <array> following the element: <key>JVMOptions</key>\nFile: " + pFile;
|
||||
|
||||
memE = null;
|
||||
childList = arrE.getChildNodes();
|
||||
@@ -134,12 +192,12 @@ public class AppleUtils
|
||||
evalStr = targNode.getNodeValue();
|
||||
updateStr = MemUtils.transformMaxMemHeapString(evalStr, numBytes);
|
||||
if (updateStr == null)
|
||||
return "Failed to transform the memory spec value. Original value: " + evalStr;
|
||||
return "Failed to transform the memory spec value. Original value: " + evalStr + "\nFile: " + pFile;
|
||||
targNode.setNodeValue(updateStr);
|
||||
|
||||
// Update the file with the changed document
|
||||
System.out.println("Updating contents of file: " + aFile);
|
||||
return saveDoc(aFile, doc);
|
||||
System.out.println("Updating contents of file: " + pFile);
|
||||
return saveDoc(pFile, doc);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -209,10 +267,7 @@ public class AppleUtils
|
||||
*/
|
||||
private static String saveDoc(File aFile, Document aDoc)
|
||||
{
|
||||
FileOutputStream oStream;
|
||||
|
||||
oStream = null;
|
||||
try
|
||||
try (FileOutputStream oStream = new FileOutputStream(aFile);)
|
||||
{
|
||||
Transformer tr = TransformerFactory.newInstance().newTransformer();
|
||||
tr.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
@@ -223,7 +278,6 @@ public class AppleUtils
|
||||
// tr.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "roles.dtd");
|
||||
|
||||
// Serialize the Document
|
||||
oStream = new FileOutputStream(aFile);
|
||||
tr.transform(new DOMSource(aDoc), new StreamResult(oStream));
|
||||
}
|
||||
catch(Exception aExp)
|
||||
@@ -231,10 +285,6 @@ public class AppleUtils
|
||||
aExp.printStackTrace();
|
||||
return "Failed to write the file: " + aFile;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IoUtil.forceClose(oStream);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,26 @@
|
||||
package distMaker.platform;
|
||||
|
||||
import glum.io.IoUtil;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import distMaker.DistUtils;
|
||||
import distMaker.MiscUtils;
|
||||
|
||||
public class LinuxUtils
|
||||
{
|
||||
/**
|
||||
* Utility method to update the JRE to reflect the specified path.
|
||||
* <P>
|
||||
* TODO: Complete this comment and method.
|
||||
*/
|
||||
public static boolean updateJrePath(File aPath)
|
||||
{
|
||||
int zios_finish;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update the specified maxMem var in the script (aFile) to the requested number of bytes.
|
||||
* <P>
|
||||
@@ -20,22 +30,28 @@ public class LinuxUtils
|
||||
* If the maxMem var definition is moved in the script file to after the launch of the application then this method will (silently) fail to configure the
|
||||
* value needed to launch the JVM.
|
||||
*/
|
||||
public static boolean updateMaxMem(File aFile, long numBytes)
|
||||
public static String updateMaxMem(long numBytes)
|
||||
{
|
||||
BufferedReader br;
|
||||
List<String> inputList;
|
||||
File scriptFile;
|
||||
String evalStr, memStr, tmpStr;
|
||||
int currLineNum, injectLineNum, targLineNum;
|
||||
|
||||
inputList = new ArrayList<>();
|
||||
int zios_clean;
|
||||
// Bail if we fail to locate the scriptFile.
|
||||
scriptFile = getScriptFile();
|
||||
if (scriptFile == null)
|
||||
return "The script file could not be located.";
|
||||
// Bail if the script file is not a regular file.
|
||||
if (scriptFile.isFile() == false)
|
||||
return "The script file does not appear to be a regular file: " + scriptFile;
|
||||
// Bail if the script file is not writeable.
|
||||
if (scriptFile.setWritable(true) == false)
|
||||
return "The script file is not writeable: " + scriptFile;
|
||||
|
||||
// Process our input
|
||||
br = null;
|
||||
try
|
||||
inputList = new ArrayList<>();
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(scriptFile)));)
|
||||
{
|
||||
br = new BufferedReader(new InputStreamReader(new FileInputStream(aFile)));
|
||||
|
||||
// Read the lines
|
||||
currLineNum = 0;
|
||||
targLineNum = -1;
|
||||
@@ -60,11 +76,7 @@ public class LinuxUtils
|
||||
catch(Exception aExp)
|
||||
{
|
||||
aExp.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IoUtil.forceClose(br);
|
||||
return "Failed while processing the script file: " + scriptFile;
|
||||
}
|
||||
|
||||
// Determine the memStr to use
|
||||
@@ -85,8 +97,12 @@ public class LinuxUtils
|
||||
}
|
||||
|
||||
// Update the script
|
||||
System.out.println("Updating contents of file: " + aFile);
|
||||
return writeDoc(aFile, inputList);
|
||||
System.out.println("Updating contents of file: " + scriptFile);
|
||||
if (MiscUtils.writeDoc(scriptFile, inputList) == false)
|
||||
return "Failed to write the script file: " + scriptFile;
|
||||
|
||||
// On success return null
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,7 +113,7 @@ public class LinuxUtils
|
||||
* TODO: In the future the launch script should pass itself as an argument to the JVM and DistMaker should keep track of that. If the script is significantly
|
||||
* manipulated from the original the launch file may be improperly detected.
|
||||
*/
|
||||
public static File getScriptFile()
|
||||
private static File getScriptFile()
|
||||
{
|
||||
File[] fileArr;
|
||||
File installPath;
|
||||
@@ -124,34 +140,4 @@ public class LinuxUtils
|
||||
return retFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to output the specified strings to aFile
|
||||
*/
|
||||
public static boolean writeDoc(File aFile, List<String> strList)
|
||||
{
|
||||
BufferedWriter bw;
|
||||
|
||||
// Output the strList
|
||||
bw = null;
|
||||
try
|
||||
{
|
||||
bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(aFile)));
|
||||
|
||||
// Write the lines
|
||||
for (String aStr : strList)
|
||||
bw.write(aStr + '\n');
|
||||
}
|
||||
catch(Exception aExp)
|
||||
{
|
||||
aExp.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IoUtil.forceClose(bw);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
package distMaker.platform;
|
||||
|
||||
import glum.gui.panel.generic.MessagePanel;
|
||||
import glum.reflect.ReflectUtil;
|
||||
import glum.unit.ByteUnit;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.OperatingSystemMXBean;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import distMaker.DistUtils;
|
||||
|
||||
public class MemUtils
|
||||
{
|
||||
// Constants
|
||||
@@ -19,8 +15,8 @@ public class MemUtils
|
||||
public static final long GB_SIZE = 1024 * 1024 * 1024;
|
||||
|
||||
/**
|
||||
* Utility method that attempts to compute the installed system memory (ram). If the installed system ram can not be
|
||||
* computed, then the system is assumed to have 4 GB.
|
||||
* Utility method that attempts to compute the installed system memory (ram). If the installed system ram can not be computed, then the system is assumed to
|
||||
* have 4 GB.
|
||||
*/
|
||||
public static long getInstalledSystemMemory()
|
||||
{
|
||||
@@ -61,107 +57,7 @@ public class MemUtils
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to configure the (active) DistMaker distribution to use the specified maxMem.
|
||||
* <P>
|
||||
* Method will return false on failure.
|
||||
*
|
||||
* @param warnPanel
|
||||
* GUI message panel to route error messages.
|
||||
* @param maxMemSize
|
||||
* Maximum heap memory in bytes.
|
||||
*/
|
||||
public static boolean setMaxHeapMem(MessagePanel warnPanel, long maxMemSize)
|
||||
{
|
||||
File installPath, pFile, configFile, scriptFile;
|
||||
String errMsg;
|
||||
boolean isValidPlatform;
|
||||
|
||||
// Get the top level install path
|
||||
installPath = DistUtils.getAppPath().getParentFile();
|
||||
isValidPlatform = false;
|
||||
|
||||
// Apple specific platform files
|
||||
pFile = new File(installPath, "Info.plist");
|
||||
if (pFile.isFile() == false)
|
||||
pFile = new File(installPath.getParentFile(), "Info.plist");
|
||||
|
||||
if (pFile.isFile() == true)
|
||||
{
|
||||
isValidPlatform = true;
|
||||
|
||||
errMsg = null;
|
||||
if (pFile.setWritable(true) == false)
|
||||
errMsg = "Failure. No writable permissions.";
|
||||
else
|
||||
errMsg = AppleUtils.updateMaxMem(pFile, maxMemSize);
|
||||
|
||||
if (errMsg != null)
|
||||
{
|
||||
errMsg = "File: " + pFile + "\n " + errMsg;
|
||||
warnPanel.setTitle("Failed setting Apple properties.");
|
||||
warnPanel.setInfo(errMsg);
|
||||
warnPanel.setVisible(true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Linux specific platform files
|
||||
scriptFile = LinuxUtils.getScriptFile();
|
||||
if (scriptFile != null && scriptFile.isFile() == true)
|
||||
{
|
||||
isValidPlatform = true;
|
||||
|
||||
errMsg = null;
|
||||
if (scriptFile.setWritable(true) == false)
|
||||
errMsg = "Failure. No writable permmisions for file: " + scriptFile;
|
||||
else if (LinuxUtils.updateMaxMem(scriptFile, maxMemSize) == false)
|
||||
errMsg = "Failure. Failed to update file: " + scriptFile;
|
||||
|
||||
if (errMsg != null)
|
||||
{
|
||||
warnPanel.setTitle("Failed setting Linux configuration.");
|
||||
warnPanel.setInfo(errMsg);
|
||||
warnPanel.setVisible(true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Windows specific platform files
|
||||
configFile = WindowsUtils.getConfigFile();
|
||||
if (configFile != null && configFile.isFile() == true)
|
||||
{
|
||||
isValidPlatform = true;
|
||||
|
||||
errMsg = null;
|
||||
if (WindowsUtils.updateMaxMem(configFile, maxMemSize) == false)
|
||||
errMsg = "Failure. Failed to update file: " + configFile;
|
||||
|
||||
if (errMsg != null)
|
||||
{
|
||||
warnPanel.setTitle("Failed setting Windows configuration.");
|
||||
warnPanel.setInfo(errMsg);
|
||||
warnPanel.setVisible(true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Bail if no valid platform found
|
||||
if (isValidPlatform == false)
|
||||
{
|
||||
errMsg = "This does not appear to be a valid DistMaker build. Memory changes will not take effect.";
|
||||
|
||||
warnPanel.setTitle("No valid DistMaker platform located.");
|
||||
warnPanel.setInfo(errMsg);
|
||||
warnPanel.setVisible(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that takes an inputStr, locates the fragment -Xmx*, and replaces the fragment with the appropriate
|
||||
* -Xmx with respect to numBytes.
|
||||
* Utility method that takes an inputStr, locates the fragment -Xmx*, and replaces the fragment with the appropriate -Xmx with respect to numBytes.
|
||||
* <P>
|
||||
* This method is a bit brittle in that it assumes the -Xmx string is surrounded with 1 white space character.
|
||||
* <P>
|
||||
|
||||
104
src/distMaker/platform/PlatformUtils.java
Normal file
104
src/distMaker/platform/PlatformUtils.java
Normal file
@@ -0,0 +1,104 @@
|
||||
package distMaker.platform;
|
||||
|
||||
import glum.gui.panel.generic.MessagePanel;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import distMaker.DistUtils;
|
||||
import distMaker.jre.JreRelease;
|
||||
|
||||
public class PlatformUtils
|
||||
{
|
||||
/**
|
||||
* Utility method that returns the path where the specified JRE should be unpacked to.
|
||||
*/
|
||||
public static File getJreLocation(JreRelease aJreRelease)
|
||||
{
|
||||
String platform, versionStr;
|
||||
File jrePath, installPath;
|
||||
|
||||
jrePath = null;
|
||||
installPath = DistUtils.getAppPath();
|
||||
versionStr = aJreRelease.getVersion().getLabel();
|
||||
|
||||
platform = DistUtils.getPlatform().toUpperCase();
|
||||
if (platform.equals("APPLE") == true)
|
||||
jrePath = new File(installPath.getParentFile(), "PlugIns/jre" + versionStr);
|
||||
else if (platform.equals("LINUX") == true)
|
||||
jrePath = new File(installPath.getParentFile(), "jre" + versionStr);
|
||||
else if (platform.equals("Windows") == true)
|
||||
jrePath = new File(installPath.getParentFile(), "jre" + versionStr);
|
||||
|
||||
return jrePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to configure the JRE location used by the active DistMaker distribution.
|
||||
* <P>
|
||||
* Note this will only take effect after the application has been relaunched.
|
||||
*/
|
||||
public static boolean setJreLocation(File aPath)
|
||||
{
|
||||
String platform;
|
||||
boolean isPass;
|
||||
|
||||
isPass = false;
|
||||
platform = DistUtils.getPlatform().toUpperCase();
|
||||
if (platform.equals("APPLE") == true)
|
||||
isPass = AppleUtils.updateJrePath(aPath);
|
||||
else if (platform.equals("LINUX") == true)
|
||||
isPass = LinuxUtils.updateJrePath(aPath);
|
||||
else if (platform.equals("Windows") == true)
|
||||
isPass = WindowsUtils.updateJrePath(aPath);
|
||||
|
||||
return isPass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to configure the (active) DistMaker distribution to use the specified maxMem.
|
||||
* <P>
|
||||
* Method will return false on failure.
|
||||
*
|
||||
* @param warnPanel
|
||||
* GUI message panel to route error messages.
|
||||
* @param maxMemSize
|
||||
* Maximum heap memory in bytes.
|
||||
*/
|
||||
public static boolean setMaxHeapMem(MessagePanel warnPanel, long maxMemSize)
|
||||
{
|
||||
String platform;
|
||||
String errMsg;
|
||||
|
||||
// Delegate to the proper platform code
|
||||
errMsg = null;
|
||||
platform = DistUtils.getPlatform().toUpperCase();
|
||||
if (platform.equals("APPLE") == true)
|
||||
errMsg = AppleUtils.updateMaxMem(maxMemSize);
|
||||
else if (platform.equals("LINUX") == true)
|
||||
errMsg = LinuxUtils.updateMaxMem(maxMemSize);
|
||||
else if (platform.equals("Windows") == true)
|
||||
errMsg = WindowsUtils.updateMaxMem(maxMemSize);
|
||||
else
|
||||
errMsg = "Unrecognized platform: " + platform;
|
||||
|
||||
// Display the warnPanel with the the error condition
|
||||
if (errMsg != null)
|
||||
{
|
||||
if (platform.equals("APPLE") == true)
|
||||
warnPanel.setTitle("Failed setting Apple properties.");
|
||||
else if (platform.equals("LINUX") == true)
|
||||
warnPanel.setTitle("Failed setting Linux configuration.");
|
||||
else if (platform.equals("Windows") == true)
|
||||
warnPanel.setTitle("Failed setting Windows configuration.");
|
||||
else
|
||||
warnPanel.setTitle("Platform is not supported.");
|
||||
|
||||
warnPanel.setInfo(errMsg);
|
||||
warnPanel.setVisible(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,38 +1,49 @@
|
||||
package distMaker.platform;
|
||||
|
||||
import glum.io.IoUtil;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import distMaker.DistUtils;
|
||||
import distMaker.MiscUtils;
|
||||
|
||||
public class WindowsUtils
|
||||
{
|
||||
/**
|
||||
* Utility method to update the specified max memory (-Xmx) value in the text file (aFile) to the specified
|
||||
* maxMemVal.
|
||||
* Utility method to update the JRE to reflect the specified path.
|
||||
* <P>
|
||||
* Note this method is very brittle, and assumes that there is a single value where the string, -Xmx, is specified in
|
||||
* the script. It assumes this string will be surrounded by a single space character on each side.
|
||||
* TODO: Complete this comment and method.
|
||||
*/
|
||||
public static boolean updateMaxMem(File aFile, long numBytes)
|
||||
public static boolean updateJrePath(File aPath)
|
||||
{
|
||||
BufferedReader br;
|
||||
int zios_finish;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update the specified max memory (-Xmx) value in the text file (aFile) to the specified maxMemVal.
|
||||
* <P>
|
||||
* Note this method is very brittle, and assumes that there is a single value where the string, -Xmx, is specified in the script. It assumes this string will
|
||||
* be surrounded by a single space character on each side.
|
||||
*/
|
||||
public static String updateMaxMem(long numBytes)
|
||||
{
|
||||
File configFile;
|
||||
List<String> inputList;
|
||||
String strLine, updateStr;
|
||||
boolean isProcessed;
|
||||
|
||||
inputList = new ArrayList<>();
|
||||
// Bail if we fail to locate the configFile.
|
||||
configFile = getConfigFile();
|
||||
if (configFile != null && configFile.isFile() == true)
|
||||
return "The config file could not be located.";
|
||||
|
||||
isProcessed = false;
|
||||
inputList = new ArrayList<>();
|
||||
|
||||
// Process our input
|
||||
br = null;
|
||||
try
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(configFile))))
|
||||
{
|
||||
br = new BufferedReader(new InputStreamReader(new FileInputStream(aFile)));
|
||||
|
||||
// Read the lines
|
||||
while (true)
|
||||
{
|
||||
@@ -62,16 +73,16 @@ public class WindowsUtils
|
||||
catch(Exception aExp)
|
||||
{
|
||||
aExp.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IoUtil.forceClose(br);
|
||||
return "Failed while processing the config file: " + configFile;
|
||||
}
|
||||
|
||||
// Update the script
|
||||
System.out.println("Updating contents of file: " + aFile);
|
||||
return LinuxUtils.writeDoc(aFile, inputList);
|
||||
System.out.println("Updating contents of file: " + configFile);
|
||||
if (MiscUtils.writeDoc(configFile, inputList) == false)
|
||||
return "Failed to write the config file: " + configFile;
|
||||
|
||||
// On success return null
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Binary file not shown.
@@ -71,7 +71,7 @@ def buildRelease(version, doNotClean=False):
|
||||
# Copy the scripts
|
||||
dstPath = os.path.join(workPath, 'script')
|
||||
os.mkdir(dstPath)
|
||||
for aScript in ['appleUtils.py', 'linuxUtils.py', 'windowsUtils.py', 'buildDist.py', 'deployDist.py', 'jreUtils.py', 'logUtils.py', 'miscUtils.py']:
|
||||
for aScript in ['appleUtils.py', 'linuxUtils.py', 'windowsUtils.py', 'buildDist.py', 'deployAppDist.py', 'deployJreDist.py', 'jreUtils.py', 'logUtils.py', 'miscUtils.py']:
|
||||
srcPath = os.path.join(installPath, 'script', aScript)
|
||||
shutil.copy2(srcPath, dstPath)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user