Code cleanup.

Fixed application argument processing.
Fixed memory configuration logic under Linux.
Improved scripts to make them more robust.
This commit is contained in:
Norberto Lopez
2016-03-08 20:28:40 +00:00
parent aa6069499a
commit 3a286b7087
20 changed files with 640 additions and 282 deletions

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="MacRoman" standalone="no"?>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<jardesc>
<jar path="distMaker/lib/distMaker.jar"/>
<options buildIfNeeded="true" compress="true" descriptionLocation="/distMaker/buildDistMakerBin.jardesc" exportErrors="false" exportWarnings="true" includeDirectoryEntries="false" overwrite="true" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/>

View File

@@ -1,6 +1,7 @@
#! /usr/bin/env python
import argparse
import copy
import getpass
import math
import os
@@ -12,28 +13,39 @@ import tempfile
import time
import glob
import jreUtils
import miscUtils
# Globals
# The global var jre is a pointer to a full jre release for an Apple system
# There should be a release located at <installpath>/jre/apple/jreRelease
jreRelease='jre1.7.0_51'
def buildRelease(args, buildPath):
# We may mutate args - thus make a custom copy
args = copy.copy(args)
# Retrieve vars of interest
appName = args.name
version = args.version
jreRelease = args.jreRelease
# Attempt to locate a default JRE if none is specified in the args.
if jreRelease == None:
jreRelease = jreUtils.getDefaultJreRelease('apple')
# Let the user know if the 'user' specified JRE is not available and locate an alternative
elif jreUtils.isJreAvailable('apple', jreRelease) == False:
print('[Warning] User specified JRE (' + jreRelease + ') is not available for Apple platform. Searching for alternative...')
jreRelease = jreUtils.getDefaultJreRelease('apple')
args.jreRelease = jreRelease
# Form the list of distributions to build
distList = [(appName + '-' + version, False)]
if miscUtils.isJreAvailable('apple', jreRelease) == True:
if jreUtils.isJreAvailable('apple', jreRelease) == True:
distList.append((appName + '-' + version + '-jre', True))
# Create the various Apple distributions
for (distName, isStaticRelease) in distList:
print('Building Apple distribution: ' + distName)
# Let the user know of the JRE release we are going to build with
if isStaticRelease == True:
print('\tUtilizing jreRelease: ' + jreRelease)
# Create a tmp folder and build the static release to the tmp folder
tmpPath = tempfile.mkdtemp(dir=buildPath)
@@ -45,10 +57,14 @@ def buildRelease(args, buildPath):
dmgFile = os.path.join(buildPath, distName + '.dmg')
# cmd = ['genisoimage', '-o', dmgFile, '-quiet', '-V', appName, '-max-iso9660-filenames', '-hfs-unlock', '-uid', '501', '-gid', '80', '-r', '-D', '-apple', tmpPath]
cmd = ['genisoimage', '-o', dmgFile, '-quiet', '-V', appName, '-max-iso9660-filenames', '-hfs-unlock', '-D', '-r', '-apple', tmpPath]
subprocess.call(cmd, stderr=subprocess.STDOUT)
print('\tForming DMG image. File: ' + dmgFile)
proc = miscUtils.executeAndLog(cmd, "\t\tgenisoimage: ")
if proc.returncode != 0:
print('\tError: Failed to form DMG image. Return code: ' + str(proc.returncode))
# Perform cleanup: Remove the tmp folder
shutil.rmtree(tmpPath)
print('\tFinished building release: ' + os.path.basename(dmgFile))
@@ -117,6 +133,7 @@ def buildDistTree(buildPath, rootPath, args, isStaticRelease):
appName = args.name
bgFile = args.bgFile
icnsFile = args.icnsFile
jreRelease = args.jreRelease
# Form the symbolic link which points to /Applications
srcPath = '/Applications'
@@ -147,7 +164,6 @@ def buildDistTree(buildPath, rootPath, args, isStaticRelease):
dstPath = os.path.join(rootPath, appName + '.app', 'Contents', 'MacOS')
shutil.copy(srcPath, dstPath)
# Write out the PkgInfo file
dstPath = os.path.join(rootPath, appName + '.app', 'Contents', "PkgInfo")
f = open(dstPath, 'wb')
@@ -212,15 +228,18 @@ def buildDistTree(buildPath, rootPath, args, isStaticRelease):
shutil.copy(srcPath, dstPath)
# Copy over the .DS_Store
srcPath = os.path.join(appTemplatePath, '.DS_Store')
dstPath = rootPath
srcPath = os.path.join(appTemplatePath, '.DS_Store.template')
dstPath = os.path.join(rootPath, '.DS_Store')
shutil.copy(srcPath, dstPath)
# Update the .DS_Store file to reflect the new volume name
srcPath = os.path.join(rootPath, '.DS_Store')
classPath = appInstallRoot + '/lib/glum.jar:' + appInstallRoot + '/lib/distMaker.jar:' + appInstallRoot + '/lib/guava-13.0.1.jar'
classPath = appInstallRoot + '/lib/glum.jar:' + appInstallRoot + '/lib/distMaker.jar:' + appInstallRoot + '/lib/guava-18.0.jar'
cmd = ['java', '-cp', classPath, 'dsstore.MainApp', srcPath, appName]
subprocess.check_call(cmd, stderr=None, stdout=None)
proc = miscUtils.executeAndLog(cmd, "\t\tdsstore.MainApp: ")
if proc.returncode != 0:
print('\tError: Failed to update .DS_Store. Return code: ' + str(proc.returncode))
@@ -368,7 +387,7 @@ def buildPListInfoStatic(destFile, args):
tupList.append(('CFBundleSignature', '????'))
tupList.append(('CFBundleVersion', args.version))
tupList.append(('NSHumanReadableCopyright', ''))
tupList.append(('JVMRuntime', jreRelease))
tupList.append(('JVMRuntime', args.jreRelease))
tupList.append(('JVMMainClassName', 'appLauncher.AppLauncher'))

View File

