Files
DistMaker/script/deployJreDist.py
Norberto Lopez 6c565557ca Changes associated with version 0.61:
[1] Updated to Java version 11.
[2] Updated to Python 3.6.
[3] Updated Glum library version 2.0.0-RC3.
[4] Updated Launch4J to version 3.14.
[5] Updated DistMaker build scripts.
2022-11-18 12:00:00 +00:00

443 lines
16 KiB
Python
Executable File

#! /usr/bin/env python3
import argparse
import collections
import getpass
import glob
import math
import os
import shutil
import signal
import subprocess
import sys
from collections import OrderedDict
import jreUtils
import logUtils
import miscUtils
from logUtils import errPrintln, regPrintln
from miscUtils import ErrorDM
def getAppLauncherSourceFile():
"""Returns the source appLauncher.jar file. This file is located in ~/template/appLauncher.jar"""
installPath = miscUtils.getInstallRoot()
installPath = os.path.dirname(installPath)
retFile = os.path.join(installPath, 'template/appLauncher.jar')
return retFile
def getAppLauncherFileName():
"""Returns the formal file name that the appLauncher.jar should be refered to as. The returned
value will contain just the file name with out any folder paths. The returned file name will
be formatted: appLauncher-<version>.jar"""
version = getAppLauncherVersion()
retFileName = 'appLauncher-' + version + '.jar'
return retFileName
def getAppLauncherVersion():
"""Returns the version of the the appLauncher.jar that is used by this DistMaker release."""
# Check for appLauncher.jar prerequisite
jarFile = getAppLauncherSourceFile()
if os.path.exists(jarFile) == False:
errPrintln('\tThis installation of DistMaker appears to be broken. Please ensure there is an appLauncher.jar file in the template folder.')
errPrintln('\tFile does not exist: ' + jarFile)
exit(-1)
try:
exeCmd = ['java', '-cp', jarFile, 'appLauncher.AppLauncher', '--version']
output = subprocess.check_output(exeCmd).decode('utf-8')
version = output.split()[1]
return version
except Exception as aExp:
errPrintln('\tThis installation of DistMaker appears to be broken. Failed to determine the AppLauncher version.')
errPrintln(str(aExp))
exit(-1)
def addAppLauncherRelease(aRootPath):
""" Adds the appLauncher.jar file to a well defined location under the deploy tree.
The appLauncher.jar file will be stored under ~/deploy/launcher/. The appLauncher.jar is
responsible for launching a DistMaker enabled application. This jar file will typically
only be updated to support JRE changes that are not compatible with prior JRE releases.
"""
# Retrive the src appLauncher.jar
srcFile = getAppLauncherSourceFile()
# Ensure that the AppLauncher deployed location exists
deployPath = os.path.join(aRootPath, 'launcher')
if os.path.isdir(deployPath) == False:
os.makedirs(deployPath, 0o755)
# Determine the file name of the deployed appLauncher.jar file
dstFileName = getAppLauncherFileName()
version = getAppLauncherVersion()
# Bail if the deployed appLauncher.jar already exists
dstFile = os.path.join(deployPath, dstFileName)
if os.path.isfile(dstFile) == True:
return
# Create the appCatalog file
catFile = os.path.join(deployPath, 'appCatalog.txt')
if os.path.isfile(catFile) == False:
with open(catFile, mode='wt', encoding='utf-8', newline='\n') as tmpFO:
tmpFO.write('name' + ',' + 'AppLauncher' + '\n')
tmpFO.write('digest' + ',' + 'sha256' + '\n\n')
os.chmod(catFile, 0o644)
# Updated the appCatalog file
with open(catFile, mode='at', encoding='utf-8', newline='\n') as tmpFO:
digestStr = miscUtils.computeDigestForFile(srcFile, 'sha256')
stat = os.stat(srcFile)
fileLen = stat.st_size
tmpFO.write("F,{},{},{},{}\n".format(digestStr, fileLen, dstFileName, version))
# tmpFO.write('\n')
# Copy the src appLauncher.jar file to it's deployed location
shutil.copy2(srcFile, dstFile)
os.chmod(dstFile, 0o644)
def addRelease(aRootPath, aJreNodeL, aVerStr):
# Normalize the JVM version for consistency
aVerStr = jreUtils.normalizeJvmVerStr(aVerStr)
# Check to see if the deployed location already exists
installPath = os.path.join(aRootPath, 'jre')
if os.path.isdir(installPath) == False:
regPrintln('A JRE has never been deployed to the root location: ' + aRootPath)
regPrintln('Create a new release of the JRE at the specified location?')
tmpAns = input('--> ').upper()
if tmpAns != 'Y' and tmpAns != 'YES':
regPrintln('Release will not be made for JRE version: ' + aVerStr)
exit()
# Build the deployed location
os.makedirs(installPath, 0o755)
# Check to see if the deploy version already exists
versionPath = os.path.join(installPath, aVerStr)
if os.path.isdir(versionPath) == True:
regPrintln('JREs with version, ' + aVerStr + ', has already been deployed.')
regPrintln('\tThe JREs have already been deployed.')
exit()
# Update the version info
addReleaseInfo(installPath, aJreNodeL, aVerStr)
addAppLauncherRelease(aRootPath)
regPrintln('JRE ({}) has been deployed to location: {}'.format(aVerStr, aRootPath))
def addReleaseInfo(aInstallPath, aJreNodeL, aVerStr):
# Var that holds the last recorded exit (distmaker) command
# By default assume the command has not been set
exitVerDM = None
# Create the jreCatalogfile
catFile = os.path.join(aInstallPath, 'jreCatalog.txt')
if os.path.isfile(catFile) == False:
with open(catFile, mode='wt', encoding='utf-8', newline='\n') as tmpFO:
tmpFO.write('name' + ',' + 'JRE' + '\n')
tmpFO.write('digest' + ',' + 'sha256' + '\n\n')
# Note new JRE catalogs require DistMaker versions 0.55 or later
tmpFO.write('exit,DistMaker,0.55' + '\n\n')
os.chmod(catFile, 0o644)
exitVerDM = [0, 55]
# Determine the last exit,DistMaker instruction specified
else:
with open(catFile, mode='rt', encoding='utf-8') as tmpFO:
for line in tmpFO:
tokens = line[:-1].split(',');
# Record the (exit) version of interest
if len(tokens) == 3 and tokens[0] == 'exit' and tokens[1] == 'DistMaker':
try:
exitVerDM = jreUtils.verStrToVerArr(tokens[2])
except:
exitVerDM = None
# Locate the list of JREs with a matching version
matchJreNodeL = jreUtils.getJreNodesForVerStr(aJreNodeL, aVerStr)
if len(matchJreNodeL) == 0:
raise ErrorDM('No JREs were located for the version: ' + aVerStr)
# Determine if we need to record an exit instruction. An exit instruction is needed if the
# the catalog was built with an old version of DistMaker. Old versions of DistMaker do
# not specify exit instructions. If none is specified - ensure one is added.
needExitInstr = False
if exitVerDM == None:
needExitInstr = True
# Updated the jreCatalogfile
with open(catFile, mode='at', encoding='utf-8', newline='\n') as tmpFO:
# Write the exit info to stop legacy DistMakers from processing further
if needExitInstr == True:
tmpFO.write('exit,DistMaker,0.48\n\n')
# Write out the JRE release info
tmpFO.write("jre,{}\n".format(aVerStr))
if needExitInstr == True:
tmpFO.write("require,AppLauncher,0.1,0.2\n")
for aJreNode in matchJreNodeL:
tmpFile = aJreNode.getFile()
stat = os.stat(tmpFile)
digestStr = miscUtils.computeDigestForFile(tmpFile, 'sha256')
fileLen = stat.st_size
archStr = aJreNode.getArchitecture();
platStr = aJreNode.getPlatform()
if exitVerDM != None and exitVerDM > [0, 54]:
tmpFO.write("F,{},{},{},{},{}\n".format(archStr, platStr, os.path.basename(tmpFile), digestStr, fileLen))
elif exitVerDM != None:
tmpFO.write("F,{},{},{},{}\n".format(digestStr, fileLen, platStr, os.path.basename(tmpFile)))
else:
tmpFO.write("F,{},{},{}\n".format(digestStr, fileLen, os.path.basename(tmpFile)))
tmpFO.write('\n')
destPath = os.path.join(aInstallPath, aVerStr)
os.makedirs(destPath, 0o755)
# Copy over the JRE files to the proper path
for aJreNode in matchJreNodeL:
tmpFile = aJreNode.getFile()
shutil.copy2(tmpFile, destPath)
destFile = os.path.join(destPath, os.path.basename(tmpFile))
os.chmod(destFile, 0o644)
def delRelease(aRootPath, aVerStr):
# Normalize the JVM version for consistency
aVerStr = jreUtils.normalizeJvmVerStr(aVerStr)
# Check to see if the deployed location already exists
installPath = os.path.join(aRootPath, 'jre')
if os.path.isdir(installPath) == False:
regPrintln('A JRE has never been deployed to the root location: ' + aRootPath)
regPrintln('There are no JRE releases to remove. ')
exit()
# Check to see if the deploy version already exists
versionPath = os.path.join(installPath, aVerStr)
if os.path.isdir(versionPath) == False:
regPrintln('JREs with version, ' + aVerStr + ', has not been deployed.')
regPrintln('There is nothing to remove.')
exit()
# Update the version info
delReleaseInfo(installPath, aVerStr)
# Remove the release from the deployed location
shutil.rmtree(versionPath)
regPrintln('JRE ({}) has been removed from location: {}'.format(aVerStr, aRootPath))
def delReleaseInfo(aInstallPath, aVerStr):
# Bail if the jreCatalogfile does not exist
catFile = os.path.join(aInstallPath, 'jreCatalog.txt')
if os.path.isfile(catFile) == False:
errPrintln('Failed to locate deployment catalog file: ' + catFile)
errPrintln('Aborting removal action for version: ' + aVerStr)
exit()
# Read the file
inputLineL = []
isDeleteMode = False
with open(catFile, mode='rt', encoding='utf-8') as tmpFO:
for line in tmpFO:
tokens = line[:-1].split(',', 1);
# Switch to deleteMode when we find a matching JRE release
if len(tokens) == 2 and tokens[0] == 'jre' and tokens[1] == aVerStr:
isDeleteMode = True
continue
# Switch out of deleteMode when we find a different JRE release
elif len(tokens) == 2 and tokens[0] == 'jre' and tokens[1] != aVerStr:
isDeleteMode = False
# Skip over the input line if we are in deleteMode
elif isDeleteMode == True:
continue
# Save off the input line
inputLineL.append(line)
# Write the updated file
with open(catFile, mode='wt', encoding='utf-8', newline='\n') as tmpFO:
for aLine in inputLineL:
tmpFO.write(aLine)
def showReleaseInfo(aRootPath, aJreNodeL):
"""This action will display information on the deployed / undeployed JREs to stdout."""
# Header section
appInstallRoot = miscUtils.getInstallRoot()
appInstallRoot = os.path.dirname(appInstallRoot)
regPrintln('Install Path: ' + os.path.abspath(appInstallRoot))
regPrintln(' Deploy Root: ' + aRootPath + '\n')
# Validate the (deploy) root location
if os.path.exists(aRootPath) == False:
errPrintln('The specified deployRoot does not exits.')
exit()
if os.path.isdir(aRootPath) == False:
errPrintln('The specified deployRoot does not appear to be a valid folder.')
exit()
# Check to see if the jre folder exists in the deployRoot
installPath = os.path.join(aRootPath, 'jre')
if os.path.isdir(installPath) == False:
errPrintln('The specified deployRoot does not have any deployed JREs...')
exit();
# Form 2 dictionaries:
# [1] File name (excluding path) to corresponding JreNode
# [2] JRE version to corresponding JreNodes
nameD = OrderedDict()
verD = OrderedDict()
for aJreNode in aJreNodeL:
tmpFileName = os.path.basename(aJreNode.getFile())
nameD[tmpFileName] = aJreNode
tmpVerArr = aJreNode.getVersion()
tmpVerStr = jreUtils.verArrToVerStr(tmpVerArr)
verD.setdefault(tmpVerStr, [])
verD[tmpVerStr].append(aJreNode)
# Get the list of available (installable) JREs
availablePathL = []
for aVer in sorted(verD.keys()):
# Skip to next if this version has already been installed
versionPath = os.path.join(installPath, aVer)
if os.path.isdir(versionPath) == True:
continue
availablePathL.append(aVer)
# Show the list of available (installable) JREs
regPrintln('Available JREs:')
if len(availablePathL) == 0:
regPrintln('\t\tThere are no installable JREs.\n')
for aVer in availablePathL:
regPrintln('\tVersion: {}'.format(aVer))
for aJreNode in verD[aVer]:
archStr = aJreNode.getArchitecture();
platStr = aJreNode.getPlatform()
pathStr = aJreNode.getFile()
regPrintln('\t\t{} {:<7} {}'.format(archStr, platStr, pathStr))
regPrintln('')
# Get the list of all installed (version) folders
installedPathL = []
searchPath = installPath + '/*'
for aFile in glob.glob(searchPath):
if os.path.isdir(aFile) == False:
continue
try:
verStr = os.path.basename(aFile)
except:
continue
installedPathL.append(verStr)
# Show the list of installed JREs
regPrintln('Installed JREs:')
if len(installedPathL) == 0:
regPrintln('\t\tThere are no installed JREs.')
for aVer in sorted(installedPathL):
regPrintln('\tVersion: {}'.format(aVer))
# Show all of the JREs in the specified (version) folder
for aFile in sorted(glob.glob(os.path.join(installPath, aVer) + '/*')):
tmpFileName = os.path.basename(aFile)
# Bail if the file name does not correspond to a JRE
tmpJreNode = nameD.get(tmpFileName, None)
if tmpJreNode == None:
errPrintln('\t\tJRE file is not in the JRE catalog. File: ' + aFile)
continue
archStr = tmpJreNode.getArchitecture();
platStr = tmpJreNode.getPlatform()
pathStr = tmpJreNode.getFile()
regPrintln('\t\t{} {:<7} {}'.format(archStr, platStr, pathStr))
regPrintln('')
if __name__ == "__main__":
# Require python version 2.7 or later
targVer = (2, 7)
miscUtils.requirePythonVersion(targVer)
# Logic to capture Ctrl-C and bail
signal.signal(signal.SIGINT, miscUtils.handleSignal)
# Retrieve the location of the scriptPath
scriptPath = os.path.realpath(__file__)
scriptPath = os.path.dirname(scriptPath)
# Set up the argument parser
tmpDescr = 'Utility that allow JREs to be deployed or removed from the specified deployRoot. The deployRoot is the '
tmpDescr += 'top level deployment location. This location is typically made available via a public web server. The ';
tmpDescr += 'deployRoot should NOT refer to the child jre folder but rather the top level folder!'
parser = argparse.ArgumentParser(prefix_chars='-', add_help=False, fromfile_prefix_chars='@', description=tmpDescr)
parser.add_argument('--help', '-h', help='Show this help message and exit.', action='help')
parser.add_argument('--jreCatalog', help='A JRE catalog file. This file provides the listing of available JREs for DistMaker to utilize.')
parser.add_argument('--deploy', metavar='version', help='Deploy the specified JRE distribution to the deployRoot.', action='store', default=None)
parser.add_argument('--remove', metavar='version', help='Remove the specified JRE distribution from the deployRoot.', action='store', default=None)
parser.add_argument('--status', help='Display stats of all deployed/undeployed JREs relative to the deployRoot.', action='store_true', default=False)
parser.add_argument('deployRoot', help='Top level folder to the deployment root.')
# Intercept any request for a help message and bail
argv = sys.argv;
if '-h' in argv or '-help' in argv or '--help' in argv:
parser.print_help()
exit()
# Parse the args
parser.formatter_class.max_help_position = 50
args = parser.parse_args()
# Load the JRE catalog
jreCatalog = args.jreCatalog
errMsg = None
if jreCatalog == None:
errMsg = 'A JRE catalog must be specified! Please specify --jreCatalog'
elif os.path.exists(jreCatalog) == False:
errMsg = 'The specified JRE catalog does not exist! File: ' + jreCatalog
elif os.path.isfile(jreCatalog) == False:
errMsg = 'The specified JRE catalog is not a valid file! File: ' + jreCatalog
if errMsg != None:
errPrintln(errMsg + '\n')
exit()
jreNodeL = jreUtils.loadJreCatalog(jreCatalog)
if len(jreNodeL) == 0:
errPrintln('Failed to load any JREs from the JRE catalog.')
errPrintln('\tA valid populated JRE catalog must be specified!')
errPrintln('\tJRE Catalog specified: {}\n'.format(jreCatalog))
exit()
# Execute the approriate action
rootPath = args.deployRoot
if args.status == True:
showReleaseInfo(rootPath, jreNodeL)
exit()
elif args.deploy != None:
# Deploy the specified JRE
version = args.deploy
try:
addRelease(rootPath, jreNodeL, version)
except ErrorDM as aExp:
errPrintln('Failed to deploy JREs with version: ' + version)
errPrintln('\t' + aExp.message)
elif args.remove != None:
# Remove the specified JRE
version = args.remove
try:
delRelease(rootPath, version)
except ErrorDM as aExp:
errPrintln('Failed to deploy JREs with version: ' + version)
errPrintln('\t' + aExp.message)
else:
regPrintln('Please specify one of the valid actions: [--deploy, --remove, --status]')