Initial changes needed to allow DistMaker to support Java 9.

This commit is contained in:
Norberto Lopez
2018-02-22 18:29:50 +00:00
parent 0ebb5049f2
commit 94fffa8b2d
5 changed files with 518 additions and 170 deletions

View File

@@ -2,8 +2,6 @@
from __future__ import print_function
import argparse
import getpass
import math
import os
import platform
import shutil
@@ -11,7 +9,6 @@ import signal
import subprocess
import sys
import tempfile
import time
import distutils.spawn
import jreUtils
@@ -36,9 +33,8 @@ def buildCatalogFile(args, deltaPath):
jreVerSpec = args.jreVerSpec
if jreVerSpec == None:
jreVerSpec = [jreUtils.getDefaultJreVerStr()]
if jreVerSpec != None:
record = ('jre', ",".join(jreVerSpec))
records.append(record)
record = ('jre', ",".join(jreVerSpec))
records.append(record)
snipLen = len(deltaPath) + 1
# for root, dirNames, fileNames in os.walk(deltaPath, onerror=failTracker.recordError):
@@ -138,6 +134,24 @@ def checkForSuggestedApplications():
return warnList
def checkReadable(src, names):
"""Utility method that will ensure that all of the files formed by <src>/<aName> exist
and are readable. An ErrorDM will be raised if any of the files are not readable. This method
is passed into shutil.copytree() and provides a way to check for issues with any files that
are about to be accessed."""
for aName in names:
tmpFile = os.path.join(src, aName)
# Ensure that symbolic links are not broken
if os.path.islink(tmpFile) == True and os.path.exists(tmpFile) == False:
raise ErrorDM('Broken symbolic link: {}'.format(tmpFile))
# Ensure that files are readable
if os.path.isfile(tmpFile) == True and os.access(tmpFile, os.R_OK) == False:
raise ErrorDM('File is not readable: {}'.format(tmpFile))
# We actually do not do any filtering
return []
def getClassPath(javaCodePath):
retList = []
@@ -161,9 +175,6 @@ def getClassPath(javaCodePath):
if __name__ == "__main__":
argv = sys.argv;
argc = len(argv);
# Logic to capture Ctrl-C and bail
signal.signal(signal.SIGINT, miscUtils.handleSignal)
@@ -195,10 +206,10 @@ if __name__ == "__main__":
# parser.add_argument('-bundleId', help='Apple specific id descriptor.')
# Intercept any request for a help message and bail
for aArg in argv:
if aArg == '-h' or aArg == '-help':
parser.print_help()
exit()
argv = sys.argv;
if '-h' in argv or '-help' in argv:
parser.print_help()
exit()
# Check to ensure all of the required applications are installed before proceeding
checkForRequiredApplicationsAndExit()
@@ -206,7 +217,6 @@ if __name__ == "__main__":
# Parse the args
parser.formatter_class.max_help_position = 50
args = parser.parse_args()
# print args
# Warn if there are not any valid targets
if args.platform == ['apple-']:
@@ -225,9 +235,9 @@ if __name__ == "__main__":
print('At a minimum the following must be specified: ' + str(errList) + '.\nExiting...')
exit()
# Ensure the reserved 'jre' name is not utilized
if args.name.lower() == 'jre':
print('The application can not be named: {}. That name is reserved for the JRE.'.format(args.name))
# Ensure the name is not reserved: ['jre', 'launcher']
if args.name.lower() == 'jre' or args.name == 'launcher':
print('The application can not be named: {}. That name is reserved.\n'.format(args.name))
exit()
#
@@ -241,7 +251,7 @@ if __name__ == "__main__":
jreUtils.validateJreVersionSpec(args.jreVerSpec)
except ErrorDM as aExp:
print('The specified jreVerVersion is invalid. Input: {}'.format(args.jreVerSpec))
print(' ' + aExp.message + "\n", file=sys.stderr)
print(' ' + aExp.message + '\n', file=sys.stderr)
exit()
# Form the classPath if none specified
@@ -272,7 +282,7 @@ if __name__ == "__main__":
# Bail if the release has already been built
buildPath = os.path.abspath(args.name + '-' + args.version)
if (os.path.exists(buildPath) == True):
print(' [ERROR] The release appears to be built. Path: ' + buildPath)
print(' [ERROR] The release appears to be built. Path: ' + buildPath + '\n')
exit(-1)
# Let the user know of any missing functionality
@@ -296,7 +306,7 @@ if __name__ == "__main__":
for aPath in args.dataCode:
srcPath = aPath
if os.path.isdir(srcPath) == False:
print(' [ERROR] The dataCode path does not exist. Path: ' + srcPath)
print(' [ERROR] The dataCode path does not exist. Path: ' + srcPath + '\n')
shutil.rmtree(buildPath)
exit(-1)
dstPath = os.path.join(deltaDataPath, os.path.basename(aPath))
@@ -307,11 +317,17 @@ if __name__ == "__main__":
# Copy the javaCode to the proper location
srcPath = args.javaCode
if os.path.isdir(srcPath) == False:
print(' [ERROR] The javaCode path does not exist. Path: ' + srcPath)
print(' [ERROR] The javaCode path does not exist. Path: ' + srcPath + '\n')
shutil.rmtree(buildPath)
exit(-1)
dstPath = deltaCodePath;
shutil.copytree(srcPath, dstPath, symlinks=False)
try:
shutil.copytree(srcPath, dstPath, symlinks=False, ignore=checkReadable)
except (ErrorDM, shutil.Error) as aExp:
print(' [ERROR] There were issues while copying the javaCode files. Path: ' + srcPath)
print(' {}\n'.format(aExp), file=sys.stderr)
shutil.rmtree(buildPath)
exit(-1)
# Form the app.cfg file
dstPath = os.path.join(buildPath, "delta/app.cfg")