@@ -1,6 +1,7 @@
#! /usr/bin/env python
import argparse
import distutils.spawn
import getpass
import math
import os
@@ -90,6 +91,42 @@ def buildCatalogFile(deltaPath):
f.write(aRecord[0] + ',' + aRecord[1] + ',' + aRecord[2] + ',' + aRecord[3] + '\n')
f.close()
def checkForRequiredApplications():
"""Method to ensure we have all of the required applications installed to support building of distributions
The current set of applications required are:
java, jar, genisoimage, ImageMagick:convert"""
evalPath = distutils.spawn.find_executable('java')
errList = []
warnList = []
if evalPath == None:
errList.append('Failed while trying to locate java. Please install Java')
evalPath = distutils.spawn.find_executable('jar')
if evalPath == None:
errList.append('Failed while trying to locate jar. Please install jar (typically included with Java)')
evalPath = distutils.spawn.find_executable('genisoimage')
if evalPath == None:
errList.append('Failed while trying to locate genisoimage. Please install genisoimage')
evalPath = distutils.spawn.find_executable('convert')
if evalPath == None:
warnList.append('Application \'convert\' was not found. Please install (ImageMagick) convert')
warnList.append('\tWindows icons will not be supported when using argument: -iconFile.')
if len(errList) > 0:
print('There are configuration errors with the environment or system.')
# print('System Path:' + str(sys.path))
print('Please correct the following:')
for aError in errList:
print('\t' + aError)
if len(warnList) > 0:
print('Please correct the following for full program functionality:')
for aWarn in warnList:
print('\t' + aWarn)
sys.exit(0)
if len(warnList) > 0:
print('There are configuration issues with the environment or system.')
print('Please correct the following for full program functionality:')
for aWarn in warnList:
print('\t' + aWarn)
def getClassPath(javaCodePath):
retList = []
@@ -102,6 +139,7 @@ def getClassPath(javaCodePath):
# Form the default list of all jar files
for path, dirs, files in os.walk(javaCodePath):
files.sort()
for file in files:
if len(file) > 4 and file[-4:] == '.jar':
filePath = os.path.join(path, file)
@@ -125,9 +163,10 @@ if __name__ == "__main__":
parser.add_argument('-name', help='The name of the application.')
parser.add_argument('-version', default='0.0.1', help='The version of the application.')
parser.add_argument('-mainClass', help='Application main entry point.')
parser.add_argument('-appArgs', help='Application arguments.', nargs='+', default=[])
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('-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)
@@ -144,20 +183,30 @@ if __name__ == "__main__":
parser.print_help()
exit()
# Check to ensure all of the required applications are installed
checkForRequiredApplications()
# Parse the args
parser.formatter_class.max_help_position = 50
args = parser.parse_args()
# print args
# Ensure we are getting the bare minimum options
errList = [];
if args.name == None:
print('At a minimum the application name must be specified. Exiting...')
exit();
# Ensure java options are specified properly
if (args.javaCode == None and args.mainClass != None) or (args.javaCode != None and args.mainClass == None):
print('Both javaCode and mainClass must be specified, if either are specified. Exiting...')
errList.append('-name')
if args.javaCode == None:
errList.append('-javaCode')
if args.mainClass == None:
errList.append('-mainClass')
if len(errList) != 0:
print('At a minimum the following must be specified: ' + str(errList) + '.\nExiting...')
exit();
#
# # Ensure java options are specified properly
# if (args.javaCode == None and args.mainClass != None) or (args.javaCode != None and args.mainClass == None):
# print('Both javaCode and mainClass must be specified, if either are specified. Exiting...')
# exit();
# Form the classPath if none specified
if args.javaCode != None and len(args.classPath) == 0:
@@ -176,7 +225,6 @@ if __name__ == "__main__":
newJvmArgs.append(aJvmArg)
args.jvmArgs = newJvmArgs
# Bail if the release has already been built
buildPath = os.path.abspath(args.name + '-' + args.version)
if (os.path.exists(buildPath) == True):
@@ -195,6 +243,10 @@ if __name__ == "__main__":
os.makedirs(deltaDataPath)
for aPath in args.dataCode:
srcPath = aPath
if os.path.isdir(srcPath) == False:
print(' [ERROR] The dataCode path does not exist. Path: ' + srcPath)
shutil.rmtree(buildPath)
exit(-1)
dstPath = os.path.join(deltaDataPath, os.path.basename(aPath))
shutil.copytree(srcPath, dstPath, symlinks=False)
@@ -202,6 +254,10 @@ if __name__ == "__main__":
if args.javaCode != None:
# 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)
shutil.rmtree(buildPath)
exit(-1)
dstPath = deltaCodePath;
shutil.copytree(srcPath, dstPath, symlinks=False)

86
script/jreUtils.py Normal file
View File

@@ -0,0 +1,86 @@
#! /usr/bin/env python
import os
import re
import miscUtils
# Globals
# The global variable defaultJreRelease is a hint for which (full) JRE release to
# default to. Note if this variable is not specified then the latest JRE release
# located in the appropriate platform directory will be utilized.
#
# There should be a release for the following:
# Apple: <installpath>/jre/apple/defaultJreRelease
# Linux: <installpath>/jre/linux/defaultJreRelease
# Windows: <installpath>/jre/windows/defaultJreRelease
defaultJreRelease = 'jre1.8.0_60'
def getDefaultJreRelease(aPlatform):
"""Utility method to locate the default JRE to utilize"""
# Retrieve vars of interest
appInstallRoot = miscUtils.getInstallRoot()
appInstallRoot = os.path.dirname(appInstallRoot)
# Locate the JRE platform search path
jreSearchPath = os.path.join(appInstallRoot, 'jre/' + aPlatform)
if os.path.isdir(jreSearchPath) == False:
print ('JRE search path is: ' + jreSearchPath + ' This path does not exist. No embedded JRE builds will be made for platform: ' + aPlatform)
return None
# Return the default if it is hard wired (and is available)
if 'defaultJreRelease' in globals():
evalPath = os.path.join(jreSearchPath, defaultJreRelease)
if os.path.isdir(evalPath) == True:
return defaultJreRelease
else:
print('[WARNING] The specified default JRE for the ' + aPlatform.capitalize() + ' platform is: ' + defaultJreRelease + '. However this JRE is not installed! <---')
# Assume no JRE found
pickJre = None
pickVer = None
# Search the platform path for available JREs
for aPath in os.listdir(jreSearchPath):
evalPath = os.path.join(jreSearchPath, aPath)
if os.path.isdir(evalPath) == True and aPath.startswith('jre') == True:
tmpVer = re.split('[._]', aPath[3:])
# print('\tEvaluating path: ' + aPath + ' Ver: ' + str(tmpVer))
if pickJre == None:
pickJre = aPath
pickVer = tmpVer
continue
# Evaluate the version and select the most recent
for i, j in zip(tmpVer, pickVer):
if i < j:
break
if i > j:
pickJre = aPath
pickVer = tmpVer
break
# Return the result (default JRE)
return pickJre
def getJreMajorVersion(aJreRelease):
"""Returns the minimum version of the JRE to utilize based on the passed in JRE release.
The passed in value should be of the form jreX.X.X_XX ---> example: jre1.8.0_60
If aJreRelease is invalid then returns the default value of: 1.8.0"""
if aJreRelease == None or aJreRelease.startswith('jre') == False:
return "1.8.0"
return aJreRelease[3:].split("_")[0]
def isJreAvailable(aPlatform, aJreRelease):
"""Tests to see if the specified JRE is available for aPlatform"""
if aPlatform == None or aJreRelease == None:
return False
appInstallRoot = miscUtils.getInstallRoot()
appInstallRoot = os.path.dirname(appInstallRoot)
srcPath = os.path.join(appInstallRoot, 'jre', aPlatform, aJreRelease)
return os.path.isdir(srcPath)

View File

@@ -1,6 +1,7 @@
#! /usr/bin/env python
import argparse
import copy
import getpass
import math
import os
@@ -12,31 +13,42 @@ import tempfile
import time
import glob
import jreUtils
import miscUtils
# Globals
# The global var jre is a pointer to a full jre release for a Linux system
# There should be a release located at <installpath>/jre/linux/jreRelease
jreRelease = 'jre1.7.0_15'
def buildRelease(args, buildPath):
# We mutate args - thus make a custom copy
args = copy.copy(args)
# Retrieve vars of interest
appName = args.name
version = args.version
jreRelease = args.jreRelease
# Attempt to locate a default JRE if none is specified in the args.
if jreRelease == None:
jreRelease = jreUtils.getDefaultJreRelease('linux')
# Let the user know if the 'user' specified JRE is not available and locate an alternative
elif jreUtils.isJreAvailable('linux', jreRelease) == False:
print('[Warning] User specified JRE (' + jreRelease + ') is not available for Linux platform. Searching for alternative...')
jreRelease = jreUtils.getDefaultJreRelease('linux')
args.jreRelease = jreRelease
# Create a tmp (working) folder
tmpPath = tempfile.mkdtemp(dir=buildPath)
# Form the list of distributions to build
distList = [(appName + '-' + version, False)]
if miscUtils.isJreAvailable('linux', jreRelease) == True:
if jreUtils.isJreAvailable('linux', jreRelease) == True:
distList.append((appName + '-' + version + '-jre', True))
# Create the various Linux distributions
# Create the various Linux distributions
for (distName, isStaticRelease) in distList:
print('Building Linux distribution: ' + distName)
# Let the user know of the JRE release we are going to build with
if isStaticRelease == True:
print('\tUtilizing jreRelease: ' + jreRelease)
# Create the (top level) distribution folder
dstPath = os.path.join(tmpPath, distName)
@@ -47,10 +59,12 @@ def buildRelease(args, buildPath):
# Create the tar.gz archive
tarFile = os.path.join(buildPath, distName + '.tar.gz')
print('\tForming tar.gz file: ' + tarFile)
childPath = distName
# print '[' + getCurrTimeStr() + '] Building tar archive: ' + tarFile
# print '[' + getCurrTimeStr() + '] Building tar archive: ' + tarFile
subprocess.check_call(["tar", "-czf", tarFile, "-C", tmpPath, childPath], stderr=subprocess.STDOUT)
# subprocess.check_call(["gzip", tarFile], stderr=subprocess.STDOUT)
print('\tFinished building release: ' + os.path.basename(tarFile))
# Perform cleanup
shutil.rmtree(tmpPath)
@@ -61,19 +75,20 @@ def buildDistTree(buildPath, rootPath, args, isStaticRelease):
appInstallRoot = miscUtils.getInstallRoot()
appInstallRoot = os.path.dirname(appInstallRoot)
appName = args.name
jreRelease = args.jreRelease
# Form the app contents folder
srcPath = os.path.join(buildPath, "delta")
dstPath = os.path.join(rootPath, "app")
shutil.copytree(srcPath, dstPath, symlinks=True)
#Copy libs to the app directory so they can be found at launch
soDir = os.path.join(rootPath,'app', 'code','linux')
for libPath in glob.iglob(os.path.join(soDir,"*.so")):
# Copy libs to the app directory so they can be found at launch
soDir = os.path.join(rootPath, 'app', 'code', 'linux')
for libPath in glob.iglob(os.path.join(soDir, "*.so")):
libFileName = os.path.basename(libPath)
srcPath = os.path.join(soDir,libFileName)
linkPath = os.path.join(dstPath,libFileName)
shutil.copy(srcPath,linkPath)
srcPath = os.path.join(soDir, libFileName)
linkPath = os.path.join(dstPath, libFileName)
shutil.copy(srcPath, linkPath)
@@ -90,7 +105,7 @@ def buildDistTree(buildPath, rootPath, args, isStaticRelease):
srcPath = os.path.join(appInstallRoot, 'jre', 'linux', jreRelease)
dstPath = os.path.join(rootPath, os.path.basename(srcPath))
shutil.copytree(srcPath, dstPath, symlinks=True)
# Form the executable bash script
dstPath = os.path.join(rootPath, 'run' + appName)
buildBashScript(dstPath, args, isStaticRelease)
@@ -104,6 +119,14 @@ def buildBashScript(destFile, args, isStaticRelease):
jvmArgsStr += aStr + ' '
f = open(destFile, 'wb')
f.write('#!/bin/bash\n')
f.write('# Do not remove the opening or closing brackets: {}. This enables safe inline\n')
f.write('# mutations to this script while it is running\n')
f.write('{ # Do not remove this bracket! \n\n')
f.write('# Define the maximum memory to allow the application to utilize\n')
f.write('#maxMem=512m # Uncomment out this line to change from defaults.\n\n')
f.write('# Get the instalation path\n')
f.write('installPath=$(readlink -f "$BASH_SOURCE")\n')
f.write('installPath=$(dirname "$installPath")\n\n')
@@ -111,14 +134,22 @@ def buildBashScript(destFile, args, isStaticRelease):
f.write('# Change the working directory to the app folder in the installation path\n')
f.write('cd "$installPath"/app\n\n')
exeCmd = 'java ' + jvmArgsStr
if isStaticRelease == True:
exeCmd = '../' + jreRelease + '/bin/java ' + jvmArgsStr
exeCmd = exeCmd + ' -Djava.system.class.loader=appLauncher.RootClassLoader -cp ../launcher/appLauncher.jar appLauncher.AppLauncher app.cfg'
f.write('# Setup the xmxStr to define the maximum JVM memory.\n')
f.write('if [ -z ${maxMem+x} ]; then\n')
f.write(' xmxStr=""\n')
f.write('else\n')
f.write(' xmxStr=\'-Xmx\'$maxMem\n')
f.write('fi\n\n')
exeCmd = 'java ' + jvmArgsStr + '$xmxStr '
if isStaticRelease == True:
exeCmd = '../' + args.jreRelease + '/bin/java ' + jvmArgsStr + '$xmxStr '
exeCmd = exeCmd + '-Djava.system.class.loader=appLauncher.RootClassLoader -cp ../launcher/appLauncher.jar appLauncher.AppLauncher app.cfg '
f.write('# Run the application\n')
f.write(exeCmd + '\n')
f.write('\n')
f.write(exeCmd + '\n\n')
f.write('exit # Do not remove this exit! (just before the bracket)\n')
f.write('} # Do not remove this bracket! \n\n')
f.close()

24
script/logUtils.py Normal file
View File

@@ -0,0 +1,24 @@
import hashlib
import os
import time
import sys
def appendLogOutputWithText(aStr, aText):
""" 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]
retStr = aText + aStr.replace('\n', '\n' + 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)

View File

@@ -2,18 +2,77 @@
import hashlib
import os
import time
import subprocess
import sys
def handleSignal(signal, frame):
"""Signal handler, typically used to capture ctrl-c."""
print('User aborted processing!')
sys.exit(0)
import logUtils
def checkRoot():
"""Determines if the script is running with root priveleges."""
# This logic will may break on SELinux systems
if os.geteuid() != 0:
msg = ' You need to have root privileges to run this script.\n'
msg += ' Please run this script with sudo!\n'
msg += ' Exiting...\n'
exit(msg)
# Source: http://stackoverflow.com/questions/1131220/get-md5-hash-of-a-files-without-open-it-in-python
def computeMd5ForFile(evalFile, block_size=2**20):
f = open(evalFile, 'rb')
md5 = hashlib.md5()
while True:
data = f.read(block_size)
if not data:
break
md5.update(data)
f.close()
return md5.hexdigest()
def getInstallRoot():
"""Returns the root path where the running script is installed."""
argv = sys.argv;
installRoot = os.path.dirname(argv[0])
# print('appInstallRoot: ' + appInstallRoot)
return installRoot
def executeAndLog(command, indentStr=""):
"""Executes the specified command via subprocess and logs all (stderr,stdout) output to the console"""
# proc = subprocess.
# proc.returncode = -1
try:
proc = subprocess.Popen(command, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
proc.wait()
outStr = proc.stdout.read()
if outStr != "":
outStr = logUtils.appendLogOutputWithText(outStr, indentStr)
print(outStr)
except Exception as aExp:
print(indentStr + 'Failed to execute command: ' + str(command))
outStr = logUtils.appendLogOutputWithText(str(aExp), indentStr)
print(outStr)
print(indentStr + 'Stack Trace:')
outStr = logUtils.appendLogOutputWithText(aExp.child_traceback, indentStr + '\t')
print(outStr)
class Proc:
returncode = None
proc = Proc
# proc = None
return proc
# if proc.returncode != 0:
# print('\tError: Failed to build executable. Return code: ' + proc.returncode)
def getPathSize(aRoot):
"""Computes the total disk space used by the specified path.
Note if aRoot does not exist or is None then this will return 0"""
# Check for existance
# Check for existence
if aRoot == None or os.path.exists(aRoot) == False:
return 0
@@ -32,31 +91,10 @@ def getPathSize(aRoot):
return numBytes
def checkRoot():
"""
Determines if the scrip ist running with root priveleges."""
# This logic will may break on SELinux systems
if os.geteuid() != 0:
msg = ' You need to have root privileges to run this script.\n'
msg += ' Please run this script with sudo!\n'
msg += ' Exiting...\n'
exit(msg)
def getInstallRoot():
"""Returns the root path where the running script is insalled."""
argv = sys.argv;
installRoot = os.path.dirname(argv[0])
# print('appInstallRoot: ' + appInstallRoot)
return installRoot
def isJreAvailable(systemName, jreRelease):
appInstallRoot = getInstallRoot()
appInstallRoot = os.path.dirname(appInstallRoot)
srcPath = os.path.join(appInstallRoot, 'jre', systemName, jreRelease)
return os.path.isdir(srcPath)
def handleSignal(signal, frame):
"""Signal handler, typically used to capture ctrl-c."""
print('User aborted processing!')
sys.exit(0)
def buildAppLauncherConfig(destFile, args):
@@ -114,15 +152,3 @@ def buildAppLauncherConfig(destFile, args):
f.close()
# Source: http://stackoverflow.com/questions/1131220/get-md5-hash-of-a-files-without-open-it-in-python
def computeMd5ForFile(evalFile, block_size=2**20):
f = open(evalFile, 'rb')
md5 = hashlib.md5()
while True:
data = f.read(block_size)
if not data:
break
md5.update(data)
f.close()
return md5.hexdigest()

View File

@@ -1,30 +1,38 @@
#! /usr/bin/env python
import argparse
import copy
import getpass
import math
import os
import shutil
import signal
import subprocess
import sys
import tempfile
import time
import glob
import jreUtils
import miscUtils
# Globals
# The global var jre is a pointer to a full jre release for a Windows system
# There should be a release located at <installpath>/jre/windows/jreRelease
jreRelease = 'jre1.7.0_15'
def buildRelease(args, buildPath):
# We mutate args - thus make a custom copy
args = copy.copy(args)
# Retrieve vars of interest
appName = args.name
version = args.version
jreRelease = args.jreRelease
# Attempt to locate a default JRE if none is specified in the args.
if jreRelease == None:
jreRelease = jreUtils.getDefaultJreRelease('windows')
# Let the user know if the 'user' specified JRE is not available and locate an alternative
elif jreUtils.isJreAvailable('windows', jreRelease) == False:
print('[Warning] User specified JRE (' + jreRelease + ') is not available for Windows platform. Searching for alternative...')
jreRelease = jreUtils.getDefaultJreRelease('windows')
args.jreRelease = jreRelease
# Bail if launch4j is not installed
appInstallRoot = miscUtils.getInstallRoot()
@@ -39,12 +47,15 @@ def buildRelease(args, buildPath):
# Form the list of distributions to build
distList = [(appName + '-' + version, False)]
if miscUtils.isJreAvailable('windows', jreRelease) == True:
if jreUtils.isJreAvailable('windows', jreRelease) == True:
distList.append((appName + '-' + version + '-jre', True))
# Create the various Windows distributions
for (distName, isStaticRelease) in distList:
print('Building Windows distribution: ' + distName)
# Let the user know of the JRE release we are going to build with
if isStaticRelease == True:
print('\tUtilizing jreRelease: ' + jreRelease)
# Create the (top level) distribution folder
dstPath = os.path.join(tmpPath, distName)
@@ -55,7 +66,14 @@ def buildRelease(args, buildPath):
# Create the zip file
zipFile = os.path.join(buildPath, distName + ".zip")
subprocess.check_call(["jar", "-cMf", zipFile, "-C", dstPath, '.'], stderr=subprocess.STDOUT)
cmd = ["jar", "-cMf", zipFile, "-C", dstPath, '.']
print('\tForming zip file: ' + zipFile)
proc = miscUtils.executeAndLog(cmd, "\t\tjar: ")
if proc.returncode != 0:
print('\tError: Failed to form zip file. Return code: ' + str(proc.returncode))
print('\tAborting build of release: ' + os.path.basename(zipFile))
else:
print('\tFinished building release: ' + os.path.basename(zipFile))
# Perform cleanup
shutil.rmtree(tmpPath)
@@ -66,6 +84,7 @@ def buildDistTree(buildPath, rootPath, args, isStaticRelease):
appInstallRoot = miscUtils.getInstallRoot()
appInstallRoot = os.path.dirname(appInstallRoot)
appName = args.name
jreRelease = args.jreRelease
# Form the app contents folder
srcPath = os.path.join(buildPath, "delta")
@@ -104,11 +123,14 @@ def buildDistTree(buildPath, rootPath, args, isStaticRelease):
origIconFile = args.iconFile
if origIconFile != None:
winIconFile = os.path.join(rootPath, os.path.basename(origIconFile) + ".ico")
eCode = subprocess.call(["convert", origIconFile, winIconFile], stderr=subprocess.STDOUT)
if eCode != 0:
print('ImageMagick convert failed with eCode: ' + str(eCode))
print('There will be no windows icon file. System call:')
print(' convert ' + origIconFile + ' ' + winIconFile)
cmd = ['convert', origIconFile, winIconFile]
proc = miscUtils.executeAndLog(cmd, "\t\t(ImageMagick) convert: ")
if proc.returncode != 0:
if proc.returncode == None:
print('\t\tImageMagick convert does not appear to be properly installed.')
else:
print('\t\tImageMagick convert failed with eCode: ' + str(proc.returncode))
print('\t\tThere will be no windows icon file.')
winIconFile = None
# Form the launch4j config file
@@ -117,8 +139,11 @@ def buildDistTree(buildPath, rootPath, args, isStaticRelease):
# Build the windows executable
launch4jExe = os.path.join(appInstallRoot, "launch4j", "launch4j")
subprocess.check_call([launch4jExe, configFile], stderr=subprocess.STDOUT)
# print(launch4jExe + ' ' + configFile)
cmd = [launch4jExe, configFile]
print('\tBuilding windows executable via launch4j')
proc = miscUtils.executeAndLog(cmd, "\t\t")
if proc.returncode != 0:
print('\tError: Failed to build executable. Return code: ' + str(proc.returncode))
# Perform cleanup
os.remove(configFile)
@@ -162,9 +187,11 @@ def buildLaunch4JConfig(destFile, args, isStaticRelease, iconFile):
writeln(f, 0, "");
writeln(f, 1, "<jre>");
if isStaticRelease == True:
writeln(f, 2, "<path>" + jreRelease + "</path>");
writeln(f, 2, "<path>" + args.jreRelease + "</path>");
else:
writeln(f, 2, "<minVersion>" + "1.7.0" + "</minVersion>");
jreVer = jreUtils.getJreMajorVersion(args.jreRelease)
# writeln(f, 2, "<minVersion>" + "1.7.0" + "</minVersion>");
writeln(f, 2, "<minVersion>" + jreVer + "</minVersion>");
# writeln(f, 2, "<jdkPreference>jreOnly|preferJre|preferJdk|jdkOnly</jdkPreference>");
writeln(f, 2, "<jdkPreference>preferJre</jdkPreference>");
for aJvmArg in args.jvmArgs:

View File

@@ -6,7 +6,7 @@ import glum.gui.panel.task.FullTaskPanel;
import glum.io.IoUtil;
import glum.net.Credential;
import glum.reflect.FunctionRunnable;
import glum.task.Task;
import glum.task.*;
import glum.unit.DateUnit;
import glum.util.ThreadUtil;
@@ -26,9 +26,9 @@ import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import distMaker.gui.PickReleasePanel;
import distMaker.node.FileNode;
import distMaker.node.Node;
import distMaker.platform.AppleUtils;
@@ -118,15 +118,14 @@ public class DistMakerEngine
return new UpdateStatus(msg);
}
// Sort the items, and isolate the newest item
LinkedList<Release> fullList = Lists.newLinkedList(unsortedReleaseList);
LinkedList<Release> fullList = new LinkedList<>(unsortedReleaseList);
Collections.sort(fullList);
Release newestRelease = fullList.removeLast();
// The check succeeded, so return wether 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.
@@ -266,9 +265,9 @@ public class DistMakerEngine
aTask.abort();
return;
}
// a successful test has been done, so notify the listener
listener.checkForNewVersionsPerformed();
// 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.
@@ -286,8 +285,6 @@ public class DistMakerEngine
}
}
// Hide the taskPanel
aTask.setVisible(false);
@@ -313,7 +310,7 @@ public class DistMakerEngine
chosenItem = pickVersionPanel.getChosenItem();
if (chosenItem == null)
return;
// Reshow the taskPanel
aTask.setVisible(true);
@@ -379,6 +376,8 @@ public class DistMakerEngine
Node staleNode, updateNode;
URL catUrl, staleUrl, updateUrl;
File catalogFile;
Task mainTask, tmpTask;
long nodeFileLen;
boolean isPass;
try
@@ -393,10 +392,10 @@ public class DistMakerEngine
return false;
}
// Download the update catalog to the (local) delta location
// 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(aTask, catUrl, catalogFile, refCredential) == false)
if (DistUtils.downloadFile(new PartialTask(aTask, 0.00, 0.01), catUrl, catalogFile, refCredential, -1L) == false)
return false;
// Load the map of stale nodes
@@ -411,43 +410,62 @@ public class DistMakerEngine
if (updateMap == null)
return false;
// Download the individual files
aTask.infoAppendln("Downloading release: " + aRelease.getVersion() + " Nodes: " + updateMap.size());
// Determine the total number of bytes to be transferred
long releaseSizeFull = 0L, releaseSizeCurr = 0L;
for (Node aNode : updateMap.values())
{
if (aNode instanceof FileNode)
releaseSizeFull += ((FileNode)aNode).getFileLen();
}
// Download the individual files (Progress -> [1% - 95%])
double progressVal = 0.00;
mainTask = new PartialTask(aTask, 0.01, 0.94);
mainTask.infoAppendln("Downloading release: " + aRelease.getVersion() + " Nodes: " + updateMap.size());
for (String aFileName : updateMap.keySet())
{
// Bail if we have been aborted
if (aTask.isActive() == false)
if (mainTask.isActive() == false)
return false;
updateNode = updateMap.get(aFileName);
staleNode = staleMap.get(aFileName);
nodeFileLen = 0L;
if (updateNode instanceof FileNode)
nodeFileLen = ((FileNode)updateNode).getFileLen();
tmpTask = new PartialTask(mainTask, mainTask.getProgress(), nodeFileLen / (releaseSizeFull + 0.00));
// Attempt to use the local copy
isPass = false;
if (staleNode != null && updateNode.areContentsEqual(staleNode) == true)
{
isPass = staleNode.transferContentTo(aTask, refCredential, destPath);
isPass = staleNode.transferContentTo(tmpTask, refCredential, destPath);
if (isPass == true)
aTask.infoAppendln("\t(L) " + staleNode.getFileName());
mainTask.infoAppendln("\t(L) " + staleNode.getFileName());
}
// Use the remote update copy, if we were not able to use a local stale copy
if (isPass == false && aTask.isActive() == true)
if (isPass == false && mainTask.isActive() == true)
{
isPass = updateNode.transferContentTo(aTask, refCredential, destPath);
isPass = updateNode.transferContentTo(tmpTask, refCredential, destPath);
if (isPass == true)
aTask.infoAppendln("\t(R) " + updateNode.getFileName());
mainTask.infoAppendln("\t(R) " + updateNode.getFileName());
}
// Log the failure and bail
if (isPass == false && aTask.isActive() == true)
if (isPass == false && mainTask.isActive() == true)
{
aTask.infoAppendln("Failed to download from update site.");
aTask.infoAppendln("\tSite: " + updateUrl);
aTask.infoAppendln("\tFile: " + updateNode.getFileName());
aTask.infoAppendln("\tDest: " + destPath);
mainTask.infoAppendln("Failed to download from update site.");
mainTask.infoAppendln("\tSite: " + updateUrl);
mainTask.infoAppendln("\tFile: " + updateNode.getFileName());
mainTask.infoAppendln("\tDest: " + destPath);
return false;
}
// Update the progress
releaseSizeCurr += nodeFileLen;
progressVal = releaseSizeCurr / (releaseSizeFull + 0.00);
mainTask.setProgress(progressVal);
}
// Update the platform configuration files

View File

@@ -2,35 +2,19 @@ package distMaker;
import glum.gui.GuiUtil;
import glum.io.IoUtil;
import glum.net.Credential;
import glum.net.NetUtil;
import glum.net.Result;
import glum.net.*;
import glum.reflect.ReflectUtil;
import glum.task.ConsoleTask;
import glum.task.Task;
import glum.unit.DateUnit;
import glum.util.ThreadUtil;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;
import java.util.*;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import distMaker.node.FileNode;
import distMaker.node.Node;
import distMaker.node.PathNode;
import distMaker.node.*;
public class DistUtils
{
@@ -39,10 +23,10 @@ public class DistUtils
private static boolean isDevelopersEnvironment = true;
private static int updateCode = 0; // Static member to declare the update status, 0: None, 1: Pass, 2: Fail
private static String updateMsg = null;
// Static field used only when developing DistMaker. Otherwise this field should always be null.
private static File developAppPath = null;
/**
* Utility method to determine the path where the application is installed.
* <P>
@@ -51,7 +35,7 @@ public class DistUtils
public static File getAppPath()
{
File jarPath, currPath, testFile;
// If we are in developer mode then return the developAppPath
if (developAppPath != null)
return developAppPath;
@@ -101,15 +85,21 @@ 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.
*/
@SuppressWarnings("resource")
public static boolean downloadFile(Task aTask, URL aUrl, File aFile, Credential aCredential)
public static boolean downloadFile(Task aTask, URL aUrl, File aFile, Credential aCredential, long aFileSize)
{
URLConnection connection;
InputStream inStream;
OutputStream outStream;
String errMsg;
byte[] byteArr;
double progressVal;
long cntByteFull, cntByteCurr;
int numBytes;
// Ensure we have a valid aTask
@@ -135,21 +125,42 @@ public class DistUtils
outStream = new FileOutputStream(aFile);
// Copy the bytes from the instream to the outstream
cntByteFull = aFileSize;
cntByteCurr = 0;
numBytes = 0;
while (numBytes != -1)
{
numBytes = inStream.read(byteArr);
if (numBytes > 0)
{
outStream.write(byteArr, 0, numBytes);
cntByteCurr += numBytes;
}
// Update the progressVal to reflect the download progress. Note however that we do update the
// progress to 100% since that would change the task to be flagged as inactive and thus cause
// the download to be aborted prematurely.
// TODO: In the future Tasks should not be marked as inactive based on progress values
progressVal = 0;
if (cntByteFull > 0)
{
progressVal = (cntByteCurr + 0.0) / cntByteFull;
if (progressVal >= 1.0)
progressVal = 0.99;
}
aTask.setProgress(progressVal);
// Bail if aTask is aborted
if (aTask.isActive() == false)
{
aTask.infoAppendln("File transfer request has been aborted...");
aTask.infoAppendln("\tFile: " + aFile);
aTask.infoAppendln("\tFile: " + aFile + " Bytes transferred: " + cntByteCurr);
return false;
}
}
// Mark aTask's progress as complete since the file was downloaded.
aTask.setProgress(1.0);
}
catch (IOException aExp)
{
@@ -180,7 +191,7 @@ public class DistUtils
String errMsg;
errMsg = null;
fullList = Lists.newArrayList();
fullList = new ArrayList<>();
catUrl = IoUtil.createURL(aUpdateUrl.toString() + "/" + appName + "/" + "releaseInfo.txt");
connection = null;
@@ -259,7 +270,7 @@ public class DistUtils
URL fetchUrl;
Result result;
String errMsg;
// Dump the stack trace
aExp.printStackTrace();
@@ -291,8 +302,8 @@ public class DistUtils
errMsg += "An undefined error occurred while retrieving the remote file.\n";
break;
}
// Log the URL which we failed on
// Log the URL which we failed on
fetchUrl = aConnection.getURL();
errMsg += "\tURL: " + fetchUrl + "\n";
@@ -307,12 +318,12 @@ public class DistUtils
public static boolean isFullyWriteable(File aPath)
{
// There is no known way to change, the write bit to true, in windows,
// so by default, assume the path is writable. This method is totally unreliable on
// the Windows platform (Gives bogus results for files on CDs).
// so by default, assume the path is writable. This method is totally unreliable on
// the Windows platform (Gives bogus results for files on CDs).
// TODO: See if File.canWrite(), returns the proper value on Windows
if (System.getProperty("os.name").startsWith("Windows") == true)
return true;
if (aPath.isDirectory() == false)
throw new RuntimeException("Specified path is not a folder: " + aPath);
@@ -342,7 +353,7 @@ public class DistUtils
String errMsg;
errMsg = null;
retMap = Maps.newLinkedHashMap();
retMap = new LinkedHashMap<>();
inStream = null;
bufReader = null;

View File

@@ -1,14 +1,13 @@
package distMaker;
import java.util.List;
import com.google.common.collect.Lists;
import glum.task.SilentTask;
import java.util.ArrayList;
import java.util.List;
public class LoggingTask extends SilentTask
{
private final List<String> messages = Lists.newArrayList();
private final List<String> messages = new ArrayList<>();
@Override
public void infoAppend(String aMsg)

View File

@@ -30,6 +30,9 @@ import static distMaker.platform.MemUtils.GB_SIZE;
public class MemoryConfigPanel extends GlassPanel implements ActionListener, ZioRaw, ListSelectionListener
{
/** Unused - but added to eliminate warning due to poorly designed java.io.Serializable interface. */
private static final long serialVersionUID = 1L;
// GUI vars
private JLabel titleL;
private GLabel maxMemL, currMemL, targMemL;

View File

@@ -6,37 +6,24 @@ import glum.gui.action.ClickAction;
import glum.gui.panel.GlassPanel;
import glum.gui.panel.itemList.ItemListPanel;
import glum.gui.panel.itemList.StaticItemProcessor;
import glum.gui.panel.itemList.query.QueryComposer;
import glum.gui.panel.itemList.query.QueryItemHandler;
import glum.gui.panel.itemList.query.QueryTableCellRenderer;
import glum.gui.panel.itemList.query.*;
import glum.unit.ConstUnitProvider;
import glum.unit.DateUnit;
import glum.zio.raw.ZioRaw;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collections;
import java.util.LinkedList;
import java.util.*;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.*;
import javax.swing.border.BevelBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import net.miginfocom.swing.MigLayout;
import com.google.common.collect.Lists;
import distMaker.LookUp;
import distMaker.Release;
@@ -97,8 +84,8 @@ public class PickReleasePanel extends GlassPanel implements ActionListener, ZioR
String appName, infoMsg;
// Sort the items, and isolate the newest item
LinkedList<Release> linkedList;
linkedList = Lists.newLinkedList(itemList);
LinkedList<Release> linkedList;
linkedList = new LinkedList<>(itemList);
Collections.sort(linkedList);
Collections.reverse(linkedList); // reverse the list to show most recent versions on top
newestItem = linkedList.removeFirst();

View File

@@ -43,6 +43,14 @@ public class FileNode implements Node
return true;
}
/**
* Returns the length of the associated file
*/
public long getFileLen()
{
return fileLen;
}
@Override
public String getFileName()
{
@@ -57,10 +65,10 @@ public class FileNode implements Node
// Determine the source URL to copy the contents from
srcUrl = IoUtil.createURL(rootUrl.toString() + "/" + fileName);
// Determine the file to transfer the contents to
dstFile = new File(dstPath, fileName);
return DistUtils.downloadFile(aTask, srcUrl, dstFile, aCredential);
return DistUtils.downloadFile(aTask, srcUrl, dstFile, aCredential, fileLen);
}
}

View File

@@ -3,29 +3,32 @@ package distMaker.platform;
import glum.io.IoUtil;
import java.io.*;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import com.google.common.collect.Lists;
import distMaker.DistUtils;
public class LinuxUtils
{
/**
* Utility method to update the specified max memory (-Xmx) value in the text file (aFile) to the specified
* maxMemVal.
* Utility method to update the specified maxMem var in the script (aFile) to the requested number of bytes.
* <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.
* Note this method assumes the specified file is a shell script built by DistMaker where the var maxMem holds the proper (right side) specification for the
* JVM's -Xmx value.
* <P>
* 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)
{
BufferedReader br;
List<String> inputList;
String strLine, updateStr;
boolean isProcessed;
String evalStr, memStr, tmpStr;
int currLineNum, injectLineNum, targLineNum;
inputList = Lists.newArrayList();
isProcessed = false;
inputList = new ArrayList<>();
int zios_clean;
// Process our input
br = null;
@@ -34,23 +37,27 @@ public class LinuxUtils
br = new BufferedReader(new InputStreamReader(new FileInputStream(aFile)));
// Read the lines
currLineNum = 0;
targLineNum = -1;
injectLineNum = -1;
while (true)
{
strLine = br.readLine();
if (strLine == null)
evalStr = br.readLine();
if (evalStr == null)
break;
updateStr = MemUtils.transformMaxMemHeapString(strLine, numBytes);
if (updateStr != null)
{
isProcessed = true;
strLine = updateStr;
}
// Locate where we should place our maxMem configuration var
tmpStr = evalStr.trim();
if (tmpStr.equals("# Define the maximum memory to allow the application to utilize") == true)
injectLineNum = currLineNum + 1;
else if (tmpStr.startsWith("maxMem=") == true)
targLineNum = currLineNum;
inputList.add(strLine);
inputList.add(evalStr);
currLineNum++;
}
}
catch (Exception aExp)
catch(Exception aExp)
{
aExp.printStackTrace();
return false;
@@ -60,13 +67,21 @@ public class LinuxUtils
IoUtil.forceClose(br);
}
// Bail if we did not find a line to change
if (isProcessed == false)
// Determine the memStr to use
if (numBytes % MemUtils.GB_SIZE == 0)
memStr = "" + (numBytes / MemUtils.GB_SIZE) + "g";
else
memStr = "" + (numBytes / MemUtils.MB_SIZE) + "m";
// Insert our changes into the script
if (targLineNum != -1)
inputList.set(targLineNum, "maxMem=" + memStr);
else if (injectLineNum != -1 && injectLineNum < currLineNum)
inputList.add(injectLineNum + 1, "maxMem=" + memStr);
else
{
Exception aExp;
aExp = new Exception("Failed to locate -Xmx string!");
aExp.printStackTrace();
return false;
inputList.add(0, "# Define the maximum memory to allow the application to utilize");
inputList.add(1, "maxMem=" + memStr + "\n");
}
// Update the script
@@ -74,6 +89,41 @@ public class LinuxUtils
return writeDoc(aFile, inputList);
}
/**
* Returns the executable script used to launch the JVM. If one can not be determined then this method will return null.
* <P>
* If there are multiple launch scripts then this method may grab the wrong file and fail.
* <P>
* 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()
{
File[] fileArr;
File installPath;
File retFile;
installPath = DistUtils.getAppPath().getParentFile();
fileArr = installPath.listFiles();
// Attempt to locate the path that matches run* file
retFile = null;
for (File aFile : fileArr)
{
if (aFile.getName().startsWith("run") == true)
retFile = aFile;
}
if (retFile == null)
return null;
if (retFile.isFile() == false && Files.isExecutable(retFile.toPath()) == false)
return null;
System.out.println("Linux launch file: " + retFile);
return retFile;
}
/**
* Helper method to output the specified strings to aFile
*/
@@ -91,7 +141,7 @@ public class LinuxUtils
for (String aStr : strList)
bw.write(aStr + '\n');
}
catch (Exception aExp)
catch(Exception aExp)
{
aExp.printStackTrace();
return false;

View File

@@ -1,10 +1,13 @@
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;
@@ -19,22 +22,33 @@ public class MemUtils
* 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.
*/
@SuppressWarnings("restriction")
public static long getInstalledSystemMemory()
{
ByteUnit byteUnit;
long systemMem;
// Attempt to interogate the system memory using the Sun/Oracle JVM specific method
// Attempt to interrogate the system memory using the Sun/Oracle JVM specific method
try
{
systemMem = ((com.sun.management.OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean()).getTotalPhysicalMemorySize();
OperatingSystemMXBean osBean;
Class<?> tmpClass;
Method tmpMethod;
// Note we gather the available memory via reflection to avoid Eclipse/IDE compilation errors due
// to restricted com.sun.management package. The commented out single line of code is equivalent to
// the next block (4 lines) of code.
// Retrieve the OS available memory via reflection equivalent to the commented method below:
// systemMem = ((com.sun.management.OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean()).getTotalPhysicalMemorySize();
osBean = ManagementFactory.getOperatingSystemMXBean();
tmpClass = Class.forName("com.sun.management.OperatingSystemMXBean");
tmpMethod = ReflectUtil.locateMatchingMethod(tmpClass, "getTotalPhysicalMemorySize");
systemMem = (Long)tmpMethod.invoke(osBean);
byteUnit = new ByteUnit(2);
System.out.println("Max memory on the system: " + byteUnit.getString(systemMem));
return systemMem;
}
catch (Throwable aThrowable)
catch(Throwable aThrowable)
{
System.out.println("Failed to query the installed system memory! Assume system memory is 4 GB.");
System.out.println("Exception: " + aThrowable.getLocalizedMessage());
@@ -91,8 +105,8 @@ public class MemUtils
}
// Linux specific platform files
scriptFile = new File(installPath, "runEcho");
if (scriptFile.isFile() == true)
scriptFile = LinuxUtils.getScriptFile();
if (scriptFile != null && scriptFile.isFile() == true)
{
isValidPlatform = true;

View File

@@ -3,10 +3,9 @@ package distMaker.platform;
import glum.io.IoUtil;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import com.google.common.collect.Lists;
import distMaker.DistUtils;
public class WindowsUtils
@@ -25,7 +24,7 @@ public class WindowsUtils
String strLine, updateStr;
boolean isProcessed;
inputList = Lists.newArrayList();
inputList = new ArrayList<>();
isProcessed = false;
// Process our input
@@ -50,7 +49,7 @@ public class WindowsUtils
inputList.add(strLine);
}
// Create a new max heap input config line if one is not specified
if (isProcessed == false)
{
@@ -60,7 +59,7 @@ public class WindowsUtils
isProcessed = true;
}
}
catch (Exception aExp)
catch(Exception aExp)
{
aExp.printStackTrace();
return false;
@@ -80,8 +79,9 @@ public class WindowsUtils
* <P>
* If the configuration file is determined but does not exist, then an empty configuration file will be created.
* <P>
* Note this method looks for a file that ends in .l4j.cfg, or an exe file and creates the corresponding config file.
* <P> If there are multiple .exe or .l4j.cfg files, then this method may grab the wrong file and fail.
* Note this method looks for a file that ends in .l4j.cfg, or an exe file and creates the corresponding config file.
* <P>
* If there are multiple .exe or .l4j.cfg files, then this method may grab the wrong file and fail.
*/
public static File getConfigFile()
{
@@ -89,10 +89,9 @@ public class WindowsUtils
File installPath;
File retFile;
installPath = DistUtils.getAppPath().getParentFile();
fileArr = installPath.listFiles();
// Attempt to locate the <appExe>.l4j.ini file
retFile = null;
for (File aFile : fileArr)
@@ -100,7 +99,7 @@ public class WindowsUtils
if (aFile.getName().endsWith(".l4j.ini") == true)
retFile = aFile;
}
if (retFile == null)
{
for (File aFile : fileArr)
@@ -109,10 +108,10 @@ public class WindowsUtils
retFile = new File(aFile.getParentFile(), aFile.getName().substring(0, aFile.getName().length() - 4) + ".l4j.ini");
}
}
if (retFile == null)
return null;
if (retFile.isFile() == false)
{
try

View File

@@ -1,10 +1,9 @@
package dsstore;
import java.nio.ByteBuffer;
import java.util.LinkedHashMap;
import java.util.Map;
import com.google.common.collect.Maps;
import dsstore.ext.*;
public class AliasRecord
@@ -67,7 +66,7 @@ public class AliasRecord
public AliasRecord()
{
extMap = Maps.newLinkedHashMap();
extMap = new LinkedHashMap<>();
}
/**
@@ -204,13 +203,11 @@ public class AliasRecord
tmpStr = "/Volumes/" + aVolName;
extMap.put(19, new StrExtInfo(19, tmpStr));
// TODO:
// Remove the (unknown) ExtInfo type == 20
// extMap.remove(20);
//System.out.println("Will not remove unknown type: 20\n\t" + extMap.get(20));
// Update the internal copy of the record size
recSize = size();
}

View File

@@ -9,7 +9,6 @@ public class BlockDir
private String name;
private int index;
public BlockDir()
{
name = null;
@@ -26,26 +25,24 @@ public class BlockDir
{
return index;
}
public void readData(ByteBuffer srcBuf)
{
int numBytes;
byte[] byteArr;
numBytes = srcBuf.get() & 0xFF;
// Directories name
byteArr = new byte[numBytes];
srcBuf.get(byteArr);
name = new String(byteArr, Charsets.US_ASCII);
// Block's address
index = srcBuf.getInt();
// Debug output
// System.out.println("[BlockDir] Name: " + name + " index: " + index);
}
}

View File

@@ -6,11 +6,10 @@ import glum.zio.*;
import java.io.*;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.google.common.collect.Lists;
import dsstore.record.*;
/**
@@ -21,7 +20,7 @@ import dsstore.record.*;
public class MainApp
{
// Constants
public static final String DT_long = "long";//convertStringToInt("long"); // An integer (4 bytes)
public static final String DT_long = "long"; //convertStringToInt("long"); // An integer (4 bytes)
public static final String DT_shor = "shor"; //convertStringToInt("shor"); // A short integer? Still stored as four bytes, but the first two are always zero.
public static final String DT_bool = "bool"; //convertStringToInt("bool"); // A boolean value, stored as one byte.
public static final String DT_blob = "blob"; //convertStringToInt("blob"); // An arbitrary block of bytes, stored as an integer followed by that many bytes of data.
@@ -32,7 +31,7 @@ public class MainApp
private Task refTask;
private ByteBuffer dataBuf;
private String volumeName;
public MainApp(String aVolumeName)
{
// Only output verbose info if we are not updating a store
@@ -43,52 +42,55 @@ public class MainApp
dataBuf = null;
volumeName = aVolumeName;
}
public void writeStore(File aFile)
{
FileZoutStream aStream;
int fileMagicKey;
// Ensure we have a valid dataBuf
if (dataBuf == null)
return;
aStream = null;
try
{
aStream = new FileZoutStream(aFile);
// Write the file's MagicKey
fileMagicKey = 0x0001;
aStream.writeInt(fileMagicKey);
// Dump the contents of aBytBuff
aStream.writeFully(dataBuf.array());
aStream.close();
}
catch (IOException aExp)
catch(IOException aExp)
{
IoUtil.forceClose(aStream);
aExp.printStackTrace();
}
}
public ByteBuffer readStore(File aFile)
}
/**
* Method to read the actual store contents.
*
* @return True if we successfully read the store
*/
public boolean readStore(File aFile)
{
ZinStream aStream;
int fileSize;
// Bail if the file is not valid
if (aFile.isFile() == false)
{
refTask.infoAppendln("File does note exist: " + aFile);
return null;
System.err.println("File does note exist: " + aFile);
return false;
}
dataBuf = null;
@@ -168,7 +170,7 @@ refTask.infoAppendln("BlockAddr[" + c1 + "] -> Size: " + blkLen + " Offset: " +
dirCnt = dataBuf.getInt();
refTask.infoAppendln("Block directory count: " + dirCnt);
blockDirList = Lists.newLinkedList();
blockDirList = new ArrayList<>(dirCnt);
for (int c1 = 0; c1 < dirCnt; c1++)
blockDirList.add(new BlockDir(dataBuf));
@@ -208,9 +210,10 @@ refTask.infoAppendln("Reading freelists...");
{
aExp.printStackTrace();
IoUtil.forceClose(aStream);
return false;
}
return dataBuf;
return true;
}
@@ -230,7 +233,7 @@ refTask.infoAppendln("Reading freelists...");
numRecords = aBuf.getInt();
bkgdRecord = null;
recordList = Lists.newLinkedList();
recordList = new ArrayList<>(numRecords);
for (int c1 = 0; c1 < numRecords; c1++)
{
BufUtils.seek(aBuf, 2); // empty
@@ -317,7 +320,7 @@ refTask.infoAppendln("Reading freelists...");
int numRecords;
int numNodes;
int valConst;
// Read the DSDB header
// 0: The block number of the root node of the B-tree
// 1: The number of levels of internal nodes (tree height minus one --- that is, for a tree containing only a single, leaf, node this will be zero)
@@ -329,7 +332,7 @@ refTask.infoAppendln("Reading freelists...");
numRecords = srcBuf.getInt();
numNodes = srcBuf.getInt();
valConst = srcBuf.getInt();
refTask.infoAppendln("rootBlockNum: " + rootBlockNum);
refTask.infoAppendln("numLevels: " + numLevels);
refTask.infoAppendln("rootRecords: " + numRecords);
@@ -338,7 +341,6 @@ refTask.infoAppendln("Reading freelists...");
}
/**
* Application main entry point
*/
@@ -347,13 +349,14 @@ refTask.infoAppendln("Reading freelists...");
MainApp aMainApp;
File aFile;
String storeFileName, newVolName;
storeFileName = null;
newVolName = null;
if (args.length == 0)
{
System.out.println("Usage: dsStoreUtil <fileName> <newVolumeName>");
System.exit(-1);
return;
}
if (args.length >= 1)
@@ -364,13 +367,16 @@ refTask.infoAppendln("Reading freelists...");
{
newVolName = args[1];
}
aFile = new File(storeFileName);
System.out.println("\tUpdating store: " + aFile);
System.out.println("Updating store: " + aFile);
aMainApp = new MainApp(newVolName);
aMainApp.readStore(aFile);
// Bail if we failed to read the store
if (aMainApp.readStore(aFile) == false)
System.exit(-1);
// Save the ds_store if there was a request for a new name
if (newVolName != null)
aMainApp.writeStore(aFile);