View File

@@ -13,25 +13,28 @@ def getDistInfo(distPath):
appName = None
version = None
buildDate = None
isLegacyJre = None
# Process the app.cfg file
cfgFile = os.path.join(distPath, 'delta', 'app.cfg')
if os.path.isfile(cfgFile) == False:
print('Distribution corresponding to the folder: ' + distPath + ' does not appear to be valid!')
print('File does not exist: ' + cfgFile)
print('Release will not be deployed...')
exit()
exeMode = None
f = open(cfgFile, 'r')
for line in f:
line = line[:-1]
if line.startswith('-') == True:
exeMode = line;
elif exeMode == '-name' and len(line) > 0:
appName = line
elif exeMode == '-version' and len(line) > 0:
version = line
elif exeMode == '-buildDate' and len(line) > 0:
buildDate = line
for aLine in f:
aLine = aLine[:-1]
if aLine.startswith('-') == True:
exeMode = aLine;
elif exeMode == '-name' and len(aLine) > 0:
appName = aLine
elif exeMode == '-version' and len(aLine) > 0:
version = aLine
elif exeMode == '-buildDate' and len(aLine) > 0:
buildDate = aLine
f.close()
if appName == None or version == None or buildDate == None:
@@ -40,7 +43,32 @@ def getDistInfo(distPath):
print('Release will not be made for app ' + appName)
exit()
return (appName, version, buildDate)
# Process the catalog.txt file
catFile = os.path.join(distPath, 'delta', 'catalog.txt')
if os.path.isfile(catFile) == False:
print('Distribution corresponding to the folder: ' + distPath + ' does not appear to be valid!')
print('File does not exist: ' + catFile)
print('Release will not be deployed...')
exit()
f = open(catFile, 'r')
for aLine in f:
aLine = aLine[:-1]
tokenL = aLine.split(',')
# Check to see if legacy JREs are allowed
if len(tokenL) >= 2 and tokenL[0] == 'jre' and isLegacyJre == None:
isLegacyJre = False
if tokenL[1].strip().startswith('1.') == True:
isLegacyJre = True
f.close()
if isLegacyJre == None:
print('Distribution corresponding to the folder: ' + distPath + ' does not appear to be valid!')
print('The catalog file, ' + catFile + ', is not valid.')
print('Release will not be made for app ' + appName)
exit()
return (appName, version, buildDate, isLegacyJre)
def handleSignal(signal, frame):
@@ -49,29 +77,81 @@ def handleSignal(signal, frame):
sys.exit(0)
def addReleaseInfo(installPath, appName, version, buildDate):
verFile = os.path.join(installPath, 'releaseInfo.txt')
def addReleaseInfo(deployPath, appName, version, buildDate, isLegacyJre):
# Determine if this Application was deployed with a a legacy DistMaker release
legacyReleaseL = []
isLegacyRelease = False
verFile = os.path.join(deployPath, 'releaseInfo.txt')
if os.path.isfile(verFile) == True:
# Read the legacy releases
f = open(verFile, 'r')
for aLine in f:
aLine = aLine[:-1]
# Ignore empty lines and comments
if len(aLine) == 0:
continue
if aLine.startswith('#') == True:
continue
# Create the release info file
if os.path.isfile(verFile) == False:
f = open(verFile, 'w')
f.write('name' + ',' + appName + '\n')
tokenL = aLine.split(',')
if len(tokenL) >= 2 and tokenL[0] == 'name':
isLegacyRelease = True
continue
# Ignore legacy exit instructions
if len(tokenL) >= 1 and tokenL[0] == 'exit':
continue
# Record all legacy releases
if len(tokenL) == 2:
legacyReleaseL += [(tokenL[0], tokenL[1])]
continue
f.close()
# Updated the release info file
f = open(verFile, 'a')
f.write(version + ',' + buildDate + '\n')
# Create the appCatalog.txt file
catFile = os.path.join(deployPath, 'appCatalog.txt')
if os.path.isfile(catFile) == False:
if isLegacyRelease == True and len(legacyReleaseL) > 0:
f = open(catFile, 'w')
f.write('name' + ',' + appName + '\n\n')
# Copy the legacy releases
for (aLegacyVer, aLegacyDate) in legacyReleaseL:
f.write('R,{},{}\n'.format(aLegacyVer, aLegacyDate))
f.write('info,msg,This is a legacy release.\n')
f.write('info,msg,\n')
if isLegacyJre == True:
f.write('info,msg,Downgrading to this version may require a mandatory upgrade (ver: ' + version + ') before further upgrades are allowed.\n\n')
else:
f.write('# A release should be made using a legacy JRE (1.8+) and this DistMaker release. The release notes will need to be manually.\n')
f.write('info,msg,Downgrading to this version will require a mandatory 2-step upgrade in order to use releases made with non legacy JREs.\n\n')
f.close()
os.chmod(catFile, 0o644)
else:
# Form the default (empty) appCatalog.txt
f = open(catFile, 'w')
f.write('name' + ',' + appName + '\n\n')
f.close()
os.chmod(catFile, 0o644)
# Updated the appCatalog.txt info file
f = open(catFile, 'a')
f.write('R,{},{}\n'.format(version, buildDate))
f.write('info,msg,There are no release notes available.\n\n')
f.close()
# Update the (legacy) releaseInfo.txt file
if isLegacyRelease == True and isLegacyJre == True:
f = open(verFile, 'a')
f.write(version + ',' + buildDate + '\n')
f.close()
def delReleaseInfo(installPath, appName, version, buildDate):
verFile = os.path.join(installPath, 'releaseInfo.txt')
def delReleaseInfoLegacy(deployPath, appName, version, buildDate):
verFile = os.path.join(deployPath, 'releaseInfo.txt')
# Bail if the release info file does not exist
if os.path.isfile(verFile) == False:
print('Failed to locate deployment release info file: ' + verFile)
print('Aborting removal action for version: ' + version)
exit()
return;
# Read the file
releaseInfo = []
@@ -93,10 +173,55 @@ def delReleaseInfo(installPath, appName, version, buildDate):
f.close()
def addRelease(appName, version, buildDate):
def delReleaseInfo(deployPath, appName, version, buildDate):
# Remove any legacy releases
delReleaseInfoLegacy(deployPath, appName, version, buildDate)
catFile = os.path.join(deployPath, 'appCatalog.txt')
# Bail if the appCatalog.txt file does not exist
if os.path.isfile(catFile) == False:
print('Failed to locate deployment appCatalog file: ' + catFile)
print('Aborting removal action for version: ' + version)
exit()
# Read the file (and skip over all lines found after the release we are searching for)
isDeleteMode = False
passLineL = []
f = open(catFile, 'r')
for aLine in f:
aLine = aLine[:-1]
tokenL = aLine.split(',', 1);
# Determine when to enter / exit isDeleteMode
if len(tokenL) == 3 and tokenL[0] == 'R' and tokenL[1] == version:
# By not adding the current record to the releaseInfo list, we are effectively removing the record
isDeleteMode = True
print('Removing release record from info file. Version: ' + version)
# We exit deleteMode when see a different release or exit instruction
elif len(tokenL) == 3 and tokenL[0] == 'R' and tokenL[1] != version:
isDeleteMode = False
elif len(tokenL) >= 1 and tokenL[0] == 'exit':
isDeleteMode = False
# Skip to next if we are in deleteMode
if isDeleteMode == True:
continue
# Save off all lines when we are not in delete mode
passLineL += aLine
f.close()
# Write the updated file
f = open(verFile, 'w')
for aLine in passLineL:
f.write(aLine + '\n')
f.close()
def addRelease(appName, version, buildDate, isLegacyJre):
# Check to see if the deployed location already exists
installPath = os.path.join(rootPath, appName)
if os.path.isdir(installPath) == False:
deployPath = os.path.join(rootPath, appName)
if os.path.isdir(deployPath) == False:
print('Application ' + appName + ' has never been deployed to the root location: ' + args.deployRoot)
print('Create a new release of the application at the specified location?')
input = raw_input('--> ').upper()
@@ -105,10 +230,10 @@ def addRelease(appName, version, buildDate):
exit()
# Build the deployed location
os.makedirs(installPath)
os.makedirs(deployPath, 0o755)
# Check to see if the deploy version already exists
versionPath = os.path.join(installPath, version)
versionPath = os.path.join(deployPath, version)
if os.path.isdir(versionPath) == True:
print('Application ' + appName + ' with version, ' + version + ', has already been deployed.')
print('Release will not be made for app ' + appName)
@@ -123,22 +248,23 @@ def addRelease(appName, version, buildDate):
os.chmod(os.path.join(root, d), 0o755)
for f in files:
os.chmod(os.path.join(root, f), 0o644)
os.chmod(versionPath, 0o755)
# Update the version info
addReleaseInfo(installPath, appName, version, buildDate)
addReleaseInfo(deployPath, appName, version, buildDate, isLegacyJre)
print('Application {} ({}) has been deployed to location: {}'.format(appName, version, args.deployRoot))
def delRelease(appName, version, buildDate):
# Check to see if the deployed location already exists
installPath = os.path.join(rootPath, appName)
if os.path.isdir(installPath) == False:
deployPath = os.path.join(rootPath, appName)
if os.path.isdir(deployPath) == False:
print('Application ' + appName + ' has never been deployed to the root location: ' + args.deployRoot)
print('There are no releases to remove. ')
exit()
# Check to see if the deploy version already exists
versionPath = os.path.join(installPath, version)
versionPath = os.path.join(deployPath, version)
if os.path.isdir(versionPath) == False:
print('Application ' + appName + ' with version, ' + version + ', has not been deployed.')
print('Release will not be removed for app ' + appName)
@@ -148,13 +274,10 @@ def delRelease(appName, version, buildDate):
shutil.rmtree(versionPath)
# Update the version info
delReleaseInfo(installPath, appName, version, buildDate)
delReleaseInfo(deployPath, appName, version, buildDate)
if __name__ == "__main__":
argv = sys.argv;
argc = len(argv);
# Logic to capture Ctrl-C and bail
signal.signal(signal.SIGINT, handleSignal)
@@ -170,10 +293,10 @@ if __name__ == "__main__":
parser.add_argument('distLoc', nargs='?', default=scriptPath, help='The location of the distribution to deploy.')
# Intercept any request for a help message and bail
for aArg in argv:
if aArg == '-h' or aArg == '-help':
parser.print_help()
exit()
argv = sys.argv;
if '-h' in argv or '-help' in argv:
parser.print_help()
exit()
# Parse the args
parser.formatter_class.max_help_position = 50
@@ -189,11 +312,11 @@ if __name__ == "__main__":
exit()
# Determine the appName, version, and buildDate of the distribution
(appName, version, buildDate) = getDistInfo(distPath)
(appName, version, buildDate, isLegacyJre) = getDistInfo(distPath)
# Uninstall the app, if remove argument is specified
if args.remove == True:
delRelease(appName, version, buildDate)
else:
addRelease(appName, version, buildDate)
addRelease(appName, version, buildDate, isLegacyJre)

View File

@@ -10,11 +10,88 @@ import signal
import subprocess
import sys
import miscUtils
import jreUtils
import logUtils
import miscUtils
from logUtils import errPrintln
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 getAppLauncherVersion():
# Check for appLauncher.jar prerequisite
jarFile = getAppLauncherSourceFile()
if os.path.exists(jarFile) == False:
errPrintln('This installation of DistMaker appears to be broken. Please ensure there is an appLauncher.jarfile in the template folder.', indent=1)
errPrintln('File does not exist: ' + jarFile, indent=1)
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('This installation of DistMaker appears to be broken. Failed to determine the AppLauncher version.', indent=1)
errPrintln(str(aExp))
exit(-1)
def addAppLauncherRelease():
""" 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(rootPath, 'launcher')
if os.path.isdir(deployPath) == False:
os.makedirs(deployPath, 0o755)
# Determine the file name of the deployed appLauncher.jar file
version = getAppLauncherVersion()
dstFileName = 'appLauncher-' + version + '.jar'
# 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:
f = open(catFile, 'w')
f.write('name' + ',' + 'AppLauncher' + '\n')
f.write('digest' + ',' + 'sha256' + '\n\n')
f.close()
os.chmod(catFile, 0o644)
# Updated the appCatalog file
f = open(catFile, 'a')
digestStr = miscUtils.computeDigestForFile(srcFile, 'sha256')
stat = os.stat(srcFile)
fileLen = stat.st_size
f.write("F,{},{},{},{}\n".format(digestStr, fileLen, dstFileName, version))
# f.write('\n')
f.close()
# Copy the src appLauncher.jar file to it's deployed location
shutil.copy2(srcFile, dstFile)
os.chmod(dstFile, 0o644)
def addRelease(version):
# Normalize the JVM version for consistency
version = jreUtils.normalizeJvmVerStr(version)
@@ -30,7 +107,7 @@ def addRelease(version):
exit()
# Build the deployed location
os.makedirs(installPath)
os.makedirs(installPath, 0o755)
# Check to see if the deploy version already exists
versionPath = os.path.join(installPath, version)
@@ -41,44 +118,90 @@ def addRelease(version):
# Update the version info
addReleaseInfo(installPath, version)
addAppLauncherRelease()
print('JRE ({}) has been deployed to location: {}'.format(version, args.deployRoot))
def addReleaseInfo(installPath, verStr):
verFile = os.path.join(installPath, 'jreCatalog.txt')
# Var that holds the last recorded exit (distmaker) command
# By default assume the command has not been set
exitVerDM = None
# Create the release info file
if os.path.isfile(verFile) == False:
f = open(verFile, 'w')
# Create the jreCatalogfile
catFile = os.path.join(installPath, 'jreCatalog.txt')
if os.path.isfile(catFile) == False:
f = open(catFile, 'w')
f.write('name' + ',' + 'JRE' + '\n')
f.write('digest' + ',' + 'sha256' + '\n\n')
f.close()
os.chmod(catFile, 0o644)
# Determine the last exit,DistMaker instruction specified
else:
f = open(catFile, 'r')
for line in f:
tokens = line[:-1].split(',');
# Record the (exit) version of interest
if len(tokens) == 3 and tokens[0] == 'exit' and tokens[1] == 'DistMaker':
exitVerDM = tokens[2]
f.close()
# Locate the list of JRE files with a matching verStr
jreFiles = jreUtils.getJreTarGzFilesForVerStr(verStr)
if len(jreFiles) == 0:
raise ErrorDM('No JREs were located for the version: ' + verStr)
# Updated the release info file
f = open(verFile, 'a')
# Determine if the user is deploying a legacy JREs. Legacy JRE versions match the pattern 1.*
isLegacyJre = verStr.startswith('1.') == True
# Let the user know that legacy JREs can NOT be deployed once an exit,DistMaker instruction
# has been found. Basically once non-legacy JREs have been deployed then legacy JREs are no
# longer allowed.
if isLegacyJre == True and exitVerDM != None:
logUtils.errPrintln('Legacy JREs can not be deployed once any non legacy JRE has been deployed.')
logUtils.errPrintln('The specified JRE ({}) is considered legacy.'.format(verStr), indent=1)
exit()
# Determine if we need to record an exit instruction. An exit instruction is needed if the
# deployed JRE is non-legacy. Legacy DistMaker apps will not be able to handle non-legacy JREs.
needExitInstr = False
if isLegacyJre == False:
try:
tokenArr = exitVerDM.split('.')
majorVerAL = int(tokenArr[0])
minorVerAL = int(tokenArr[1])
if majorVerAL == 0 and minorVerAL < 1:
needExitInstr = True
except:
needExitInstr = True
pass
# Updated the jreCatalogfile
f = open(catFile, 'a')
# Write the exit info to stop legacy DistMakers from processing further
if needExitInstr == True:
f.write('exit,DistMaker,0.48\n\n')
# Write out the JRE release info
f.write("jre,{}\n".format(verStr))
if needExitInstr == True:
f.write("require,AppLauncher,0.1,0.2\n")
for aFile in jreFiles:
stat = os.stat(aFile)
digestStr = miscUtils.computeDigestForFile(aFile, 'sha256')
# platformStr = jreUtils.getPlatformForJre(aFile)
# stat = os.stat(aFile)
# fileLen = os.path.s
# f.write("jre,{},{},{},{},{}\n".format(verStr, platformStr, os.path.basename(aFile), fileLen, digestStr))
f.write("F,{},{},{}\n".format(digestStr, stat.st_size, os.path.basename(aFile)))
fileLen = stat.st_size
platformStr = jreUtils.getPlatformForJreTarGzFile(aFile)
if isLegacyJre == False:
f.write("F,{},{},{},{}\n".format(digestStr, fileLen, platformStr, os.path.basename(aFile)))
else:
f.write("F,{},{},{}\n".format(digestStr, fileLen, os.path.basename(aFile)))
f.write('\n')
f.close()
destPath = os.path.join(installPath, verStr)
os.makedirs(destPath)
os.makedirs(destPath, 0o755)
# Copy over the JRE files to the proper path
for aFile in jreFiles:
shutil.copy(aFile, destPath)
shutil.copy2(aFile, destPath)
destFile = os.path.join(destPath, aFile)
os.chmod(destFile, 0o644)
@@ -109,18 +232,17 @@ def delRelease(verStr):
def delReleaseInfo(installPath, version):
verFile = os.path.join(installPath, 'jreCatalog.txt')
# Bail if the release info file does not exist
if os.path.isfile(verFile) == False:
print('Failed to locate deployment release info file: ' + verFile)
# Bail if the jreCatalogfile does not exist
catFile = os.path.join(installPath, 'jreCatalog.txt')
if os.path.isfile(catFile) == False:
print('Failed to locate deployment catalog file: ' + catFile)
print('Aborting removal action for version: ' + version)
exit()
# Read the file
inputLineL = []
isDeleteMode = False
f = open(verFile, 'r')
f = open(catFile, 'r')
for line in f:
tokens = line[:-1].split(',', 1);
# Switch to deleteMode when we find a matching JRE release
@@ -139,16 +261,13 @@ def delReleaseInfo(installPath, version):
f.close()
# Write the updated file
f = open(verFile, 'w')
f = open(catFile, 'w')
for aLine in inputLineL:
f.write(aLine)
f.close()
if __name__ == "__main__":
argv = sys.argv;
argc = len(argv);
# Logic to capture Ctrl-C and bail
signal.signal(signal.SIGINT, miscUtils.handleSignal)
@@ -164,10 +283,10 @@ if __name__ == "__main__":
parser.add_argument('deployRoot', help='Root location to deploy the specified JRE distribution.')
# Intercept any request for a help message and bail
for aArg in argv:
if aArg == '-h' or aArg == '-help':
parser.print_help()
exit()
argv = sys.argv;
if '-h' in argv or '-help' in argv:
parser.print_help()
exit()
# Parse the args
parser.formatter_class.max_help_position = 50

View File

@@ -15,23 +15,35 @@ from miscUtils import ErrorDM
# default to. Note if this variable is not specified then the latest JRE release
# located in the appropriate <installPath>/jre directory will be utilized.
#
# There should be corresponding tar.gz files with the following pattern:
# <installpath>/jre/jre-<VERSION>-<PLATFORM>-x64.tar.gz
# There should be corresponding tar.gz files with patterns that match one of the below:
# <installpath>/jre/jre-<VERSION>-<PLATFORM>-x64.tar.gz
# <installpath>/jre/jre-<VERSION>_<PLATFORM>-x64_bin.tar.gz
# where PLATFORM is one of the following: apple, linux, windows
# where VERSION is something like: 8u73
# For example the Linux JRE 1.8.0_73 tar.gz release would be:
# <installpath>/jre/jre-8u73-linux-x64.tar.gz
# where VERSION is something like: 8u73 or 9.0.4
#
# Following are valid examples of named JRE tar.gz files:
# The Linux JRE 1.8.0_73 tar.gz release would be:
# <installpath>/jre/jre-8u73-linux-x64.tar.gz
# The Apple JRE 9.0.4 tar.gz release would be:
# <installpath>/jre/jre-9.0.4_osx-x64_bin.tar.gz
defaultVersionStr = '1.8'
def getBasePathForJreTarGzFile(aJreTarGzFile):
"""Returns the JRE (base) path that should be used to access the JRE found in the specified JRE tar.gz.
This is needed since different JRE tar.gz files have been found to have different top level paths. Using
this method ensures consistency between JRE tar.gz releases after the tar.gz file is unpacked."""
this method ensures consistency between JRE tar.gz releases after the tar.gz file is unpacked.
Please note that legacy JREs will expand to a different path than non-legacy JREs.
"""
verArr = getJreTarGzVerArr(aJreTarGzFile);
if verArr == None:
raise ErrorDM('File name (' + aJreTarGzFile + ') does not conform to proper JRE tar.gz name specification.')
basePath = 'jre' + verArrToVerStr(verArr)
verStr = verArrToVerStr(verArr)
if verStr.startswith("1.") == True:
basePath = 'jre' + verArrToVerStr(verArr)
else:
basePath = 'jre-' + verArrToVerStr(verArr)
return basePath;
@@ -45,22 +57,44 @@ def getDefaultJreVerStr():
def getJreTarGzFilesForVerStr(aVerStr):
"""Returns the JRE tar.gz files matching the specified specific JRE version specification. This will return an empty
list if there is no JRE tar.gz files that is sufficient for the request.
list if there is no JRE tar.gz files that is sufficient for the request.
The version must be fully qualified (must specify platform, major, minor, and update components). If it is not then
an ErrorDM will be raised. An example of a valid fully qualified version string is: '1.8.0_73'"""
aVerStr --- The version of interest. The version must be fully qualified.
Fully qualified is defined as having the following:
Pre Java 9 ---> Exactly 4 fields:
<A>.<B>.<C>.<D>
where:
A ---> Platform (always defined as 1)
B ---> Major (stored in minor index)
C ---> Minor version (always defined as 0)
D ---> Patch
Java 9 or later ---> 3 fields or more
<A>.<B>.<C>...
where:
A ---> The major version
B ---> The minor version
C ---> The security release
... Any extra fields are vendor specific.
An ErrorDM will be raised if the version is not fully qualified Below are examples of fully qualified fields:
'1.8.0_73'
'9.0.4'
"""
appInstallRoot = miscUtils.getInstallRoot()
appInstallRoot = os.path.dirname(appInstallRoot)
# Retrieve the target version - and ensure it is fully qualified
targVer = verStrToVerArr(aVerStr)
if len(targVer) != 4:
if len(targVer) < 3:
raise ErrorDM('The specified version is not a fully qualified version. Version: ' + aVerStr)
if targVer[0] == 1 and len(targVer) != 4:
raise ErrorDM('Legacy JRE releases require exactly 4 elements for the release. Legacy releases refer to any release before Java 9. Version: ' + aVerStr)
# Search all the appropriate tar.gz JREs for exact matches in our JRE folder
retList = []
matchName = "jre-*-*-x64.tar.gz";
searchPath = os.path.join(os.path.abspath(appInstallRoot), 'jre', matchName)
searchName = "jre-*.tar.gz";
searchPath = os.path.join(os.path.abspath(appInstallRoot), 'jre', searchName)
# for aFile in ['jre-8u739-windows-x64.tar.gz', 'jre-8u60-windows-x64.tar.gz', 'jre-7u27-windows-x64.tar.gz']:
for aFile in glob.glob(searchPath):
# Ensure that the aFile's JVM version is an exact match of targVer
@@ -74,20 +108,25 @@ def getJreTarGzFilesForVerStr(aVerStr):
def getJreTarGzFile(aPlatform, aJvmVerSpec):
"""Returns the JRE tar.gz file for the appropriate platform and JRE release. If there are several possible
matches then the tar.gz with the latest version will be returned.
"""Returns the JRE tar.gz file for the appropriate platform and JRE release. If there are several possible
matches then the tar.gz with the latest version will be returned.
This will return None if there is no file that is sufficient for the request. Note if you do not care about
aPlatform --- The platform of the JRE tar.gz file of interest. Platform will typically be one of: 'apple',
'linux', 'windows'
aJvmVerSpec --- A list of 1 or 2 items that define the range of JRE versions you are interested in. If the
list has just one item then that version will be used as the minimum version.
Method will return None if there is no file that is sufficient for the request. Note if you do not care about
any specific update for a major version of JAVA then just specify the major version. Example '1.8' instead of
1.8.0_73'"""
# Transform a single string to a list of size 1
if isinstance(aJvmVerSpec, basestring):
aJvmVerSpec = [aJvmVerSpec]
# Retrieve the application installation location
appInstallRoot = miscUtils.getInstallRoot()
appInstallRoot = os.path.dirname(appInstallRoot)
# Normalize aPlotform to the proper string
platStr = aPlatform.lower()
if platStr == 'apple':
platStr = 'macosx'
# Retrieve the min and max JVM versions from aJvmVerSpec
minJvmVer = None
if aJvmVerSpec != None and len(aJvmVerSpec) >= 1:
@@ -95,20 +134,28 @@ def getJreTarGzFile(aPlatform, aJvmVerSpec):
maxJvmVer = None
if aJvmVerSpec != None and len(aJvmVerSpec) == 2:
maxJvmVer = verStrToVerArr(aJvmVerSpec[1])
if aJvmVerSpec != None and len(aJvmVerSpec) > 2:
errorMsg = 'At most only 2 elements are allowed. Number of elements specified: {}'.format(aJvmVerSpec)
raise ValueError(errorMsg)
# Search all the appropriate tar.gz JREs for the best match from our JRE folder
aPlatform = aPlatform.lower()
matchList = []
searchName = "jre-*-" + platStr + "-x64.tar.gz";
searchName = "jre-*.tar.gz";
searchPath = os.path.join(os.path.abspath(appInstallRoot), 'jre', searchName)
# for file in ['jre-8u739-windows-x64.tar.gz', 'jre-8u60-windows-x64.tar.gz', 'jre-7u27-windows-x64.tar.gz']:
for file in glob.glob(searchPath):
for aFile in glob.glob(searchPath):
# Retrieve the platform and skip to next if it is not a match
platStr = getPlatformForJreTarGzFile(aFile)
if platStr != aPlatform:
continue
# Ensure that the file's JVM version is in range of minJvmVer and maxJvmVer
tmpVer = getJreTarGzVerArr(file)
tmpVer = getJreTarGzVerArr(aFile)
if minJvmVer != None and isVerAfterAB(minJvmVer, tmpVer) == True:
continue
if maxJvmVer != None and isVerAfterAB(tmpVer, maxJvmVer) == True:
continue
matchList.append(file);
matchList.append(aFile);
# Determine the best match of all the matches
bestMatch = None
@@ -134,35 +181,76 @@ def getJreTarGzFile(aPlatform, aJvmVerSpec):
def getJreTarGzVerArr(aFile):
"""Returns the version corresponding to the passed in JRE tar.gz file.
The returned value will be a list consisting of the (platform, major, minor, update) integer components of the version.
The file naming convention is expected to be:
jre-<B>u<D>-*.tar.gz
where:
B ---> The major version
D ---> The update version
Note that the platform version <A> will be assumed to be: 1
Note that the minor version <C> will be assumed to be: 0
"""
# Retrieve the version component of the fileName
fileName = os.path.basename(aFile)
idx = fileName[4:].find('-')
if idx == -1:
return None
verStr = fileName[4: 4 + idx]
if len(verStr) == 0:
return None
# print('verStr: ' + verStr)
The returned value will be a list consisting of intergers defining the version associated with the
tar.gz file.
See the following references:
https://docs.oracle.com/javase/9/migrate/#GUID-3A71ECEF-5FC5-46FE-9BA9-88CBFCE828CB
http://openjdk.java.net/jeps/223
# Determine the version based on the pattern '<A>u<B>' where:
# if there is no <B> component then just assume 0 for minor version
tokenArr = verStr.split('u')
retVerArr = [1, int(tokenArr[0]), 0]
if len(retVerArr) == 1:
retVerArr.append(0)
The file naming convention is expected to follow the standard:
jre-<Version>-<Platform>.tar.gz
where <Version> can be:
Pre Java 9:
<B>u<D>
where:
B ---> The major version (stored in minor index)
D ---> The update version (stored as the security)
- Note the major version will be assumed to be: 1
Java 9 or later:
<A>.<B>.<C>.<D>
A ---> The major version
B ---> The minor version
C ---> The security release
"""
# Retrieve the base file name of the path
fileName = os.path.basename(aFile)
# Tokenize the filename by spliting along chars: '_', '-'
compL = re.split('[_-]', fileName)
if len(compL) < 3:
return None
# raise Error('Failed to tokenize the file name: ' + fileName)
# The version string should be the second item
verStr = compL[1]
# Retrieve the version component of the fileName
# Based on the old naming convention - prior to Java 9
if verStr.find('u') != -1:
# Determine the version based on the pattern '<A>u<B>' where:
# if there is no <B> component then just assume 0 for minor version
tokenL = verStr.split('u')
retVerL = [1, int(tokenL[0]), 0]
if len(tokenL) == 1:
retVerL.append(0)
else:
retVerL.append(int(tokenL[1]))
return retVerL
# Retrieve the version component of the fileName
# Based on the new naming convention - Java 9 and later
else:
retVerArr.append(int(tokenArr[1]))
return retVerArr
retVerL = [int(aVal) for aVal in verStr.split('.')]
return retVerL
def getPlatformForJreTarGzFile(aFile):
"""Returns a string representing the platform of the specified JRE file. The platform is computed by evaluating the name of the
JRE tar.gz file. The returned values will be in lowercase. Currently the known returned values are one of the following: (apple,
linux, windows). These returned values should correspond to x86-64 JRE releases. On failure None will be returned.
"""
# Tokenize the filename by spliting along chars: '_', '-'
fileName = os.path.basename(aFile)
compL = re.split('[_-]', fileName)
if len(compL) != 4 and len(compL) != 5:
return None
# The platform component is stored in the 3rd token. Any string matching osx or macosx will be transformed to apple
platStr = compL[2].lower()
if platStr == 'osx' or platStr == 'macosx':
platStr = 'apple'
return platStr;
def normalizeJvmVerStr(aVerStr):
@@ -172,6 +260,7 @@ def normalizeJvmVerStr(aVerStr):
1.8 ---> 1.8
1.8.0.73 ---> 1.8.0_73
1.7.0_55 ---> 1.7.0_55
9.0.4 ---> 9.0.4
"""
verArr = verStrToVerArr(aVerStr)
retVerStr = verArrToVerStr(verArr)
@@ -179,7 +268,7 @@ def normalizeJvmVerStr(aVerStr):
def unpackAndRenameToStandard(aJreTarGzFile, aDestPath):
"""Method that will unpack the specified JRE tar.gz into the folder aDestPath. The unpacked JRE folder will also
"""Method that will unpack the specified JRE tar.gz into the folder aDestPath. The unpacked JRE folder will also
be renamed to a standard convention: jre<A>.<B> where
A: represents the major (classical) version
B: represents the minor version
@@ -252,29 +341,31 @@ def verStrToVerArr(aVerStr):
'1.7.0 ---> [1, 7, 0]
'1.8' ---> [1, 8]
'1.8.0_73' ---> [1, 8, 0, 73]"""
verStrArr = re.compile("[._]").split(aVerStr)
verStrL = re.compile("[._]").split(aVerStr)
# Transform from string list to integer list
try:
retVerArr = [int(val) for val in verStrArr]
retVerL = [int(val) for val in verStrL]
except:
raise ErrorDM('Invalid JVM version: ' + aVerStr)
return retVerArr
return retVerL
def verArrToVerStr(aVerArr):
def verArrToVerStr(aVerL):
"""Utility method to convert an integral version (list) to the equivalent jvm version string. If the specified version is not a valid jvm version
then an ErrorDM will be raised. Each component in the list must be integral. Note typical versions follow this pattern: <langVer>.<majVer>.<minVer>_<upVer>
Thus the following will get transformed to:
[1, 7, 0] ---> '1.7.0'
[1, 8] ---> '1.8'
[1, 8, 0, 73] ---> '1.8.0_73'"""
then an ErrorDM will be raised. Each component in the list must be integral.
Note that as of Java 9 the version scheme has changed. Below defines the version scheme
Prior to Java 9: <language>.<major>.<minor>_<update> to <majVer>.<minVer>.<s>
Java 9 and later: <major>.<minor>.<security>.<patch>
[1, 8] ---> '1.8'
[1, 8, 0, 73] ---> '1.8.0_73'
[9, 0, 4] ---> '9.0.4'"""
# Transform from integer list to string
if len(aVerArr) <= 3:
retVerStr = ".".join(str(x) for x in aVerArr)
if len(aVerL) <= 3:
retVerStr = ".".join(str(x) for x in aVerL)
return retVerStr
else:
retVerStr = ".".join(str(x) for x in aVerArr[0:3])
retVerStr += '_' + ".".join(str(x) for x in aVerArr[3:])
retVerStr = ".".join(str(x) for x in aVerL[0:3])
retVerStr += '_' + ".".join(str(x) for x in aVerL[3:])
return retVerStr

View File

@@ -5,7 +5,7 @@ import sys
def appendLogOutputWithText(aStr, aText):
""" Method which given a string from a log will insert all occurances of newlines with the
""" Method which given a string from a log will insert all occurances of newlines with the
specified text. Note if the last character is a newline then it will be stripped before the replacement"""
if aStr.endswith("\n") == True:
aStr = aStr[:-1]
@@ -14,11 +14,10 @@ def appendLogOutputWithText(aStr, aText):
return retStr;
def log(aStr, tabReplace=None):
""" Method which will print aStr to the console and optionally replace all tab
characters with tabReplace"""
if tabReplace != None:
aStr.replace('\t', tabReplace)
print(aStr)
def errPrintln(aMsg="", indent=0):
"""Print the specified string with a trailing newline to stderr."""
while indent > 0:
indent -= 1
aMsg = ' ' + aMsg
sys.stderr.write(aMsg + '\n')