# HG changeset patch # User Doug Simon # Date 1436184693 -7200 # Node ID 258eaaa9848456ca1af8463777dbef21ff640945 # Parent 103f53747955fac19bef1a611c3610ef88e25b94 Initial split off from monolithic basic-graal repo diff -r 103f53747955 -r 258eaaa98484 mx.graal/.project --- a/mx.graal/.project Thu Jul 02 12:42:20 2015 +0200 +++ b/mx.graal/.project Mon Jul 06 14:11:33 2015 +0200 @@ -3,7 +3,8 @@ mx.graal - mxtool + mx.jvmci + mxtool2 diff -r 103f53747955 -r 258eaaa98484 mx.graal/.pydevproject --- a/mx.graal/.pydevproject Thu Jul 02 12:42:20 2015 +0200 +++ b/mx.graal/.pydevproject Mon Jul 06 14:11:33 2015 +0200 @@ -8,7 +8,7 @@ /mx.graal -/mxtool +/mxtool2 diff -r 103f53747955 -r 258eaaa98484 mx.graal/mx_graal.py --- a/mx.graal/mx_graal.py Thu Jul 02 12:42:20 2015 +0200 +++ b/mx.graal/mx_graal.py Mon Jul 06 14:11:33 2015 +0200 @@ -1,5 +1,3 @@ -# -# commands.py - the GraalVM specific commands # # ---------------------------------------------------------------------------------------------------- # @@ -26,296 +24,26 @@ # # ---------------------------------------------------------------------------------------------------- -import os, stat, errno, sys, shutil, zipfile, tarfile, tempfile, re, time, datetime, platform, subprocess, StringIO, socket -from os.path import join, exists, dirname, basename -from argparse import ArgumentParser, REMAINDER -from outputparser import OutputParser, ValuesMatcher -import xml.dom.minidom +import os, platform +from os.path import join, exists import sanitycheck import itertools -import json, textwrap +import json import mx -import mx_unittest -import mx_findbugs -import mx_graal_makefile +import mx_jvmci +from mx_jvmci import JDKDeployedDist, buildvms, vm, VM, Task, parseVmArgs, get_vm, unittest, ctw, isVMSupported _suite = mx.suite('graal') -_graal_home = _suite.dir -""" The VMs that can be built and run along with an optional description. Only VMs with a - description are listed in the dialogue for setting the default VM (see _get_vm()). """ -_vmChoices = { - 'jvmci' : 'VM triggered compilation is performed with a tiered system (C1 + Graal) and Graal is available for hosted compilation.', - 'server' : 'Normal compilation is performed with a tiered system (C1 + C2) and Graal is available for hosted compilation.', - 'client' : None, # VM compilation with client compiler, hosted compilation with Graal - 'server-nojvmci' : None, # all compilation with tiered system (i.e., client + server), JVMCI omitted - 'client-nojvmci' : None, # all compilation with client compiler, JVMCI omitted - 'original' : None, # default VM copied from bootstrap JDK - 'graal' : None, # alias for jvmci - 'server-nograal' : None, # alias for server-nojvmci - 'client-nograal' : None, # alias for client-nojvmci -} - -""" The VM that will be run by the 'vm' command and built by default by the 'build' command. - This can be set via the global '--vm' option or the DEFAULT_VM environment variable. - It can also be temporarily set by using of a VM context manager object in a 'with' statement. """ -_vm = None - -""" The VM builds that will be run by the 'vm' command - default is first in list """ -_vmbuildChoices = ['product', 'fastdebug', 'debug', 'optimized'] - -""" The VM build that will be run by the 'vm' command. - This can be set via the global '--vmbuild' option. - It can also be temporarily set by using of a VM context manager object in a 'with' statement. """ -_vmbuild = _vmbuildChoices[0] - -_jacoco = 'off' - -""" The current working directory to switch to before running the VM. """ -_vm_cwd = None - -""" The base directory in which the JDKs cloned from $JAVA_HOME exist. """ -_installed_jdks = None - -""" Prefix for running the VM. """ -_vm_prefix = None - -_make_eclipse_launch = False - -_minVersion = mx.VersionSpec('1.8') - -# max version (first _unsupported_ version) -_untilVersion = None - -class JDKDeployedDist: - def __init__(self, name, isExtension=False, usesJVMCIClassLoader=False, partOfHotSpot=False): - self.name = name - self.isExtension = isExtension - self.usesJVMCIClassLoader = usesJVMCIClassLoader - self.partOfHotSpot = partOfHotSpot # true when this distribution is delivered with HotSpot - -_jdkDeployedDists = [ - JDKDeployedDist('JVMCI_SERVICE', partOfHotSpot=True), - JDKDeployedDist('JVMCI_API', usesJVMCIClassLoader=True, partOfHotSpot=True), - JDKDeployedDist('JVMCI_HOTSPOT', usesJVMCIClassLoader=True, partOfHotSpot=True), - JDKDeployedDist('GRAAL', usesJVMCIClassLoader=True), - JDKDeployedDist('GRAAL_TRUFFLE', usesJVMCIClassLoader=True) -] - -JDK_UNIX_PERMISSIONS_DIR = 0755 -JDK_UNIX_PERMISSIONS_FILE = 0644 -JDK_UNIX_PERMISSIONS_EXEC = 0755 - -def isVMSupported(vm): - if 'client' == vm and len(platform.mac_ver()[0]) != 0: - # Client VM not supported: java launcher on Mac OS X translates '-client' to '-server' - return False - return True - -def _get_vm(): - """ - Gets the configured VM, presenting a dialogue if there is no currently configured VM. - """ - global _vm - if _vm: - return _vm - vm = mx.get_env('DEFAULT_VM') - envPath = join(_suite.mxDir, 'env') - if vm and 'graal' in vm: - if exists(envPath): - with open(envPath) as fp: - if 'DEFAULT_VM=' + vm in fp.read(): - mx.log('Please update the DEFAULT_VM value in ' + envPath + ' to replace "graal" with "jvmci"') - vm = vm.replace('graal', 'jvmci') - if vm is None: - if not mx.is_interactive(): - mx.abort('Need to specify VM with --vm option or DEFAULT_VM environment variable') - mx.log('Please select the VM to be executed from the following: ') - items = [k for k in _vmChoices.keys() if _vmChoices[k] is not None] - descriptions = [_vmChoices[k] for k in _vmChoices.keys() if _vmChoices[k] is not None] - vm = mx.select_items(items, descriptions, allowMultiple=False) - mx.ask_persist_env('DEFAULT_VM', vm) - _vm = vm - return vm - -""" -A context manager that can be used with the 'with' statement to set the VM -used by all VM executions within the scope of the 'with' statement. For example: - - with VM('server'): - dacapo(['pmd']) -""" -class VM: - def __init__(self, vm=None, build=None): - assert vm is None or vm in _vmChoices.keys() - assert build is None or build in _vmbuildChoices - self.vm = vm if vm else _vm - self.build = build if build else _vmbuild - self.previousVm = _vm - self.previousBuild = _vmbuild - - def __enter__(self): - global _vm, _vmbuild - _vm = self.vm - _vmbuild = self.build - - def __exit__(self, exc_type, exc_value, traceback): - global _vm, _vmbuild - _vm = self.previousVm - _vmbuild = self.previousBuild - -def chmodRecursive(dirname, chmodFlagsDir): - if mx.get_os() == 'windows': - return - - def _chmodDir(chmodFlags, dirname, fnames): - os.chmod(dirname, chmodFlagsDir) - - os.path.walk(dirname, _chmodDir, chmodFlagsDir) - -def clean(args): - """clean the source tree""" - opts = mx.clean(args, parser=ArgumentParser(prog='mx clean')) +_graalDeployedDist = JDKDeployedDist('GRAAL', usesJVMCIClassLoader=True) +_graalTruffleDeployedDist = JDKDeployedDist('GRAAL_TRUFFLE', usesJVMCIClassLoader=True) - if opts.native: - def handleRemoveReadonly(func, path, exc): - excvalue = exc[1] - if mx.get_os() == 'windows' and func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES: - os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # 0777 - func(path) - else: - raise - - def rmIfExists(name): - if os.path.isdir(name): - shutil.rmtree(name, ignore_errors=False, onerror=handleRemoveReadonly) - elif os.path.isfile(name): - os.unlink(name) - - rmIfExists(join(_graal_home, 'build')) - rmIfExists(join(_graal_home, 'build-nojvmci')) - rmIfExists(_jdksDir()) - -def export(args): - """create archives of builds split by vmbuild and vm""" - - parser = ArgumentParser(prog='mx export') - args = parser.parse_args(args) - - # collect data about export - infos = dict() - infos['timestamp'] = time.time() - - hgcfg = mx.HgConfig() - hgcfg.check() - infos['revision'] = hgcfg.tip('.') + ('+' if hgcfg.isDirty('.') else '') - # TODO: infos['repository'] - - infos['jdkversion'] = str(mx.java().version) - - infos['architecture'] = mx.get_arch() - infos['platform'] = mx.get_os() - - if mx.get_os != 'windows': - pass - # infos['ccompiler'] - # infos['linker'] - - infos['hostname'] = socket.gethostname() - - def _writeJson(suffix, properties): - d = infos.copy() - for k, v in properties.iteritems(): - assert not d.has_key(k) - d[k] = v - - jsonFileName = 'export-' + suffix + '.json' - with open(jsonFileName, 'w') as f: - print >> f, json.dumps(d) - return jsonFileName - - - def _genFileName(archivtype, middle): - idPrefix = infos['revision'] + '_' - idSuffix = '.tar.gz' - return join(_graal_home, "graalvm_" + archivtype + "_" + idPrefix + middle + idSuffix) - - def _genFileArchPlatformName(archivtype, middle): - return _genFileName(archivtype, infos['platform'] + '_' + infos['architecture'] + '_' + middle) - +_graalDeployedDist.postJdkInstall = lambda jdkDir, targetDir: _updateGraalPropertiesFile(join(jdkDir, 'jre', 'lib')) - # archive different build types of hotspot - for vmBuild in _vmbuildChoices: - jdkpath = join(_jdksDir(), vmBuild) - if not exists(jdkpath): - mx.logv("skipping " + vmBuild) - continue - - tarName = _genFileArchPlatformName('basejdk', vmBuild) - mx.logv("creating basejdk " + tarName) - vmSet = set() - with tarfile.open(tarName, 'w:gz') as tar: - for root, _, files in os.walk(jdkpath): - if basename(root) in _vmChoices.keys(): - # TODO: add some assert to check path assumption - vmSet.add(root) - continue - - for f in files: - name = join(root, f) - # print name - tar.add(name, name) - - n = _writeJson("basejdk-" + vmBuild, {'vmbuild' : vmBuild}) - tar.add(n, n) - - # create a separate archive for each VM - for vm in vmSet: - bVm = basename(vm) - vmTarName = _genFileArchPlatformName('vm', vmBuild + '_' + bVm) - mx.logv("creating vm " + vmTarName) - - debugFiles = set() - with tarfile.open(vmTarName, 'w:gz') as tar: - for root, _, files in os.walk(vm): - for f in files: - # TODO: mac, windows, solaris? - if any(map(f.endswith, [".debuginfo"])): - debugFiles.add(f) - else: - name = join(root, f) - # print name - tar.add(name, name) - - n = _writeJson("vm-" + vmBuild + "-" + bVm, {'vmbuild' : vmBuild, 'vm' : bVm}) - tar.add(n, n) - - if len(debugFiles) > 0: - debugTarName = _genFileArchPlatformName('debugfilesvm', vmBuild + '_' + bVm) - mx.logv("creating debugfilesvm " + debugTarName) - with tarfile.open(debugTarName, 'w:gz') as tar: - for f in debugFiles: - name = join(root, f) - # print name - tar.add(name, name) - - n = _writeJson("debugfilesvm-" + vmBuild + "-" + bVm, {'vmbuild' : vmBuild, 'vm' : bVm}) - tar.add(n, n) - - # graal directory - graalDirTarName = _genFileName('classfiles', 'javac') - mx.logv("creating graal " + graalDirTarName) - with tarfile.open(graalDirTarName, 'w:gz') as tar: - for root, _, files in os.walk("graal"): - for f in [f for f in files if not f.endswith('.java')]: - name = join(root, f) - # print name - tar.add(name, name) - - n = _writeJson("graal", {'javacompiler' : 'javac'}) - tar.add(n, n) - +mx_jvmci.jdkDeployedDists += [_graalDeployedDist, _graalTruffleDeployedDist] +mx_jvmci.jacocoIncludes += ['com.oracle.graal.*'] +mx_jvmci.jacocoExcludedAnnotations += ['@Snippet', '@ClassSubstitution'] def _run_benchmark(args, availableBenchmarks, runBenchmark): @@ -349,7 +77,7 @@ """run one or more DaCapo benchmarks""" def launcher(bm, harnessArgs, extraVmOpts): - return sanitycheck.getDacapo(bm, harnessArgs).test(_get_vm(), extraVmOpts=extraVmOpts) + return sanitycheck.getDacapo(bm, harnessArgs).test(get_vm(), extraVmOpts=extraVmOpts) _run_benchmark(args, sanitycheck.dacapoSanityWarmup.keys(), launcher) @@ -357,259 +85,16 @@ """run one or more Scala DaCapo benchmarks""" def launcher(bm, harnessArgs, extraVmOpts): - return sanitycheck.getScalaDacapo(bm, harnessArgs).test(_get_vm(), extraVmOpts=extraVmOpts) + return sanitycheck.getScalaDacapo(bm, harnessArgs).test(get_vm(), extraVmOpts=extraVmOpts) _run_benchmark(args, sanitycheck.dacapoScalaSanityWarmup.keys(), launcher) -def _vmLibDirInJdk(jdk): - """ - Get the directory within a JDK where the server and client - subdirectories are located. - """ - mxos = mx.get_os() - if mxos == 'darwin': - return join(jdk, 'jre', 'lib') - if mxos == 'windows' or mxos == 'cygwin': - return join(jdk, 'jre', 'bin') - return join(jdk, 'jre', 'lib', mx.get_arch()) - -def _vmJliLibDirs(jdk): - """ - Get the directories within a JDK where the jli library designates to. - """ - mxos = mx.get_os() - if mxos == 'darwin': - return [join(jdk, 'jre', 'lib', 'jli')] - if mxos == 'windows' or mxos == 'cygwin': - return [join(jdk, 'jre', 'bin'), join(jdk, 'bin')] - return [join(jdk, 'jre', 'lib', mx.get_arch(), 'jli'), join(jdk, 'lib', mx.get_arch(), 'jli')] - -def _vmCfgInJdk(jdk, jvmCfgFile='jvm.cfg'): - """ - Get the jvm.cfg file. - """ - mxos = mx.get_os() - if mxos == "windows" or mxos == "cygwin": - return join(jdk, 'jre', 'lib', mx.get_arch(), jvmCfgFile) - return join(_vmLibDirInJdk(jdk), jvmCfgFile) - -def _jdksDir(): - return os.path.abspath(join(_installed_jdks if _installed_jdks else _graal_home, 'jdk' + str(mx.java().version))) - -def _handle_missing_VM(bld, vm=None): - if not vm: - vm = _get_vm() - mx.log('The ' + bld + ' ' + vm + ' VM has not been created') - if mx.is_interactive(): - if mx.ask_yes_no('Build it now', 'y'): - with VM(vm, bld): - build([]) - return - mx.abort('You need to run "mx --vm ' + vm + ' --vmbuild ' + bld + ' build" to build the selected VM') - -def _jdk(build=None, vmToCheck=None, create=False, installJars=True): - """ - Get the JDK into which Graal is installed, creating it first if necessary. - """ - if not build: - build = _vmbuild - jdk = join(_jdksDir(), build) - if create: - srcJdk = mx.java().jdk - if not exists(jdk): - mx.log('Creating ' + jdk + ' from ' + srcJdk) - shutil.copytree(srcJdk, jdk) - - # Make a copy of the default VM so that this JDK can be - # reliably used as the bootstrap for a HotSpot build. - jvmCfg = _vmCfgInJdk(jdk) - if not exists(jvmCfg): - mx.abort(jvmCfg + ' does not exist') - - defaultVM = None - jvmCfgLines = [] - with open(jvmCfg) as f: - for line in f: - if line.startswith('-') and defaultVM is None: - parts = line.split() - if len(parts) == 2: - assert parts[1] == 'KNOWN', parts[1] - defaultVM = parts[0][1:] - jvmCfgLines += ['# default VM is a copy of the unmodified ' + defaultVM + ' VM\n'] - jvmCfgLines += ['-original KNOWN\n'] - else: - # skip lines which we cannot parse (e.g. '-hotspot ALIASED_TO -client') - mx.log("WARNING: skipping not parsable line \"" + line + "\"") - else: - jvmCfgLines += [line] - - assert defaultVM is not None, 'Could not find default VM in ' + jvmCfg - chmodRecursive(jdk, JDK_UNIX_PERMISSIONS_DIR) - shutil.move(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), 'original')) - - if mx.get_os() != 'windows': - os.chmod(jvmCfg, JDK_UNIX_PERMISSIONS_FILE) - with open(jvmCfg, 'w') as fp: - for line in jvmCfgLines: - fp.write(line) - - # patch 'release' file (append graalvm revision) - releaseFile = join(jdk, 'release') - if exists(releaseFile): - releaseFileLines = [] - with open(releaseFile) as f: - for line in f: - releaseFileLines.append(line) - - if mx.get_os() != 'windows': - os.chmod(releaseFile, JDK_UNIX_PERMISSIONS_FILE) - with open(releaseFile, 'w') as fp: - for line in releaseFileLines: - if line.startswith("SOURCE="): - try: - sourceLine = line[0:-2] # remove last char - hgcfg = mx.HgConfig() - hgcfg.check() - revision = hgcfg.tip('.')[:12] # take first 12 chars - fp.write(sourceLine + ' graal:' + revision + '\"\n') - except: - fp.write(line) - else: - fp.write(line) - - # Install a copy of the disassembler library - try: - hsdis([], copyToDir=_vmLibDirInJdk(jdk)) - except SystemExit: - pass - else: - if not exists(jdk): - if _installed_jdks: - mx.log("The selected JDK directory does not (yet) exist: " + jdk) - _handle_missing_VM(build, vmToCheck) - - if installJars: - for jdkDist in _jdkDeployedDists: - dist = mx.distribution(jdkDist.name) - if exists(dist.path) and jdkDist.partOfHotSpot: - _installDistInJdks(jdkDist) - - if vmToCheck is not None: - jvmCfg = _vmCfgInJdk(jdk) - found = False - with open(jvmCfg) as f: - for line in f: - if line.strip() == '-' + vmToCheck + ' KNOWN': - found = True - break - if not found: - _handle_missing_VM(build, vmToCheck) - - return jdk - -def _updateInstalledJVMCIOptionsFile(jdk): - jvmciOptions = join(_graal_home, 'jvmci.options') - jreLibDir = join(jdk, 'jre', 'lib') - if exists(jvmciOptions): - shutil.copy(jvmciOptions, join(jreLibDir, 'jvmci.options')) - else: - toDelete = join(jreLibDir, 'jvmci.options') - if exists(toDelete): - os.unlink(toDelete) - -def _makeHotspotGeneratedSourcesDir(): - """ - Gets the directory containing all the HotSpot sources generated from - JVMCI Java sources. This directory will be created if it doesn't yet exist. - """ - hsSrcGenDir = join(mx.project('jdk.internal.jvmci.hotspot').source_gen_dir(), 'hotspot') - if not exists(hsSrcGenDir): - os.makedirs(hsSrcGenDir) - return hsSrcGenDir - -def _copyToJdk(src, dst, permissions=JDK_UNIX_PERMISSIONS_FILE): - name = os.path.basename(src) - dstLib = join(dst, name) - if mx.get_env('SYMLINK_GRAAL_JAR', None) == 'true': - # Using symlinks is much faster than copying but may - # cause issues if the lib is being updated while - # the VM is running. - if not os.path.islink(dstLib) or not os.path.realpath(dstLib) == src: - if exists(dstLib): - os.remove(dstLib) - os.symlink(src, dstLib) - else: - # do a copy and then a move to get atomic updating (on Unix) - fd, tmp = tempfile.mkstemp(suffix='', prefix=name, dir=dst) - shutil.copyfile(src, tmp) - os.close(fd) - shutil.move(tmp, dstLib) - os.chmod(dstLib, permissions) - -def _extractJVMCIFiles(jdkJars, jvmciJars, servicesDir, optionsDir): - - oldServices = os.listdir(servicesDir) if exists(servicesDir) else os.makedirs(servicesDir) - oldOptions = os.listdir(optionsDir) if exists(optionsDir) else os.makedirs(optionsDir) - - jvmciServices = {} - optionsFiles = [] - for jar in jvmciJars: - if os.path.isfile(jar): - with zipfile.ZipFile(jar) as zf: - for member in zf.namelist(): - if member.startswith('META-INF/jvmci.services/') and member != 'META-INF/jvmci.services/': - service = basename(member) - assert service != "", member - with zf.open(member) as serviceFile: - providers = jvmciServices.setdefault(service, []) - for line in serviceFile.readlines(): - line = line.strip() - if line: - providers.append(line) - elif member.startswith('META-INF/jvmci.options/') and member != 'META-INF/jvmci.options/': - filename = basename(member) - assert filename != "", member - targetpath = join(optionsDir, filename) - optionsFiles.append(filename) - with zf.open(member) as optionsFile, \ - file(targetpath, "wb") as target: - shutil.copyfileobj(optionsFile, target) - if oldOptions and filename in oldOptions: - oldOptions.remove(filename) - for service, providers in jvmciServices.iteritems(): - fd, tmp = tempfile.mkstemp(prefix=service) - f = os.fdopen(fd, 'w+') - for provider in providers: - f.write(provider + os.linesep) - target = join(servicesDir, service) - f.close() - shutil.move(tmp, target) - if oldServices and service in oldServices: - oldServices.remove(service) - if mx.get_os() != 'windows': - os.chmod(target, JDK_UNIX_PERMISSIONS_FILE) - - if mx.is_interactive(): - for d, files in [(servicesDir, oldServices), (optionsDir, oldOptions)]: - if files and mx.ask_yes_no('These files in ' + d + ' look obsolete:\n ' + '\n '.join(files) + '\nDelete them', 'n'): - for f in files: - path = join(d, f) - os.remove(path) - mx.log('Deleted ' + path) - -def _updateJVMCIFiles(jdkDir): - jreJVMCIDir = join(jdkDir, 'jre', 'lib', 'jvmci') - jvmciJars = [join(jreJVMCIDir, e) for e in os.listdir(jreJVMCIDir) if e.endswith('.jar')] - jreJVMCIServicesDir = join(jreJVMCIDir, 'services') - jreJVMCIOptionsDir = join(jreJVMCIDir, 'options') - _extractJVMCIFiles(_getJdkDeployedJars(jdkDir), jvmciJars, jreJVMCIServicesDir, jreJVMCIOptionsDir) - def _updateGraalPropertiesFile(jreLibDir): """ Updates (or creates) 'jreLibDir'/jvmci/graal.properties to set/modify the graal.version property. """ - version = graal_version() + version = _suite.release_version() graalProperties = join(jreLibDir, 'jvmci', 'graal.properties') if not exists(graalProperties): with open(graalProperties, 'w') as fp: @@ -625,538 +110,6 @@ with open(graalProperties, 'w') as fp: fp.write(os.linesep.join(content)) -def _installDistInJdks(deployableDist): - """ - Installs the jar(s) for a given Distribution into all existing JVMCI JDKs - """ - dist = mx.distribution(deployableDist.name) - jdks = _jdksDir() - if exists(jdks): - for e in os.listdir(jdks): - jdkDir = join(jdks, e) - jreLibDir = join(jdkDir, 'jre', 'lib') - if exists(jreLibDir): - if deployableDist.isExtension: - targetDir = join(jreLibDir, 'ext') - elif deployableDist.usesJVMCIClassLoader: - targetDir = join(jreLibDir, 'jvmci') - else: - targetDir = jreLibDir - if not exists(targetDir): - os.makedirs(targetDir) - _copyToJdk(dist.path, targetDir) - if dist.sourcesPath: - _copyToJdk(dist.sourcesPath, jdkDir) - if deployableDist.usesJVMCIClassLoader: - # deploy service files - _updateJVMCIFiles(jdkDir) - if dist.name == 'GRAAL': - _updateGraalPropertiesFile(jreLibDir) - -def _getJdkDeployedJars(jdkDir): - """ - Gets jar paths for all deployed distributions in the context of - a given JDK directory. - """ - jreLibDir = join(jdkDir, 'jre', 'lib') - jars = [] - for dist in _jdkDeployedDists: - jar = basename(mx.distribution(dist.name).path) - if dist.isExtension: - jars.append(join(jreLibDir, 'ext', jar)) - elif dist.usesJVMCIClassLoader: - jars.append(join(jreLibDir, 'jvmci', jar)) - else: - jars.append(join(jreLibDir, jar)) - return jars - - -# run a command in the windows SDK Debug Shell -def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo=None): - if respondTo is None: - respondTo = {} - newLine = os.linesep - startToken = 'RUNINDEBUGSHELL_STARTSEQUENCE' - endToken = 'RUNINDEBUGSHELL_ENDSEQUENCE' - - winSDK = mx.get_env('WIN_SDK', 'C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\') - - if not exists(mx._cygpathW2U(winSDK)): - mx.abort("Could not find Windows SDK : '" + winSDK + "' does not exist") - - winSDKSetEnv = mx._cygpathW2U(join(winSDK, 'Bin', 'SetEnv.cmd')) - if not exists(winSDKSetEnv): - mx.abort("Invalid Windows SDK path (" + winSDK + ") : could not find Bin/SetEnv.cmd (you can use the WIN_SDK environment variable to specify an other path)") - - wincmd = 'cmd.exe /E:ON /V:ON /K "' + mx._cygpathU2W(winSDKSetEnv) + '"' - p = subprocess.Popen(wincmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - stdout = p.stdout - stdin = p.stdin - if logFile: - log = open(logFile, 'w') - ret = False - - def _writeProcess(s): - stdin.write(s + newLine) - - _writeProcess("echo " + startToken) - while True: - # encoding may be None on windows plattforms - if sys.stdout.encoding is None: - encoding = 'utf-8' - else: - encoding = sys.stdout.encoding - - line = stdout.readline().decode(encoding) - if logFile: - log.write(line.encode('utf-8')) - line = line.strip() - mx.log(line) - if line == startToken: - _writeProcess('cd /D ' + workingDir + ' & ' + cmd + ' & echo ' + endToken) - for regex in respondTo.keys(): - match = regex.search(line) - if match: - _writeProcess(respondTo[regex]) - if findInOutput: - match = findInOutput.search(line) - if match: - ret = True - if line == endToken: - if not findInOutput: - _writeProcess('echo ERRXXX%errorlevel%') - else: - break - if line.startswith('ERRXXX'): - if line == 'ERRXXX0': - ret = True - break - _writeProcess("exit") - if logFile: - log.close() - return ret - -def jdkhome(vm=None): - """return the JDK directory selected for the 'vm' command""" - return _jdk(installJars=False) - -def print_jdkhome(args, vm=None): - """print the JDK directory selected for the 'vm' command""" - print jdkhome(vm) - -def buildvars(args): - """describe the variables that can be set by the -D option to the 'mx build' commmand""" - - buildVars = { - 'ALT_BOOTDIR' : 'The location of the bootstrap JDK installation (default: ' + mx.java().jdk + ')', - 'ALT_OUTPUTDIR' : 'Build directory', - 'HOTSPOT_BUILD_JOBS' : 'Number of CPUs used by make (default: ' + str(mx.cpu_count()) + ')', - 'INSTALL' : 'Install the built VM into the JDK? (default: y)', - 'ZIP_DEBUGINFO_FILES' : 'Install zipped debug symbols file? (default: 0)', - } - - mx.log('HotSpot build variables that can be set by the -D option to "mx build":') - mx.log('') - for n in sorted(buildVars.iterkeys()): - mx.log(n) - mx.log(textwrap.fill(buildVars[n], initial_indent=' ', subsequent_indent=' ', width=200)) - - mx.log('') - mx.log('Note that these variables can be given persistent values in the file ' + join(_suite.mxDir, 'env') + ' (see \'mx about\').') - -cached_graal_version = None - -def graal_version(dev_suffix='dev'): - global cached_graal_version - - if not cached_graal_version: - # extract latest release tag for graal - try: - tags = [x.split() for x in subprocess.check_output(['hg', '-R', _graal_home, 'tags']).split('\n') if x.startswith("graal-")] - current_id = subprocess.check_output(['hg', '-R', _graal_home, 'log', '--template', '{rev}\n', '--rev', 'tip']).strip() - except: - # not a mercurial repository or hg commands are not available. - tags = None - - if tags and current_id: - sorted_tags = sorted(tags, key=lambda e: [int(x) for x in e[0][len("graal-"):].split('.')], reverse=True) - most_recent_tag_name, most_recent_tag_revision = sorted_tags[0] - most_recent_tag_id = most_recent_tag_revision[:most_recent_tag_revision.index(":")] - most_recent_tag_version = most_recent_tag_name[len("graal-"):] - - # tagged commit is one-off with commit that tags it - if int(current_id) - int(most_recent_tag_id) <= 1: - cached_graal_version = most_recent_tag_version - else: - major, minor = map(int, most_recent_tag_version.split('.')) - cached_graal_version = str(major) + '.' + str(minor + 1) + '-' + dev_suffix - else: - cached_graal_version = 'unknown-{0}-{1}'.format(platform.node(), time.strftime('%Y-%m-%d_%H-%M-%S_%Z')) - - return cached_graal_version - -def build(args, vm=None): - """build the VM binary - - The global '--vm' and '--vmbuild' options select which VM type and build target to build.""" - - # Override to fail quickly if extra arguments are given - # at the end of the command line. This allows for a more - # helpful error message. - class AP(ArgumentParser): - def __init__(self): - ArgumentParser.__init__(self, prog='mx build') - def parse_args(self, args): - result = ArgumentParser.parse_args(self, args) - if len(result.remainder) != 0: - firstBuildTarget = result.remainder[0] - mx.abort('To specify the ' + firstBuildTarget + ' VM build target, you need to use the global "--vmbuild" option. For example:\n' + - ' mx --vmbuild ' + firstBuildTarget + ' build') - return result - - # Call mx.build to compile the Java sources - parser = AP() - parser.add_argument('-D', action='append', help='set a HotSpot build variable (run \'mx buildvars\' to list variables)', metavar='name=value') - - opts2 = mx.build(['--source', '1.7'] + args, parser=parser) - assert len(opts2.remainder) == 0 - - if not opts2.native: - return - - builds = [_vmbuild] - - if os.environ.get('BUILDING_FROM_IDE', None) == 'true': - build = os.environ.get('IDE_BUILD_TARGET', None) - if build is None or len(build) == 0: - return - if build not in _vmbuildChoices: - mx.abort('VM build "' + build + '" specified by IDE_BUILD_TARGET environment variable is unknown (must be one of ' + - str(_vmbuildChoices) + ')') - builds = [build] - - if vm is None: - vm = _get_vm() - - if vm == 'original': - pass - elif vm.startswith('server'): - buildSuffix = '' - elif vm.startswith('client'): - buildSuffix = '1' - else: - assert vm == 'jvmci', vm - buildSuffix = 'jvmci' - - if _installed_jdks and _installed_jdks != _graal_home: - if not mx.ask_yes_no("Warning: building while --installed-jdks is set (" + _installed_jdks + ") is not recommanded - are you sure you want to continue", 'n'): - mx.abort(1) - - isWindows = platform.system() == 'Windows' or "CYGWIN" in platform.system() - for build in builds: - installJars = vm != 'original' and (isWindows or not opts2.java) - jdk = _jdk(build, create=True, installJars=installJars) - - if vm == 'original': - if build != 'product': - mx.log('only product build of original VM exists') - continue - - if not isVMSupported(vm): - mx.log('The ' + vm + ' VM is not supported on this platform - skipping') - continue - - vmDir = join(_vmLibDirInJdk(jdk), vm) - if not exists(vmDir): - chmodRecursive(jdk, JDK_UNIX_PERMISSIONS_DIR) - mx.log('Creating VM directory in JDK: ' + vmDir) - os.makedirs(vmDir) - - def filterXusage(line): - if not 'Xusage.txt' in line: - sys.stderr.write(line + os.linesep) - - # Check if a build really needs to be done - timestampFile = join(vmDir, '.build-timestamp') - if opts2.force or not exists(timestampFile): - mustBuild = True - else: - mustBuild = False - timestamp = os.path.getmtime(timestampFile) - sources = [] - for d in ['src', 'make', join('jvmci', 'jdk.internal.jvmci.hotspot', 'src_gen', 'hotspot')]: - for root, dirnames, files in os.walk(join(_graal_home, d)): - # ignore /src/share/tools - if root == join(_graal_home, 'src', 'share'): - dirnames.remove('tools') - sources += [join(root, name) for name in files] - for f in sources: - if len(f) != 0 and os.path.getmtime(f) > timestamp: - mustBuild = True - break - - if not mustBuild: - mx.logv('[all files in src and make directories are older than ' + timestampFile[len(_graal_home) + 1:] + ' - skipping native build]') - continue - - if isWindows: - t_compilelogfile = mx._cygpathU2W(os.path.join(_graal_home, "graalCompile.log")) - mksHome = mx.get_env('MKS_HOME', 'C:\\cygwin\\bin') - - variant = {'client': 'compiler1', 'server': 'compiler2'}.get(vm, vm) - project_config = variant + '_' + build - t_graal_home = mx._cygpathU2W(_graal_home) - _runInDebugShell('msbuild ' + t_graal_home + r'\build\vs-amd64\jvm.vcproj /p:Configuration=' + project_config + ' /target:clean', t_graal_home) - winCompileCmd = r'set HotSpotMksHome=' + mksHome + r'& set OUT_DIR=' + mx._cygpathU2W(jdk) + r'& set JAVA_HOME=' + mx._cygpathU2W(jdk) + r'& set path=%JAVA_HOME%\bin;%path%;%HotSpotMksHome%& cd /D "' + t_graal_home + r'\make\windows"& call create.bat ' + t_graal_home - print winCompileCmd - winCompileSuccess = re.compile(r"^Writing \.vcxproj file:") - if not _runInDebugShell(winCompileCmd, t_graal_home, t_compilelogfile, winCompileSuccess): - mx.log('Error executing create command') - return - winBuildCmd = 'msbuild ' + t_graal_home + r'\build\vs-amd64\jvm.vcxproj /p:Configuration=' + project_config + ' /p:Platform=x64' - if not _runInDebugShell(winBuildCmd, t_graal_home, t_compilelogfile): - mx.log('Error building project') - return - else: - cpus = mx.cpu_count() - makeDir = join(_graal_home, 'make') - runCmd = [mx.gmake_cmd(), '-C', makeDir] - - env = os.environ.copy() - - # These must be passed as environment variables - env.setdefault('LANG', 'C') - env['JAVA_HOME'] = jdk - - def setMakeVar(name, default, env=None): - """Sets a make variable on the command line to the value - of the variable in 'env' with the same name if defined - and 'env' is not None otherwise to 'default' - """ - runCmd.append(name + '=' + (env.get(name, default) if env else default)) - - if opts2.D: - for nv in opts2.D: - name, value = nv.split('=', 1) - setMakeVar(name.strip(), value) - - setMakeVar('ARCH_DATA_MODEL', '64', env=env) - setMakeVar('HOTSPOT_BUILD_JOBS', str(cpus), env=env) - setMakeVar('ALT_BOOTDIR', mx.java().jdk, env=env) - setMakeVar("EXPORT_PATH", jdk) - - setMakeVar('MAKE_VERBOSE', 'y' if mx._opts.verbose else '') - if vm.endswith('nojvmci'): - setMakeVar('INCLUDE_JVMCI', 'false') - setMakeVar('ALT_OUTPUTDIR', join(_graal_home, 'build-nojvmci', mx.get_os()), env=env) - else: - version = graal_version() - setMakeVar('USER_RELEASE_SUFFIX', 'jvmci-' + version) - setMakeVar('INCLUDE_JVMCI', 'true') - setMakeVar('INSTALL', 'y', env=env) - if mx.get_os() == 'darwin' and platform.mac_ver()[0] != '': - # Force use of clang on MacOS - setMakeVar('USE_CLANG', 'true') - if mx.get_os() == 'solaris': - # If using sparcWorks, setup flags to avoid make complaining about CC version - cCompilerVersion = subprocess.Popen('CC -V', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).stderr.readlines()[0] - if cCompilerVersion.startswith('CC: Sun C++'): - compilerRev = cCompilerVersion.split(' ')[3] - setMakeVar('ENFORCE_COMPILER_REV', compilerRev, env=env) - setMakeVar('ENFORCE_CC_COMPILER_REV', compilerRev, env=env) - if build == 'jvmg': - # We want ALL the symbols when debugging on Solaris - setMakeVar('STRIP_POLICY', 'no_strip') - # This removes the need to unzip the *.diz files before debugging in gdb - setMakeVar('ZIP_DEBUGINFO_FILES', '0', env=env) - - if buildSuffix == "1": - setMakeVar("BUILD_CLIENT_ONLY", "true") - - # Clear this variable as having it set can cause very confusing build problems - env.pop('CLASSPATH', None) - - # Issue an env prefix that can be used to run the make on the command line - if not mx._opts.verbose: - mx.log('--------------- make command line ----------------------') - - envPrefix = ' '.join([key + '=' + env[key] for key in env.iterkeys() if not os.environ.has_key(key) or env[key] != os.environ[key]]) - if len(envPrefix): - mx.log('env ' + envPrefix + ' \\') - - runCmd.append(build + buildSuffix) - runCmd.append("docs") - runCmd.append("export_" + build) - - if not mx._opts.verbose: - mx.log(' '.join(runCmd)) - mx.log('--------------------------------------------------------') - mx.run(runCmd, err=filterXusage, env=env) - - jvmCfg = _vmCfgInJdk(jdk) - if not exists(jvmCfg): - mx.abort(jvmCfg + ' does not exist') - - prefix = '-' + vm + ' ' - vmKnown = prefix + 'KNOWN\n' - lines = [] - found = False - with open(jvmCfg) as f: - for line in f: - if line.strip() == vmKnown.strip(): - found = True - lines.append(line) - - if not found: - mx.log('Prepending "' + prefix + 'KNOWN" to ' + jvmCfg) - if mx.get_os() != 'windows': - os.chmod(jvmCfg, JDK_UNIX_PERMISSIONS_FILE) - with open(jvmCfg, 'w') as f: - written = False - for line in lines: - if line.startswith('#'): - f.write(line) - continue - if not written: - f.write(vmKnown) - if vm == 'jvmci': - # Legacy support - f.write('-graal ALIASED_TO -jvmci\n') - written = True - if line.startswith(prefix): - line = vmKnown - if written: - continue - f.write(line) - - for jdkDist in _jdkDeployedDists: # Install non HotSpot distribution - if not jdkDist.partOfHotSpot: - _installDistInJdks(jdkDist) - if exists(timestampFile): - os.utime(timestampFile, None) - else: - file(timestampFile, 'a') - -def vmg(args): - """run the debug build of VM selected by the '--vm' option""" - return vm(args, vmbuild='debug') - -def vmfg(args): - """run the fastdebug build of VM selected by the '--vm' option""" - return vm(args, vmbuild='fastdebug') - -def _parseVmArgs(args, vm=None, cwd=None, vmbuild=None): - """run the VM selected by the '--vm' option""" - - if vm is None: - vm = _get_vm() - - if not isVMSupported(vm): - mx.abort('The ' + vm + ' is not supported on this platform') - - if cwd is None: - cwd = _vm_cwd - elif _vm_cwd is not None and _vm_cwd != cwd: - mx.abort("conflicting working directories: do not set --vmcwd for this command") - - build = vmbuild if vmbuild else _vmbuild - jdk = _jdk(build, vmToCheck=vm, installJars=False) - _updateInstalledJVMCIOptionsFile(jdk) - mx.expand_project_in_args(args) - if _make_eclipse_launch: - mx.make_eclipse_launch(_suite, args, 'graal-' + build, name=None, deps=mx.project('com.oracle.graal.hotspot').all_deps([], True)) - if _jacoco == 'on' or _jacoco == 'append': - jacocoagent = mx.library("JACOCOAGENT", True) - # Exclude all compiler tests and snippets - - includes = ['com.oracle.graal.*', 'jdk.internal.jvmci.*'] - baseExcludes = [] - for p in mx.projects(): - projsetting = getattr(p, 'jacoco', '') - if projsetting == 'exclude': - baseExcludes.append(p.name) - if projsetting == 'include': - includes.append(p.name + '.*') - - def _filter(l): - # filter out specific classes which are already covered by a baseExclude package - return [clazz for clazz in l if not any([clazz.startswith(package) for package in baseExcludes])] - excludes = [] - for p in mx.projects(): - excludes += _filter(_find_classes_with_annotations(p, None, ['@Snippet', '@ClassSubstitution', '@Test'], includeInnerClasses=True).keys()) - excludes += _filter(p.find_classes_with_matching_source_line(None, lambda line: 'JaCoCo Exclude' in line, includeInnerClasses=True).keys()) - - excludes += [package + '.*' for package in baseExcludes] - agentOptions = { - 'append' : 'true' if _jacoco == 'append' else 'false', - 'bootclasspath' : 'true', - 'includes' : ':'.join(includes), - 'excludes' : ':'.join(excludes), - 'destfile' : 'jacoco.exec' - } - args = ['-javaagent:' + jacocoagent.get_path(True) + '=' + ','.join([k + '=' + v for k, v in agentOptions.items()])] + args - exe = join(jdk, 'bin', mx.exe_suffix('java')) - pfx = _vm_prefix.split() if _vm_prefix is not None else [] - - if '-version' in args: - ignoredArgs = args[args.index('-version') + 1:] - if len(ignoredArgs) > 0: - mx.log("Warning: The following options will be ignored by the vm because they come after the '-version' argument: " + ' '.join(ignoredArgs)) - - # Unconditionally prepend truffle.jar to the boot class path. - # This used to be done by the VM itself but was removed to - # separate the VM from Truffle. - truffle_jar = mx.library('TRUFFLE').path - args = ['-Xbootclasspath/p:' + truffle_jar] + args - - args = mx.java().processArgs(args) - return (pfx, exe, vm, args, cwd) - -def vm(args, vm=None, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, vmbuild=None): - (pfx_, exe_, vm_, args_, cwd) = _parseVmArgs(args, vm, cwd, vmbuild) - return mx.run(pfx_ + [exe_, '-' + vm_] + args_, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout) - -def _find_classes_with_annotations(p, pkgRoot, annotations, includeInnerClasses=False): - """ - Scan the sources of project 'p' for Java source files containing a line starting with 'annotation' - (ignoring preceding whitespace) and return the fully qualified class name for each Java - source file matched in a list. - """ - - matches = lambda line: len([a for a in annotations if line == a or line.startswith(a + '(')]) != 0 - return p.find_classes_with_matching_source_line(pkgRoot, matches, includeInnerClasses) - -def _find_classpath_arg(vmArgs): - for index in range(len(vmArgs)): - if vmArgs[index] in ['-cp', '-classpath']: - return index + 1, vmArgs[index + 1] - -def unittest(args): - def vmLauncher(vmArgs, mainClass, mainClassArgs): - if isJVMCIEnabled(_get_vm()): - # Remove entries from class path that are in JVMCI loaded jars - cpIndex, cp = _find_classpath_arg(vmArgs) - if cp: - excluded = set() - for jdkDist in _jdkDeployedDists: - dist = mx.distribution(jdkDist.name) - excluded.update([d.output_dir() for d in dist.sorted_deps()]) - cp = os.pathsep.join([e for e in cp.split(os.pathsep) if e not in excluded]) - vmArgs[cpIndex] = cp - - # Run the VM in a mode where application/test classes can - # access JVMCI loaded classes. - vmArgs = ['-XX:-UseJVMCIClassLoader'] + vmArgs - - vm(vmArgs + [mainClass] + mainClassArgs) - mx_unittest.unittest(args, vmLauncher=vmLauncher) - -def shortunittest(args): - """alias for 'unittest --whitelist test/whitelist_shortunittest.txt'""" - - args = ['--whitelist', 'test/whitelist_shortunittest.txt'] + args - unittest(args) - def microbench(args): """run JMH microbenchmark projects""" vmArgs, jmhArgs = mx.extract_VM_args(args, useDoubleDash=True) @@ -1193,138 +146,11 @@ args += vmArgs args += ['org.openjdk.jmh.Main'] if forking: - (_, _, jvm, _, _) = _parseVmArgs(vmArgs) + (_, _, jvm, _, _) = parseVmArgs(vmArgs) args += ['--jvmArgsPrepend', ' '.join(['-' + jvm] + vmArgs)] vm(args + jmhArgs) -def buildvms(args): - """build one or more VMs in various configurations""" - - vmsDefault = ','.join(_vmChoices.keys()) - vmbuildsDefault = ','.join(_vmbuildChoices) - - parser = ArgumentParser(prog='mx buildvms') - parser.add_argument('--vms', help='a comma separated list of VMs to build (default: ' + vmsDefault + ')', metavar='', default=vmsDefault) - parser.add_argument('--builds', help='a comma separated list of build types (default: ' + vmbuildsDefault + ')', metavar='', default=vmbuildsDefault) - parser.add_argument('--check-distributions', action='store_true', dest='check_distributions', help='check built distributions for overlap') - parser.add_argument('-n', '--no-check', action='store_true', help='omit running "java -version" after each build') - parser.add_argument('-c', '--console', action='store_true', help='send build output to console instead of log file') - - args = parser.parse_args(args) - vms = args.vms.split(',') - builds = args.builds.split(',') - - allStart = time.time() - check_dists_args = ['--check-distributions'] if args.check_distributions else [] - for v in vms: - if not isVMSupported(v): - mx.log('The ' + v + ' VM is not supported on this platform - skipping') - continue - - for vmbuild in builds: - if v == 'original' and vmbuild != 'product': - continue - if not args.console: - logFile = join(v + '-' + vmbuild + '.log') - log = open(join(_graal_home, logFile), 'wb') - start = time.time() - mx.log('BEGIN: ' + v + '-' + vmbuild + '\t(see: ' + logFile + ')') - verbose = ['-v'] if mx._opts.verbose else [] - # Run as subprocess so that output can be directed to a file - cmd = [sys.executable, '-u', join('mxtool', 'mx.py')] + verbose + ['--vm', v, '--vmbuild', vmbuild, 'build'] + check_dists_args - mx.logv("executing command: " + str(cmd)) - subprocess.check_call(cmd, cwd=_graal_home, stdout=log, stderr=subprocess.STDOUT) - duration = datetime.timedelta(seconds=time.time() - start) - mx.log('END: ' + v + '-' + vmbuild + '\t[' + str(duration) + ']') - else: - with VM(v, vmbuild): - build(check_dists_args) - if not args.no_check: - vmargs = ['-version'] - if v == 'jvmci': - vmargs.insert(0, '-XX:-BootstrapJVMCI') - vm(vmargs, vm=v, vmbuild=vmbuild) - allDuration = datetime.timedelta(seconds=time.time() - allStart) - mx.log('TOTAL TIME: ' + '[' + str(allDuration) + ']') - -class Task: - # None or a list of strings. If not None, only tasks whose title - # matches at least one of the substrings in this list will return - # a non-None value from __enter__. The body of a 'with Task(...) as t' - # statement should check 't' and exit immediately if it is None. - filters = None - filtersExclude = False - - def __init__(self, title, tasks=None): - self.tasks = tasks - self.title = title - if tasks is not None and Task.filters is not None: - if Task.filtersExclude: - self.skipped = any([f in title for f in Task.filters]) - else: - self.skipped = not any([f in title for f in Task.filters]) - else: - self.skipped = False - if not self.skipped: - self.start = time.time() - self.end = None - self.duration = None - mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: BEGIN: ') + title) - def __enter__(self): - assert self.tasks is not None, "using Task with 'with' statement requires to pass the tasks list in the constructor" - if self.skipped: - return None - return self - def __exit__(self, exc_type, exc_value, traceback): - if not self.skipped: - self.tasks.append(self.stop()) - def stop(self): - self.end = time.time() - self.duration = datetime.timedelta(seconds=self.end - self.start) - mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: END: ') + self.title + ' [' + str(self.duration) + ']') - return self - def abort(self, codeOrMessage): - self.end = time.time() - self.duration = datetime.timedelta(seconds=self.end - self.start) - mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: ABORT: ') + self.title + ' [' + str(self.duration) + ']') - mx.abort(codeOrMessage) - return self - -def ctw(args): - """run CompileTheWorld""" - - defaultCtwopts = '-Inline' - - parser = ArgumentParser(prog='mx ctw') - parser.add_argument('--ctwopts', action='store', help='space separated JVMCI options used for CTW compilations (default: --ctwopts="' + defaultCtwopts + '")', default=defaultCtwopts, metavar='') - parser.add_argument('--jar', action='store', help='jar of classes to compiled instead of rt.jar', metavar='') - - args, vmargs = parser.parse_known_args(args) - - if args.ctwopts: - vmargs.append('-G:CompileTheWorldConfig=' + args.ctwopts) - - if args.jar: - jar = os.path.abspath(args.jar) - else: - jar = join(_jdk(installJars=False), 'jre', 'lib', 'rt.jar') - vmargs.append('-G:CompileTheWorldExcludeMethodFilter=sun.awt.X11.*.*') - - vmargs += ['-XX:+CompileTheWorld'] - vm_ = _get_vm() - if isJVMCIEnabled(vm_): - if vm_ == 'jvmci': - vmargs += ['-XX:+BootstrapJVMCI'] - vmargs += ['-G:CompileTheWorldClasspath=' + jar] - else: - vmargs += ['-Xbootclasspath/p:' + jar] - - # suppress menubar and dock when running on Mac; exclude x11 classes as they may cause vm crashes (on Solaris) - vmargs = ['-Djava.awt.headless=true'] + vmargs - - vm(vmargs) - -def _basic_gate_body(args, tasks): +def _graal_gate_runner(args, tasks): # Build server-hosted-jvmci now so we can run the unit tests with Task('BuildHotSpotJVMCIHosted: product', tasks) as t: if t: buildvms(['--vms', 'server', '--builds', 'product', '--check-distributions']) @@ -1407,25 +233,8 @@ with Task('XCompMode:product', tasks) as t: if t: vm(['-Xcomp', '-version']) - if args.jacocout is not None: - jacocoreport([args.jacocout]) - - global _jacoco - _jacoco = 'off' - - with Task('CleanAndBuildIdealGraphVisualizer', tasks) as t: - if t and platform.processor() != 'sparc': - buildxml = mx._cygpathU2W(join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml')) - mx.run(['ant', '-f', buildxml, '-q', 'clean', 'build'], env=_igvBuildEnv()) - # Prevent JVMCI modifications from breaking the standard builds if args.buildNonJVMCI: - with Task('BuildHotSpotVarieties', tasks) as t: - if t: - buildvms(['--vms', 'client,server', '--builds', 'fastdebug,product']) - if mx.get_os() not in ['windows', 'cygwin']: - buildvms(['--vms', 'server-nojvmci', '--builds', 'product,optimized']) - for vmbuild in ['product', 'fastdebug']: for theVm in ['client', 'server']: if not isVMSupported(theVm): @@ -1438,126 +247,6 @@ with Task('UnitTests:' + theVm + ':' + vmbuild, tasks) as t: if t: unittest(['-XX:CompileCommand=exclude,*::run*', 'graal.api', 'java.test']) - -def gate(args, gate_body=_basic_gate_body): - """run the tests used to validate a push - - If this command exits with a 0 exit code, then the source code is in - a state that would be accepted for integration into the main repository.""" - - parser = ArgumentParser(prog='mx gate') - parser.add_argument('-j', '--omit-java-clean', action='store_false', dest='cleanJava', help='omit cleaning Java native code') - parser.add_argument('-n', '--omit-native-clean', action='store_false', dest='cleanNative', help='omit cleaning and building native code') - parser.add_argument('-i', '--omit-ide-clean', action='store_false', dest='cleanIde', help='omit cleaning the ide project files') - parser.add_argument('-g', '--only-build-jvmci', action='store_false', dest='buildNonJVMCI', help='only build the JVMCI VM') - parser.add_argument('-t', '--task-filter', help='comma separated list of substrings to select subset of tasks to be run') - parser.add_argument('-x', action='store_true', help='makes --task-filter an exclusion instead of inclusion filter') - parser.add_argument('--jacocout', help='specify the output directory for jacoco report') - - args = parser.parse_args(args) - - global _jacoco - if args.task_filter: - Task.filters = args.task_filter.split(',') - Task.filtersExclude = args.x - elif args.x: - mx.abort('-x option cannot be used without --task-filter option') - - # Force - if not mx._opts.strict_compliance: - mx.log("[gate] forcing strict compliance") - mx._opts.strict_compliance = True - - tasks = [] - total = Task('Gate') - try: - with Task('Check jvmci.make in sync with suite.py', tasks) as t: - if t: - jvmciMake = join('make', 'jvmci.make') - if mx_graal_makefile.build_makefile(['-o', jvmciMake]) != 0: - t.abort('Rerun "mx makefile -o ' + jvmciMake + ' and check-in the modified ' + jvmciMake) - - with Task('Pylint', tasks) as t: - if t: mx.pylint([]) - - def _clean(name='Clean'): - with Task(name, tasks) as t: - if t: - cleanArgs = [] - if not args.cleanNative: - cleanArgs.append('--no-native') - if not args.cleanJava: - cleanArgs.append('--no-java') - clean(cleanArgs) - _clean() - - with Task('IDEConfigCheck', tasks) as t: - if t: - if args.cleanIde: - mx.ideclean([]) - mx.ideinit([]) - - eclipse_exe = mx.get_env('ECLIPSE_EXE') - if eclipse_exe is not None: - with Task('CodeFormatCheck', tasks) as t: - if t and mx.eclipseformat(['-e', eclipse_exe]) != 0: - t.abort('Formatter modified files - run "mx eclipseformat", check in changes and repush') - - with Task('Canonicalization Check', tasks) as t: - if t: - mx.log(time.strftime('%d %b %Y %H:%M:%S - Ensuring mx/projects files are canonicalized...')) - if mx.canonicalizeprojects([]) != 0: - t.abort('Rerun "mx canonicalizeprojects" and check-in the modified mx/suite*.py files.') - - if mx.get_env('JDT'): - with Task('BuildJavaWithEcj', tasks): - if t: build(['-p', '--no-native', '--jdt-warning-as-error']) - _clean('CleanAfterEcjBuild') - - with Task('BuildJavaWithJavac', tasks): - if t: build(['-p', '--no-native', '--force-javac']) - - with Task('Checkstyle', tasks) as t: - if t and mx.checkstyle([]) != 0: - t.abort('Checkstyle warnings were found') - - with Task('Checkheaders', tasks) as t: - if t and checkheaders([]) != 0: - t.abort('Checkheaders warnings were found') - - with Task('FindBugs', tasks) as t: - if t and mx_findbugs.findbugs([]) != 0: - t.abort('FindBugs warnings were found') - - if exists('jacoco.exec'): - os.unlink('jacoco.exec') - - if args.jacocout is not None: - _jacoco = 'append' - else: - _jacoco = 'off' - - gate_body(args, tasks) - - except KeyboardInterrupt: - total.abort(1) - - except BaseException as e: - import traceback - traceback.print_exc() - total.abort(str(e)) - - total.stop() - - mx.log('Gate task times:') - for t in tasks: - mx.log(' ' + str(t.duration) + '\t' + t.title) - mx.log(' =======') - mx.log(' ' + str(total.duration)) - - if args.task_filter: - Task.filters = None - def deoptalot(args): """bootstrap a VM with DeoptimizeALot and VerifyOops on @@ -1578,90 +267,6 @@ dacapo(['100', 'eclipse', '-esa']) -def _igvJdk(): - v8u20 = mx.VersionSpec("1.8.0_20") - v8u40 = mx.VersionSpec("1.8.0_40") - v8 = mx.VersionSpec("1.8") - def _igvJdkVersionCheck(version): - return version >= v8 and (version < v8u20 or version >= v8u40) - return mx.java(_igvJdkVersionCheck, versionDescription='>= 1.8 and < 1.8.0u20 or >= 1.8.0u40', purpose="building & running IGV").jdk - -def _igvBuildEnv(): - # When the http_proxy environment variable is set, convert it to the proxy settings that ant needs - env = dict(os.environ) - proxy = os.environ.get('http_proxy') - if not (proxy is None) and len(proxy) > 0: - if '://' in proxy: - # Remove the http:// prefix (or any other protocol prefix) - proxy = proxy.split('://', 1)[1] - # Separate proxy server name and port number - proxyName, proxyPort = proxy.split(':', 1) - proxyEnv = '-DproxyHost="' + proxyName + '" -DproxyPort=' + proxyPort - env['ANT_OPTS'] = proxyEnv - - env['JAVA_HOME'] = _igvJdk() - return env - -def igv(args): - """run the Ideal Graph Visualizer""" - logFile = '.ideal_graph_visualizer.log' - with open(join(_graal_home, logFile), 'w') as fp: - mx.logv('[Ideal Graph Visualizer log is in ' + fp.name + ']') - nbplatform = join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'nbplatform') - - # Remove NetBeans platform if it is earlier than the current supported version - if exists(nbplatform): - updateTrackingFile = join(nbplatform, 'platform', 'update_tracking', 'org-netbeans-core.xml') - if not exists(updateTrackingFile): - mx.log('Could not find \'' + updateTrackingFile + '\', removing NetBeans platform') - shutil.rmtree(nbplatform) - else: - dom = xml.dom.minidom.parse(updateTrackingFile) - currentVersion = mx.VersionSpec(dom.getElementsByTagName('module_version')[0].getAttribute('specification_version')) - supportedVersion = mx.VersionSpec('3.43.1') - if currentVersion < supportedVersion: - mx.log('Replacing NetBeans platform version ' + str(currentVersion) + ' with version ' + str(supportedVersion)) - shutil.rmtree(nbplatform) - elif supportedVersion < currentVersion: - mx.log('Supported NetBeans version in igv command should be updated to ' + str(currentVersion)) - - if not exists(nbplatform): - mx.logv('[This execution may take a while as the NetBeans platform needs to be downloaded]') - - env = _igvBuildEnv() - # make the jar for Batik 1.7 available. - env['IGV_BATIK_JAR'] = mx.library('BATIK').get_path(True) - if mx.run(['ant', '-f', mx._cygpathU2W(join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml')), '-l', mx._cygpathU2W(fp.name), 'run'], env=env, nonZeroIsFatal=False): - mx.abort("IGV ant build & launch failed. Check '" + logFile + "'. You can also try to delete 'src/share/tools/IdealGraphVisualizer/nbplatform'.") - -def c1visualizer(args): - """run the Cl Compiler Visualizer""" - libpath = join(_graal_home, 'lib') - if mx.get_os() == 'windows': - executable = join(libpath, 'c1visualizer', 'bin', 'c1visualizer.exe') - else: - executable = join(libpath, 'c1visualizer', 'bin', 'c1visualizer') - - # Check whether the current C1Visualizer installation is the up-to-date - if exists(executable) and not exists(mx.library('C1VISUALIZER_DIST').get_path(resolve=False)): - mx.log('Updating C1Visualizer') - shutil.rmtree(join(libpath, 'c1visualizer')) - - archive = mx.library('C1VISUALIZER_DIST').get_path(resolve=True) - - if not exists(executable): - zf = zipfile.ZipFile(archive, 'r') - zf.extractall(libpath) - - if not exists(executable): - mx.abort('C1Visualizer binary does not exist: ' + executable) - - if mx.get_os() != 'windows': - # Make sure that execution is allowed. The zip file does not always specfiy that correctly - os.chmod(executable, 0777) - - mx.run([executable]) - def bench(args): """run benchmarks and parse their output for results @@ -1675,7 +280,7 @@ del args[index] else: mx.abort('-resultfile must be followed by a file name') - vm = _get_vm() + vm = get_vm() if len(args) is 0: args = ['all'] @@ -1741,224 +346,11 @@ with open(resultFile, 'w') as f: f.write(json.dumps(results)) -def _get_jmh_path(): - path = mx.get_env('JMH_BENCHMARKS', None) - if not path: - probe = join(dirname(_graal_home), 'java-benchmarks') - if exists(probe): - path = probe - - if not path: - mx.abort("Please set the JMH_BENCHMARKS environment variable to point to the java-benchmarks workspace") - if not exists(path): - mx.abort("The directory denoted by the JMH_BENCHMARKS environment variable does not exist: " + path) - return path - -def makejmhdeps(args): - """creates and installs Maven dependencies required by the JMH benchmarks - - The dependencies are specified by files named pom.mxdeps in the - JMH directory tree. Each such file contains a list of dependencies - defined in JSON format. For example: - - '[{"artifactId" : "compiler.test", "groupId" : "com.oracle.graal", "deps" : ["com.oracle.graal.compiler.test"]}]' - - will result in a dependency being installed in the local Maven repository - that can be referenced in a pom.xml file as follows: - - - com.oracle.graal - compiler.test - 1.0-SNAPSHOT - """ - - parser = ArgumentParser(prog='mx makejmhdeps') - parser.add_argument('-s', '--settings', help='alternative path for Maven user settings file', metavar='') - parser.add_argument('-p', '--permissive', action='store_true', help='issue note instead of error if a Maven dependency cannot be built due to missing projects/libraries') - args = parser.parse_args(args) - - def makejmhdep(artifactId, groupId, deps): - graalSuite = mx.suite("graal") - path = artifactId + '.jar' - if args.permissive: - allDeps = [] - for name in deps: - dist = mx.distribution(name, fatalIfMissing=False) - if dist: - allDeps = allDeps + [d.name for d in dist.sorted_deps(transitive=True)] - else: - if not mx.project(name, fatalIfMissing=False): - if not mx.library(name, fatalIfMissing=False): - mx.log('Skipping dependency ' + groupId + '.' + artifactId + ' as ' + name + ' cannot be resolved') - return - allDeps.append(name) - d = mx.Distribution(graalSuite, name=artifactId, path=path, sourcesPath=path, deps=allDeps, mainClass=None, excludedDependencies=[], distDependencies=[], javaCompliance=None) - d.make_archive() - cmd = ['mvn', 'install:install-file', '-DgroupId=' + groupId, '-DartifactId=' + artifactId, - '-Dversion=1.0-SNAPSHOT', '-Dpackaging=jar', '-Dfile=' + d.path] - if not mx._opts.verbose: - cmd.append('-q') - if args.settings: - cmd = cmd + ['-s', args.settings] - mx.run(cmd) - os.unlink(d.path) - - jmhPath = _get_jmh_path() - for root, _, filenames in os.walk(jmhPath): - for f in [join(root, n) for n in filenames if n == 'pom.mxdeps']: - mx.logv('[processing ' + f + ']') - try: - with open(f) as fp: - for d in json.load(fp): - artifactId = d['artifactId'] - groupId = d['groupId'] - deps = d['deps'] - makejmhdep(artifactId, groupId, deps) - except ValueError as e: - mx.abort('Error parsing {0}:\n{1}'.format(f, e)) - -def buildjmh(args): - """build the JMH benchmarks""" - - parser = ArgumentParser(prog='mx buildjmh') - parser.add_argument('-s', '--settings', help='alternative path for Maven user settings file', metavar='') - parser.add_argument('-c', action='store_true', dest='clean', help='clean before building') - args = parser.parse_args(args) - - jmhPath = _get_jmh_path() - mx.log('JMH benchmarks: ' + jmhPath) - - # Ensure the mx injected dependencies are up to date - makejmhdeps(['-p'] + (['-s', args.settings] if args.settings else [])) - - timestamp = mx.TimeStampFile(join(_suite.mxDir, 'jmh', jmhPath.replace(os.sep, '_') + '.timestamp')) - mustBuild = args.clean - if not mustBuild: - try: - hgfiles = [join(jmhPath, f) for f in subprocess.check_output(['hg', '-R', jmhPath, 'locate']).split('\n')] - mustBuild = timestamp.isOlderThan(hgfiles) - except: - # not a Mercurial repository or hg commands are not available. - mustBuild = True - - if mustBuild: - buildOutput = [] - def _redirect(x): - if mx._opts.verbose: - mx.log(x[:-1]) - else: - buildOutput.append(x) - env = os.environ.copy() - env['JAVA_HOME'] = _jdk(vmToCheck='server') - env['MAVEN_OPTS'] = '-server -XX:-UseJVMCIClassLoader' - mx.log("Building benchmarks...") - cmd = ['mvn'] - if args.settings: - cmd = cmd + ['-s', args.settings] - if args.clean: - cmd.append('clean') - cmd.append('package') - retcode = mx.run(cmd, cwd=jmhPath, out=_redirect, env=env, nonZeroIsFatal=False) - if retcode != 0: - mx.log(''.join(buildOutput)) - mx.abort(retcode) - timestamp.touch() - else: - mx.logv('[all Mercurial controlled files in ' + jmhPath + ' are older than ' + timestamp.path + ' - skipping build]') - -def jmh(args): - """run the JMH benchmarks - - This command respects the standard --vm and --vmbuild options - for choosing which VM to run the benchmarks with.""" - if '-h' in args: - mx.help_(['jmh']) - mx.abort(1) - - vmArgs, benchmarksAndJsons = mx.extract_VM_args(args) - if isJVMCIEnabled(_get_vm()) and '-XX:-UseJVMCIClassLoader' not in vmArgs: - vmArgs = ['-XX:-UseJVMCIClassLoader'] + vmArgs - - benchmarks = [b for b in benchmarksAndJsons if not b.startswith('{')] - jmhArgJsons = [b for b in benchmarksAndJsons if b.startswith('{')] - jmhOutDir = join(_suite.mxDir, 'jmh') - if not exists(jmhOutDir): - os.makedirs(jmhOutDir) - jmhOut = join(jmhOutDir, 'jmh.out') - jmhArgs = {'-rff' : jmhOut, '-v' : 'EXTRA' if mx._opts.verbose else 'NORMAL'} - - # e.g. '{"-wi" : 20}' - for j in jmhArgJsons: - try: - for n, v in json.loads(j).iteritems(): - if v is None: - del jmhArgs[n] - else: - jmhArgs[n] = v - except ValueError as e: - mx.abort('error parsing JSON input: {0}\n{1}'.format(j, e)) - - jmhPath = _get_jmh_path() - mx.log('Using benchmarks in ' + jmhPath) - - matchedSuites = set() - numBench = [0] - for micros in os.listdir(jmhPath): - absoluteMicro = os.path.join(jmhPath, micros) - if not os.path.isdir(absoluteMicro): - continue - if not micros.startswith("micros-"): - mx.logv('JMH: ignored ' + absoluteMicro + " because it doesn't start with 'micros-'") - continue - - microJar = os.path.join(absoluteMicro, "target", "microbenchmarks.jar") - if not exists(microJar): - mx.log('Missing ' + microJar + ' - please run "mx buildjmh"') - continue - if benchmarks: - def _addBenchmark(x): - if x.startswith("Benchmark:"): - return - match = False - for b in benchmarks: - match = match or (b in x) - - if match: - numBench[0] += 1 - matchedSuites.add(micros) - - mx.run_java(['-jar', microJar, "-l"], cwd=jmhPath, out=_addBenchmark, addDefaultArgs=False) - else: - matchedSuites.add(micros) - - mx.logv("matchedSuites: " + str(matchedSuites)) - plural = 's' if not benchmarks or numBench[0] > 1 else '' - number = str(numBench[0]) if benchmarks else "all" - mx.log("Running " + number + " benchmark" + plural + '...') - - regex = [] - if benchmarks: - regex.append(r".*(" + "|".join(benchmarks) + ").*") - - for suite in matchedSuites: - absoluteMicro = os.path.join(jmhPath, suite) - (pfx, exe, vm, forkedVmArgs, _) = _parseVmArgs(vmArgs) - if pfx: - mx.log("JMH ignores prefix: \"" + ' '.join(pfx) + "\"") - javaArgs = ['-jar', os.path.join(absoluteMicro, "target", "microbenchmarks.jar"), - '--jvm', exe, - '--jvmArgs', ' '.join(["-" + vm] + forkedVmArgs)] - for k, v in jmhArgs.iteritems(): - javaArgs.append(k) - if len(str(v)): - javaArgs.append(str(v)) - mx.run_java(javaArgs + regex, addDefaultArgs=False, cwd=jmhPath) - def specjvm2008(args): """run one or more SPECjvm2008 benchmarks""" def launcher(bm, harnessArgs, extraVmOpts): - return sanitycheck.getSPECjvm2008(harnessArgs + [bm]).bench(_get_vm(), extraVmOpts=extraVmOpts) + return sanitycheck.getSPECjvm2008(harnessArgs + [bm]).bench(get_vm(), extraVmOpts=extraVmOpts) availableBenchmarks = set(sanitycheck.specjvm2008Names) for name in sanitycheck.specjvm2008Names: @@ -1975,7 +367,7 @@ def launcher(bm, harnessArgs, extraVmOpts): assert bm is None - return sanitycheck.getSPECjbb2013(harnessArgs).bench(_get_vm(), extraVmOpts=extraVmOpts) + return sanitycheck.getSPECjbb2013(harnessArgs).bench(get_vm(), extraVmOpts=extraVmOpts) _run_benchmark(args, None, launcher) @@ -1984,431 +376,21 @@ def launcher(bm, harnessArgs, extraVmOpts): assert bm is None - return sanitycheck.getSPECjbb2005(harnessArgs).bench(_get_vm(), extraVmOpts=extraVmOpts) + return sanitycheck.getSPECjbb2005(harnessArgs).bench(get_vm(), extraVmOpts=extraVmOpts) _run_benchmark(args, None, launcher) -def hsdis(args, copyToDir=None): - """download the hsdis library - - This is needed to support HotSpot's assembly dumping features. - By default it downloads the Intel syntax version, use the 'att' argument to install AT&T syntax.""" - flavor = 'intel' - if 'att' in args: - flavor = 'att' - if mx.get_arch() == "sparcv9": - flavor = "sparcv9" - lib = mx.add_lib_suffix('hsdis-' + mx.get_arch()) - path = join(_graal_home, 'lib', lib) - - sha1s = { - 'att/hsdis-amd64.dll' : 'bcbd535a9568b5075ab41e96205e26a2bac64f72', - 'att/hsdis-amd64.so' : '58919ba085d4ef7a513f25bae75e7e54ee73c049', - 'intel/hsdis-amd64.dll' : '6a388372cdd5fe905c1a26ced614334e405d1f30', - 'intel/hsdis-amd64.so' : '844ed9ffed64fe9599638f29a8450c50140e3192', - 'intel/hsdis-amd64.dylib' : 'fdb13ef0d7d23d93dacaae9c98837bea0d4fc5a2', - 'sparcv9/hsdis-sparcv9.so': '970640a9af0bd63641f9063c11275b371a59ee60', - } - - flavoredLib = flavor + "/" + lib - if flavoredLib not in sha1s: - mx.logv("hsdis not supported on this plattform or architecture") - return - - if not exists(path): - sha1 = sha1s[flavoredLib] - sha1path = path + '.sha1' - mx.download_file_with_sha1('hsdis', path, ['http://lafo.ssw.uni-linz.ac.at/hsdis/' + flavoredLib], sha1, sha1path, True, True, sources=False) - if copyToDir is not None and exists(copyToDir): - shutil.copy(path, copyToDir) - -def hcfdis(args): - """disassemble HexCodeFiles embedded in text files - - Run a tool over the input files to convert all embedded HexCodeFiles - to a disassembled format.""" - - parser = ArgumentParser(prog='mx hcfdis') - parser.add_argument('-m', '--map', help='address to symbol map applied to disassembler output') - parser.add_argument('files', nargs=REMAINDER, metavar='files...') - - args = parser.parse_args(args) - - path = mx.library('HCFDIS').get_path(resolve=True) - mx.run_java(['-cp', path, 'com.oracle.max.hcfdis.HexCodeFileDis'] + args.files) - - if args.map is not None: - addressRE = re.compile(r'0[xX]([A-Fa-f0-9]+)') - with open(args.map) as fp: - lines = fp.read().splitlines() - symbols = dict() - for l in lines: - addressAndSymbol = l.split(' ', 1) - if len(addressAndSymbol) == 2: - address, symbol = addressAndSymbol - if address.startswith('0x'): - address = long(address, 16) - symbols[address] = symbol - for f in args.files: - with open(f) as fp: - lines = fp.read().splitlines() - updated = False - for i in range(0, len(lines)): - l = lines[i] - for m in addressRE.finditer(l): - sval = m.group(0) - val = long(sval, 16) - sym = symbols.get(val) - if sym: - l = l.replace(sval, sym) - updated = True - lines[i] = l - if updated: - mx.log('updating ' + f) - with open('new_' + f, "w") as fp: - for l in lines: - print >> fp, l - -def jacocoreport(args): - """create a JaCoCo coverage report - - Creates the report from the 'jacoco.exec' file in the current directory. - Default output directory is 'coverage', but an alternative can be provided as an argument.""" - jacocoreport = mx.library("JACOCOREPORT", True) - out = 'coverage' - if len(args) == 1: - out = args[0] - elif len(args) > 1: - mx.abort('jacocoreport takes only one argument : an output directory') - - includes = ['com.oracle.graal', 'jdk.internal.jvmci'] - for p in mx.projects(): - projsetting = getattr(p, 'jacoco', '') - if projsetting == 'include': - includes.append(p.name) - - includedirs = set() - for p in mx.projects(): - projsetting = getattr(p, 'jacoco', '') - if projsetting == 'exclude': - continue - for include in includes: - if include in p.dir: - includedirs.add(p.dir) - - for i in includedirs: - bindir = i + '/bin' - if not os.path.exists(bindir): - os.makedirs(bindir) - - mx.run_java(['-jar', jacocoreport.get_path(True), '--in', 'jacoco.exec', '--out', out] + sorted(includedirs)) - -def isJVMCIEnabled(vm): - return vm != 'original' and not vm.endswith('nojvmci') - -def jol(args): - """Java Object Layout""" - joljar = mx.library('JOL_INTERNALS').get_path(resolve=True) - candidates = mx.findclass(args, logToConsole=False, matcher=lambda s, classname: s == classname or classname.endswith('.' + s) or classname.endswith('$' + s)) - - if len(candidates) > 0: - candidates = mx.select_items(sorted(candidates)) - else: - # mx.findclass can be mistaken, don't give up yet - candidates = args - - vm(['-javaagent:' + joljar, '-cp', os.pathsep.join([mx.classpath(), joljar]), "org.openjdk.jol.MainObjectInternals"] + candidates) - -def site(args): - """create a website containing javadoc and the project dependency graph""" - - return mx.site(['--name', 'Graal', - '--jd', '@-tag', '--jd', '@test:X', - '--jd', '@-tag', '--jd', '@run:X', - '--jd', '@-tag', '--jd', '@bug:X', - '--jd', '@-tag', '--jd', '@summary:X', - '--jd', '@-tag', '--jd', '@vmoption:X', - '--overview', join(_graal_home, 'graal', 'overview.html'), - '--title', 'Graal OpenJDK Project Documentation', - '--dot-output-base', 'projects'] + args) - -def generateZshCompletion(args): - """generate zsh completion for mx""" - try: - from genzshcomp import CompletionGenerator - except ImportError: - mx.abort("install genzshcomp (pip install genzshcomp)") - - # need to fake module for the custom mx arg parser, otherwise a check in genzshcomp fails - originalModule = mx._argParser.__module__ - mx._argParser.__module__ = "argparse" - generator = CompletionGenerator("mx", mx._argParser) - mx._argParser.__module__ = originalModule - - # strip last line and define local variable "ret" - complt = "\n".join(generator.get().split('\n')[0:-1]).replace('context state line', 'context state line ret=1') - - # add array of possible subcommands (as they are not part of the argument parser) - complt += '\n ": :->command" \\\n' - complt += ' "*::args:->args" && ret=0\n' - complt += '\n' - complt += 'case $state in\n' - complt += '\t(command)\n' - complt += '\t\tlocal -a main_commands\n' - complt += '\t\tmain_commands=(\n' - for cmd in sorted(mx._commands.iterkeys()): - c, _ = mx._commands[cmd][:2] - doc = c.__doc__ - complt += '\t\t\t"{0}'.format(cmd) - if doc: - complt += ':{0}'.format(_fixQuotes(doc.split('\n', 1)[0])) - complt += '"\n' - complt += '\t\t)\n' - complt += '\t\t_describe -t main_commands command main_commands && ret=0\n' - complt += '\t\t;;\n' - - complt += '\t(args)\n' - # TODO: improve matcher: if mx args are given, this doesn't work - complt += '\t\tcase $line[1] in\n' - complt += '\t\t\t(vm | vmg | vmfg | unittest | jmh | dacapo | scaladacapo | specjvm2008 | specjbb2013 | specjbb2005)\n' - complt += '\t\t\t\tnoglob \\\n' - complt += '\t\t\t\t\t_arguments -s -S \\\n' - complt += _appendOptions("jvmci", r"G\:") - # TODO: fix -XX:{-,+}Use* flags - complt += _appendOptions("hotspot", r"XX\:") - complt += '\t\t\t\t\t"-version" && ret=0 \n' - complt += '\t\t\t\t;;\n' - complt += '\t\tesac\n' - complt += '\t\t;;\n' - complt += 'esac\n' - complt += '\n' - complt += 'return $ret' - print complt - -def _fixQuotes(arg): - return arg.replace('\"', '').replace('\'', '').replace('`', '').replace('{', '\\{').replace('}', '\\}').replace('[', '\\[').replace(']', '\\]') - -def _appendOptions(optionType, optionPrefix): - def isBoolean(vmap, field): - return vmap[field] == "Boolean" or vmap[field] == "bool" - - def hasDescription(vmap): - return vmap['optDefault'] or vmap['optDoc'] - - complt = "" - for vmap in _parseVMOptions(optionType): - complt += '\t\t\t\t\t-"' - complt += optionPrefix - if isBoolean(vmap, 'optType'): - complt += '"{-,+}"' - complt += vmap['optName'] - if not isBoolean(vmap, 'optType'): - complt += '=' - if hasDescription(vmap): - complt += "[" - if vmap['optDefault']: - complt += r"(default\: " + vmap['optDefault'] + ")" - if vmap['optDoc']: - complt += _fixQuotes(vmap['optDoc']) - if hasDescription(vmap): - complt += "]" - complt += '" \\\n' - return complt - -def _parseVMOptions(optionType): - parser = OutputParser() - # TODO: the optDoc part can wrapped accross multiple lines, currently only the first line will be captured - # TODO: fix matching for float literals - jvmOptions = re.compile( - r"^[ \t]*" - r"(?P(Boolean|Integer|Float|Double|String|bool|intx|uintx|ccstr|double)) " - r"(?P[a-zA-Z0-9]+)" - r"[ \t]+=[ \t]*" - r"(?P([\-0-9]+(\.[0-9]+(\.[0-9]+\.[0-9]+))?|false|true|null|Name|sun\.boot\.class\.path))?" - r"[ \t]*" - r"(?P.+)?", - re.MULTILINE) - parser.addMatcher(ValuesMatcher(jvmOptions, { - 'optType' : '', - 'optName' : '', - 'optDefault' : '', - 'optDoc' : '', - })) - - # gather JVMCI options - output = StringIO.StringIO() - vm(['-XX:-BootstrapJVMCI', '-XX:+UnlockDiagnosticVMOptions', '-G:+PrintFlags' if optionType == "jvmci" else '-XX:+PrintFlagsWithComments'], - vm="jvmci", - vmbuild="optimized", - nonZeroIsFatal=False, - out=output.write, - err=subprocess.STDOUT) - - valueMap = parser.parse(output.getvalue()) - return valueMap - -def checkheaders(args): - """check Java source headers against any required pattern""" - failures = {} - for p in mx.projects(): - if p.native: - continue - - csConfig = join(mx.project(p.checkstyleProj).dir, '.checkstyle_checks.xml') - if not exists(csConfig): - mx.log('Cannot check headers for ' + p.name + ' - ' + csConfig + ' does not exist') - continue - dom = xml.dom.minidom.parse(csConfig) - for module in dom.getElementsByTagName('module'): - if module.getAttribute('name') == 'RegexpHeader': - for prop in module.getElementsByTagName('property'): - if prop.getAttribute('name') == 'header': - value = prop.getAttribute('value') - matcher = re.compile(value, re.MULTILINE) - for sourceDir in p.source_dirs(): - for root, _, files in os.walk(sourceDir): - for name in files: - if name.endswith('.java') and name != 'package-info.java': - f = join(root, name) - with open(f) as fp: - content = fp.read() - if not matcher.match(content): - failures[f] = csConfig - for n, v in failures.iteritems(): - mx.log('{0}: header does not match RegexpHeader defined in {1}'.format(n, v)) - return len(failures) - def mx_init(suite): commands = { - 'build': [build, ''], - 'buildjmh': [buildjmh, '[-options]'], - 'buildvars': [buildvars, ''], - 'buildvms': [buildvms, '[-options]'], - 'c1visualizer' : [c1visualizer, ''], - 'checkheaders': [checkheaders, ''], - 'clean': [clean, ''], - 'ctw': [ctw, '[-vmoptions|noinline|nocomplex|full]'], - 'export': [export, '[-options] [zipfile]'], - 'generateZshCompletion' : [generateZshCompletion, ''], - 'hsdis': [hsdis, '[att]'], - 'hcfdis': [hcfdis, ''], - 'igv' : [igv, ''], - 'jdkhome': [print_jdkhome, ''], - 'jmh': [jmh, '[VM options] [filters|JMH-args-as-json...]'], 'dacapo': [dacapo, '[VM options] benchmarks...|"all" [DaCapo options]'], 'scaladacapo': [scaladacapo, '[VM options] benchmarks...|"all" [Scala DaCapo options]'], 'specjvm2008': [specjvm2008, '[VM options] benchmarks...|"all" [SPECjvm2008 options]'], 'specjbb2013': [specjbb2013, '[VM options] [-- [SPECjbb2013 options]]'], 'specjbb2005': [specjbb2005, '[VM options] [-- [SPECjbb2005 options]]'], - 'gate' : [gate, '[-options]'], 'bench' : [bench, '[-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'], 'microbench' : [microbench, '[VM options] [-- [JMH options]]'], - 'makejmhdeps' : [makejmhdeps, ''], - 'unittest' : [unittest, '[unittest options] [--] [VM options] [filters...]', mx_unittest.unittestHelpSuffix], - 'shortunittest' : [shortunittest, '[unittest options] [--] [VM options] [filters...]', mx_unittest.unittestHelpSuffix], - 'jacocoreport' : [jacocoreport, '[output directory]'], - 'site' : [site, '[-options]'], - 'vm': [vm, '[-options] class [args...]'], - 'vmg': [vmg, '[-options] class [args...]'], - 'vmfg': [vmfg, '[-options] class [args...]'], 'deoptalot' : [deoptalot, '[n]'], 'longtests' : [longtests, ''], - 'jol' : [jol, ''], - 'makefile' : [mx_graal_makefile.build_makefile, 'build makefiles for JDK build'], } - mx.add_argument('--jacoco', help='instruments com.oracle.* classes using JaCoCo', default='off', choices=['off', 'on', 'append']) - mx.add_argument('--vmcwd', dest='vm_cwd', help='current directory will be changed to before the VM is executed', default=None, metavar='') - mx.add_argument('--installed-jdks', help='the base directory in which the JDKs cloned from $JAVA_HOME exist. ' + - 'The VM selected by --vm and --vmbuild options is under this directory (i.e., ' + - join('', '', '', 'jre', 'lib', '', mx.add_lib_prefix(mx.add_lib_suffix('jvm'))) + ')', default=None, metavar='') - - mx.add_argument('--vm', action='store', dest='vm', choices=_vmChoices.keys(), help='the VM type to build/run') - mx.add_argument('--vmbuild', action='store', dest='vmbuild', choices=_vmbuildChoices, help='the VM build to build/run (default: ' + _vmbuildChoices[0] + ')') - mx.add_argument('--ecl', action='store_true', dest='make_eclipse_launch', help='create launch configuration for running VM execution(s) in Eclipse') - mx.add_argument('--vmprefix', action='store', dest='vm_prefix', help='prefix for running the VM (e.g. "/usr/bin/gdb --args")', metavar='') - mx.add_argument('--gdb', action='store_const', const='/usr/bin/gdb --args', dest='vm_prefix', help='alias for --vmprefix "/usr/bin/gdb --args"') - mx.add_argument('--lldb', action='store_const', const='lldb --', dest='vm_prefix', help='alias for --vmprefix "lldb --"') - mx.update_commands(suite, commands) - -class JVMCIArchiveParticipant: - def __init__(self, dist): - self.dist = dist - self.jvmciServices = {} - - def __opened__(self, arc, srcArc, services): - self.services = services - self.arc = arc - self.expectedOptionsProviders = set() - - def __add__(self, arcname, contents): - if arcname.startswith('META-INF/jvmci.services/'): - service = arcname[len('META-INF/jvmci.services/'):] - self.jvmciServices.setdefault(service, []).extend([provider for provider in contents.split('\n')]) - return True - if arcname.startswith('META-INF/jvmci.providers/'): - provider = arcname[len('META-INF/jvmci.providers/'):] - for service in contents.split('\n'): - self.jvmciServices.setdefault(service, []).append(provider) - return True - elif arcname.startswith('META-INF/jvmci.options/'): - # Need to create service files for the providers of the - # jdk.internal.jvmci.options.Options service created by - # jdk.internal.jvmci.options.processor.OptionProcessor. - optionsOwner = arcname[len('META-INF/jvmci.options/'):] - provider = optionsOwner + '_Options' - self.expectedOptionsProviders.add(provider.replace('.', '/') + '.class') - self.services.setdefault('jdk.internal.jvmci.options.Options', []).append(provider) - return False - - def __addsrc__(self, arcname, contents): - return False - - def __closing__(self): - self.expectedOptionsProviders -= set(self.arc.zf.namelist()) - assert len(self.expectedOptionsProviders) == 0, 'missing generated Options providers:\n ' + '\n '.join(self.expectedOptionsProviders) - for service, providers in self.jvmciServices.iteritems(): - arcname = 'META-INF/jvmci.services/' + service - # Convert providers to a set before printing to remove duplicates - self.arc.zf.writestr(arcname, '\n'.join(frozenset(providers))) - -def mx_post_parse_cmd_line(opts): # - # TODO _minVersion check could probably be part of a Suite in mx? - def _versionCheck(version): - return version >= _minVersion and (not _untilVersion or version >= _untilVersion) - versionDesc = ">=" + str(_minVersion) - if _untilVersion: - versionDesc += " and <=" + str(_untilVersion) - mx.java(_versionCheck, versionDescription=versionDesc, defaultJdk=True) - - if hasattr(opts, 'vm') and opts.vm is not None: - global _vm - _vm = opts.vm - _vm = _vm.replace('graal', 'jvmci') - if hasattr(opts, 'vmbuild') and opts.vmbuild is not None: - global _vmbuild - _vmbuild = opts.vmbuild - global _make_eclipse_launch - _make_eclipse_launch = getattr(opts, 'make_eclipse_launch', False) - global _jacoco - _jacoco = opts.jacoco - global _vm_cwd - _vm_cwd = opts.vm_cwd - global _installed_jdks - _installed_jdks = opts.installed_jdks - global _vm_prefix - _vm_prefix = opts.vm_prefix - - for jdkDist in _jdkDeployedDists: - def _close(jdkDeployable): - def _install(dist): - assert dist.name == jdkDeployable.name, dist.name + "!=" + jdkDeployable.name - if not jdkDist.partOfHotSpot: - _installDistInJdks(jdkDeployable) - return _install - dist = mx.distribution(jdkDist.name) - dist.add_update_listener(_close(jdkDist)) - if jdkDist.usesJVMCIClassLoader: - dist.set_archiveparticipant(JVMCIArchiveParticipant(dist)) - diff -r 103f53747955 -r 258eaaa98484 mx.graal/suite.py --- a/mx.graal/suite.py Thu Jul 02 12:42:20 2015 +0200 +++ b/mx.graal/suite.py Mon Jul 06 14:11:33 2015 +0200 @@ -1,6 +1,27 @@ suite = { - "mxversion" : "1.0", + "mxversion" : "4.0.0", "name" : "graal", + + "imports" : { + "suites": [ + { + "name" : "jvmci", + "version" : "ed35cb99842854869c6a18a3626064932db32968", + "urls" : [ + {"url" : "http://lafo.ssw.uni-linz.ac.at/hg/graal-jvmci-8", "kind" : "hg"}, + ] + }, + { + "name" : "truffle", + "version" : "4858c5e074e9005075e89cf5b1c2347ee73a5d31", + "urls" : [ + {"url" : "http://lafo.ssw.uni-linz.ac.at/hg/truffle", "kind" : "hg"}, + {"url" : "http://lafo.ssw.uni-linz.ac.at/nexus/content/repositories/snapshots", "kind" : "binary", "version-adjust" : "0.8-{version}-SNAPSHOT"}, + ] + }, + ] + }, + "libraries" : { # ------------- Libraries ------------- @@ -91,32 +112,6 @@ "sha1" : "122b87ca88e41a415cf8b523fd3d03b4325134a3", "urls" : ["http://lafo.ssw.uni-linz.ac.at/graal-external-deps/batik-all-1.7.jar"], }, - - # ------------- Truffle ------------- - - "TRUFFLE" : { - "path" : "lib/truffle-0.8-SNAPSHOT.jar", - "urls" : [ - "http://lafo.ssw.uni-linz.ac.at/nexus/content/repositories/snapshots/com/oracle/truffle/0.8-cf1503da2456b46677cbf0ed286614d660126a1b-SNAPSHOT/truffle-0.8-cf1503da2456b46677cbf0ed286614d660126a1b-20150626.073755-1.jar", - ], - "sha1" : "cf1bff27e6a59c994d3e9249ef451a9eeac5371a", - }, - "TRUFFLE_DSL_PROCESSOR" : { - "path" : "lib/truffle-dsl-processor-0.8-SNAPSHOT.jar", - "urls" : [ - "http://lafo.ssw.uni-linz.ac.at/nexus/content/repositories/snapshots/com/oracle/truffle-dsl-processor/0.8-cf1503da2456b46677cbf0ed286614d660126a1b-SNAPSHOT/truffle-dsl-processor-0.8-cf1503da2456b46677cbf0ed286614d660126a1b-20150626.073758-1.jar" - ], - "sha1" : "892ca5cbdddc9ac162e70731b415c7f0ca167905", - "annotationProcessor" : "true", - "dependencies" : ["TRUFFLE"] - }, - "TRUFFLE_SL" : { - "path" : "lib/truffle-sl-0.8-SNAPSHOT.jar", - "urls" : [ - "http://lafo.ssw.uni-linz.ac.at/nexus/content/repositories/snapshots/com/oracle/truffle-sl/0.8-dd4050aadaf8d91301b159cb30a609d8bb99feeb-SNAPSHOT/truffle-sl-0.8-dd4050aadaf8d91301b159cb30a609d8bb99feeb-20150616.114825-1.jar", - ], - "sha1" : "bf3f09792dc8fab2bd55bf94ddc69859692cbd27", - } }, "jrelibraries" : { @@ -127,242 +122,6 @@ "projects" : { - # ------------- JVMCI:Service ------------- - - "jdk.internal.jvmci.service" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "checkstyle" : "com.oracle.graal.graph", - "javaCompliance" : "1.8", - "workingSets" : "API,JVMCI", - }, - - "jdk.internal.jvmci.service.processor" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "dependencies" : ["jdk.internal.jvmci.service"], - "checkstyle" : "com.oracle.graal.graph", - "javaCompliance" : "1.8", - "workingSets" : "JVMCI,Codegen,HotSpot", - }, - - # ------------- JVMCI:API ------------- - - "jdk.internal.jvmci.common" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "checkstyle" : "com.oracle.graal.graph", - "javaCompliance" : "1.8", - "workingSets" : "API,JVMCI", - }, - - "jdk.internal.jvmci.meta" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "checkstyle" : "com.oracle.graal.graph", - "javaCompliance" : "1.8", - "workingSets" : "API,JVMCI", - }, - - "jdk.internal.jvmci.code" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "dependencies" : ["jdk.internal.jvmci.meta"], - "checkstyle" : "com.oracle.graal.graph", - "javaCompliance" : "1.8", - "workingSets" : "API,JVMCI", - }, - - "jdk.internal.jvmci.runtime" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "dependencies" : [ - "jdk.internal.jvmci.code" - ], - "checkstyle" : "com.oracle.graal.graph", - "javaCompliance" : "1.8", - "workingSets" : "API,JVMCI", - }, - - "jdk.internal.jvmci.runtime.test" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "dependencies" : [ - "JUNIT", - "jdk.internal.jvmci.common", - "jdk.internal.jvmci.runtime", - ], - "checkstyle" : "com.oracle.graal.graph", - "javaCompliance" : "1.8", - "workingSets" : "API,JVMCI", - }, - - "jdk.internal.jvmci.debug" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "checkstyle" : "com.oracle.graal.graph", - "dependencies" : [ - "jdk.internal.jvmci.options", - "jdk.internal.jvmci.code", - "jdk.internal.jvmci.service", - ], - "annotationProcessors" : ["jdk.internal.jvmci.options.processor"], - "javaCompliance" : "1.8", - "workingSets" : "JVMCI,Debug", - }, - - "jdk.internal.jvmci.debug.test" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "dependencies" : [ - "JUNIT", - "jdk.internal.jvmci.debug", - ], - "checkstyle" : "com.oracle.graal.graph", - "javaCompliance" : "1.8", - "workingSets" : "JVMCI,Debug,Test", - }, - - "jdk.internal.jvmci.options" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "checkstyle" : "com.oracle.graal.graph", - "javaCompliance" : "1.8", - "workingSets" : "JVMCI", - }, - - "jdk.internal.jvmci.compiler" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "dependencies" : [ - "jdk.internal.jvmci.debug", - ], - "checkstyle" : "com.oracle.graal.graph", - "annotationProcessors" : ["jdk.internal.jvmci.options.processor"], - "javaCompliance" : "1.8", - "workingSets" : "JVMCI", - }, - - "jdk.internal.jvmci.options.processor" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "dependencies" : [ - "jdk.internal.jvmci.options", - ], - "checkstyle" : "com.oracle.graal.graph", - "javaCompliance" : "1.8", - "workingSets" : "JVMCI,Codegen", - }, - - "jdk.internal.jvmci.options.test" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "dependencies" : [ - "jdk.internal.jvmci.options", - "JUNIT", - ], - "checkstyle" : "com.oracle.graal.graph", - "annotationProcessors" : ["jdk.internal.jvmci.options.processor"], - "javaCompliance" : "1.8", - "workingSets" : "JVMCI", - }, - - # ------------- JVMCI:HotSpot ------------- - - "jdk.internal.jvmci.amd64" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "dependencies" : ["jdk.internal.jvmci.code"], - "checkstyle" : "com.oracle.graal.graph", - "javaCompliance" : "1.8", - "workingSets" : "JVMCI,AMD64", - }, - - "jdk.internal.jvmci.sparc" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "dependencies" : ["jdk.internal.jvmci.code"], - "checkstyle" : "com.oracle.graal.graph", - "javaCompliance" : "1.8", - "workingSets" : "JVMCI,SPARC", - }, - - "jdk.internal.jvmci.hotspot" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "dependencies" : [ - "jdk.internal.jvmci.hotspotvmconfig", - "jdk.internal.jvmci.runtime", - "jdk.internal.jvmci.common", - "jdk.internal.jvmci.compiler", - ], - "annotationProcessors" : [ - "jdk.internal.jvmci.hotspotvmconfig.processor", - "jdk.internal.jvmci.options.processor", - "jdk.internal.jvmci.service.processor", - ], - "checkstyle" : "com.oracle.graal.graph", - "javaCompliance" : "1.8", - "workingSets" : "JVMCI", - }, - - "jdk.internal.jvmci.hotspotvmconfig" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "checkstyle" : "com.oracle.graal.graph", - "javaCompliance" : "1.8", - "workingSets" : "JVMCI,HotSpot", - }, - - "jdk.internal.jvmci.hotspotvmconfig.processor" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "dependencies" : ["jdk.internal.jvmci.hotspotvmconfig", "jdk.internal.jvmci.common"], - "checkstyle" : "com.oracle.graal.graph", - "javaCompliance" : "1.8", - "workingSets" : "JVMCI,HotSpot,Codegen", - }, - - "jdk.internal.jvmci.hotspot.amd64" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "dependencies" : [ - "jdk.internal.jvmci.amd64", - "jdk.internal.jvmci.hotspot", - ], - "checkstyle" : "com.oracle.graal.graph", - "annotationProcessors" : ["jdk.internal.jvmci.service.processor"], - "javaCompliance" : "1.8", - "workingSets" : "JVMCI,HotSpot,AMD64", - }, - - "jdk.internal.jvmci.hotspot.sparc" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "dependencies" : [ - "jdk.internal.jvmci.sparc", - "jdk.internal.jvmci.hotspot", - ], - "checkstyle" : "com.oracle.graal.graph", - "annotationProcessors" : ["jdk.internal.jvmci.service.processor"], - "javaCompliance" : "1.8", - "workingSets" : "JVMCI,HotSpot,SPARC", - }, - - "jdk.internal.jvmci.hotspot.jfr" : { - "subDir" : "jvmci", - "sourceDirs" : ["src"], - "dependencies" : [ - "jdk.internal.jvmci.hotspot", - "JFR", - ], - "checkstyle" : "com.oracle.graal.graph", - "annotationProcessors" : ["jdk.internal.jvmci.service.processor"], - "javaCompliance" : "1.8", - "profile" : "", - "workingSets" : "JVMCI,HotSpot", - }, - # ------------- NFI ------------- "com.oracle.nfi" : { @@ -377,7 +136,7 @@ "sourceDirs" : ["test"], "dependencies" : [ "com.oracle.nfi", - "jdk.internal.jvmci.common", + "jvmci:JVMCI_API", "JUNIT", ], "checkstyle" : "com.oracle.graal.graph", @@ -390,10 +149,10 @@ "subDir" : "graal", "sourceDirs" : ["src"], "dependencies" : [ - "jdk.internal.jvmci.service", - "jdk.internal.jvmci.code", + "jvmci:JVMCI_SERVICE", + "jvmci:JVMCI_API", ], - "annotationProcessors" : ["jdk.internal.jvmci.service.processor"], + "annotationProcessors" : ["jvmci:JDK_INTERNAL_JVMCI_SERVICE_PROCESSOR"], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", "workingSets" : "Graal", @@ -430,7 +189,7 @@ "subDir" : "graal", "sourceDirs" : ["src"], "dependencies" : [ - "jdk.internal.jvmci.service", + "jvmci:JVMCI_SERVICE", ], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", @@ -452,7 +211,7 @@ "com.oracle.graal.api.replacements" : { "subDir" : "graal", "sourceDirs" : ["src"], - "dependencies" : ["jdk.internal.jvmci.meta"], + "dependencies" : ["jvmci:JVMCI_API"], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", "workingSets" : "API,Graal,Replacements", @@ -462,7 +221,7 @@ "subDir" : "graal", "sourceDirs" : ["src"], "dependencies" : [ - "jdk.internal.jvmci.hotspot", + "jvmci:JVMCI_HOTSPOT", "com.oracle.graal.replacements", "com.oracle.graal.runtime", "com.oracle.graal.code", @@ -470,7 +229,7 @@ "checkstyle" : "com.oracle.graal.graph", "annotationProcessors" : [ "com.oracle.graal.replacements.verifier", - "jdk.internal.jvmci.service.processor", + "jvmci:JDK_INTERNAL_JVMCI_SERVICE_PROCESSOR", ], "javaCompliance" : "1.8", "workingSets" : "Graal,HotSpot", @@ -480,13 +239,13 @@ "subDir" : "graal", "sourceDirs" : ["src"], "dependencies" : [ - "jdk.internal.jvmci.hotspot.amd64", + "jvmci:JVMCI_HOTSPOT", "com.oracle.graal.compiler.amd64", "com.oracle.graal.hotspot", "com.oracle.graal.replacements.amd64", ], "checkstyle" : "com.oracle.graal.graph", - "annotationProcessors" : ["jdk.internal.jvmci.service.processor"], + "annotationProcessors" : ["jvmci:JDK_INTERNAL_JVMCI_SERVICE_PROCESSOR"], "javaCompliance" : "1.8", "workingSets" : "Graal,HotSpot,AMD64", }, @@ -496,12 +255,12 @@ "sourceDirs" : ["src"], "dependencies" : [ "com.oracle.graal.hotspot", - "jdk.internal.jvmci.hotspot.sparc", + "jvmci:JVMCI_HOTSPOT", "com.oracle.graal.compiler.sparc", "com.oracle.graal.replacements.sparc", ], "checkstyle" : "com.oracle.graal.graph", - "annotationProcessors" : ["jdk.internal.jvmci.service.processor", "com.oracle.graal.compiler.match.processor"], + "annotationProcessors" : ["jvmci:JDK_INTERNAL_JVMCI_SERVICE_PROCESSOR", "com.oracle.graal.compiler.match.processor"], "javaCompliance" : "1.8", "workingSets" : "Graal,HotSpot,SPARC", }, @@ -578,7 +337,7 @@ "com.oracle.graal.asm" : { "subDir" : "graal", "sourceDirs" : ["src"], - "dependencies" : ["jdk.internal.jvmci.code"], + "dependencies" : ["jvmci:JVMCI_API"], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", "workingSets" : "Graal,Assembler", @@ -589,7 +348,7 @@ "sourceDirs" : ["src"], "dependencies" : [ "com.oracle.graal.asm", - "jdk.internal.jvmci.amd64", + "jvmci:JVMCI_HOTSPOT", ], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", @@ -601,7 +360,7 @@ "sourceDirs" : ["src"], "dependencies" : [ "com.oracle.graal.asm", - "jdk.internal.jvmci.sparc", + "jvmci:JVMCI_HOTSPOT", ], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", @@ -622,8 +381,7 @@ "dependencies" : [ "com.oracle.graal.code", "com.oracle.graal.test", - "jdk.internal.jvmci.runtime", - "jdk.internal.jvmci.debug", + "jvmci:JVMCI_API", ], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", @@ -635,7 +393,7 @@ "sourceDirs" : ["src"], "dependencies" : [ "com.oracle.graal.asm.test", - "jdk.internal.jvmci.common", + "jvmci:JVMCI_API", "com.oracle.graal.asm.amd64", ], "checkstyle" : "com.oracle.graal.graph", @@ -724,7 +482,7 @@ "javaCompliance" : "1.8", "annotationProcessors" : [ "com.oracle.graal.replacements.verifier", - "jdk.internal.jvmci.service.processor", + "jvmci:JDK_INTERNAL_JVMCI_SERVICE_PROCESSOR", ], "workingSets" : "Graal,Replacements", }, @@ -739,7 +497,7 @@ ], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", - "annotationProcessors" : ["jdk.internal.jvmci.service.processor"], + "annotationProcessors" : ["jvmci:JDK_INTERNAL_JVMCI_SERVICE_PROCESSOR"], "workingSets" : "Graal,Replacements,AMD64", }, @@ -788,7 +546,7 @@ "com.oracle.graal.api.replacements", "com.oracle.graal.lir", "com.oracle.graal.bytecode", - "jdk.internal.jvmci.compiler", + "jvmci:JVMCI_HOTSPOT", ], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", @@ -871,7 +629,7 @@ ], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", - "annotationProcessors" : ["jdk.internal.jvmci.service.processor"], + "annotationProcessors" : ["jvmci:JDK_INTERNAL_JVMCI_SERVICE_PROCESSOR"], "workingSets" : "Graal", }, @@ -904,7 +662,7 @@ "subDir" : "graal", "sourceDirs" : ["src"], "dependencies" : [ - "jdk.internal.jvmci.amd64", + "jvmci:JVMCI_HOTSPOT", "com.oracle.graal.lir.jtt", ], "checkstyle" : "com.oracle.graal.graph", @@ -928,7 +686,7 @@ "subDir" : "graal", "sourceDirs" : ["src"], "dependencies" : [ - "jdk.internal.jvmci.sparc", + "jvmci:JVMCI_HOTSPOT", "com.oracle.graal.compiler.test", ], "checkstyle" : "com.oracle.graal.graph", @@ -953,7 +711,7 @@ "com.oracle.graal.graphbuilderconf", ], "checkstyle" : "com.oracle.graal.graph", - "annotationProcessors" : ["jdk.internal.jvmci.service.processor"], + "annotationProcessors" : ["jvmci:JDK_INTERNAL_JVMCI_SERVICE_PROCESSOR"], "javaCompliance" : "1.8", "workingSets" : "Graal,Java", }, @@ -973,10 +731,9 @@ "subDir" : "graal", "sourceDirs" : ["src"], "dependencies" : [ - "jdk.internal.jvmci.debug", - "jdk.internal.jvmci.common", + "jvmci:JVMCI_API", ], - "annotationProcessors" : ["jdk.internal.jvmci.options.processor"], + "annotationProcessors" : ["jvmci:JDK_INTERNAL_JVMCI_OPTIONS_PROCESSOR"], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", "workingSets" : "Graal,Java", @@ -990,7 +747,7 @@ "com.oracle.graal.java", "com.oracle.graal.compiler", ], - "annotationProcessors" : ["jdk.internal.jvmci.service.processor"], + "annotationProcessors" : ["jvmci:JDK_INTERNAL_JVMCI_SERVICE_PROCESSOR"], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", "workingSets" : "Graal,Graph", @@ -1042,7 +799,7 @@ "subDir" : "graal", "sourceDirs" : ["src"], "dependencies" : [ - "TRUFFLE", + "truffle:TRUFFLE", "com.oracle.graal.runtime", "com.oracle.graal.replacements", ], @@ -1058,8 +815,7 @@ "dependencies" : [ "com.oracle.graal.truffle", "com.oracle.graal.compiler.test", - "TRUFFLE_DSL_PROCESSOR", - "TRUFFLE_SL", + "truffle:TRUFFLE_SL", ], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", @@ -1077,7 +833,7 @@ ], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", - "annotationProcessors" : ["jdk.internal.jvmci.service.processor"], + "annotationProcessors" : ["jvmci:JDK_INTERNAL_JVMCI_SERVICE_PROCESSOR"], "workingSets" : "Graal,Truffle", }, @@ -1090,7 +846,7 @@ ], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", - "annotationProcessors" : ["jdk.internal.jvmci.service.processor"], + "annotationProcessors" : ["jvmci:JDK_INTERNAL_JVMCI_SERVICE_PROCESSOR"], "workingSets" : "Graal,Truffle", }, @@ -1103,7 +859,7 @@ ], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", - "annotationProcessors" : ["jdk.internal.jvmci.service.processor"], + "annotationProcessors" : ["jvmci:JDK_INTERNAL_JVMCI_SERVICE_PROCESSOR"], "workingSets" : "Graal,Truffle,SPARC", } }, @@ -1112,42 +868,6 @@ # ------------- Distributions ------------- - "JVMCI_SERVICE" : { - "path" : "build/jvmci-service.jar", - "subDir" : "jvmci", - "sourcesPath" : "build/jvmci-service.src.zip", - "dependencies" : ["jdk.internal.jvmci.service"], - }, - - "JVMCI_API" : { - "path" : "build/jvmci-api.jar", - "subDir" : "jvmci", - "sourcesPath" : "build/jvmci-api.src.zip", - "dependencies" : [ - "jdk.internal.jvmci.runtime", - "jdk.internal.jvmci.options", - "jdk.internal.jvmci.common", - "jdk.internal.jvmci.debug", - ], - "distDependencies" : [ - "JVMCI_SERVICE", - ], - }, - - "JVMCI_HOTSPOT" : { - "path" : "build/jvmci-hotspot.jar", - "subDir" : "jvmci", - "sourcesPath" : "build/jvmci-hotspot.src.zip", - "dependencies" : [ - "jdk.internal.jvmci.hotspot.amd64", - "jdk.internal.jvmci.hotspot.sparc", - "jdk.internal.jvmci.hotspot.jfr", - ], - "distDependencies" : [ - "JVMCI_API", - ], - }, - "GRAAL" : { "path" : "build/graal.jar", "subDir" : "graal", @@ -1176,10 +896,8 @@ ], "distDependencies" : [ "GRAAL", + "truffle:TRUFFLE", ], - "exclude" : [ - "TRUFFLE" - ] }, "GRAAL_TRUFFLE_TEST" : { diff -r 103f53747955 -r 258eaaa98484 mxtool/.project --- a/mxtool/.project Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ - - - mxtool - - - - - - org.python.pydev.PyDevBuilder - - - - - - org.python.pydev.pythonNature - - diff -r 103f53747955 -r 258eaaa98484 mxtool/.pydevproject --- a/mxtool/.pydevproject Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ - - - - - -/mxtool - -python 2.7 -Default - diff -r 103f53747955 -r 258eaaa98484 mxtool/.pylintrc --- a/mxtool/.pylintrc Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,281 +0,0 @@ -[MASTER] - -# Specify a configuration file. -#rcfile= - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= - -# Profiled execution. -profile=no - -# Add files or directories to the blacklist. They should be base names, not -# paths. -ignore=CVS - -# Pickle collected data for later comparisons. -persistent=no - -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins= - - -[MESSAGES CONTROL] - -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time. See also the "--disable" option for examples. -#enable= - -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifiers separated by comma (,) or put this -# option multiple times (only on the command line, not in the configuration -# file where it should appear only once).You can also use "--disable=all" to -# disable everything first and then reenable specific checks. For example, if -# you want to run only the similarities checker, you can use "--disable=all -# --enable=similarities". If you want to run only the classes checker, but have -# no Warning level messages displayed, use"--disable=all --enable=classes -# --disable=W" -disable=attribute-defined-outside-init,arguments-differ, - bare-except,global-statement,protected-access,redefined-outer-name, - unused-argument,star-args,pointless-string-statement,old-style-class, - too-many-lines,missing-docstring,no-init,no-self-use,too-many-statements, - too-many-locals,too-few-public-methods,too-many-instance-attributes, - too-many-arguments,too-many-branches,too-many-public-methods, - multiple-statements,abstract-method,F0401,no-member,non-parent-init-called, - maybe-no-member - -# F0401: http://www.logilab.org/ticket/9386 - -[REPORTS] - -# Set the output format. Available formats are text, parseable, colorized, msvs -# (visual studio) and html. You can also give a reporter class, eg -# mypackage.mymodule.MyReporterClass. -output-format=text - -# Put messages in a separate file for each module / package specified on the -# command line instead of printing them on stdout. Reports (if any) will be -# written in a file name "pylint_global.[txt|html]". -files-output=no - -# Tells whether to display a full report or only the messages -reports=no - -# Python expression which should return a note less than 10 (10 is the highest -# note). You have access to the variables errors warning, statement which -# respectively contain the number of errors / warnings messages and the total -# number of statements analyzed. This is used by the global evaluation report -# (RP0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) - -# Add a comment according to your evaluation note. This is used by the global -# evaluation report (RP0004). -comment=no - -# Template used to display messages. This is a python new-style format string -# used to format the massage information. See doc for all details -#msg-template= - - -[BASIC] - -# Required attributes for module, separated by a comma -required-attributes= - -# List of builtins function names that should not be used, separated by a comma -bad-functions=filter,apply,input - -# Regular expression which should only match correct module names -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - -# Regular expression which should only match correct module level names -const-rgx=[a-zA-Z0-9_]{2,30}$ - -# Regular expression which should only match correct class names -class-rgx=[A-Z_][a-zA-Z0-9]+$ - -# Regular expression which should only match correct function names -function-rgx=[a-z_][a-zA-Z0-9_]{1,40}$ - -# Regular expression which should only match correct method names -method-rgx=[a-z_][a-zA-Z0-9_]{2,40}$ - -# Regular expression which should only match correct instance attribute names -attr-rgx=[a-z_][a-zA-Z0-9_]{1,30}$ - -# Regular expression which should only match correct argument names -argument-rgx=[a-z_][a-zA-Z0-9_]{0,30}$ - -# Regular expression which should only match correct variable names -variable-rgx=[a-z_][a-zA-Z0-9_]{0,30}$ - -# Regular expression which should only match correct attribute names in class -# bodies -class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ - -# Regular expression which should only match correct list comprehension / -# generator expression variable names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ - -# Good variable names which should always be accepted, separated by a comma -good-names=i,j,k,ex,Run,_ - -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata - -# Regular expression which should only match function or class names that do -# not require a docstring. -no-docstring-rgx=.* - -# Minimum line length for functions/classes that require docstrings, shorter -# ones are exempt. -docstring-min-length=-1 - - -[FORMAT] - -# Maximum number of characters on a single line. -max-line-length=300 - -# Regexp for a line that is allowed to be longer than the limit. -ignore-long-lines=^\s*(# )??$ - -# Maximum number of lines in a module -max-module-lines=1000 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' - - -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -notes=FIXME - - -[SIMILARITIES] - -# Minimum lines number of a similarity. -min-similarity-lines=4 - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes - -# Ignore imports when computing similarities. -ignore-imports=no - - -[TYPECHECK] - -# Tells whether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# List of classes names for which member attributes should not be checked -# (useful for classes with attributes dynamically set). -ignored-classes=SQLObject - -# When zope mode is activated, add a predefined set of Zope acquired attributes -# to generated-members. -zope=no - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E0201 when accessed. Python regular -# expressions are accepted. -generated-members=REQUEST,acl_users,aq_parent - - -[VARIABLES] - -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# A regular expression matching the beginning of the name of dummy variables -# (i.e. not used). -dummy-variables-rgx=_$|dummy - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins= - - -[CLASSES] - -# List of interface methods to ignore, separated by a comma. This is used for -# instance to not check methods defines in Zope's Interface base class. -ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__,__new__,setUp - -# List of valid names for the first argument in a class method. -valid-classmethod-first-arg=cls - -# List of valid names for the first argument in a metaclass class method. -valid-metaclass-classmethod-first-arg=mcs - - -[DESIGN] - -# Maximum number of arguments for function / method -max-args=5 - -# Argument names that match this expression will be ignored. Default to name -# with leading underscore -ignored-argument-names=_.* - -# Maximum number of locals for function / method body -max-locals=15 - -# Maximum number of return / yield for function / method body -max-returns=6 - -# Maximum number of branch for function / method body -max-branches=12 - -# Maximum number of statements in function / method body -max-statements=50 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of attributes for a class (see R0902). -max-attributes=7 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=2 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - - -[IMPORTS] - -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=regsub,TERMIOS,Bastion,rexec - -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report RP0402 must not be disabled) -import-graph= - -# Create a graph of external dependencies in the given file (report RP0402 must -# not be disabled) -ext-import-graph= - -# Create a graph of internal dependencies in the given file (report RP0402 must -# not be disabled) -int-import-graph= - - -[EXCEPTIONS] - -# Exceptions that will emit a warning when being caught. Defaults to -# "Exception" -overgeneral-exceptions=Exception diff -r 103f53747955 -r 258eaaa98484 mxtool/CheckCopyright.java --- a/mxtool/CheckCopyright.java Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,918 +0,0 @@ -/* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -import java.io.*; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.*; -import java.util.regex.*; - - -/** - * A program to check the existence and correctness of the copyright notice on a given set of sources. - * Sources are defined to be those under management by Mercurial and various options are available - * to limit the set of sources scanned. - */ -public class CheckCopyright { - - static class YearInfo { - - final int firstYear; - final int lastYear; - - YearInfo(int firstYear, int lastYear) { - this.firstYear = firstYear; - this.lastYear = lastYear; - } - - @Override - public boolean equals(Object other) { - final YearInfo yearInfo = (YearInfo) other; - return yearInfo.firstYear == firstYear && yearInfo.lastYear == lastYear; - } - - @Override - public int hashCode() { - return firstYear ^ lastYear; - } - } - - static class Info extends YearInfo { - - final String fileName; - - Info(String fileName, int firstYear, int lastYear) { - super(firstYear, lastYear); - this.fileName = fileName; - } - - @Override - public String toString() { - return fileName + " " + firstYear + ", " + lastYear; - } - } - - private static abstract class CopyrightHandler { - enum CommentType{ - STAR, HASH - } - - private static Map copyrightMap; - private static String copyrightFiles = ".*/makefile|.*/Makefile|.*\\.sh|.*\\.bash|.*\\.mk|.*\\.java|.*\\.c|.*\\.h|.*\\.py|.*\\.g|.*\\.r"; - private static Pattern copyrightFilePattern; - - protected final String suffix; - private CopyrightHandler customHandler; - - CopyrightHandler(CommentType commentType) { - this.suffix = commentType.name().toLowerCase(); - initCopyrightMap(); - } - - void addCustomhandler(CopyrightHandler copyrightHandler) { - this.customHandler = copyrightHandler; - } - - /** - * Add @code extension to files handled by this {@code CopyrightKind} - */ - protected void updateMap(String extension) { - copyrightMap.put(extension, this); - } - - static void addCopyrightFilesPattern(String pattern) { - copyrightFiles += "|" + pattern; - } - - protected abstract void readCopyrights() throws IOException; - - protected abstract Matcher getMatcher(String fileName, String fileContent) throws IOException; - - protected abstract String getText(String fileName) throws IOException ; - - protected abstract boolean handlesFile(String fileName); - - /** - * Checks that the Oracle copyright year info was correct. - * @return {@code false} if the year info was incorrect and was not fixed otherwise return {@code true} - * @throws IOException - */ - protected abstract boolean checkYearInfo(String fileName, String fileContent, Matcher matcher, Info info) throws IOException; - - static String getCopyrightText(String fileName) throws IOException { - return getCopyrightHandler(fileName).getText(fileName); - } - - private static CopyrightHandler getCopyrightHandler(String fileName) { - initCopyrightMap(); - if (!copyrightFilePattern.matcher(fileName).matches()) { - return null; - } - CopyrightHandler ck = getDefaultHandler(fileName); - if (ck.customHandler != null && ck.customHandler.handlesFile(fileName)) { - return ck.customHandler; - } else { - return ck; - } - } - - private static void initCopyrightMap() { - if (copyrightMap == null) { - copyrightMap = new HashMap(); - copyrightFilePattern = Pattern.compile(copyrightFiles); - } - } - - static CopyrightHandler getDefaultHandler(String fileName) { - int index = fileName.lastIndexOf(File.separatorChar); - if (index > 0) { - fileName = fileName.substring(index + 1); - } - String ext = ""; - index = fileName.lastIndexOf('.'); - if (index > 0) { - ext = fileName.substring(index + 1); - } - if (fileName.equals("makefile")) { - ext = "mk"; - } - CopyrightHandler ck = copyrightMap.get(ext); - assert ck != null : fileName; - return ck; - } - - protected String readCopyright(InputStream is) throws IOException { - byte[] b = new byte[16384]; - int n = is.read(b); - is.close(); - return new String(b, 0, n); - } - - } - - private static class DefaultCopyrightHandler extends CopyrightHandler { - private static String ORACLE_COPYRIGHT = "oracle.copyright"; - private static String ORACLE_COPYRIGHT_REGEX = "oracle.copyright.regex"; - - private String copyrightRegex; - private String copyright; - Pattern copyrightPattern; - - DefaultCopyrightHandler(CopyrightHandler.CommentType commentType) throws IOException { - super(commentType); - if (commentType == CopyrightHandler.CommentType.STAR) { - updateMap("java"); - updateMap("c"); - updateMap("h"); - updateMap("g"); - } else { - updateMap("r"); - updateMap("R"); - updateMap("py"); - updateMap("sh"); - updateMap("mk"); - updateMap("bash"); - updateMap(""); - } - readCopyrights(); - } - - private String readCopyright(String name) throws IOException { - String copyRightDir = COPYRIGHT_DIR.getValue(); - String fileName = "copyrights/" + name + "." + suffix; - String copyrightPath; - if (copyRightDir != null) { - copyrightPath = new File(new File(copyRightDir), fileName).getAbsolutePath(); - } else { - URL url = CheckCopyright.class.getResource(fileName); - try { - copyrightPath = url.toURI().getPath(); - } catch (URISyntaxException ex) { - throw new IOException(ex); - } - } - InputStream is = new FileInputStream(copyrightPath); - return readCopyright(is); - } - - @Override - protected void readCopyrights() throws IOException { - copyright = readCopyright(ORACLE_COPYRIGHT); - copyrightRegex = readCopyright(ORACLE_COPYRIGHT_REGEX); - copyrightPattern = Pattern.compile(copyrightRegex, Pattern.DOTALL); - } - - @Override - protected Matcher getMatcher(String fileName, String fileContent) { - return copyrightPattern.matcher(fileContent); - } - - @Override - protected String getText(String fileName) { - return copyright; - } - - @Override - protected boolean handlesFile(String fileName) { - return true; - } - - /** - * Check the year info against the copyright header. - * N.B. In the case of multiple matching groups, only the last group is checked. - * I.e., only the last lines containing year info is checked/updated. - */ - @Override - protected boolean checkYearInfo(String fileName, String fileContent, Matcher matcher, Info info) throws IOException { - int yearInCopyright; - int yearInCopyrightIndex; - int groupCount = matcher.groupCount(); - String yearInCopyrightString = matcher.group(groupCount); - yearInCopyright = Integer.parseInt(yearInCopyrightString); - yearInCopyrightIndex = matcher.start(groupCount); - if (yearInCopyright != info.lastYear) { - System.out.println(fileName + " copyright last modified year " + yearInCopyright + ", hg last modified year " + info.lastYear); - if (FIX.getValue()) { - // Use currentYear as that is what it will be when it's checked in! - System.out.println("updating last modified year of " + fileName + " to " + info.lastYear); - // If the previous copyright only specified a single (initial) year, we convert it to the pair form - String newContent = fileContent.substring(0, yearInCopyrightIndex); - if (matcher.group(groupCount - 1) == null) { - // single year form - newContent += yearInCopyrightString + ", "; - } - newContent += info.lastYear + fileContent.substring(yearInCopyrightIndex + 4); - final FileOutputStream os = new FileOutputStream(fileName); - os.write(newContent.getBytes()); - os.close(); - return true; - } else { - return false; - } - } - return true; - } - - } - - private static class CustomCopyrightHandler extends CopyrightHandler { - private Map overrides = new HashMap(); - private CopyrightHandler defaultHandler; - - CustomCopyrightHandler(CopyrightHandler.CommentType commentType, CopyrightHandler defaultHandler) { - super(commentType); - this.defaultHandler = defaultHandler; - } - - void addFile(String fileName, String copyright) { - overrides.put(fileName, copyright); - } - - @Override - protected void readCopyrights() throws IOException { - } - - @Override - protected Matcher getMatcher(String fileName, String fileContent) throws IOException { - String copyright = overrides.get(fileName); - assert copyright != null : fileName; - try (InputStream fs = new FileInputStream(copyright + "." + suffix + ".regex")) { - return Pattern.compile(readCopyright(fs), Pattern.DOTALL).matcher(fileContent); - } - } - - @Override - protected String getText(String fileName) throws IOException { - String copyright = overrides.get(fileName); - assert copyright != null : fileName; - try (InputStream fs = new FileInputStream(copyright + "." + suffix)) { - return readCopyright(fs); - } - } - - @Override - protected boolean handlesFile(String fileName) { - return overrides.get(fileName) != null; - } - - @Override - protected boolean checkYearInfo(String fileName, String fileContent, Matcher matcher, Info info) throws IOException { - // This is a bit tacky - String copyright = overrides.get(fileName); - if (copyright.endsWith("no.copyright")) { - return true; - } - return defaultHandler.checkYearInfo(fileName, fileContent, matcher, info); - } - } - - private static void initCopyrightKinds() throws IOException { - CopyrightHandler starHandler = new DefaultCopyrightHandler(CopyrightHandler.CommentType.STAR); - CopyrightHandler hashHandler = new DefaultCopyrightHandler(CopyrightHandler.CommentType.HASH); - - String customCopyrightDir = CUSTOM_COPYRIGHT_DIR.getValue(); - if (customCopyrightDir != null) { - CustomCopyrightHandler customStarHandler = new CustomCopyrightHandler(CopyrightHandler.CommentType.STAR, starHandler); - CustomCopyrightHandler customHashHandler = new CustomCopyrightHandler(CopyrightHandler.CommentType.HASH, hashHandler); - starHandler.addCustomhandler(customStarHandler); - hashHandler.addCustomhandler(customHashHandler); - - File overrides = new File(new File(customCopyrightDir), "overrides"); - if (overrides.exists()) { - ArrayList lines = new ArrayList<>(); - boolean changed = false; - try (BufferedReader br = new BufferedReader(new FileReader( - overrides))) { - while (true) { - String line = br.readLine(); - if (line == null) { - break; - } - if (line.length() == 0 || line.startsWith("#")) { - lines.add(line); - continue; - } - String[] parts = line.split(","); - // filename,copyright-file - CopyrightHandler defaultHandler = CopyrightHandler.getDefaultHandler(parts[0]); - if (defaultHandler == null) { - System.err.println("no default copyright handler for: " + parts[0]); - System.exit(1); - } - if (!new File(parts[0]).exists()) { - System.err.printf("file %s in overrides file does not exist", parts[0]); - if (FIX.getValue()) { - System.err.print(" - removing"); - line = null; - changed = true; - } - System.err.println(); - } - if (line != null) { - lines.add(line); - } - CustomCopyrightHandler customhandler = (CustomCopyrightHandler) defaultHandler.customHandler; - customhandler.addFile(parts[0], new File(new File(customCopyrightDir), parts[1]).getAbsolutePath()); - } - } - if (changed) { - try (BufferedWriter bw = new BufferedWriter(new FileWriter( - overrides))) { - for (String line : lines) { - bw.write(line); - bw.write('\n'); - } - } - } - } - } - } - - private static int currentYear = Calendar.getInstance().get(Calendar.YEAR); - private static Options options = new Options(); - private static Option help = options.newBooleanOption("help", false, "Show help message and exit."); - private static Option COPYRIGHT_DIR = options.newStringOption("copyright-dir", null, "override default location of copyright files"); - private static Option> FILES_TO_CHECK = options.newStringListOption("files", null, "list of files to check"); - private static Option FILE_LIST = options.newStringOption("file-list", null, "file containing list of files to check"); - private static Option DIR_WALK = options.newBooleanOption("list-dir", false, "check all files in directory tree requiring a copyright (ls -R)"); - private static Option HG_ALL = options.newBooleanOption("hg-all", false, "check all hg managed files requiring a copyright (hg status --all)"); - private static Option HG_MODIFIED = options.newBooleanOption("hg-modified", false, "check all modified hg managed files requiring a copyright (hg status)"); - private static Option HG_OUTGOING = options.newBooleanOption("hg-outgoing", false, "check outgoing hg managed files requiring a copyright (hg outgoing)"); - private static Option HG_LOG = options.newStringOption("hg-last", "0", "check hg managed files requiring a copyright in last N changesets (hg log -l N)"); - private static Option> PROJECT = options.newStringListOption("projects", null, "filter files to specific projects"); - private static Option OUTGOING_REPO = options.newStringOption("hg-repo", null, "override outgoing repository"); - private static Option EXHAUSTIVE = options.newBooleanOption("hg-exhaustive", false, "check all hg managed files"); - private static Option FIX = options.newBooleanOption("fix", false, "fix all copyright errors"); - private static Option FILE_PATTERN = options.newStringOption("file-pattern", null, "append additional file patterns for copyright checks"); - private static Option REPORT_ERRORS = options.newBooleanOption("report-errors", false, "report non-fatal errors"); - private static Option HALT_ON_ERROR = options.newBooleanOption("halt-on-error", false, "continue after normally fatal error"); - private static Option HG_PATH = options.newStringOption("hg-path", "hg", "path to hg executable"); - private static Option VERBOSE = options.newBooleanOption("verbose", false, "verbose output"); - private static Option VERY_VERBOSE = options.newBooleanOption("very-verbose", false, "very verbose output"); - private static Option CUSTOM_COPYRIGHT_DIR = options.newStringOption("custom-copyright-dir", null, "file containing filenames with custom copyrights"); - - private static String CANNOT_FOLLOW_FILE = "abort: cannot follow"; - private static String hgPath; - private static boolean error; -// private static File workSpaceDirectory; - private static boolean verbose; - private static boolean veryVerbose; - - public static void main(String[] args) { - // parse the arguments - options.parseArguments(args); - if (help.getValue()) { - options.printHelp(); - return; - } - - verbose = VERBOSE.getValue(); - veryVerbose = VERY_VERBOSE.getValue(); - - hgPath = HG_PATH.getValue(); - - if (FILE_PATTERN.getValue() != null) { - CopyrightHandler.addCopyrightFilesPattern(FILE_PATTERN.getValue()); - } - - try { - initCopyrightKinds(); - List filesToCheck = null; - if (HG_ALL.getValue()) { - filesToCheck = getAllFiles(true); - } else if (HG_OUTGOING.getValue()) { - filesToCheck = getOutgoingFiles(); - } else if (HG_MODIFIED.getValue()) { - filesToCheck = getAllFiles(false); - } else if (Integer.parseInt(HG_LOG.getValue()) > 0) { - filesToCheck = getLastNFiles(Integer.parseInt(HG_LOG.getValue())); - } else if (FILE_LIST.getValue() != null) { - filesToCheck = readFileList(FILE_LIST.getValue()); - } else if (DIR_WALK.getValue()) { - filesToCheck = getDirWalkFiles(); - } else if (FILES_TO_CHECK.getValue() != null) { - filesToCheck = FILES_TO_CHECK.getValue(); - } else { - // no option set, default to HG_ALL - filesToCheck = getAllFiles(true); - } - if (filesToCheck != null && filesToCheck.size() > 0) { - processFiles(filesToCheck); - } else { - System.out.println("nothing to check"); - } - System.exit(error ? 1 : 0); - } catch (Exception ex) { - System.err.println("processing failed: " + ex); - ex.printStackTrace(); - } - } - - private static void processFiles(List fileNames) throws Exception { - final List projects = PROJECT.getValue(); - Calendar cal = Calendar.getInstance(); - for (String fileName : fileNames) { - if (projects == null || isInProjects(fileName, projects)) { - File file = new File(fileName); - if (file.isDirectory()) { - continue; - } - if (verbose) { - System.out.println("checking " + fileName); - } - try { - Info info = null; - if (DIR_WALK.getValue()) { - info = getFromLastModified(cal, fileName); - } else { - final List logInfo = hglog(fileName); - if (logInfo.size() == 0) { - // an added file, so go with last modified - info = getFromLastModified(cal, fileName); - } else { - info = getInfo(fileName, true, logInfo); - } - } - checkFile(fileName, info); - } catch (Exception e) { - System.err.format("COPYRIGHT CHECK WARNING: error while processing %s: %s%n", fileName, e.getMessage()); - } - } - } - } - - private static Info getFromLastModified(Calendar cal, String fileName) { - File file = new File(fileName); - cal.setTimeInMillis(file.lastModified()); - int year = cal.get(Calendar.YEAR); - return new Info(fileName, year, year); - } - - private static boolean isInProjects(String fileName, List projects) { - final int ix = fileName.indexOf(File.separatorChar); - if (ix < 0) { - return false; - } - final String fileProject = fileName.substring(0, ix); - for (String project : projects) { - if (fileProject.equals(project)) { - return true; - } - } - return false; - } - - private static List readFileList(String fileListName) throws IOException { - final List result = new ArrayList(); - BufferedReader b = null; - try { - b = new BufferedReader(new FileReader(fileListName)); - while (true) { - final String fileName = b.readLine(); - if (fileName == null) { - break; - } - if (fileName.length() == 0) { - continue; - } - result.add(fileName); - } - } finally { - if (b != null) { - b.close(); - } - } - return result; - } - - private static Info getInfo(String fileName, boolean lastOnly, List logInfo) { - // process sequence of changesets - int lastYear = 0; - int firstYear = 0; - int ix = 0; - - while (ix < logInfo.size()) { - Map tagMap = new HashMap<>(); - ix = getChangeset(logInfo, ix, tagMap); - String date = tagMap.get("date"); - assert date != null; - final int csYear = getYear(date); - if (lastYear == 0) { - lastYear = csYear; - firstYear = lastYear; - } else { - firstYear = csYear; - } - // if we only want the last modified year, quit now - if (lastOnly) { - break; - } - - } - - if (HG_MODIFIED.getValue()) { - // We are only looking at modified and, therefore, uncommitted files. - // This means that the lastYear value will be the current year once the - // file is committed, so that is what we want to check against. - lastYear = currentYear; - } - return new Info(fileName, firstYear, lastYear); - } - - /** - * Process all the changeset data, storing in {@outMap}. - * Return updated value of {@code ix}. - */ - private static int getChangeset(List logInfo, int ixx, Map outMap) { - int ix = ixx; - String s = logInfo.get(ix++); - while (s.length() > 0) { - int cx = s.indexOf(':'); - String tag = s.substring(0, cx); - String value = s.substring(cx + 1); - outMap.put(tag, value); - s = logInfo.get(ix++); - } - return ix; - } - - private static int getYear(String dateLine) { - final String[] parts = dateLine.split(" "); - assert parts[parts.length - 2].startsWith("20"); - return Integer.parseInt(parts[parts.length - 2]); - } - - private static void checkFile(String c, Info info) throws IOException { - String fileName = info.fileName; - File file = new File(fileName); - if (!file.exists()) { - System.err.println("COPYRIGHT CHECK WARNING: file " + file + " doesn't exist"); - return; - } - int fileLength = (int) file.length(); - byte[] fileContentBytes = new byte[fileLength]; - FileInputStream is = new FileInputStream(file); - is.read(fileContentBytes); - is.close(); - final String fileContent = new String(fileContentBytes); - CopyrightHandler copyrightHandler = CopyrightHandler.getCopyrightHandler(fileName); - if (file.getName().equals("Makefile")) { - System.console(); - } - if (copyrightHandler != null) { - Matcher copyrightMatcher = copyrightHandler.getMatcher(fileName, fileContent); - if (copyrightMatcher.matches()) { - error = error | !copyrightHandler.checkYearInfo(fileName, fileContent, copyrightMatcher, info); - } else { - // If copyright is missing, insert it, otherwise user has to manually fix existing copyright. - if (!fileContent.contains("Copyright")) { - System.out.print("file " + fileName + " has missing copyright"); - if (FIX.getValue()) { - final FileOutputStream os = new FileOutputStream(file); - os.write(CopyrightHandler.getCopyrightText(fileName) - .getBytes()); - os.write(fileContentBytes); - os.close(); - System.out.println("...fixed"); - } else { - System.out.println(); - error = true; - } - } else { - System.out.println("file " + fileName + " has malformed copyright" + (FIX.getValue() ? " not fixing" : "")); - error = true; - } - } - } else if (EXHAUSTIVE.getValue()) { - System.out.println("ERROR: file " + fileName + " has no copyright"); - error = true; - } - } - - - private static List hglog(String fileName) throws Exception { - final String[] cmd = new String[] {hgPath, "log", "-f", fileName}; - return exec(null, cmd, true); - } - - private static List getLastNFiles(int n) throws Exception { - final String[] cmd = new String[] {hgPath, "log", "-v", "-l", Integer.toString(n)}; - return getFilesFiles(exec(null, cmd, false)); - } - - private static List getAllFiles(boolean all) throws Exception { - final String[] cmd; - if (HG_MODIFIED.getValue()) { - cmd = new String[] {hgPath, "status"}; - } else { - cmd = new String[] {hgPath, "status", "--all"}; - } - List output = exec(null, cmd, true); - final List result = new ArrayList(output.size()); - for (String s : output) { - final char ch = s.charAt(0); - if (!(ch == 'R' || ch == 'I' || ch == '?' || ch == '!')) { - result.add(s.substring(2)); - } - } - return result; - } - - private static List getOutgoingFiles() throws Exception { - final String[] cmd; - if (OUTGOING_REPO.getValue() == null) { - cmd = new String[] {hgPath, "-v", "outgoing"}; - } else { - cmd = new String[] {hgPath, "-v", "outgoing", OUTGOING_REPO.getValue()}; - } - - final List output = exec(null, cmd, false); // no outgoing exits with result 1 - return getFilesFiles(output); - } - - private static List getFilesFiles(List output) { - // there may be multiple changesets so merge the "files:" - final Map outSet = new TreeMap(); - for (String s : output) { - if (s.startsWith("files:")) { - int ix = s.indexOf(' '); - while (ix < s.length() && s.charAt(ix) == ' ') { - ix++; - } - final String[] files = s.substring(ix).split(" "); - for (String file : files) { - outSet.put(file, file); - } - } - } - return new ArrayList(outSet.values()); - } - - private static List getDirWalkFiles() { - File cwd = new File(System.getProperty("user.dir")); - ArrayList result = new ArrayList(); - getDirWalkFiles(cwd, result); - // remove "user.dir" prefix to make files relative as per hg - String cwdPath = cwd.getAbsolutePath() + '/'; - for (int i = 0; i < result.size(); i++) { - String path = result.get(i); - result.set(i, path.replace(cwdPath, "")); - } - return result; - } - - private static void getDirWalkFiles(File dir, ArrayList list) { - File[] files = dir.listFiles(); - for (File file : files) { - if (ignoreFile(file.getName())) { - continue; - } - if (file.isDirectory()) { - getDirWalkFiles(file, list); - } else { - list.add(file.getAbsolutePath()); - } - } - } - - private static final String IGNORE_LIST = "\\.hg|.*\\.class|bin|src_gen"; - private static final Pattern ignorePattern = Pattern.compile(IGNORE_LIST); - - private static boolean ignoreFile(String name) { - return ignorePattern.matcher(name).matches(); - } - - private static List exec(File workingDir, String[] command, boolean failOnError) throws IOException, InterruptedException { - List result = new ArrayList(); - if (veryVerbose) { - System.out.println("Executing process in directory: " + workingDir); - for (String c : command) { - System.out.println(" " + c); - } - } - final Process process = Runtime.getRuntime().exec(command, null, workingDir); - try { - result = readOutput(process.getInputStream()); - final int exitValue = process.waitFor(); - if (exitValue != 0) { - final List errorResult = readOutput(process.getErrorStream()); - if (REPORT_ERRORS.getValue()) { - System.err.print("execution of command: "); - for (String c : command) { - System.err.print(c); - System.err.print(' '); - } - System.err.println("failed with result " + exitValue); - for (String e : errorResult) { - System.err.println(e); - } - } - if (failOnError && HALT_ON_ERROR.getValue()) { - if (!cannotFollowNonExistentFile(errorResult)) { - throw new Error("terminating"); - } - } - } - } finally { - process.destroy(); - } - return result; - } - - private static boolean cannotFollowNonExistentFile(List errorResult) { - return errorResult.size() == 1 && errorResult.get(0).startsWith(CANNOT_FOLLOW_FILE); - } - - private static List readOutput(InputStream is) throws IOException { - final List result = new ArrayList(); - BufferedReader bs = null; - try { - bs = new BufferedReader(new InputStreamReader(is)); - while (true) { - final String line = bs.readLine(); - if (line == null) { - break; - } - result.add(line); - } - } finally { - if (bs != null) { - bs.close(); - } - } - return result; - } - - private static class Options { - private static Map> optionMap = new TreeMap<>(); - - private Option newBooleanOption(String name, boolean defaultValue, String help) { - Option option = new Option(name, help, defaultValue, false, false); - optionMap.put(key(name), option); - return option; - } - - private Option newStringOption(String name, String defaultValue, String help) { - Option option = new Option(name, help, defaultValue); - optionMap.put(key(name), option); - return option; - } - - private Option> newStringListOption(String name, List defaultValue, String help) { - Option> option = new Option>(name, help, defaultValue, true, true); - optionMap.put(key(name), option); - return option; - } - - private static String key(String name) { - return "--" + name; - } - - void parseArguments(String[] args) { - for (int i = 0; i < args.length; i++) { - final String arg = args[i]; - if (arg.startsWith("--")) { - Option option = optionMap.get(arg); - if (option == null || (option.consumesNext() && i == args.length - 1)) { - System.out.println("usage:"); - printHelp(); - System.exit(1); - } - if (option.consumesNext()) { - i++; - option.setValue(args[i]); - } else { - option.setValue(true); - } - } - } - } - - void printHelp() { - int maxKeyLen = 0; - for (Map.Entry> entrySet : optionMap.entrySet()) { - int l = entrySet.getKey().length(); - if (l > maxKeyLen) { - maxKeyLen = l; - } - } - for (Map.Entry> entrySet : optionMap.entrySet()) { - String key = entrySet.getKey(); - System.out.printf(" %s", key); - for (int i = 0; i < maxKeyLen - key.length(); i++) { - System.out.print(' '); - } - System.out.printf(" %s%n", entrySet.getValue().help); - } - } -} - - private static class Option { - private final String name; - private final String help; - private final boolean consumesNext; - private final boolean isList; - private T value; - - Option(String name, String help, T defaultValue, boolean consumesNext, boolean isList) { - this.name = name; - this.help = help; - this.value = defaultValue; - this.consumesNext = consumesNext; - this.isList = isList; - - } - - Option(String name, String help, T defaultValue) { - this(name, help, defaultValue, true, false); - } - - T getValue() { - return value; - } - - boolean consumesNext() { - return consumesNext; - } - - @SuppressWarnings("unchecked") - void setValue(boolean value) { - this.value = (T) new Boolean(value); - } - - @SuppressWarnings("unchecked") - void setValue(String value) { - if (isList) { - String[] parts = value.split(","); - this.value = (T) Arrays.asList(parts); - } else { - this.value = (T) value; - } - } - - @SuppressWarnings("unused") - String getName() { - return name; - } - } - -} diff -r 103f53747955 -r 258eaaa98484 mxtool/ClasspathDump.java --- a/mxtool/ClasspathDump.java Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -public class ClasspathDump { - public static void main(String[] args) { - System.out.print(System.getProperty("sun.boot.class.path")); - System.out.print("|"); - System.out.print(System.getProperty("java.ext.dirs")); - System.out.print("|"); - System.out.print(System.getProperty("java.endorsed.dirs")); - } -} \ No newline at end of file diff -r 103f53747955 -r 258eaaa98484 mxtool/URLConnectionDownload.java --- a/mxtool/URLConnectionDownload.java Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -import java.io.*; -import java.net.*; -import java.util.*; -import java.util.regex.*; - -/** - * Downloads content from a given URL to a given file. - * - * @param path where to write the content - * @param urls the URLs to try, stopping after the first successful one - */ -public class URLConnectionDownload { - /** - * Iterate over list of environment variable to find one that correctly specify an proxy. - * - * @param propPrefix indicates which proxy property to set (i.e., http or https) - * @param proxyEnvVariableNames list of environment variable - * @return a string specifying the proxy url - */ - private static String setProxy(String[] proxyEnvVariableNames, String propPrefix) { - String proxy = null; - String proxyEnvVar = ""; - for (String envvar : proxyEnvVariableNames) { - proxy = System.getenv(envvar); - if (proxy != null) { - proxyEnvVar = envvar; - break; - } - } - if (proxy != null) { - Pattern p = Pattern.compile("(?:http://)?([^:]+)(:\\d+)?"); - Matcher m = p.matcher(proxy); - if (m.matches()) { - String host = m.group(1); - String port = m.group(2); - System.setProperty(propPrefix + ".proxyHost", host); - if (port != null) { - port = port.substring(1); // strip ':' - System.setProperty(propPrefix + ".proxyPort", port); - } - return proxy; - } else { - System.err.println("Value of " + proxyEnvVar + " is not valid: " + proxy); - } - } else { - System.err.println("** If behind a firewall without direct internet access, use the " + proxyEnvVariableNames[0] + " environment variable (e.g. 'env " + proxyEnvVariableNames[0] + - "=proxy.company.com:80 max ...') or download manually with a web browser."); - } - return ""; - } - - /** - * Downloads content from a given URL to a given file. - * - * @param args arg[0] is the path where to write the content. The remainder of args are the URLs - * to try, stopping after the first successful one - */ - public static void main(String[] args) { - File path = new File(args[0]); - boolean verbose = args[1].equals("-v"); - int offset = verbose ? 2 : 1; - String[] urls = new String[args.length - offset]; - System.arraycopy(args, offset, urls, 0, urls.length); - - File parent = path.getParentFile(); - makeDirectory(parent); - - // Enable use of system proxies - System.setProperty("java.net.useSystemProxies", "true"); - - // Set standard proxy if any - String proxy = setProxy(new String[]{"HTTP_PROXY", "http_proxy"}, "http"); - // Set proxy for secure http if explicitely set, default to http proxy otherwise - String secureProxy = setProxy(new String[]{"HTTPS_PROXY", "https_proxy", "HTTP_PROXY", "http_proxy"}, "https"); - String proxyMsg = ""; - if (secureProxy.length() > 0 && proxy.length() > 0 && !secureProxy.equals(proxy)) { - proxyMsg = " via " + proxy + " / " + secureProxy; - } else if (proxy.length() > 0) { - proxyMsg = " via " + proxy; - } else if (secureProxy.length() > 0) { - proxyMsg = " via " + secureProxy; - } - - for (String s : urls) { - try { - while (true) { - System.err.println("Downloading " + s + " to " + path + proxyMsg); - URL url = new URL(s); - URLConnection conn = url.openConnection(); - // 10 second timeout to establish connection - conn.setConnectTimeout(10000); - - if (conn instanceof HttpURLConnection) { - // HttpURLConnection per default follows redirections, - // but not if it changes the protocol (e.g. http -> - // https). While this is a sane default, in our - // situation it's okay to follow a protocol transition. - HttpURLConnection httpconn = (HttpURLConnection) conn; - switch (httpconn.getResponseCode()) { - case HttpURLConnection.HTTP_MOVED_PERM: - case HttpURLConnection.HTTP_MOVED_TEMP: - System.err.println("follow redirect..."); - s = httpconn.getHeaderField("Location"); - continue; - } - } - InputStream in = conn.getInputStream(); - int size = conn.getContentLength(); - FileOutputStream out = new FileOutputStream(path); - int read = 0; - byte[] buf = new byte[8192]; - int n = 0; - while ((read = in.read(buf)) != -1) { - n += read; - if (verbose) { - long percent = ((long) n * 100 / size); - System.err.print("\r " + n + " bytes " + (size == -1 ? "" : " (" + percent + "%)")); - } - out.write(buf, 0, read); - } - System.err.println(); - out.close(); - in.close(); - return; - } - } catch (MalformedURLException e) { - throw new Error("Error in URL " + s, e); - } catch (IOException e) { - System.err.println("Error reading from " + s + ": " + e); - path.delete(); - } - } - throw new Error("Could not download content to " + path + " from " + Arrays.toString(urls)); - } - - private static void makeDirectory(File directory) { - if (!directory.exists() && !directory.mkdirs()) { - throw new Error("Could not make directory " + directory); - } - } -} diff -r 103f53747955 -r 258eaaa98484 mxtool/copyrights/oracle.copyright.hash --- a/mxtool/copyrights/oracle.copyright.hash Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -# -# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# diff -r 103f53747955 -r 258eaaa98484 mxtool/copyrights/oracle.copyright.regex.hash --- a/mxtool/copyrights/oracle.copyright.regex.hash Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -(?:#!.*\n#\n#\ -*\n)?#\n# Copyright \(c\) (?:(20[0-9][0-9]), )?(20[0-9][0-9]), Oracle and/or its affiliates. All rights reserved.\n# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n#\n# This code is free software; you can redistribute it and/or modify it\n# under the terms of the GNU General Public License version 2 only, as\n# published by the Free Software Foundation.\n#\n# This code is distributed in the hope that it will be useful, but WITHOUT\n# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n# version 2 for more details \(a copy is included in the LICENSE file that\n# accompanied this code\).\n#\n# You should have received a copy of the GNU General Public License version\n# 2 along with this work; if not, write to the Free Software Foundation,\n# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n#\n# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n# or visit www.oracle.com if you need additional information or have any\n# questions.\n#\n.* diff -r 103f53747955 -r 258eaaa98484 mxtool/copyrights/oracle.copyright.regex.star --- a/mxtool/copyrights/oracle.copyright.regex.star Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -/\*\n \* Copyright \(c\) (?:(20[0-9][0-9]), )?(20[0-9][0-9]), Oracle and/or its affiliates. All rights reserved.\n \* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n \*\n \* This code is free software; you can redistribute it and/or modify it\n \* under the terms of the GNU General Public License version 2 only, as\n \* published by the Free Software Foundation.\n \*\n \* This code is distributed in the hope that it will be useful, but WITHOUT\n \* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n \* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n \* version 2 for more details \(a copy is included in the LICENSE file that\n \* accompanied this code\).\n \*\n \* You should have received a copy of the GNU General Public License version\n \* 2 along with this work; if not, write to the Free Software Foundation,\n \* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n \*\n \* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n \* or visit www.oracle.com if you need additional information or have any\n \* questions.\n \*/\n.* diff -r 103f53747955 -r 258eaaa98484 mxtool/copyrights/oracle.copyright.star --- a/mxtool/copyrights/oracle.copyright.star Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ diff -r 103f53747955 -r 258eaaa98484 mxtool/eclipse-settings/org.eclipse.core.resources.prefs --- a/mxtool/eclipse-settings/org.eclipse.core.resources.prefs Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -encoding/=UTF-8 diff -r 103f53747955 -r 258eaaa98484 mxtool/eclipse-settings/org.eclipse.jdt.apt.core.prefs --- a/mxtool/eclipse-settings/org.eclipse.jdt.apt.core.prefs Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.apt.aptEnabled=true -org.eclipse.jdt.apt.genSrcDir=src_gen -org.eclipse.jdt.apt.reconcileEnabled=true diff -r 103f53747955 -r 258eaaa98484 mxtool/eclipse-settings/org.eclipse.jdt.core.prefs --- a/mxtool/eclipse-settings/org.eclipse.jdt.core.prefs Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,417 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.builder.cleanOutputFolder=clean -org.eclipse.jdt.core.builder.duplicateResourceTask=warning -org.eclipse.jdt.core.builder.invalidClasspath=abort -org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore -org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch -org.eclipse.jdt.core.circularClasspath=error -org.eclipse.jdt.core.classpath.exclusionPatterns=enabled -org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled -org.eclipse.jdt.core.codeComplete.argumentPrefixes= -org.eclipse.jdt.core.codeComplete.argumentSuffixes= -org.eclipse.jdt.core.codeComplete.fieldPrefixes= -org.eclipse.jdt.core.codeComplete.fieldSuffixes= -org.eclipse.jdt.core.codeComplete.localPrefixes= -org.eclipse.jdt.core.codeComplete.localSuffixes= -org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= -org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= -org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes= -org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes= -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=${javaCompliance} -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=${javaCompliance} -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.doc.comment.support=enabled -org.eclipse.jdt.core.compiler.maxProblemPerUnit=100 -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=enabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=ignore -org.eclipse.jdt.core.compiler.problem.emptyStatement=warning -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=ignore -org.eclipse.jdt.core.compiler.problem.forbiddenReference=ignore -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error -org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled -org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled -org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled -org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private -org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=error -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning -org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore -org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled -org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public -org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag -org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore -org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled -org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled -org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=disabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=warning -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=enabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=error -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unsafeTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning -org.eclipse.jdt.core.compiler.problem.unusedParameter=warning -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.processAnnotations=disabled -org.eclipse.jdt.core.compiler.source=${javaCompliance} -org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled -org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,HIGH,NORMAL -org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME,XXX -org.eclipse.jdt.core.formatter.align_type_members_on_columns=false -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=48 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 -org.eclipse.jdt.core.formatter.alignment_for_assignment=0 -org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 -org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 -org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 -org.eclipse.jdt.core.formatter.alignment_for_enum_constants=49 -org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 -org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 -org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 -org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 -org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 -org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=48 -org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 -org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 -org.eclipse.jdt.core.formatter.blank_lines_after_package=1 -org.eclipse.jdt.core.formatter.blank_lines_before_field=0 -org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 -org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 -org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 -org.eclipse.jdt.core.formatter.blank_lines_before_method=1 -org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 -org.eclipse.jdt.core.formatter.blank_lines_before_package=0 -org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 -org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 -org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line -org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false -org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false -org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false -org.eclipse.jdt.core.formatter.comment.format_block_comments=true -org.eclipse.jdt.core.formatter.comment.format_comments=true -org.eclipse.jdt.core.formatter.comment.format_header=false -org.eclipse.jdt.core.formatter.comment.format_html=true -org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true -org.eclipse.jdt.core.formatter.comment.format_line_comments=true -org.eclipse.jdt.core.formatter.comment.format_source_code=true -org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true -org.eclipse.jdt.core.formatter.comment.indent_root_tags=true -org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert -org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert -org.eclipse.jdt.core.formatter.comment.line_length=100 -org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true -org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true -org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true -org.eclipse.jdt.core.formatter.compact_else_if=true -org.eclipse.jdt.core.formatter.continuation_indentation=4 -org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 -org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off -org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on -org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false -org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true -org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true -org.eclipse.jdt.core.formatter.indent_empty_lines=false -org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true -org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true -org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true -org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true -org.eclipse.jdt.core.formatter.indentation.size=4 -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert -org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert -org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert -org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert -org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert -org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert -org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert -org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert -org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.join_lines_in_comments=true -org.eclipse.jdt.core.formatter.join_wrapped_lines=true -org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false -org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=true -org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false -org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false -org.eclipse.jdt.core.formatter.lineSplit=200 -org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true -org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true -org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 -org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 -org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true -org.eclipse.jdt.core.formatter.tabulation.char=space -org.eclipse.jdt.core.formatter.tabulation.size=4 -org.eclipse.jdt.core.formatter.use_on_off_tags=true -org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false -org.eclipse.jdt.core.formatter.wrap_before_binary_operator=false -org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true -org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true -org.eclipse.jdt.core.incompatibleJDKLevel=ignore -org.eclipse.jdt.core.incompleteClasspath=error diff -r 103f53747955 -r 258eaaa98484 mxtool/eclipse-settings/org.eclipse.jdt.ui.prefs --- a/mxtool/eclipse-settings/org.eclipse.jdt.ui.prefs Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +0,0 @@ -cleanup.add_default_serial_version_id=false -cleanup.add_generated_serial_version_id=false -cleanup.add_missing_annotations=false -cleanup.add_missing_deprecated_annotations=false -cleanup.add_missing_nls_tags=false -cleanup.add_missing_override_annotations=false -cleanup.add_serial_version_id=false -cleanup.always_use_blocks=false -cleanup.always_use_parentheses_in_expressions=false -cleanup.always_use_this_for_non_static_field_access=false -cleanup.always_use_this_for_non_static_method_access=false -cleanup.convert_to_enhanced_for_loop=false -cleanup.format_source_code=false -cleanup.make_local_variable_final=false -cleanup.make_parameters_final=false -cleanup.make_private_fields_final=true -cleanup.make_variable_declarations_final=false -cleanup.never_use_blocks=false -cleanup.never_use_parentheses_in_expressions=false -cleanup.organize_imports=false -cleanup.qualify_static_field_accesses_with_declaring_class=false -cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=false -cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=false -cleanup.qualify_static_member_accesses_with_declaring_class=false -cleanup.qualify_static_method_accesses_with_declaring_class=false -cleanup.remove_private_constructors=false -cleanup.remove_trailing_whitespaces=false -cleanup.remove_trailing_whitespaces_all=false -cleanup.remove_trailing_whitespaces_ignore_empty=false -cleanup.remove_unnecessary_casts=false -cleanup.remove_unnecessary_nls_tags=false -cleanup.remove_unused_imports=false -cleanup.remove_unused_local_variables=false -cleanup.remove_unused_private_fields=false -cleanup.remove_unused_private_members=false -cleanup.remove_unused_private_methods=false -cleanup.remove_unused_private_types=false -cleanup.sort_members=false -cleanup.sort_members_all=false -cleanup.use_blocks=false -cleanup.use_blocks_only_for_return_and_throw=false -cleanup.use_parentheses_in_expressions=false -cleanup.use_this_for_non_static_field_access=false -cleanup.use_this_for_non_static_field_access_only_if_necessary=false -cleanup.use_this_for_non_static_method_access=false -cleanup.use_this_for_non_static_method_access_only_if_necessary=false -cleanup_profile=_CleanUpAgitarTests -cleanup_settings_version=2 -comment_clear_blank_lines=false -comment_format_comments=true -comment_format_header=false -comment_format_html=true -comment_format_source_code=true -comment_indent_parameter_description=true -comment_indent_root_tags=true -comment_line_length=120 -comment_new_line_for_parameter=true -comment_separate_root_tags=true -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -formatter_profile=_Graal -formatter_settings_version=12 -org.eclipse.jdt.ui.exception.name=e -org.eclipse.jdt.ui.gettersetter.use.is=true -org.eclipse.jdt.ui.ignorelowercasenames=true -org.eclipse.jdt.ui.importorder=java;javax;org;com; -org.eclipse.jdt.ui.javadoc=false -org.eclipse.jdt.ui.keywordthis=false -org.eclipse.jdt.ui.ondemandthreshold=0 -org.eclipse.jdt.ui.overrideannotation=true -org.eclipse.jdt.ui.staticondemandthreshold=0 -sp_cleanup.add_default_serial_version_id=false -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=false -sp_cleanup.add_missing_deprecated_annotations=false -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=false -sp_cleanup.add_missing_override_annotations_interface_methods=false -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=false -sp_cleanup.always_use_parentheses_in_expressions=false -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=false -sp_cleanup.correct_indentation=false -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=false -sp_cleanup.make_local_variable_final=false -sp_cleanup.make_parameters_final=false -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=false -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=false -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_with_declaring_class=false -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=false -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=false -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=false -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=false -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=false -sp_cleanup.remove_unused_private_types=false -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=false -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false -sp_cleanup.use_this_for_non_static_method_access=false -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false diff -r 103f53747955 -r 258eaaa98484 mxtool/java/com.oracle.mxtool.junit/.checkstyle_checks.xml --- a/mxtool/java/com.oracle.mxtool.junit/.checkstyle_checks.xml Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,212 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 103f53747955 -r 258eaaa98484 mxtool/java/com.oracle.mxtool.junit/src/com/oracle/mxtool/junit/AnsiTerminalDecorator.java --- a/mxtool/java/com.oracle.mxtool.junit/src/com/oracle/mxtool/junit/AnsiTerminalDecorator.java Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.mxtool.junit; - -import org.junit.runner.*; -import org.junit.runner.notification.*; - -/** - * Color support for JUnit test output using ANSI escapes codes. - */ -public class AnsiTerminalDecorator extends MxRunListenerDecorator { - - /** Foreground black. */ - public static final String BLACK = "\u001b[30m"; - /** Foreground red. */ - public static final String RED = "\u001b[31m"; - /** Foreground green. */ - public static final String GREEN = "\u001b[32m"; - /** Foreground yellow. */ - public static final String YELLOW = "\u001b[33m"; - /** Foreground blue. */ - public static final String BLUE = "\u001b[34m"; - /** Foreground magenta. */ - public static final String MAGENTA = "\u001b[35m"; - /** Foreground cyan. */ - public static final String CYAN = "\u001b[36m"; - /** Foreground white. */ - public static final String WHITE = "\u001b[37m"; - - /** Foreground bold black. */ - public static final String BOLD_BLACK = "\u001b[30;1m"; - /** Foreground bold red. */ - public static final String BOLD_RED = "\u001b[31;1m"; - /** Foreground bold green. */ - public static final String BOLD_GREEN = "\u001b[32;1m"; - /** Foreground bold yellow. */ - public static final String BOLD_YELLOW = "\u001b[33;1m"; - /** Foreground bold blue. */ - public static final String BOLD_BLUE = "\u001b[34;1m"; - /** Foreground bold magenta. */ - public static final String BOLD_MAGENTA = "\u001b[35;1m"; - /** Foreground bold cyan. */ - public static final String BOLD_CYAN = "\u001b[36;1m"; - /** Foreground bold white. */ - public static final String BOLD_WHITE = "\u001b[37;1m"; - - /** Background black. */ - public static final String BG_BLACK = "\u001b[40m"; - /** Background red. */ - public static final String BG_RED = "\u001b[41m"; - /** Background green. */ - public static final String BG_GREEN = "\u001b[42m"; - /** Background yellow. */ - public static final String BG_YELLOW = "\u001b[43m"; - /** Background blue. */ - public static final String BG_BLUE = "\u001b[44m"; - /** Background magenta. */ - public static final String BG_MAGENTA = "\u001b[45m"; - /** Background cyan. */ - public static final String BG_CYAN = "\u001b[46m"; - /** Background white. */ - public static final String BG_WHITE = "\u001b[47m"; - - /** Reset. */ - public static final String RESET = "\u001b[0m"; - /** Underline. */ - public static final String UNDERLINED = "\u001b[4m"; - - public AnsiTerminalDecorator(MxRunListener l) { - super(l); - } - - @Override - public void testSucceeded(Description description) { - getWriter().print(GREEN); - super.testSucceeded(description); - getWriter().print(RESET); - } - - @Override - public void testAssumptionFailure(Failure failure) { - getWriter().print(BLUE); - super.testAssumptionFailure(failure); - getWriter().print(RESET); - } - - @Override - public void testFailed(Failure failure) { - getWriter().print(RED); - super.testFailed(failure); - getWriter().print(RESET); - } - - @Override - public void testIgnored(Description description) { - getWriter().print(MAGENTA); - super.testIgnored(description); - getWriter().print(RESET); - } -} diff -r 103f53747955 -r 258eaaa98484 mxtool/java/com.oracle.mxtool.junit/src/com/oracle/mxtool/junit/EagerStackTraceDecorator.java --- a/mxtool/java/com.oracle.mxtool.junit/src/com/oracle/mxtool/junit/EagerStackTraceDecorator.java Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.mxtool.junit; - -import org.junit.runner.notification.*; - -public class EagerStackTraceDecorator extends MxRunListenerDecorator { - - public EagerStackTraceDecorator(MxRunListener l) { - super(l); - } - - @Override - public void testFailed(Failure failure) { - super.testFailed(failure); - failure.getException().printStackTrace(getWriter()); - } - -} diff -r 103f53747955 -r 258eaaa98484 mxtool/java/com.oracle.mxtool.junit/src/com/oracle/mxtool/junit/GCAfterTestDecorator.java --- a/mxtool/java/com.oracle.mxtool.junit/src/com/oracle/mxtool/junit/GCAfterTestDecorator.java Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.mxtool.junit; - -import org.junit.runner.*; - -public class GCAfterTestDecorator extends MxRunListenerDecorator { - - public GCAfterTestDecorator(MxRunListener l) { - super(l); - } - - @Override - public void testFinished(Description description) { - System.gc(); - super.testFinished(description); - } -} diff -r 103f53747955 -r 258eaaa98484 mxtool/java/com.oracle.mxtool.junit/src/com/oracle/mxtool/junit/MxJUnitWrapper.java --- a/mxtool/java/com.oracle.mxtool.junit/src/com/oracle/mxtool/junit/MxJUnitWrapper.java Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,246 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.mxtool.junit; - -import java.io.*; -import java.lang.reflect.Modifier; -import java.nio.file.*; -import java.util.*; - -import junit.runner.*; - -import org.junit.internal.*; -import org.junit.runner.*; -import org.junit.runner.notification.*; -import org.junit.runners.*; -import org.junit.runners.model.*; - -public class MxJUnitWrapper { - - /** - * Run the tests contained in the classes named in the args. A single test method - * can be specified by adding #method after the class name. Only a single test can be run in - * this way. If all tests run successfully, exit with a status of 0. Otherwise exit with a - * status of 1. Write feedback while tests are running and write stack traces for all failed - * tests after the tests all complete. - * - * @param args names of classes in which to find tests to run - */ - public static void main(String... args) { - JUnitSystem system = new RealSystem(); - JUnitCore junitCore = new JUnitCore(); - system.out().println("MxJUnitCore"); - system.out().println("JUnit version " + Version.id()); - List> classes = new ArrayList<>(); - String methodName = null; - List missingClasses = new ArrayList<>(); - boolean verbose = false; - boolean enableTiming = false; - boolean failFast = false; - boolean color = false; - boolean eagerStackTrace = false; - boolean gcAfterTest = false; - - String[] expandedArgs = expandArgs(args); - for (int i = 0; i < expandedArgs.length; i++) { - String each = expandedArgs[i]; - if (each.charAt(0) == '-') { - // command line arguments - if (each.contentEquals("-JUnitVerbose")) { - verbose = true; - } else if (each.contentEquals("-JUnitFailFast")) { - failFast = true; - } else if (each.contentEquals("-JUnitEnableTiming")) { - enableTiming = true; - } else if (each.contentEquals("-JUnitColor")) { - color = true; - } else if (each.contentEquals("-JUnitEagerStackTrace")) { - eagerStackTrace = true; - } else if (each.contentEquals("-JUnitGCAfterTest")) { - gcAfterTest = true; - } else { - system.out().println("Unknown command line argument: " + each); - } - - } else { - /* - * Entries of the form class#method are handled specially. Only one can be specified - * on the command line as there's no obvious way to build a runner for multiple - * ones. - */ - if (methodName != null) { - system.out().println("Only a single class and method can be specified: " + each); - System.exit(1); - } else if (each.contains("#")) { - String[] pair = each.split("#"); - if (pair.length != 2) { - system.out().println("Malformed class and method request: " + each); - System.exit(1); - } else if (classes.size() != 0) { - system.out().println("Only a single class and method can be specified: " + each); - System.exit(1); - } else { - methodName = pair[1]; - each = pair[0]; - } - } - try { - Class cls = Class.forName(each, false, MxJUnitWrapper.class.getClassLoader()); - if ((cls.getModifiers() & Modifier.ABSTRACT) == 0) { - classes.add(cls); - } - } catch (ClassNotFoundException e) { - system.out().println("Could not find class: " + each); - Description description = Description.createSuiteDescription(each); - Failure failure = new Failure(description, e); - missingClasses.add(failure); - } - } - } - final TextRunListener textListener; - if (!verbose) { - textListener = new TextRunListener(system); - } else { - textListener = new VerboseTextListener(system); - } - MxRunListener mxListener = textListener; - if (enableTiming) { - mxListener = new TimingDecorator(mxListener); - } - if (color) { - mxListener = new AnsiTerminalDecorator(mxListener); - } - if (eagerStackTrace) { - mxListener = new EagerStackTraceDecorator(mxListener); - } - if (gcAfterTest) { - mxListener = new GCAfterTestDecorator(mxListener); - } - junitCore.addListener(TextRunListener.createRunListener(mxListener)); - Request request; - if (methodName == null) { - request = Request.classes(classes.toArray(new Class[0])); - if (failFast) { - Runner runner = request.getRunner(); - if (runner instanceof ParentRunner) { - ParentRunner parentRunner = (ParentRunner) runner; - parentRunner.setScheduler(new RunnerScheduler() { - public void schedule(Runnable childStatement) { - if (textListener.getLastFailure() == null) { - childStatement.run(); - } - } - - public void finished() { - } - }); - } else { - system.out().println("Unexpected Runner subclass " + runner.getClass().getName() + " - fail fast not supported"); - } - } - } else { - if (failFast) { - system.out().println("Single method selected - fail fast not supported"); - } - request = Request.method(classes.get(0), methodName); - } - Result result = junitCore.run(request); - for (Failure each : missingClasses) { - result.getFailures().add(each); - } - System.exit(result.wasSuccessful() ? 0 : 1); - } - - /** - * Gets the command line for the current process. - * - * @return the command line arguments for the current process or {@code null} if they are not - * available - */ - public static List getProcessCommandLine() { - String processArgsFile = System.getenv().get("MX_SUBPROCESS_COMMAND_FILE"); - if (processArgsFile != null) { - try { - return Files.readAllLines(new File(processArgsFile).toPath()); - } catch (IOException e) { - } - } - return null; - } - - /** - * Expand any arguments starting with @ and return the resulting argument array. - * - * @param args - * @return the expanded argument array - */ - private static String[] expandArgs(String[] args) { - List result = null; - for (int i = 0; i < args.length; i++) { - String arg = args[i]; - if (arg.length() > 0 && arg.charAt(0) == '@') { - if (result == null) { - result = new ArrayList<>(); - for (int j = 0; j < i; j++) { - result.add(args[j]); - } - expandArg(arg.substring(1), result); - } - } else if (result != null) { - result.add(arg); - } - } - return result != null ? result.toArray(new String[0]) : args; - } - - /** - * Add each line from {@code filename} to the list {@code args}. - * - * @param filename - * @param args - */ - private static void expandArg(String filename, List args) { - BufferedReader br = null; - try { - br = new BufferedReader(new FileReader(filename)); - - String buf; - while ((buf = br.readLine()) != null) { - args.add(buf); - } - br.close(); - } catch (IOException ioe) { - ioe.printStackTrace(); - System.exit(2); - } finally { - try { - if (br != null) { - br.close(); - } - } catch (IOException ioe) { - ioe.printStackTrace(); - System.exit(3); - } - } - } -} diff -r 103f53747955 -r 258eaaa98484 mxtool/java/com.oracle.mxtool.junit/src/com/oracle/mxtool/junit/MxRunListener.java --- a/mxtool/java/com.oracle.mxtool.junit/src/com/oracle/mxtool/junit/MxRunListener.java Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.mxtool.junit; - -import java.io.*; - -import org.junit.internal.*; -import org.junit.runner.*; -import org.junit.runner.notification.*; - -public interface MxRunListener { - - /** - * Called before any tests have been run. - * - * @param description describes the tests to be run - */ - void testRunStarted(Description description); - - /** - * Called when all tests have finished. - * - * @param result the summary of the test run, including all the tests that failed - */ - void testRunFinished(Result result); - - /** - * Called when a test class is about to be started. - * - * @param clazz the test class - */ - void testClassStarted(Class clazz); - - /** - * Called when all tests of a test class have finished. - * - * @param clazz the test class - */ - void testClassFinished(Class clazz); - - /** - * Called when an atomic test is about to be started. This is also called for ignored tests. - * - * @param description the description of the test that is about to be run (generally a class and - * method name) - */ - void testStarted(Description description); - - /** - * Called when an atomic test has finished, whether the test succeeds, fails or is ignored. - * - * @param description the description of the test that just ran - */ - void testFinished(Description description); - - /** - * Called when an atomic test fails. - * - * @param failure describes the test that failed and the exception that was thrown - */ - void testFailed(Failure failure); - - /** - * Called when a test will not be run, generally because a test method is annotated with - * {@link org.junit.Ignore}. - * - * @param description describes the test that will not be run - */ - void testIgnored(Description description); - - /** - * Called when an atomic test succeeds. - * - * @param description describes the test that will not be run - */ - void testSucceeded(Description description); - - /** - * Called when an atomic test flags that it assumes a condition that is false. - * - * @param failure describes the test that failed and the {@link AssumptionViolatedException} - * that was thrown - */ - void testAssumptionFailure(Failure failure); - - /** - * Called after {@link #testClassFinished(Class)}. - */ - void testClassFinishedDelimiter(); - - /** - * Called after {@link #testClassStarted(Class)}. - */ - void testClassStartedDelimiter(); - - /** - * Called after {@link #testStarted(Description)}. - */ - void testStartedDelimiter(); - - /** - * Called after {@link #testFailed(Failure)}. - */ - void testFinishedDelimiter(); - - PrintStream getWriter(); - -} diff -r 103f53747955 -r 258eaaa98484 mxtool/java/com.oracle.mxtool.junit/src/com/oracle/mxtool/junit/MxRunListenerDecorator.java --- a/mxtool/java/com.oracle.mxtool.junit/src/com/oracle/mxtool/junit/MxRunListenerDecorator.java Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.mxtool.junit; - -import java.io.*; - -import org.junit.runner.*; -import org.junit.runner.notification.*; - -public class MxRunListenerDecorator implements MxRunListener { - - private final MxRunListener l; - - public MxRunListenerDecorator(MxRunListener l) { - this.l = l; - } - - @Override - public void testRunStarted(Description description) { - l.testRunStarted(description); - } - - @Override - public void testRunFinished(Result result) { - l.testRunFinished(result); - } - - @Override - public void testAssumptionFailure(Failure failure) { - l.testAssumptionFailure(failure); - } - - @Override - public void testIgnored(Description description) { - l.testIgnored(description); - } - - @Override - public void testClassStarted(Class clazz) { - l.testClassStarted(clazz); - } - - @Override - public void testClassFinished(Class clazz) { - l.testClassFinished(clazz); - } - - @Override - public void testStarted(Description description) { - l.testStarted(description); - } - - @Override - public void testFinished(Description description) { - l.testFinished(description); - } - - @Override - public void testFailed(Failure failure) { - l.testFailed(failure); - } - - @Override - public void testSucceeded(Description description) { - l.testSucceeded(description); - } - - @Override - public PrintStream getWriter() { - return l.getWriter(); - } - - public void testClassFinishedDelimiter() { - l.testClassFinishedDelimiter(); - } - - public void testClassStartedDelimiter() { - l.testClassStartedDelimiter(); - } - - public void testStartedDelimiter() { - l.testStartedDelimiter(); - } - - public void testFinishedDelimiter() { - l.testFinishedDelimiter(); - } - -} diff -r 103f53747955 -r 258eaaa98484 mxtool/java/com.oracle.mxtool.junit/src/com/oracle/mxtool/junit/TextRunListener.java --- a/mxtool/java/com.oracle.mxtool.junit/src/com/oracle/mxtool/junit/TextRunListener.java Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,182 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.mxtool.junit; - -import java.io.*; - -import org.junit.internal.*; -import org.junit.runner.*; -import org.junit.runner.notification.*; - -public class TextRunListener implements MxRunListener { - - private final PrintStream fWriter; - protected Failure lastFailure; - - public TextRunListener(JUnitSystem system) { - this(system.out()); - } - - public TextRunListener(PrintStream writer) { - fWriter = writer; - } - - @Override - public PrintStream getWriter() { - return fWriter; - } - - public Failure getLastFailure() { - return lastFailure; - } - - @Override - public void testRunStarted(Description description) { - } - - @Override - public void testRunFinished(Result result) { - } - - @Override - public void testAssumptionFailure(Failure failure) { - } - - @Override - public void testClassStarted(Class clazz) { - } - - @Override - public void testClassFinished(Class clazz) { - } - - @Override - public void testStarted(Description description) { - getWriter().print('.'); - } - - @Override - public void testFinished(Description description) { - } - - @Override - public void testFailed(Failure failure) { - getWriter().print('E'); - lastFailure = failure; - } - - @Override - public void testSucceeded(Description description) { - } - - @Override - public void testIgnored(Description description) { - getWriter().print('I'); - } - - @Override - public void testClassFinishedDelimiter() { - } - - @Override - public void testClassStartedDelimiter() { - } - - @Override - public void testStartedDelimiter() { - } - - @Override - public void testFinishedDelimiter() { - } - - public static RunListener createRunListener(MxRunListener l) { - return new TextListener(l.getWriter()) { - private Class lastClass; - private boolean failed; - - @Override - public final void testStarted(Description description) { - Class currentClass = description.getTestClass(); - if (currentClass != lastClass) { - if (lastClass != null) { - l.testClassFinished(lastClass); - l.testClassFinishedDelimiter(); - } - lastClass = currentClass; - l.testClassStarted(currentClass); - l.testClassStartedDelimiter(); - } - failed = false; - l.testStarted(description); - l.testStartedDelimiter(); - } - - @Override - public final void testFailure(Failure failure) { - failed = true; - l.testFailed(failure); - } - - @Override - public final void testFinished(Description description) { - // we have to do this because there is no callback for successful tests - if (!failed) { - l.testSucceeded(description); - } - l.testFinished(description); - l.testFinishedDelimiter(); - } - - @Override - public void testIgnored(Description description) { - l.testStarted(description); - l.testStartedDelimiter(); - l.testIgnored(description); - l.testFinished(description); - l.testFinishedDelimiter(); - } - - @Override - public void testRunStarted(Description description) { - l.testRunStarted(description); - } - - @Override - public void testRunFinished(Result result) { - if (lastClass != null) { - l.testClassFinished(lastClass); - } - l.testRunFinished(result); - super.testRunFinished(result); - } - - @Override - public void testAssumptionFailure(Failure failure) { - l.testAssumptionFailure(failure); - } - - }; - } - -} diff -r 103f53747955 -r 258eaaa98484 mxtool/java/com.oracle.mxtool.junit/src/com/oracle/mxtool/junit/TimingDecorator.java --- a/mxtool/java/com.oracle.mxtool.junit/src/com/oracle/mxtool/junit/TimingDecorator.java Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.mxtool.junit; - -import org.junit.runner.*; - -/** - * Timing support for JUnit test runs. - */ -public class TimingDecorator extends MxRunListenerDecorator { - - private long startTime; - private long classStartTime; - - public TimingDecorator(MxRunListener l) { - super(l); - } - - @Override - public void testClassStarted(Class clazz) { - classStartTime = System.nanoTime(); - super.testClassStarted(clazz); - } - - @Override - public void testClassFinished(Class clazz) { - long totalTime = System.nanoTime() - classStartTime; - super.testClassFinished(clazz); - getWriter().print(' ' + valueToString(totalTime)); - } - - @Override - public void testStarted(Description description) { - startTime = System.nanoTime(); - super.testStarted(description); - } - - @Override - public void testFinished(Description description) { - long totalTime = System.nanoTime() - startTime; - super.testFinished(description); - getWriter().print(" " + valueToString(totalTime)); - } - - private static String valueToString(long value) { - return String.format("%d.%d ms", value / 1000000, (value / 100000) % 10); - } - -} diff -r 103f53747955 -r 258eaaa98484 mxtool/java/com.oracle.mxtool.junit/src/com/oracle/mxtool/junit/VerboseTextListener.java --- a/mxtool/java/com.oracle.mxtool.junit/src/com/oracle/mxtool/junit/VerboseTextListener.java Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.mxtool.junit; - -import java.io.*; - -import org.junit.internal.*; -import org.junit.runner.*; -import org.junit.runner.notification.*; - -public class VerboseTextListener extends TextRunListener { - - public VerboseTextListener(JUnitSystem system) { - this(system.out()); - } - - public VerboseTextListener(PrintStream writer) { - super(writer); - } - - @Override - public void testClassStarted(Class clazz) { - getWriter().print(clazz.getName() + " started"); - } - - @Override - public void testClassFinished(Class clazz) { - getWriter().print(clazz.getName() + " finished"); - } - - @Override - public void testStarted(Description description) { - getWriter().print(" " + description.getMethodName() + ": "); - } - - @Override - public void testIgnored(Description description) { - getWriter().print("Ignored"); - } - - @Override - public void testSucceeded(Description description) { - getWriter().print("Passed"); - } - - @Override - public void testAssumptionFailure(Failure failure) { - getWriter().printf("(%s) ", failure.getMessage()); - } - - @Override - public void testFailed(Failure failure) { - getWriter().print("FAILED"); - lastFailure = failure; - } - - @Override - public void testClassFinishedDelimiter() { - getWriter().println(); - } - - @Override - public void testClassStartedDelimiter() { - getWriter().println(); - } - - @Override - public void testFinishedDelimiter() { - getWriter().println(); - } - -} diff -r 103f53747955 -r 258eaaa98484 mxtool/mx --- a/mxtool/mx Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -#!/bin/bash -# -# ---------------------------------------------------------------------------------------------------- -# -# Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# -# ---------------------------------------------------------------------------------------------------- - -dir=`/bin/pwd` - -# Resolve location of this script so that mx.py can be found in the same directory -source="${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}" -while [ -h "$source" ]; do - dir="$(cd -P "$(dirname "$source")" && pwd)" - source="$(readlink "$source")" - [[ $source != /* ]] && source="$dir/$source" -done -dir="$(cd -P "$(dirname "$source")" && pwd)" - -if [ ! -f "$dir/mx.py" ]; then - echo "Cannot find mx.py in $dir" - exit 1 -fi - -# Not all systems (e.g. Mac OS X) have 'python2' on the path. -type python2.7 >/dev/null 2>&1 -if [ $? -eq 0 ]; then - python_exe=python2.7 -else - type python2 > /dev/null 2>&1 - if [ $? -eq 0 ]; then - python_exe=python2 - else - python_exe=python - fi -fi - -$python_exe < self.javaCompliance: - abort("Compliance level doesn't match: Distribution {0} requires {1}, but {2} is {3}.".format(self.name, self.javaCompliance, p.name, p.javaCompliance)) - - logv('[' + self.path + ': adding project ' + p.name + ']') - outputDir = p.output_dir() - for root, _, files in os.walk(outputDir): - relpath = root[len(outputDir) + 1:] - if relpath == join('META-INF', 'services'): - for service in files: - with open(join(root, service), 'r') as fp: - services.setdefault(service, []).extend([provider.strip() for provider in fp.readlines()]) - else: - for f in files: - arcname = join(relpath, f).replace(os.sep, '/') - with open(join(root, f), 'r') as fp: - contents = fp.read() - if not self.archiveparticipant or not self.archiveparticipant.__add__(arcname, contents): - arc.zf.writestr(arcname, contents) - if srcArc.zf: - sourceDirs = p.source_dirs() - if p.source_gen_dir(): - sourceDirs.append(p.source_gen_dir()) - for srcDir in sourceDirs: - for root, _, files in os.walk(srcDir): - relpath = root[len(srcDir) + 1:] - for f in files: - if f.endswith('.java'): - arcname = join(relpath, f).replace(os.sep, '/') - if not overwriteCheck(srcArc.zf, arcname, join(root, f)): - with open(join(root, f), 'r') as fp: - contents = fp.read() - if not self.archiveparticipant or not self.archiveparticipant.__addsrc__(arcname, contents): - srcArc.zf.writestr(arcname, contents) - - if self.archiveparticipant: - self.archiveparticipant.__closing__() - - for service, providers in services.iteritems(): - arcname = 'META-INF/services/' + service - # Convert providers to a set before printing to remove duplicates - arc.zf.writestr(arcname, '\n'.join(frozenset(providers))) - - self.notify_updated() - - def notify_updated(self): - for l in self.update_listeners: - l(self) - -""" -A dependency is a library or project specified in a suite. -""" -class Dependency: - def __init__(self, suite, name): - self.name = name - self.suite = suite - - def __cmp__(self, other): - return cmp(self.name, other.name) - - def __str__(self): - return self.name - - def __eq__(self, other): - return self.name == other.name - - def __ne__(self, other): - return self.name != other.name - - def __hash__(self): - return hash(self.name) - - def isLibrary(self): - return isinstance(self, Library) - - def isJreLibrary(self): - return isinstance(self, JreLibrary) - - def isProject(self): - return isinstance(self, Project) - -class Project(Dependency): - def __init__(self, suite, name, srcDirs, deps, javaCompliance, workingSets, d): - Dependency.__init__(self, suite, name) - self.srcDirs = srcDirs - self.deps = deps - self.checkstyleProj = name - self.javaCompliance = JavaCompliance(javaCompliance) if javaCompliance is not None else None - self.native = False - self.workingSets = workingSets - self.dir = d - - # The annotation processors defined by this project - self.definedAnnotationProcessors = None - self.definedAnnotationProcessorsDist = None - - # Create directories for projects that don't yet exist - if not exists(d): - os.mkdir(d) - for s in self.source_dirs(): - if not exists(s): - os.mkdir(s) - - def all_deps(self, deps, includeLibs, includeSelf=True, includeJreLibs=False, includeAnnotationProcessors=False): - """ - Add the transitive set of dependencies for this project, including - libraries if 'includeLibs' is true, to the 'deps' list. - """ - return sorted(self._all_deps_helper(deps, [], includeLibs, includeSelf, includeJreLibs, includeAnnotationProcessors)) - - def _all_deps_helper(self, deps, dependants, includeLibs, includeSelf=True, includeJreLibs=False, includeAnnotationProcessors=False): - if self in dependants: - abort(str(self) + 'Project dependency cycle found:\n ' + - '\n |\n V\n '.join(map(str, dependants[dependants.index(self):])) + - '\n |\n V\n ' + self.name) - childDeps = list(self.deps) - if includeAnnotationProcessors and len(self.annotation_processors()) > 0: - childDeps = self.annotation_processors() + childDeps - if self in deps: - return deps - for name in childDeps: - assert name != self.name - dep = dependency(name) - if not dep in deps: - if dep.isProject(): - dep._all_deps_helper(deps, dependants + [self], includeLibs=includeLibs, includeJreLibs=includeJreLibs, includeAnnotationProcessors=includeAnnotationProcessors) - elif dep.isProject or (dep.isLibrary() and includeLibs) or (dep.isJreLibrary() and includeJreLibs): - dep.all_deps(deps, includeLibs=includeLibs, includeJreLibs=includeJreLibs, includeAnnotationProcessors=includeAnnotationProcessors) - if not self in deps and includeSelf: - deps.append(self) - return deps - - def _compute_max_dep_distances(self, name, distances, dist): - currentDist = distances.get(name) - if currentDist is None or currentDist < dist: - distances[name] = dist - p = project(name, False) - if p is not None: - for dep in p.deps: - self._compute_max_dep_distances(dep, distances, dist + 1) - - def canonical_deps(self): - """ - Get the dependencies of this project that are not recursive (i.e. cannot be reached - via other dependencies). - """ - distances = dict() - result = set() - self._compute_max_dep_distances(self.name, distances, 0) - for n, d in distances.iteritems(): - assert d > 0 or n == self.name - if d == 1: - result.add(n) - - if len(result) == len(self.deps) and frozenset(self.deps) == result: - return self.deps - return result - - def max_depth(self): - """ - Get the maximum canonical distance between this project and its most distant dependency. - """ - distances = dict() - self._compute_max_dep_distances(self.name, distances, 0) - return max(distances.values()) - - def source_dirs(self): - """ - Get the directories in which the sources of this project are found. - """ - return [join(self.dir, s) for s in self.srcDirs] - - def source_gen_dir(self): - """ - Get the directory in which source files generated by the annotation processor are found/placed. - """ - if self.native: - return None - return join(self.dir, 'src_gen') - - def output_dir(self): - """ - Get the directory in which the class files of this project are found/placed. - """ - if self.native: - return None - return join(self.dir, 'bin') - - def jasmin_output_dir(self): - """ - Get the directory in which the Jasmin assembled class files of this project are found/placed. - """ - if self.native: - return None - return join(self.dir, 'jasmin_classes') - - def append_to_classpath(self, cp, resolve): - if not self.native: - cp.append(self.output_dir()) - - def eclipse_settings_sources(self): - """ - Gets a dictionary from the name of an Eclipse settings file to - the list of files providing its generated content, in overriding order - (i.e., settings from files later in the list override settings from - files earlier in the list). - """ - if not hasattr(self, '_eclipse_settings'): - esdict = {} - hasAps = self.annotation_processors_path() is not None - # start with the mxtool defaults - defaultEclipseSettingsDir = join(_mx_suite.dir, 'eclipse-settings') - if exists(defaultEclipseSettingsDir): - for name in os.listdir(defaultEclipseSettingsDir): - if isfile(join(defaultEclipseSettingsDir, name)) and name != "org.eclipse.jdt.apt.core.prefs" or hasAps: - esdict[name] = [os.path.abspath(join(defaultEclipseSettingsDir, name))] - - # append suite overrides - eclipseSettingsDir = join(self.suite.mxDir, 'eclipse-settings') - if exists(eclipseSettingsDir): - for name in os.listdir(eclipseSettingsDir): - if isfile(join(eclipseSettingsDir, name)) and name != "org.eclipse.jdt.apt.core.prefs" or hasAps: - esdict.setdefault(name, []).append(os.path.abspath(join(eclipseSettingsDir, name))) - - # check for project overrides - projectSettingsDir = join(self.dir, 'eclipse-settings') - if exists(projectSettingsDir): - for name in os.listdir(projectSettingsDir): - if isfile(join(projectSettingsDir, name)) and name != "org.eclipse.jdt.apt.core.prefs" or hasAps: - esdict.setdefault(name, []).append(os.path.abspath(join(projectSettingsDir, name))) - self._eclipse_settings = esdict - return self._eclipse_settings - - def find_classes_with_matching_source_line(self, pkgRoot, function, includeInnerClasses=False): - """ - Scan the sources of this project for Java source files containing a line for which - 'function' returns true. A map from class name to source file path for each existing class - corresponding to a matched source file is returned. - """ - result = dict() - pkgDecl = re.compile(r"^package\s+([a-zA-Z_][\w\.]*)\s*;$") - for srcDir in self.source_dirs(): - outputDir = self.output_dir() - for root, _, files in os.walk(srcDir): - for name in files: - if name.endswith('.java') and name != 'package-info.java': - matchFound = False - source = join(root, name) - with open(source) as f: - pkg = None - for line in f: - if line.startswith("package "): - match = pkgDecl.match(line) - if match: - pkg = match.group(1) - if function(line.strip()): - matchFound = True - if pkg and matchFound: - break - - if matchFound: - simpleClassName = name[:-len('.java')] - assert pkg is not None, 'could not find package statement in file ' + name - if pkgRoot is None or pkg.startswith(pkgRoot): - pkgOutputDir = join(outputDir, pkg.replace('.', os.path.sep)) - if exists(pkgOutputDir): - for e in os.listdir(pkgOutputDir): - if includeInnerClasses: - if e.endswith('.class') and (e.startswith(simpleClassName) or e.startswith(simpleClassName + '$')): - className = pkg + '.' + e[:-len('.class')] - result[className] = source - elif e == simpleClassName + '.class': - className = pkg + '.' + simpleClassName - result[className] = source - return result - - def _init_packages_and_imports(self): - if not hasattr(self, '_defined_java_packages'): - packages = set() - extendedPackages = set() - depPackages = set() - for d in self.all_deps([], includeLibs=False, includeSelf=False): - depPackages.update(d.defined_java_packages()) - imports = set() - importRe = re.compile(r'import\s+(?:static\s+)?([^;]+);') - for sourceDir in self.source_dirs(): - for root, _, files in os.walk(sourceDir): - javaSources = [name for name in files if name.endswith('.java')] - if len(javaSources) != 0: - pkg = root[len(sourceDir) + 1:].replace(os.sep, '.') - if not pkg in depPackages: - packages.add(pkg) - else: - # A project extends a package already defined by one of it dependencies - extendedPackages.add(pkg) - imports.add(pkg) - - for n in javaSources: - with open(join(root, n)) as fp: - content = fp.read() - imports.update(importRe.findall(content)) - self._defined_java_packages = frozenset(packages) - self._extended_java_packages = frozenset(extendedPackages) - - importedPackages = set() - for imp in imports: - name = imp - while not name in depPackages and len(name) > 0: - lastDot = name.rfind('.') - if lastDot == -1: - name = None - break - name = name[0:lastDot] - if name is not None: - importedPackages.add(name) - self._imported_java_packages = frozenset(importedPackages) - - def defined_java_packages(self): - """Get the immutable set of Java packages defined by the Java sources of this project""" - self._init_packages_and_imports() - return self._defined_java_packages - - def extended_java_packages(self): - """Get the immutable set of Java packages extended by the Java sources of this project""" - self._init_packages_and_imports() - return self._extended_java_packages - - def imported_java_packages(self): - """Get the immutable set of Java packages defined by other Java projects that are - imported by the Java sources of this project.""" - self._init_packages_and_imports() - return self._imported_java_packages - - """ - Gets the list of projects defining the annotation processors that will be applied - when compiling this project. This includes the projects declared by the annotationProcessors property - of this project and any of its project dependencies. It also includes - any project dependencies that define an annotation processors. - """ - def annotation_processors(self): - if not hasattr(self, '_annotationProcessors'): - aps = set() - if hasattr(self, '_declaredAnnotationProcessors'): - aps = set(self._declaredAnnotationProcessors) - for ap in aps: - # ap may be a Project or a Distribution - apd = dependency(ap) - if apd.isLibrary(): - # trust it, we could look inside I suppose - pass - elif apd.isProject(): - if apd.definedAnnotationProcessorsDist is None: - config = join(project(ap).source_dirs()[0], 'META-INF', 'services', 'javax.annotation.processing.Processor') - if not exists(config): - TimeStampFile(config).touch() - abort('Project ' + ap + ' declared in annotationProcessors property of ' + self.name + ' does not define any annotation processors.\n' + - 'Please specify the annotation processors in ' + config) - - allDeps = self.all_deps([], includeLibs=False, includeSelf=False, includeAnnotationProcessors=False) - for p in allDeps: - # Add an annotation processor dependency - if p.definedAnnotationProcessorsDist is not None: - aps.add(p.name) - - # Inherit annotation processors from dependencies - aps.update(p.annotation_processors()) - - self._annotationProcessors = sorted(list(aps)) - return self._annotationProcessors - - """ - Gets the class path composed of the distribution jars containing the - annotation processors that will be applied when compiling this project. - """ - def annotation_processors_path(self): - aps = [dependency(ap) for ap in self.annotation_processors()] - libAps = set() - for dep in self.all_deps([], includeLibs=True, includeSelf=False): - if dep.isLibrary() and hasattr(dep, 'annotationProcessor') and getattr(dep, 'annotationProcessor').lower() == 'true': - libAps = libAps.union(dep.all_deps([], includeLibs=True, includeSelf=True)) - if len(aps) + len(libAps): - apPaths = [] - for ap in aps: - if ap.isLibrary(): - for dep in ap.all_deps([], includeLibs=True): - dep.append_to_classpath(apPaths, True) - elif ap.definedAnnotationProcessorsDist: - apPaths.append(ap.definedAnnotationProcessorsDist.path) - return os.pathsep.join(apPaths + [lib.get_path(False) for lib in libAps]) - return None - - def uses_annotation_processor_library(self): - for dep in self.all_deps([], includeLibs=True, includeSelf=False): - if dep.isLibrary() and hasattr(dep, 'annotationProcessor'): - return True - return False - - def update_current_annotation_processors_file(self): - aps = self.annotation_processors() - outOfDate = False - currentApsFile = join(self.suite.mxDir, 'currentAnnotationProcessors', self.name) - currentApsFileExists = exists(currentApsFile) - if currentApsFileExists: - with open(currentApsFile) as fp: - currentAps = [l.strip() for l in fp.readlines()] - if currentAps != aps: - outOfDate = True - if outOfDate or not currentApsFileExists: - if not exists(dirname(currentApsFile)): - os.mkdir(dirname(currentApsFile)) - with open(currentApsFile, 'w') as fp: - for ap in aps: - print >> fp, ap - return outOfDate - - def make_archive(self, path=None): - outputDir = self.output_dir() - if not path: - path = join(self.dir, self.name + '.jar') - with Archiver(path) as arc: - for root, _, files in os.walk(outputDir): - for f in files: - relpath = root[len(outputDir) + 1:] - arcname = join(relpath, f).replace(os.sep, '/') - arc.zf.write(join(root, f), arcname) - return path - -def _make_absolute(path, prefix): - """ - Makes 'path' absolute if it isn't already by prefixing 'prefix' - """ - if not isabs(path): - return join(prefix, path) - return path - -def sha1OfFile(path): - with open(path, 'rb') as f: - d = hashlib.sha1() - while True: - buf = f.read(4096) - if not buf: - break - d.update(buf) - return d.hexdigest() - -def download_file_with_sha1(name, path, urls, sha1, sha1path, resolve, mustExist, sources=False, canSymlink=True): - canSymlink = canSymlink and not (get_os() == 'windows' or get_os() == 'cygwin') - def _download_lib(): - cacheDir = _cygpathW2U(get_env('MX_CACHE_DIR', join(_opts.user_home, '.mx', 'cache'))) - if not exists(cacheDir): - os.makedirs(cacheDir) - base = basename(path) - cachePath = join(cacheDir, base + '_' + sha1) - - if not exists(cachePath) or sha1OfFile(cachePath) != sha1: - if exists(cachePath): - log('SHA1 of ' + cachePath + ' does not match expected value (' + sha1 + ') - found ' + sha1OfFile(cachePath) + ' - re-downloading') - print 'Downloading ' + ("sources " if sources else "") + name + ' from ' + str(urls) - download(cachePath, urls) - - d = dirname(path) - if d != '' and not exists(d): - os.makedirs(d) - - if canSymlink and 'symlink' in dir(os): - if exists(path): - os.unlink(path) - try: - os.symlink(cachePath, path) - except OSError as e: - # When doing parallel building, the symlink can fail - # if another thread wins the race to create the symlink - if not exists(path): - # It was some other error - raise e - - else: - shutil.copy(cachePath, path) - - def _sha1Cached(): - with open(sha1path, 'r') as f: - return f.read()[0:40] - - def _writeSha1Cached(): - with open(sha1path, 'w') as f: - f.write(sha1OfFile(path)) - - if resolve and mustExist and not exists(path): - assert not len(urls) == 0, 'cannot find required library ' + name + ' ' + path - _download_lib() - - if exists(path): - if sha1 and not exists(sha1path): - _writeSha1Cached() - - if sha1 and sha1 != _sha1Cached(): - _download_lib() - if sha1 != sha1OfFile(path): - abort("SHA1 does not match for " + name + ". Broken download? SHA1 not updated in projects file?") - _writeSha1Cached() - - return path - -class BaseLibrary(Dependency): - def __init__(self, suite, name, optional): - Dependency.__init__(self, suite, name) - self.optional = optional - - def __ne__(self, other): - result = self.__eq__(other) - if result is NotImplemented: - return result - return not result - -""" -A library that will be provided by the JRE but may be absent. -Any project or normal library that depends on a missing library -will be removed from the global project and library dictionaries -(i.e., _projects and _libs). - -This mechanism exists primarily to be able to support code -that may use functionality in one JRE (e.g., Oracle JRE) -that is not present in another JRE (e.g., OpenJDK). A -motivating example is the Java Flight Recorder library -found in the Oracle JRE. -""" -class JreLibrary(BaseLibrary): - def __init__(self, suite, name, jar, optional): - BaseLibrary.__init__(self, suite, name, optional) - self.jar = jar - - def __eq__(self, other): - if isinstance(other, JreLibrary): - return self.jar == other.jar - else: - return NotImplemented - - def is_present_in_jdk(self, jdk): - return jdk.containsJar(self.jar) - - def all_deps(self, deps, includeLibs, includeSelf=True, includeJreLibs=False, includeAnnotationProcessors=False): - """ - Add the transitive set of dependencies for this JRE library to the 'deps' list. - """ - if includeJreLibs and includeSelf and not self in deps: - deps.append(self) - return sorted(deps) - -class Library(BaseLibrary): - def __init__(self, suite, name, path, optional, urls, sha1, sourcePath, sourceUrls, sourceSha1, deps): - BaseLibrary.__init__(self, suite, name, optional) - self.path = path.replace('/', os.sep) - self.urls = urls - self.sha1 = sha1 - self.sourcePath = sourcePath - self.sourceUrls = sourceUrls - if sourcePath == path: - assert sourceSha1 is None or sourceSha1 == sha1 - sourceSha1 = sha1 - self.sourceSha1 = sourceSha1 - self.deps = deps - abspath = _make_absolute(path, self.suite.dir) - if not optional and not exists(abspath): - if not len(urls): - abort('Non-optional library {0} must either exist at {1} or specify one or more URLs from which it can be retrieved'.format(name, abspath)) - - def _checkSha1PropertyCondition(propName, cond, inputPath): - if not cond: - absInputPath = _make_absolute(inputPath, self.suite.dir) - if exists(absInputPath): - abort('Missing "{0}" property for library {1}. Add the following line to projects file:\nlibrary@{2}@{3}={4}'.format(propName, name, name, propName, sha1OfFile(absInputPath))) - abort('Missing "{0}" property for library {1}'.format(propName, name)) - - _checkSha1PropertyCondition('sha1', sha1, path) - _checkSha1PropertyCondition('sourceSha1', not sourcePath or sourceSha1, sourcePath) - - for url in urls: - if url.endswith('/') != self.path.endswith(os.sep): - abort('Path for dependency directory must have a URL ending with "/": path=' + self.path + ' url=' + url) - - def __eq__(self, other): - if isinstance(other, Library): - if len(self.urls) == 0: - return self.path == other.path - else: - return self.urls == other.urls - else: - return NotImplemented - - def get_path(self, resolve): - path = _make_absolute(self.path, self.suite.dir) - sha1path = path + '.sha1' - - includedInJDK = getattr(self, 'includedInJDK', None) - # TODO since we don't know which JDK will be used, this check is dubious - if includedInJDK and java().javaCompliance >= JavaCompliance(includedInJDK): - return None - - bootClassPathAgent = getattr(self, 'bootClassPathAgent').lower() == 'true' if hasattr(self, 'bootClassPathAgent') else False - - return download_file_with_sha1(self.name, path, self.urls, self.sha1, sha1path, resolve, not self.optional, canSymlink=not bootClassPathAgent) - - def get_source_path(self, resolve): - if self.sourcePath is None: - return None - path = _make_absolute(self.sourcePath, self.suite.dir) - sha1path = path + '.sha1' - - return download_file_with_sha1(self.name, path, self.sourceUrls, self.sourceSha1, sha1path, resolve, len(self.sourceUrls) != 0, sources=True) - - def append_to_classpath(self, cp, resolve): - path = self.get_path(resolve) - if path and (exists(path) or not resolve): - cp.append(path) - - def all_deps(self, deps, includeLibs, includeSelf=True, includeJreLibs=False, includeAnnotationProcessors=False): - """ - Add the transitive set of dependencies for this library to the 'deps' list. - """ - if not includeLibs: - return sorted(deps) - childDeps = list(self.deps) - if self in deps: - return sorted(deps) - for name in childDeps: - assert name != self.name - dep = library(name) - if not dep in deps: - dep.all_deps(deps, includeLibs=includeLibs, includeJreLibs=includeJreLibs, includeAnnotationProcessors=includeAnnotationProcessors) - if not self in deps and includeSelf: - deps.append(self) - return sorted(deps) - -class HgConfig: - """ - Encapsulates access to Mercurial (hg) - """ - def __init__(self): - self.missing = 'no hg executable found' - self.has_hg = None - - def check(self, abortOnFail=True): - if self.has_hg is None: - try: - subprocess.check_output(['hg']) - self.has_hg = True - except OSError: - self.has_hg = False - warn(self.missing) - - if not self.has_hg: - if abortOnFail: - abort(self.missing) - else: - warn(self.missing) - - def tip(self, sDir, abortOnError=True): - try: - return subprocess.check_output(['hg', 'tip', '-R', sDir, '--template', '{node}']) - except OSError: - warn(self.missing) - except subprocess.CalledProcessError: - if abortOnError: - abort('failed to get tip revision id') - else: - return None - - def isDirty(self, sDir, abortOnError=True): - try: - return len(subprocess.check_output(['hg', 'status', '-R', sDir])) > 0 - except OSError: - warn(self.missing) - except subprocess.CalledProcessError: - if abortOnError: - abort('failed to get status') - else: - return None - - def locate(self, sDir, patterns=None, abortOnError=True): - try: - if patterns is None: - patterns = [] - elif not isinstance(patterns, list): - patterns = [patterns] - return subprocess.check_output(['hg', 'locate', '-R', sDir] + patterns).split('\n') - except OSError: - warn(self.missing) - except subprocess.CalledProcessError as e: - if e.returncode == 1: - # hg locate returns 1 if no matches were found - return [] - if abortOnError: - abort('failed to locate') - else: - return None - -def _load_suite_dict(mxDir): - - suffix = 1 - suite = None - dictName = 'suite' - - def expand(value, context): - if isinstance(value, types.DictionaryType): - for n, v in value.iteritems(): - value[n] = expand(v, context + [n]) - elif isinstance(value, types.ListType): - for i in range(len(value)): - value[i] = expand(value[i], context + [str(i)]) - else: - if not isinstance(value, types.StringTypes): - abort('value of ' + '.'.join(context) + ' is of unexpected type ' + str(type(value))) - value = expandvars(value) - if '$' in value or '%' in value: - abort('value of ' + '.'.join(context) + ' contains an undefined environment variable: ' + value) - - return value - - moduleName = 'suite' - modulePath = join(mxDir, moduleName + '.py') - while exists(modulePath): - - savedModule = sys.modules.get(moduleName) - if savedModule: - warn(modulePath + ' conflicts with ' + savedModule.__file__) - # temporarily extend the Python path - sys.path.insert(0, mxDir) - - snapshot = frozenset(sys.modules.keys()) - module = __import__(moduleName) - - if savedModule: - # restore the old module into the module name space - sys.modules[moduleName] = savedModule - else: - # remove moduleName from the module name space - sys.modules.pop(moduleName) - - # For now fail fast if extra modules were loaded. - # This can later be relaxed to simply remove the extra modules - # from the sys.modules name space if necessary. - extraModules = frozenset(sys.modules.keys()) - snapshot - assert len(extraModules) == 0, 'loading ' + modulePath + ' caused extra modules to be loaded: ' + ', '.join([m for m in extraModules]) - - # revert the Python path - del sys.path[0] - - if not hasattr(module, dictName): - abort(modulePath + ' must define a variable named "' + dictName + '"') - d = expand(getattr(module, dictName), [dictName]) - sections = ['projects', 'libraries', 'jrelibraries', 'distributions'] + (['distribution_extensions'] if suite else ['name', 'mxversion']) - unknown = frozenset(d.keys()) - frozenset(sections) - if unknown: - abort(modulePath + ' defines unsupported suite sections: ' + ', '.join(unknown)) - - if suite is None: - suite = d - else: - for s in sections: - existing = suite.get(s) - additional = d.get(s) - if additional: - if not existing: - suite[s] = additional - else: - conflicting = frozenset(additional.keys()) & frozenset(existing.keys()) - if conflicting: - abort(modulePath + ' redefines: ' + ', '.join(conflicting)) - existing.update(additional) - distExtensions = d.get('distribution_extensions') - if distExtensions: - existing = suite['distributions'] - for n, attrs in distExtensions.iteritems(): - original = existing.get(n) - if not original: - abort('cannot extend non-existing distribution ' + n) - for k, v in attrs.iteritems(): - if k != 'dependencies': - abort('Only the dependencies of distribution ' + n + ' can be extended') - if not isinstance(v, types.ListType): - abort('distribution_extensions.' + n + '.dependencies must be a list') - original['dependencies'] += v - - dictName = 'extra' - moduleName = 'suite' + str(suffix) - modulePath = join(mxDir, moduleName + '.py') - - deprecatedModulePath = join(mxDir, 'projects' + str(suffix) + '.py') - if exists(deprecatedModulePath): - abort('Please rename ' + deprecatedModulePath + ' to ' + modulePath) - - suffix = suffix + 1 - - return suite, modulePath - -class Suite: - def __init__(self, mxDir, primary, load=True): - self.dir = dirname(mxDir) - self.mxDir = mxDir - self.projects = [] - self.libs = [] - self.jreLibs = [] - self.dists = [] - self.commands = None - self.primary = primary - self.requiredMxVersion = None - self.name = _suitename(mxDir) # validated in _load_projects - _suites[self.name] = self - if load: - # just check that there are no imports - self._load_imports() - self._load_env() - self._load_commands() - - def __str__(self): - return self.name - - def _load_projects(self): - suitePyFile = join(self.mxDir, 'suite.py') - if not exists(suitePyFile): - return - - suiteDict, _ = _load_suite_dict(self.mxDir) - - if suiteDict.get('name') is not None and suiteDict.get('name') != self.name: - abort('suite name in project file does not match ' + _suitename(self.mxDir)) - - if suiteDict.has_key('mxversion'): - try: - self.requiredMxVersion = VersionSpec(suiteDict['mxversion']) - except AssertionError as ae: - abort('Exception while parsing "mxversion" in project file: ' + str(ae)) - - libsMap = suiteDict.get('libraries', {}) - jreLibsMap = suiteDict.get('jrelibraries', {}) - projsMap = suiteDict.get('projects', {}) - distsMap = suiteDict.get('distributions', {}) - - def pop_list(attrs, name, context): - v = attrs.pop(name, None) - if not v: - return [] - if not isinstance(v, list): - abort('Attribute "' + name + '" for ' + context + ' must be a list') - return v - - for name, attrs in sorted(projsMap.iteritems()): - context = 'project ' + name - srcDirs = pop_list(attrs, 'sourceDirs', context) - deps = pop_list(attrs, 'dependencies', context) - ap = pop_list(attrs, 'annotationProcessors', context) - javaCompliance = attrs.pop('javaCompliance', None) - subDir = attrs.pop('subDir', None) - if subDir is None: - d = join(self.dir, name) - else: - d = join(self.dir, subDir, name) - workingSets = attrs.pop('workingSets', None) - p = Project(self, name, srcDirs, deps, javaCompliance, workingSets, d) - p.checkstyleProj = attrs.pop('checkstyle', name) - p.native = attrs.pop('native', '') == 'true' - p.checkPackagePrefix = attrs.pop('checkPackagePrefix', 'true') == 'true' - if not p.native and p.javaCompliance is None: - abort('javaCompliance property required for non-native project ' + name) - if len(ap) > 0: - p._declaredAnnotationProcessors = ap - p.__dict__.update(attrs) - self.projects.append(p) - - for name, attrs in sorted(jreLibsMap.iteritems()): - jar = attrs.pop('jar') - # JRE libraries are optional by default - optional = attrs.pop('optional', 'true') != 'false' - l = JreLibrary(self, name, jar, optional) - self.jreLibs.append(l) - - for name, attrs in sorted(libsMap.iteritems()): - context = 'library ' + name - if "|" in name: - if name.count('|') != 2: - abort("Format error in library name: " + name + "\nsyntax: libname|os-platform|architecture") - name, platform, architecture = name.split("|") - if platform != get_os() or architecture != get_arch(): - continue - path = attrs.pop('path') - urls = pop_list(attrs, 'urls', context) - sha1 = attrs.pop('sha1', None) - sourcePath = attrs.pop('sourcePath', None) - sourceUrls = pop_list(attrs, 'sourceUrls', context) - sourceSha1 = attrs.pop('sourceSha1', None) - deps = pop_list(attrs, 'dependencies', context) - # Add support optional libraries once we have a good use case - optional = False - l = Library(self, name, path, optional, urls, sha1, sourcePath, sourceUrls, sourceSha1, deps) - l.__dict__.update(attrs) - self.libs.append(l) - - for name, attrs in sorted(distsMap.iteritems()): - context = 'distribution ' + name - path = attrs.pop('path') - sourcesPath = attrs.pop('sourcesPath', None) - deps = pop_list(attrs, 'dependencies', context) - mainClass = attrs.pop('mainClass', None) - exclDeps = pop_list(attrs, 'exclude', context) - distDeps = pop_list(attrs, 'distDependencies', context) - javaCompliance = attrs.pop('javaCompliance', None) - d = Distribution(self, name, path, sourcesPath, deps, mainClass, exclDeps, distDeps, javaCompliance) - d.__dict__.update(attrs) - self.dists.append(d) - - # Create a distribution for each project that defines annotation processors - for p in self.projects: - annotationProcessors = None - for srcDir in p.source_dirs(): - configFile = join(srcDir, 'META-INF', 'services', 'javax.annotation.processing.Processor') - if exists(configFile): - with open(configFile) as fp: - annotationProcessors = [ap.strip() for ap in fp] - if len(annotationProcessors) != 0: - for ap in annotationProcessors: - if not ap.startswith(p.name): - abort(ap + ' in ' + configFile + ' does not start with ' + p.name) - if annotationProcessors: - dname = p.name.replace('.', '_').upper() - apDir = join(p.dir, 'ap') - path = join(apDir, p.name + '.jar') - sourcesPath = None - deps = [p.name] - mainClass = None - exclDeps = [] - distDeps = [] - javaCompliance = None - d = Distribution(self, dname, path, sourcesPath, deps, mainClass, exclDeps, distDeps, javaCompliance, True) - d.subDir = os.path.relpath(os.path.dirname(p.dir), self.dir) - self.dists.append(d) - p.definedAnnotationProcessors = annotationProcessors - p.definedAnnotationProcessorsDist = d - d.definingProject = p - - # Restrict exported annotation processors to those explicitly defined by the project - def _refineAnnotationProcessorServiceConfig(dist): - aps = dist.definingProject.definedAnnotationProcessors - apsJar = dist.path - config = 'META-INF/services/javax.annotation.processing.Processor' - with zipfile.ZipFile(apsJar, 'r') as zf: - currentAps = zf.read(config).split() - if currentAps != aps: - logv('[updating ' + config + ' in ' + apsJar + ']') - with Archiver(apsJar) as arc: - with zipfile.ZipFile(apsJar, 'r') as lp: - for arcname in lp.namelist(): - if arcname == config: - arc.zf.writestr(arcname, '\n'.join(aps)) - else: - arc.zf.writestr(arcname, lp.read(arcname)) - d.add_update_listener(_refineAnnotationProcessorServiceConfig) - self.dists.append(d) - - if self.name is None: - abort('Missing "suite=" in ' + suitePyFile) - - def _commands_name(self): - return 'mx_' + self.name.replace('-', '_') - - def _find_commands(self, name): - commandsPath = join(self.mxDir, name + '.py') - if exists(commandsPath): - return name - else: - return None - - def _load_commands(self): - commandsName = self._find_commands(self._commands_name()) - if commandsName is not None: - if commandsName in sys.modules: - abort(commandsName + '.py in suite ' + self.name + ' duplicates ' + sys.modules[commandsName].__file__) - # temporarily extend the Python path - sys.path.insert(0, self.mxDir) - mod = __import__(commandsName) - - self.commands = sys.modules.pop(commandsName) - sys.modules[commandsName] = self.commands - - # revert the Python path - del sys.path[0] - - if not hasattr(mod, 'mx_init'): - abort(commandsName + '.py in suite ' + self.name + ' must define an mx_init(suite) function') - if hasattr(mod, 'mx_post_parse_cmd_line'): - self.mx_post_parse_cmd_line = mod.mx_post_parse_cmd_line - - mod.mx_init(self) - self.commands = mod - - def _load_imports(self): - if exists(join(self.mxDir, 'imports')): - abort('multiple suites are not supported in this version of mx') - - def _load_env(self): - e = join(self.mxDir, 'env') - if exists(e): - with open(e) as f: - lineNum = 0 - for line in f: - lineNum = lineNum + 1 - line = line.strip() - if len(line) != 0 and line[0] != '#': - if not '=' in line: - abort(e + ':' + str(lineNum) + ': line does not match pattern "key=value"') - key, value = line.split('=', 1) - os.environ[key.strip()] = expandvars_in_property(value.strip()) - - def _post_init(self, opts): - self._load_projects() - if self.requiredMxVersion is None: - warn("This suite does not express any required mx version. Consider adding 'mxversion=' to your projects file.") - elif self.requiredMxVersion > version: - abort("This suite requires mx version " + str(self.requiredMxVersion) + " while your current mx version is " + str(version) + ". Please update mx.") - # set the global data structures, checking for conflicts unless _check_global_structures is False - for p in self.projects: - existing = _projects.get(p.name) - if existing is not None: - abort('cannot override project ' + p.name + ' in ' + p.dir + " with project of the same name in " + existing.dir) - if not p.name in _opts.ignored_projects: - _projects[p.name] = p - for l in self.libs: - existing = _libs.get(l.name) - # Check that suites that define same library are consistent - if existing is not None and existing != l: - abort('inconsistent library redefinition of ' + l.name + ' in ' + existing.suite.dir + ' and ' + l.suite.dir) - _libs[l.name] = l - for l in self.jreLibs: - existing = _jreLibs.get(l.name) - # Check that suites that define same library are consistent - if existing is not None and existing != l: - abort('inconsistent JRE library redefinition of ' + l.name + ' in ' + existing.suite.dir + ' and ' + l.suite.dir) - _jreLibs[l.name] = l - for d in self.dists: - existing = _dists.get(d.name) - if existing is not None: - # allow redefinition, so use path from existing - # abort('cannot redefine distribution ' + d.name) - warn('distribution ' + d.name + ' redefined') - d.path = existing.path - _dists[d.name] = d - - # Remove projects and libraries that (recursively) depend on an optional library - # whose artifact does not exist or on a JRE library that is not present in the - # JDK for a project. Also remove projects whose Java compliance requirement - # cannot be satisfied by the configured JDKs. - # - # Removed projects and libraries are also removed from - # distributions in they are listed as dependencies. - ommittedDeps = set() - for d in sorted_deps(includeLibs=True): - if d.isLibrary(): - if d.optional: - try: - d.optional = False - path = d.get_path(resolve=True) - except SystemExit: - path = None - finally: - d.optional = True - if not path: - logv('[omitting optional library {0} as {1} does not exist]'.format(d, d.path)) - ommittedDeps.add(d.name) - del _libs[d.name] - self.libs.remove(d) - elif d.isProject(): - if java(d.javaCompliance, cancel='some projects will be omitted which may result in errors', purpose="building projects with compliance " + str(d.javaCompliance)) is None: - logv('[omitting project {0} as Java compliance {1} cannot be satisfied by configured JDKs]'.format(d, d.javaCompliance)) - ommittedDeps.add(d.name) - del _projects[d.name] - self.projects.remove(d) - else: - for name in list(d.deps): - jreLib = _jreLibs.get(name) - if jreLib: - if not jreLib.is_present_in_jdk(java(d.javaCompliance)): - if jreLib.optional: - logv('[omitting project {0} as dependency {1} is missing]'.format(d, name)) - ommittedDeps.add(d.name) - del _projects[d.name] - self.projects.remove(d) - else: - abort('JRE library {0} required by {1} not found'.format(jreLib, d)) - elif not dependency(name, fatalIfMissing=False): - logv('[omitting project {0} as dependency {1} is missing]'.format(d, name)) - ommittedDeps.add(d.name) - del _projects[d.name] - self.projects.remove(d) - for dist in _dists.itervalues(): - for name in list(dist.deps): - if name in ommittedDeps: - logv('[omitting {0} from distribution {1}]'.format(name, dist)) - dist.deps.remove(name) - - if hasattr(self, 'mx_post_parse_cmd_line'): - self.mx_post_parse_cmd_line(opts) - -class XMLElement(xml.dom.minidom.Element): - def writexml(self, writer, indent="", addindent="", newl=""): - writer.write(indent + "<" + self.tagName) - - attrs = self._get_attributes() - a_names = attrs.keys() - a_names.sort() - - for a_name in a_names: - writer.write(" %s=\"" % a_name) - xml.dom.minidom._write_data(writer, attrs[a_name].value) - writer.write("\"") - if self.childNodes: - if not self.ownerDocument.padTextNodeWithoutSiblings and len(self.childNodes) == 1 and isinstance(self.childNodes[0], xml.dom.minidom.Text): - # if the only child of an Element node is a Text node, then the - # text is printed without any indentation or new line padding - writer.write(">") - self.childNodes[0].writexml(writer) - writer.write("%s" % (self.tagName, newl)) - else: - writer.write(">%s" % (newl)) - for node in self.childNodes: - node.writexml(writer, indent + addindent, addindent, newl) - writer.write("%s%s" % (indent, self.tagName, newl)) - else: - writer.write("/>%s" % (newl)) - -class XMLDoc(xml.dom.minidom.Document): - - def __init__(self): - xml.dom.minidom.Document.__init__(self) - self.current = self - self.padTextNodeWithoutSiblings = False - - def createElement(self, tagName): - # overwritten to create XMLElement - e = XMLElement(tagName) - e.ownerDocument = self - return e - - def comment(self, txt): - self.current.appendChild(self.createComment(txt)) - - def open(self, tag, attributes=None, data=None): - if attributes is None: - attributes = {} - element = self.createElement(tag) - for key, value in attributes.items(): - element.setAttribute(key, value) - self.current.appendChild(element) - self.current = element - if data is not None: - element.appendChild(self.createTextNode(data)) - return self - - def close(self, tag): - assert self.current != self - assert tag == self.current.tagName, str(tag) + ' != ' + self.current.tagName - self.current = self.current.parentNode - return self - - def element(self, tag, attributes=None, data=None): - if attributes is None: - attributes = {} - return self.open(tag, attributes, data).close(tag) - - def xml(self, indent='', newl='', escape=False, standalone=None): - assert self.current == self - result = self.toprettyxml(indent, newl, encoding="UTF-8") - if escape: - entities = {'"': """, "'": "'", '\n': ' '} - result = xml.sax.saxutils.escape(result, entities) - if standalone is not None: - result = result.replace('encoding="UTF-8"?>', 'encoding="UTF-8" standalone="' + str(standalone) + '"?>') - return result - -def get_jython_os(): - from java.lang import System as System - os_name = System.getProperty('os.name').lower() - if System.getProperty('isCygwin'): - return 'cygwin' - elif os_name.startswith('mac'): - return 'darwin' - elif os_name.startswith('linux'): - return 'linux' - elif os_name.startswith('sunos'): - return 'solaris' - elif os_name.startswith('win'): - return 'windows' - else: - abort('Unknown operating system ' + os_name) - -def get_os(): - """ - Get a canonical form of sys.platform. - """ - if is_jython(): - return get_jython_os() - elif sys.platform.startswith('darwin'): - return 'darwin' - elif sys.platform.startswith('linux'): - return 'linux' - elif sys.platform.startswith('sunos'): - return 'solaris' - elif sys.platform.startswith('win32'): - return 'windows' - elif sys.platform.startswith('cygwin'): - return 'cygwin' - else: - abort('Unknown operating system ' + sys.platform) - -def _cygpathU2W(p): - """ - Translate a path from unix-style to windows-style. - This method has no effects on other platforms than cygwin. - """ - if p is None or get_os() != "cygwin": - return p - return subprocess.check_output(['cygpath', '-a', '-w', p]).strip() - -def _cygpathW2U(p): - """ - Translate a path from windows-style to unix-style. - This method has no effects on other platforms than cygwin. - """ - if p is None or get_os() != "cygwin": - return p - return subprocess.check_output(['cygpath', '-a', '-u', p]).strip() - -def _separatedCygpathU2W(p): - """ - Translate a group of paths, separated by a path separator. - unix-style to windows-style. - This method has no effects on other platforms than cygwin. - """ - if p is None or p == "" or get_os() != "cygwin": - return p - return ';'.join(map(_cygpathU2W, p.split(os.pathsep))) - -def _separatedCygpathW2U(p): - """ - Translate a group of paths, separated by a path separator. - windows-style to unix-style. - This method has no effects on other platforms than cygwin. - """ - if p is None or p == "" or get_os() != "cygwin": - return p - return os.pathsep.join(map(_cygpathW2U, p.split(';'))) - -def get_arch(): - machine = platform.uname()[4] - if machine in ['amd64', 'AMD64', 'x86_64', 'i86pc']: - return 'amd64' - if machine in ['sun4v', 'sun4u']: - return 'sparcv9' - if machine == 'i386' and get_os() == 'darwin': - try: - # Support for Snow Leopard and earlier version of MacOSX - if subprocess.check_output(['sysctl', '-n', 'hw.cpu64bit_capable']).strip() == '1': - return 'amd64' - except OSError: - # sysctl is not available - pass - abort('unknown or unsupported architecture: os=' + get_os() + ', machine=' + machine) - -def _loadSuite(mxDir, primary=False): - """ - Load a suite from 'mxDir'. - """ - for s in _suites.itervalues(): - if s.mxDir == mxDir: - return s - # create the new suite - s = Suite(mxDir, primary) - return s - -def suites(opt_limit_to_suite=False): - """ - Get the list of all loaded suites. - """ - return _suites.values() - -def suite(name, fatalIfMissing=True): - """ - Get the suite for a given name. - """ - s = _suites.get(name) - if s is None and fatalIfMissing: - abort('suite named ' + name + ' not found') - return s - - -def projects_from_names(projectNames): - """ - Get the list of projects corresponding to projectNames; all projects if None - """ - if projectNames is None: - return projects() - else: - return [project(name) for name in projectNames] - -def projects(opt_limit_to_suite=False): - """ - Get the list of all loaded projects limited by --suite option if opt_limit_to_suite == True - """ - sortedProjects = sorted(_projects.values(), key=lambda p: p.name) - if opt_limit_to_suite: - return _projects_opt_limit_to_suites(sortedProjects) - else: - return sortedProjects - -def projects_opt_limit_to_suites(): - """ - Get the list of all loaded projects optionally limited by --suite option - """ - return projects(True) - -def _projects_opt_limit_to_suites(projects): - return projects - -def annotation_processors(): - """ - Get the list of all loaded projects that define an annotation processor. - """ - global _annotationProcessors - if _annotationProcessors is None: - aps = set() - for p in projects(): - for ap in p.annotation_processors(): - if project(ap, False): - aps.add(ap) - _annotationProcessors = list(aps) - return _annotationProcessors - -def distribution(name, fatalIfMissing=True): - """ - Get the distribution for a given name. This will abort if the named distribution does - not exist and 'fatalIfMissing' is true. - """ - d = _dists.get(name) - if d is None and fatalIfMissing: - abort('distribution named ' + name + ' not found') - return d - -def dependency(name, fatalIfMissing=True): - """ - Get the project or library for a given name. This will abort if a project or library does - not exist for 'name' and 'fatalIfMissing' is true. - """ - d = _projects.get(name) - if d is None: - d = _libs.get(name) - if d is None: - d = _jreLibs.get(name) - if d is None and fatalIfMissing: - if name in _opts.ignored_projects: - abort('project named ' + name + ' is ignored') - abort('project or library named ' + name + ' not found') - return d - -def project(name, fatalIfMissing=True): - """ - Get the project for a given name. This will abort if the named project does - not exist and 'fatalIfMissing' is true. - """ - p = _projects.get(name) - if p is None and fatalIfMissing: - if name in _opts.ignored_projects: - abort('project named ' + name + ' is ignored') - abort('project named ' + name + ' not found') - return p - -def library(name, fatalIfMissing=True): - """ - Gets the library for a given name. This will abort if the named library does - not exist and 'fatalIfMissing' is true. - """ - l = _libs.get(name) - if l is None and fatalIfMissing: - if _projects.get(name): - abort(name + ' is a project, not a library') - abort('library named ' + name + ' not found') - return l - -def _as_classpath(deps, resolve): - cp = [] - if _opts.cp_prefix is not None: - cp = [_opts.cp_prefix] - for d in deps: - d.append_to_classpath(cp, resolve) - if _opts.cp_suffix is not None: - cp += [_opts.cp_suffix] - return os.pathsep.join(cp) - -def classpath(names=None, resolve=True, includeSelf=True, includeBootClasspath=False): - """ - Get the class path for a list of given dependencies and distributions, resolving each entry in the - path (e.g. downloading a missing library) if 'resolve' is true. - """ - if names is None: - deps = sorted_deps(includeLibs=True) - dists = list(_dists.values()) - else: - deps = [] - dists = [] - if isinstance(names, types.StringTypes): - names = [names] - for n in names: - dep = dependency(n, fatalIfMissing=False) - if dep: - dep.all_deps(deps, True, includeSelf) - else: - dist = distribution(n) - if not dist: - abort('project, library or distribution named ' + n + ' not found') - dists.append(dist) - - if len(dists): - distsDeps = set() - for d in dists: - distsDeps.update(d.sorted_deps()) - - # remove deps covered by a dist that will be on the class path - deps = [d for d in deps if d not in distsDeps] - - result = _as_classpath(deps, resolve) - - # prepend distributions - if len(dists): - distsCp = os.pathsep.join(dist.path for dist in dists) - if len(result): - result = distsCp + os.pathsep + result - else: - result = distsCp - - if includeBootClasspath: - result = os.pathsep.join([java().bootclasspath(), result]) - - return result - -def classpath_walk(names=None, resolve=True, includeSelf=True, includeBootClasspath=False): - """ - Walks the resources available in a given classpath, yielding a tuple for each resource - where the first member of the tuple is a directory path or ZipFile object for a - classpath entry and the second member is the qualified path of the resource relative - to the classpath entry. - """ - cp = classpath(names, resolve, includeSelf, includeBootClasspath) - for entry in cp.split(os.pathsep): - if not exists(entry): - continue - if isdir(entry): - for root, dirs, files in os.walk(entry): - for d in dirs: - entryPath = join(root[len(entry) + 1:], d) - yield entry, entryPath - for f in files: - entryPath = join(root[len(entry) + 1:], f) - yield entry, entryPath - elif entry.endswith('.jar') or entry.endswith('.zip'): - with zipfile.ZipFile(entry, 'r') as zf: - for zi in zf.infolist(): - entryPath = zi.filename - yield zf, entryPath - -def sorted_deps(projectNames=None, includeLibs=False, includeJreLibs=False, includeAnnotationProcessors=False): - """ - Gets projects and libraries sorted such that dependencies - are before the projects that depend on them. Unless 'includeLibs' is - true, libraries are omitted from the result. - """ - projects = projects_from_names(projectNames) - - return sorted_project_deps(projects, includeLibs=includeLibs, includeJreLibs=includeJreLibs, includeAnnotationProcessors=includeAnnotationProcessors) - -def sorted_dists(): - """ - Gets distributions sorted such that each distribution comes after - any distributions it depends upon. - """ - dists = [] - def add_dist(dist): - if not dist in dists: - for depDist in [distribution(name) for name in dist.distDependencies]: - add_dist(depDist) - if not dist in dists: - dists.append(dist) - - for d in _dists.itervalues(): - add_dist(d) - return dists - -def sorted_project_deps(projects, includeLibs=False, includeJreLibs=False, includeAnnotationProcessors=False): - deps = [] - for p in projects: - p.all_deps(deps, includeLibs=includeLibs, includeJreLibs=includeJreLibs, includeAnnotationProcessors=includeAnnotationProcessors) - return deps - -def extract_VM_args(args, useDoubleDash=False, allowClasspath=False): - """ - Partitions 'args' into a leading sequence of HotSpot VM options and the rest. If - 'useDoubleDash' then 'args' is partititioned by the first instance of "--". If - not 'allowClasspath' then mx aborts if "-cp" or "-classpath" is in 'args'. - - """ - for i in range(len(args)): - if useDoubleDash: - if args[i] == '--': - vmArgs = args[:i] - remainder = args[i + 1:] - return vmArgs, remainder - else: - if not args[i].startswith('-'): - if i != 0 and (args[i - 1] == '-cp' or args[i - 1] == '-classpath'): - if not allowClasspath: - abort('Cannot supply explicit class path option') - else: - continue - vmArgs = args[:i] - remainder = args[i:] - return vmArgs, remainder - return args, [] - -class ArgParser(ArgumentParser): - # Override parent to append the list of available commands - def format_help(self): - return ArgumentParser.format_help(self) + _format_commands() - - - def __init__(self): - self.java_initialized = False - # this doesn't resolve the right way, but can't figure out how to override _handle_conflict_resolve in _ActionsContainer - ArgumentParser.__init__(self, prog='mx', conflict_handler='resolve') - - self.add_argument('-v', action='store_true', dest='verbose', help='enable verbose output') - self.add_argument('-V', action='store_true', dest='very_verbose', help='enable very verbose output') - self.add_argument('-w', action='store_true', dest='warn', help='enable warning messages') - self.add_argument('-y', action='store_const', const='y', dest='answer', help='answer \'y\' to all questions asked') - self.add_argument('-n', action='store_const', const='n', dest='answer', help='answer \'n\' to all questions asked') - self.add_argument('-p', '--primary-suite-path', help='set the primary suite directory', metavar='') - self.add_argument('--dbg', type=int, dest='java_dbg_port', help='make Java processes wait on for a debugger', metavar='') - self.add_argument('-d', action='store_const', const=8000, dest='java_dbg_port', help='alias for "-dbg 8000"') - self.add_argument('--backup-modified', action='store_true', help='backup generated files if they pre-existed and are modified') - self.add_argument('--cp-pfx', dest='cp_prefix', help='class path prefix', metavar='') - self.add_argument('--cp-sfx', dest='cp_suffix', help='class path suffix', metavar='') - self.add_argument('--J', dest='java_args', help='Java VM arguments (e.g. --J @-dsa)', metavar='@') - self.add_argument('--Jp', action='append', dest='java_args_pfx', help='prefix Java VM arguments (e.g. --Jp @-dsa)', metavar='@', default=[]) - self.add_argument('--Ja', action='append', dest='java_args_sfx', help='suffix Java VM arguments (e.g. --Ja @-dsa)', metavar='@', default=[]) - self.add_argument('--user-home', help='users home directory', metavar='', default=os.path.expanduser('~')) - self.add_argument('--java-home', help='primary JDK directory (must be JDK 7 or later)', metavar='') - self.add_argument('--extra-java-homes', help='secondary JDK directories separated by "' + os.pathsep + '"', metavar='') - self.add_argument('--strict-compliance', action='store_true', dest='strict_compliance', help='Projects with an explicit compliance will only be built if a JDK exactly matching the compliance is available', default=False) - self.add_argument('--ignore-project', action='append', dest='ignored_projects', help='name of project to ignore', metavar='', default=[]) - self.add_argument('--kill-with-sigquit', action='store_true', dest='killwithsigquit', help='send sigquit first before killing child processes') - if get_os() != 'windows': - # Time outs are (currently) implemented with Unix specific functionality - self.add_argument('--timeout', help='timeout (in seconds) for command', type=int, default=0, metavar='') - self.add_argument('--ptimeout', help='timeout (in seconds) for subprocesses', type=int, default=0, metavar='') - - def _parse_cmd_line(self, args=None): - if args is None: - args = sys.argv[1:] - - self.add_argument('commandAndArgs', nargs=REMAINDER, metavar='command args...') - - opts = self.parse_args() - - global _opts - _opts = opts - - # Give the timeout options a default value to avoid the need for hasattr() tests - opts.__dict__.setdefault('timeout', 0) - opts.__dict__.setdefault('ptimeout', 0) - - if opts.very_verbose: - opts.verbose = True - - if opts.user_home is None or opts.user_home == '': - abort('Could not find user home. Use --user-home option or ensure HOME environment variable is set.') - - if opts.java_home: - os.environ['JAVA_HOME'] = opts.java_home - os.environ['HOME'] = opts.user_home - - if os.environ.get('STRICT_COMPLIANCE'): - _opts.strict_compliance = True - - opts.ignored_projects = opts.ignored_projects + os.environ.get('IGNORED_PROJECTS', '').split(',') - - commandAndArgs = opts.__dict__.pop('commandAndArgs') - return opts, commandAndArgs - - def _handle_conflict_resolve(self, action, conflicting_actions): - self._handle_conflict_error(action, conflicting_actions) - -def _format_commands(): - msg = '\navailable commands:\n\n' - for cmd in sorted([k for k in _commands.iterkeys() if ':' not in k]) + sorted([k for k in _commands.iterkeys() if ':' in k]): - c, _ = _commands[cmd][:2] - doc = c.__doc__ - if doc is None: - doc = '' - msg += ' {0:<20} {1}\n'.format(cmd, doc.split('\n', 1)[0]) - return msg + '\n' - -_canceled_java_requests = set() - -def java(versionCheck=None, purpose=None, cancel=None, versionDescription=None, defaultJdk=None): - """ - Get a JavaConfig object containing Java commands launch details. - """ - - if defaultJdk is None: - defaultJdk = versionCheck is None and not purpose - - # interpret string and compliance as compliance check - if isinstance(versionCheck, types.StringTypes): - requiredCompliance = JavaCompliance(versionCheck) - versionCheck, versionDescription = _convert_compliance_to_version_check(requiredCompliance) - elif isinstance(versionCheck, JavaCompliance): - versionCheck, versionDescription = _convert_compliance_to_version_check(versionCheck) - - global _default_java_home, _extra_java_homes - if cancel and (versionDescription, purpose) in _canceled_java_requests: - return None - - if defaultJdk: - if not _default_java_home: - _default_java_home = _find_jdk(versionCheck=versionCheck, versionDescription=versionDescription, purpose=purpose, cancel=cancel, isDefaultJdk=True) - if not _default_java_home: - assert cancel and (versionDescription or purpose) - _canceled_java_requests.add((versionDescription, purpose)) - return _default_java_home - - for java in _extra_java_homes: - if not versionCheck or versionCheck(java.version): - return java - - jdk = _find_jdk(versionCheck=versionCheck, versionDescription=versionDescription, purpose=purpose, cancel=cancel, isDefaultJdk=False) - if jdk: - assert jdk not in _extra_java_homes - _extra_java_homes = _sorted_unique_jdk_configs(_extra_java_homes + [jdk]) - else: - assert cancel and (versionDescription or purpose) - _canceled_java_requests.add((versionDescription, purpose)) - return jdk - -def _convert_compliance_to_version_check(requiredCompliance): - if _opts.strict_compliance: - versionDesc = str(requiredCompliance) - versionCheck = requiredCompliance.exactMatch - else: - versionDesc = '>=' + str(requiredCompliance) - compVersion = VersionSpec(str(requiredCompliance)) - versionCheck = lambda version: version >= compVersion - return (versionCheck, versionDesc) - -def _find_jdk(versionCheck=None, versionDescription=None, purpose=None, cancel=None, isDefaultJdk=False): - assert (versionDescription and versionCheck) or (not versionDescription and not versionCheck) - if not versionCheck: - versionCheck = lambda v: True - - candidateJdks = [] - source = '' - if _opts.java_home: - candidateJdks.append(_opts.java_home) - source = '--java-home' - elif os.environ.get('JAVA_HOME'): - candidateJdks.append(os.environ.get('JAVA_HOME')) - source = 'JAVA_HOME' - - result = _find_jdk_in_candidates(candidateJdks, versionCheck, warn=True, source=source) - if result: - return result - - candidateJdks = [] - - if _opts.extra_java_homes: - candidateJdks += _opts.extra_java_homes.split(os.pathsep) - source = '--extra-java-homes' - elif os.environ.get('EXTRA_JAVA_HOMES'): - candidateJdks += os.environ.get('EXTRA_JAVA_HOMES').split(os.pathsep) - source = 'EXTRA_JAVA_HOMES' - - result = _find_jdk_in_candidates(candidateJdks, versionCheck, warn=True, source=source) - if not result: - configs = _find_available_jdks(versionCheck) - elif isDefaultJdk: # we found something in EXTRA_JAVA_HOMES but we want to set JAVA_HOME, look for further options - configs = [result] + _find_available_jdks(versionCheck) - else: - if not isDefaultJdk: - return result - configs = [result] - - configs = _sorted_unique_jdk_configs(configs) - - if len(configs) > 1: - if not is_interactive(): - msg = "Multiple possible choices for a JDK" - if purpose: - msg += ' for ' + purpose - msg += ': ' - if versionDescription: - msg += '(version ' + versionDescription + ')' - selected = configs[0] - msg += ". Selecting " + str(selected) - log(msg) - else: - msg = 'Please select a ' - if isDefaultJdk: - msg += 'default ' - msg += 'JDK' - if purpose: - msg += ' for ' + purpose - msg += ': ' - if versionDescription: - msg += '(version ' + versionDescription + ')' - log(msg) - choices = configs + [''] - if cancel: - choices.append('Cancel (' + cancel + ')') - - selected = select_items(choices, allowMultiple=False) - if isinstance(selected, types.StringTypes) and selected == '': - selected = None - if isinstance(selected, types.StringTypes) and selected == 'Cancel (' + cancel + ')': - return None - elif len(configs) == 1: - selected = configs[0] - msg = 'Selected ' + str(selected) + ' as ' - if isDefaultJdk: - msg += 'default ' - msg += 'JDK' - if versionDescription: - msg = msg + ' ' + versionDescription - if purpose: - msg += ' for ' + purpose - log(msg) - else: - msg = 'Could not find any JDK' - if purpose: - msg += ' for ' + purpose - msg += ' ' - if versionDescription: - msg = msg + '(version ' + versionDescription + ')' - log(msg) - selected = None - - while not selected: - jdkLocation = raw_input('Enter path of JDK: ') - selected = _find_jdk_in_candidates([jdkLocation], versionCheck, warn=True) - if not selected: - assert versionDescription - log("Error: JDK at '" + jdkLocation + "' is not compatible with version " + versionDescription) - - varName = 'JAVA_HOME' if isDefaultJdk else 'EXTRA_JAVA_HOMES' - allowMultiple = not isDefaultJdk - valueSeparator = os.pathsep if allowMultiple else None - ask_persist_env(varName, selected.jdk, valueSeparator) - - os.environ[varName] = selected.jdk - - return selected - -def ask_persist_env(varName, value, valueSeparator=None): - envPath = join(_primary_suite.mxDir, 'env') - if is_interactive() and ask_yes_no('Persist this setting by adding "{0}={1}" to {2}'.format(varName, value, envPath), 'y'): - envLines = [] - if exists(envPath): - with open(envPath) as fp: - append = True - for line in fp: - if line.rstrip().startswith(varName): - _, currentValue = line.split('=', 1) - currentValue = currentValue.strip() - if not valueSeparator and currentValue: - if not ask_yes_no('{0} is already set to {1}, overwrite with {2}?'.format(varName, currentValue, value), 'n'): - return - else: - line = varName + '=' + value + os.linesep - else: - line = line.rstrip() - if currentValue: - line += valueSeparator - line += value + os.linesep - append = False - if not line.endswith(os.linesep): - line += os.linesep - envLines.append(line) - else: - append = True - - if append: - envLines.append(varName + '=' + value + os.linesep) - - with open(envPath, 'w') as fp: - for line in envLines: - fp.write(line) - -_os_jdk_locations = { - 'darwin': { - 'bases': ['/Library/Java/JavaVirtualMachines'], - 'suffix': 'Contents/Home' - }, - 'linux': { - 'bases': [ - '/usr/lib/jvm', - '/usr/java' - ] - }, - 'solaris': { - 'bases': ['/usr/jdk/instances'] - }, - 'windows': { - 'bases': [r'C:\Program Files\Java'] - }, -} - -def _find_available_jdks(versionCheck): - candidateJdks = [] - os_name = get_os() - if os_name in _os_jdk_locations: - jdkLocations = _os_jdk_locations[os_name] - for base in jdkLocations['bases']: - if exists(base): - if 'suffix' in jdkLocations: - suffix = jdkLocations['suffix'] - candidateJdks += [join(base, n, suffix) for n in os.listdir(base)] - else: - candidateJdks += [join(base, n) for n in os.listdir(base)] - - return _filtered_jdk_configs(candidateJdks, versionCheck) - -def _sorted_unique_jdk_configs(configs): - path_seen = set() - unique_configs = [c for c in configs if c.jdk not in path_seen and not path_seen.add(c.jdk)] - - def _compare_configs(c1, c2): - if c1 == _default_java_home: - if c2 != _default_java_home: - return 1 - elif c2 == _default_java_home: - return -1 - if c1 in _extra_java_homes: - if c2 not in _extra_java_homes: - return 1 - elif c2 in _extra_java_homes: - return -1 - return VersionSpec.__cmp__(c1.version, c2.version) - return sorted(unique_configs, cmp=_compare_configs, reverse=True) - -def is_interactive(): - return sys.__stdin__.isatty() - -def _filtered_jdk_configs(candidates, versionCheck, warn=False, source=None): - filtered = [] - for candidate in candidates: - try: - config = JavaConfig(candidate) - if versionCheck(config.version): - filtered.append(config) - except JavaConfigException as e: - if warn: - log('Path in ' + source + "' is not pointing to a JDK (" + e.message + ")") - return filtered - -def _find_jdk_in_candidates(candidates, versionCheck, warn=False, source=None): - filtered = _filtered_jdk_configs(candidates, versionCheck, warn, source) - if filtered: - return filtered[0] - return None - -def run_java(args, nonZeroIsFatal=True, out=None, err=None, cwd=None, addDefaultArgs=True, javaConfig=None): - if not javaConfig: - javaConfig = java() - return run(javaConfig.format_cmd(args, addDefaultArgs), nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd) - -def _kill_process_group(pid, sig): - if not sig: - sig = signal.SIGKILL - pgid = os.getpgid(pid) - try: - os.killpg(pgid, sig) - return True - except: - log('Error killing subprocess ' + str(pgid) + ': ' + str(sys.exc_info()[1])) - return False - -def _waitWithTimeout(process, args, timeout): - def _waitpid(pid): - while True: - try: - return os.waitpid(pid, os.WNOHANG) - except OSError, e: - if e.errno == errno.EINTR: - continue - raise - - def _returncode(status): - if os.WIFSIGNALED(status): - return -os.WTERMSIG(status) - elif os.WIFEXITED(status): - return os.WEXITSTATUS(status) - else: - # Should never happen - raise RuntimeError("Unknown child exit status!") - - end = time.time() + timeout - delay = 0.0005 - while True: - (pid, status) = _waitpid(process.pid) - if pid == process.pid: - return _returncode(status) - remaining = end - time.time() - if remaining <= 0: - abort('Process timed out after {0} seconds: {1}'.format(timeout, ' '.join(args))) - delay = min(delay * 2, remaining, .05) - time.sleep(delay) - -# Makes the current subprocess accessible to the abort() function -# This is a list of tuples of the subprocess.Popen or -# multiprocessing.Process object and args. -_currentSubprocesses = [] - -def _addSubprocess(p, args): - entry = (p, args) - _currentSubprocesses.append(entry) - return entry - -def _removeSubprocess(entry): - if entry and entry in _currentSubprocesses: - try: - _currentSubprocesses.remove(entry) - except: - pass - -def waitOn(p): - if get_os() == 'windows': - # on windows use a poll loop, otherwise signal does not get handled - retcode = None - while retcode == None: - retcode = p.poll() - time.sleep(0.05) - else: - retcode = p.wait() - return retcode - -def run(args, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, env=None): - """ - Run a command in a subprocess, wait for it to complete and return the exit status of the process. - If the exit status is non-zero and `nonZeroIsFatal` is true, then mx is exited with - the same exit status. - Each line of the standard output and error streams of the subprocess are redirected to - out and err if they are callable objects. - """ - - assert isinstance(args, types.ListType), "'args' must be a list: " + str(args) - for arg in args: - assert isinstance(arg, types.StringTypes), 'argument is not a string: ' + str(arg) - - if env is None: - env = os.environ.copy() - - # Ideally the command line could be communicated directly in an environment - # variable. However, since environment variables share the same resource - # space as the command line itself (on Unix at least), this would cause the - # limit to be exceeded too easily. - with tempfile.NamedTemporaryFile(suffix='', prefix='mx_subprocess_command.', mode='w', delete=False) as fp: - subprocessCommandFile = fp.name - for arg in args: - # TODO: handle newlines in args once there's a use case - assert '\n' not in arg - print >> fp, arg - env['MX_SUBPROCESS_COMMAND_FILE'] = subprocessCommandFile - - if _opts.verbose: - if _opts.very_verbose: - log('Environment variables:') - for key in sorted(env.keys()): - log(' ' + key + '=' + env[key]) - log(' '.join(map(pipes.quote, args))) - - if timeout is None and _opts.ptimeout != 0: - timeout = _opts.ptimeout - - sub = None - try: - # On Unix, the new subprocess should be in a separate group so that a timeout alarm - # can use os.killpg() to kill the whole subprocess group - preexec_fn = None - creationflags = 0 - if not is_jython(): - if get_os() == 'windows': - creationflags = subprocess.CREATE_NEW_PROCESS_GROUP - else: - preexec_fn = os.setsid - def redirect(stream, f): - for line in iter(stream.readline, ''): - f(line) - stream.close() - stdout = out if not callable(out) else subprocess.PIPE - stderr = err if not callable(err) else subprocess.PIPE - p = subprocess.Popen(args, cwd=cwd, stdout=stdout, stderr=stderr, preexec_fn=preexec_fn, creationflags=creationflags, env=env) - sub = _addSubprocess(p, args) - joiners = [] - if callable(out): - t = Thread(target=redirect, args=(p.stdout, out)) - # Don't make the reader thread a daemon otherwise output can be droppped - t.start() - joiners.append(t) - if callable(err): - t = Thread(target=redirect, args=(p.stderr, err)) - # Don't make the reader thread a daemon otherwise output can be droppped - t.start() - joiners.append(t) - while any([t.is_alive() for t in joiners]): - # Need to use timeout otherwise all signals (including CTRL-C) are blocked - # see: http://bugs.python.org/issue1167930 - for t in joiners: - t.join(10) - if timeout is None or timeout == 0: - retcode = waitOn(p) - else: - if get_os() == 'windows': - abort('Use of timeout not (yet) supported on Windows') - retcode = _waitWithTimeout(p, args, timeout) - except OSError as e: - log('Error executing \'' + ' '.join(args) + '\': ' + str(e)) - if _opts.verbose: - raise e - abort(e.errno) - except KeyboardInterrupt: - abort(1) - finally: - _removeSubprocess(sub) - os.remove(subprocessCommandFile) - - if retcode and nonZeroIsFatal: - if _opts.verbose: - if _opts.very_verbose: - raise subprocess.CalledProcessError(retcode, ' '.join(args)) - else: - log('[exit code: ' + str(retcode) + ']') - abort(retcode) - - return retcode - -def exe_suffix(name): - """ - Gets the platform specific suffix for an executable - """ - if get_os() == 'windows': - return name + '.exe' - return name - -def add_lib_prefix(name): - """ - Adds the platform specific library prefix to a name - """ - os = get_os() - if os == 'linux' or os == 'solaris' or os == 'darwin': - return 'lib' + name - return name - -def add_lib_suffix(name): - """ - Adds the platform specific library suffix to a name - """ - os = get_os() - if os == 'windows': - return name + '.dll' - if os == 'linux' or os == 'solaris': - return name + '.so' - if os == 'darwin': - return name + '.dylib' - return name - -""" -Utility for filtering duplicate lines. -""" -class DuplicateSuppressingStream: - """ - Creates an object that will suppress duplicate lines sent to 'out'. - The lines considered for suppression are those that contain one of the - strings in 'restrictTo' if it is not None. - """ - def __init__(self, restrictTo=None, out=sys.stdout): - self.restrictTo = restrictTo - self.seen = set() - self.out = out - self.currentFilteredLineCount = 0 - self.currentFilteredTime = None - - def isSuppressionCandidate(self, line): - if self.restrictTo: - for p in self.restrictTo: - if p in line: - return True - return False - else: - return True - - def write(self, line): - if self.isSuppressionCandidate(line): - if line in self.seen: - self.currentFilteredLineCount += 1 - if self.currentFilteredTime: - if time.time() - self.currentFilteredTime > 1 * 60: - self.out.write(" Filtered " + str(self.currentFilteredLineCount) + " repeated lines...\n") - self.currentFilteredTime = time.time() - else: - self.currentFilteredTime = time.time() - return - self.seen.add(line) - self.currentFilteredLineCount = 0 - self.out.write(line) - self.currentFilteredTime = None - -""" -A JavaCompliance simplifies comparing Java compliance values extracted from a JDK version string. -""" -class JavaCompliance: - def __init__(self, ver): - m = re.match(r'1\.(\d+).*', ver) - assert m is not None, 'not a recognized version string: ' + ver - self.value = int(m.group(1)) - - def __str__(self): - return '1.' + str(self.value) - - def __cmp__(self, other): - if isinstance(other, types.StringType): - other = JavaCompliance(other) - - return cmp(self.value, other.value) - - def __hash__(self): - return self.value.__hash__() - - def exactMatch(self, version): - assert isinstance(version, VersionSpec) - return len(version.parts) > 1 and version.parts[0] == 1 and version.parts[1] == self.value - -""" -A version specification as defined in JSR-56 -""" -class VersionSpec: - def __init__(self, versionString): - validChar = r'[\x21-\x25\x27-\x29\x2c\x2f-\x5e\x60-\x7f]' - separator = r'[.\-_]' - m = re.match("^" + validChar + '+(' + separator + validChar + '+)*$', versionString) - assert m is not None, 'not a recognized version string: ' + versionString - self.versionString = versionString - self.parts = [int(f) if f.isdigit() else f for f in re.split(separator, versionString)] - - def __str__(self): - return self.versionString - - def __cmp__(self, other): - return cmp(self.parts, other.parts) - -def _filter_non_existant_paths(paths): - if paths: - return os.pathsep.join([path for path in _separatedCygpathW2U(paths).split(os.pathsep) if exists(path)]) - return None - -class JavaConfigException(Exception): - def __init__(self, value): - Exception.__init__(self, value) - -""" -A JavaConfig object encapsulates info on how Java commands are run. -""" -class JavaConfig: - def __init__(self, java_home): - self.jdk = java_home - self.jar = exe_suffix(join(self.jdk, 'bin', 'jar')) - self.java = exe_suffix(join(self.jdk, 'bin', 'java')) - self.javac = exe_suffix(join(self.jdk, 'bin', 'javac')) - self.javap = exe_suffix(join(self.jdk, 'bin', 'javap')) - self.javadoc = exe_suffix(join(self.jdk, 'bin', 'javadoc')) - self.pack200 = exe_suffix(join(self.jdk, 'bin', 'pack200')) - self.toolsjar = join(self.jdk, 'lib', 'tools.jar') - self._classpaths_initialized = False - self._bootclasspath = None - self._extdirs = None - self._endorseddirs = None - - if not exists(self.java): - raise JavaConfigException('Java launcher does not exist: ' + self.java) - - def delAtAndSplit(s): - return shlex.split(s.lstrip('@')) - - self.java_args = delAtAndSplit(_opts.java_args) if _opts.java_args else [] - self.java_args_pfx = sum(map(delAtAndSplit, _opts.java_args_pfx), []) - self.java_args_sfx = sum(map(delAtAndSplit, _opts.java_args_sfx), []) - - # Prepend the -d64 VM option only if the java command supports it - try: - output = subprocess.check_output([self.java, '-d64', '-version'], stderr=subprocess.STDOUT) - self.java_args = ['-d64'] + self.java_args - except subprocess.CalledProcessError as e: - try: - output = subprocess.check_output([self.java, '-version'], stderr=subprocess.STDOUT) - except subprocess.CalledProcessError as e: - raise JavaConfigException(e.returncode + " :" + e.output) - - def _checkOutput(out): - return 'version' in out - - # hotspot can print a warning, e.g. if there's a .hotspot_compiler file in the cwd - output = output.split('\n') - version = None - for o in output: - if _checkOutput(o): - assert version is None - version = o - - self.version = VersionSpec(version.split()[2].strip('"')) - self.javaCompliance = JavaCompliance(self.version.versionString) - - if _opts.java_dbg_port is not None: - self.java_args += ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(_opts.java_dbg_port)] - - def _init_classpaths(self): - if not self._classpaths_initialized: - _, binDir = _compile_mx_class('ClasspathDump', jdk=self) - self._bootclasspath, self._extdirs, self._endorseddirs = [x if x != 'null' else None for x in subprocess.check_output([self.java, '-cp', _cygpathU2W(binDir), 'ClasspathDump'], stderr=subprocess.PIPE).split('|')] - if self.javaCompliance <= JavaCompliance('1.8'): - # All 3 system properties accessed by ClasspathDump are expected to exist - if not self._bootclasspath or not self._extdirs or not self._endorseddirs: - warn("Could not find all classpaths: boot='" + str(self._bootclasspath) + "' extdirs='" + str(self._extdirs) + "' endorseddirs='" + str(self._endorseddirs) + "'") - self._bootclasspath = _filter_non_existant_paths(self._bootclasspath) - self._extdirs = _filter_non_existant_paths(self._extdirs) - self._endorseddirs = _filter_non_existant_paths(self._endorseddirs) - self._classpaths_initialized = True - - def __repr__(self): - return "JavaConfig(" + str(self.jdk) + ")" - - def __str__(self): - return "Java " + str(self.version) + " (" + str(self.javaCompliance) + ") from " + str(self.jdk) - - def __hash__(self): - return hash(self.jdk) - - def __cmp__(self, other): - if other is None: - return False - if isinstance(other, JavaConfig): - compilanceCmp = cmp(self.javaCompliance, other.javaCompliance) - if compilanceCmp: - return compilanceCmp - versionCmp = cmp(self.version, other.version) - if versionCmp: - return versionCmp - return cmp(self.jdk, other.jdk) - raise TypeError() - - def format_cmd(self, args, addDefaultArgs): - if addDefaultArgs: - return [self.java] + self.processArgs(args) - else: - return [self.java] + args - - def processArgs(self, args): - return self.java_args_pfx + self.java_args + self.java_args_sfx + args - - def bootclasspath(self): - self._init_classpaths() - return _separatedCygpathU2W(self._bootclasspath) - - - """ - Add javadoc style options for the library paths of this JDK. - """ - def javadocLibOptions(self, args): - self._init_classpaths() - if args is None: - args = [] - if self._bootclasspath: - args.append('-bootclasspath') - args.append(_separatedCygpathU2W(self._bootclasspath)) - if self._extdirs: - args.append('-extdirs') - args.append(_separatedCygpathU2W(self._extdirs)) - return args - - """ - Add javac style options for the library paths of this JDK. - """ - def javacLibOptions(self, args): - args = self.javadocLibOptions(args) - if self._endorseddirs: - args.append('-endorseddirs') - args.append(_separatedCygpathU2W(self._endorseddirs)) - return args - - def containsJar(self, jar): - self._init_classpaths() - - if self._bootclasspath: - for e in self._bootclasspath.split(os.pathsep): - if basename(e) == jar: - return True - if self._extdirs: - for d in self._extdirs.split(os.pathsep): - if len(d) and jar in os.listdir(d): - return True - if self._endorseddirs: - for d in self._endorseddirs.split(os.pathsep): - if len(d) and jar in os.listdir(d): - return True - return False - -def check_get_env(key): - """ - Gets an environment variable, aborting with a useful message if it is not set. - """ - value = get_env(key) - if value is None: - abort('Required environment variable ' + key + ' must be set') - return value - -def get_env(key, default=None): - """ - Gets an environment variable. - """ - value = os.environ.get(key, default) - return value - -def logv(msg=None): - if _opts.verbose: - log(msg) - -def log(msg=None): - """ - Write a message to the console. - All script output goes through this method thus allowing a subclass - to redirect it. - """ - if msg is None: - print - else: - print msg - -def expand_project_in_class_path_arg(cpArg): - cp = [] - for part in cpArg.split(os.pathsep): - if part.startswith('@'): - cp += classpath(part[1:]).split(os.pathsep) - else: - cp.append(part) - return os.pathsep.join(cp) - -def expand_project_in_args(args): - for i in range(len(args)): - if args[i] == '-cp' or args[i] == '-classpath': - if i + 1 < len(args): - args[i + 1] = expand_project_in_class_path_arg(args[i + 1]) - return - - -def gmake_cmd(): - for a in ['make', 'gmake', 'gnumake']: - try: - output = subprocess.check_output([a, '--version']) - if 'GNU' in output: - return a - except: - pass - abort('Could not find a GNU make executable on the current path.') - -def expandvars_in_property(value): - result = expandvars(value) - if '$' in result or '%' in result: - abort('Property contains an undefined environment variable: ' + value) - return result - -def _send_sigquit(): - for p, args in _currentSubprocesses: - - def _isJava(): - if args: - name = args[0].split(os.sep)[-1] - return name == "java" - return False - - if p is not None and _isJava(): - if get_os() == 'windows': - log("mx: implement me! want to send SIGQUIT to my child process") - else: - _kill_process_group(p.pid, sig=signal.SIGQUIT) - time.sleep(0.1) - -def abort(codeOrMessage): - """ - Aborts the program with a SystemExit exception. - If 'codeOrMessage' is a plain integer, it specifies the system exit status; - if it is None, the exit status is zero; if it has another type (such as a string), - the object's value is printed and the exit status is one. - """ - - if _opts and _opts.killwithsigquit: - _send_sigquit() - - def is_alive(p): - if isinstance(p, subprocess.Popen): - return p.poll() is None - assert is_jython() or isinstance(p, multiprocessing.Process), p - return p.is_alive() - - for p, args in _currentSubprocesses: - if is_alive(p): - try: - if get_os() == 'windows': - p.terminate() - else: - _kill_process_group(p.pid, signal.SIGKILL) - except BaseException as e: - if is_alive(p): - log('error while killing subprocess {0} "{1}": {2}'.format(p.pid, ' '.join(args), e)) - - if _opts and _opts.verbose: - import traceback - traceback.print_stack() - raise SystemExit(codeOrMessage) - -def download(path, urls, verbose=False): - """ - Attempts to downloads content for each URL in a list, stopping after the first successful download. - If the content cannot be retrieved from any URL, the program is aborted. The downloaded content - is written to the file indicated by 'path'. - """ - d = dirname(path) - if d != '' and not exists(d): - os.makedirs(d) - - assert not path.endswith(os.sep) - - _, binDir = _compile_mx_class('URLConnectionDownload') - - verbose = [] - if sys.stderr.isatty(): - verbose.append("-v") - if run([java().java, '-cp', _cygpathU2W(binDir), 'URLConnectionDownload', _cygpathU2W(path)] + verbose + urls, nonZeroIsFatal=False) == 0: - return - - abort('Could not download to ' + path + ' from any of the following URLs:\n\n ' + - '\n '.join(urls) + '\n\nPlease use a web browser to do the download manually') - -def update_file(path, content, showDiff=False): - """ - Updates a file with some given content if the content differs from what's in - the file already. The return value indicates if the file was updated. - """ - existed = exists(path) - try: - old = None - if existed: - with open(path, 'rb') as f: - old = f.read() - - if old == content: - return False - - if existed and _opts.backup_modified: - shutil.move(path, path + '.orig') - - with open(path, 'wb') as f: - f.write(content) - - if existed: - log('modified ' + path) - if showDiff: - log('diff: ' + path) - log(''.join(difflib.unified_diff(old.splitlines(1), content.splitlines(1)))) - - else: - log('created ' + path) - return True - except IOError as e: - abort('Error while writing to ' + path + ': ' + str(e)) - -# Builtin commands - -def _defaultEcjPath(): - return get_env('JDT', join(_primary_suite.mxDir, 'ecj.jar')) - -class JavaCompileTask: - def __init__(self, args, proj, reason, javafilelist, jdk, outputDir, jdtJar, deps): - self.proj = proj - self.reason = reason - self.javafilelist = javafilelist - self.deps = deps - self.jdk = jdk - self.outputDir = outputDir - self.done = False - self.jdtJar = jdtJar - self.args = args - - def __str__(self): - return self.proj.name - - def logCompilation(self, compiler): - log('Compiling Java sources for {0} with {1}... [{2}]'.format(self.proj.name, compiler, self.reason)) - - def execute(self): - argfileName = join(self.proj.dir, 'javafilelist.txt') - argfile = open(argfileName, 'wb') - argfile.write('\n'.join(map(_cygpathU2W, self.javafilelist))) - argfile.close() - - processorArgs = [] - processorPath = self.proj.annotation_processors_path() - if processorPath: - genDir = self.proj.source_gen_dir() - if exists(genDir): - shutil.rmtree(genDir) - os.mkdir(genDir) - processorArgs += ['-processorpath', _separatedCygpathU2W(join(processorPath)), '-s', _cygpathU2W(genDir)] - else: - processorArgs += ['-proc:none'] - - args = self.args - jdk = self.jdk - outputDir = _cygpathU2W(self.outputDir) - compliance = str(jdk.javaCompliance) - cp = _separatedCygpathU2W(classpath(self.proj.name, includeSelf=True)) - toBeDeleted = [argfileName] - - try: - if not self.jdtJar: - mainJava = java() - if not args.error_prone: - javac = args.alt_javac if args.alt_javac else mainJava.javac - self.logCompilation('javac' if not args.alt_javac else args.alt_javac) - javacCmd = [javac, '-g', '-J-Xmx1g', '-source', compliance, '-target', compliance, '-classpath', cp, '-d', outputDir] - if _opts.very_verbose: - javacCmd.append('-verbose') - jdk.javacLibOptions(javacCmd) - if _opts.java_dbg_port is not None: - javacCmd += ['-J-Xdebug', '-J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(_opts.java_dbg_port)] - javacCmd += processorArgs - javacCmd += ['@' + _cygpathU2W(argfile.name)] - - if not args.warnAPI: - javacCmd.append('-XDignore.symbol.file') - run(javacCmd) - else: - self.logCompilation('javac (with error-prone)') - javaArgs = ['-Xmx1g'] - javacArgs = ['-g', '-source', compliance, '-target', compliance, '-classpath', cp, '-d', outputDir] - if _opts.very_verbose: - javacArgs.append('-verbose') - jdk.javacLibOptions(javacCmd) - javacArgs += processorArgs - javacArgs += ['@' + argfile.name] - if not args.warnAPI: - javacArgs.append('-XDignore.symbol.file') - run_java(javaArgs + ['-cp', os.pathsep.join([mainJava.toolsjar, args.error_prone]), 'com.google.errorprone.ErrorProneCompiler'] + javacArgs) - else: - self.logCompilation('JDT') - - jdtVmArgs = ['-Xmx1g', '-jar', _cygpathU2W(self.jdtJar)] - - jdtArgs = ['-' + compliance, - '-cp', cp, '-g', '-enableJavadoc', - '-d', outputDir] - if _opts.very_verbose: - jdtArgs.append('-verbose') - jdk.javacLibOptions(jdtArgs) - jdtArgs += processorArgs - - jdtProperties = join(self.proj.dir, '.settings', 'org.eclipse.jdt.core.prefs') - jdtPropertiesSources = self.proj.eclipse_settings_sources()['org.eclipse.jdt.core.prefs'] - if not exists(jdtProperties) or os.path.getmtime(jdtProperties) < min(map(os.path.getmtime, jdtPropertiesSources)): - # Try to fix a missing or out of date properties file by running eclipseinit - _eclipseinit_project(self.proj) - if not exists(jdtProperties): - log('JDT properties file {0} not found'.format(jdtProperties)) - else: - with open(jdtProperties) as fp: - origContent = fp.read() - content = origContent - if self.proj.uses_annotation_processor_library(): - # unfortunately, the command line compiler doesn't let us ignore warnings for generated files only - content = content.replace('=warning', '=ignore') - elif args.jdt_warning_as_error: - content = content.replace('=warning', '=error') - if not args.jdt_show_task_tags: - content = content + '\norg.eclipse.jdt.core.compiler.problem.tasks=ignore' - if origContent != content: - jdtPropertiesTmp = jdtProperties + '.tmp' - with open(jdtPropertiesTmp, 'w') as fp: - fp.write(content) - toBeDeleted.append(jdtPropertiesTmp) - jdtArgs += ['-properties', _cygpathU2W(jdtPropertiesTmp)] - else: - jdtArgs += ['-properties', _cygpathU2W(jdtProperties)] - jdtArgs.append('@' + _cygpathU2W(argfile.name)) - - run_java(jdtVmArgs + jdtArgs) - - # Create annotation processor jar for a project that defines annotation processors - if self.proj.definedAnnotationProcessorsDist: - self.proj.definedAnnotationProcessorsDist.make_archive() - - finally: - # Do not clean up temp files if verbose as there's - # a good chance the user wants to copy and paste the - # Java compiler command directly - if not _opts.verbose: - for n in toBeDeleted: - os.remove(n) - - self.done = True - -def build(args, parser=None): - """compile the Java and C sources, linking the latter - - Compile all the Java source code using the appropriate compilers - and linkers for the various source code types.""" - - suppliedParser = parser is not None - if not suppliedParser: - parser = ArgumentParser(prog='mx build') - - parser = parser if parser is not None else ArgumentParser(prog='mx build') - parser.add_argument('-f', action='store_true', dest='force', help='force build (disables timestamp checking)') - parser.add_argument('-c', action='store_true', dest='clean', help='removes existing build output') - parser.add_argument('-p', action='store_true', dest='parallelize', help='parallelizes Java compilation if possible') - parser.add_argument('--source', dest='compliance', help='Java compliance level for projects without an explicit one') - parser.add_argument('--Wapi', action='store_true', dest='warnAPI', help='show warnings about using internal APIs') - parser.add_argument('--check-distributions', action='store_true', dest='check_distributions', help='check built distributions for overlap') - parser.add_argument('--projects', action='store', help='comma separated projects to build (omit to build all projects)') - parser.add_argument('--only', action='store', help='comma separated projects to build, without checking their dependencies (omit to build all projects)') - parser.add_argument('--no-java', action='store_false', dest='java', help='do not build Java projects') - parser.add_argument('--no-native', action='store_false', dest='native', help='do not build native projects') - parser.add_argument('--jdt-warning-as-error', action='store_true', help='convert all Eclipse batch compiler warnings to errors') - parser.add_argument('--jdt-show-task-tags', action='store_true', help='show task tags as Eclipse batch compiler warnings') - parser.add_argument('--alt-javac', dest='alt_javac', help='path to alternative javac executable', metavar='') - compilerSelect = parser.add_mutually_exclusive_group() - compilerSelect.add_argument('--error-prone', dest='error_prone', help='path to error-prone.jar', metavar='') - compilerSelect.add_argument('--jdt', help='path to ecj.jar, the stand alone Eclipse batch compiler', default=_defaultEcjPath(), metavar='') - compilerSelect.add_argument('--force-javac', action='store_true', dest='javac', help='use javac whether ecj.jar is found or not') - - if suppliedParser: - parser.add_argument('remainder', nargs=REMAINDER, metavar='...') - - args = parser.parse_args(args) - - if is_jython(): - if args.parallelize: - logv('[multiprocessing not available in jython]') - args.parallelize = False - - jdtJar = None - if not args.javac and args.jdt is not None: - if not args.jdt.endswith('.jar'): - abort('Path for Eclipse batch compiler does not look like a jar file: ' + args.jdt) - jdtJar = args.jdt - if not exists(jdtJar): - if os.path.abspath(jdtJar) == os.path.abspath(_defaultEcjPath()) and get_env('JDT', None) is None: - # Silently ignore JDT if default location is used but does not exist - jdtJar = None - else: - abort('Eclipse batch compiler jar does not exist: ' + args.jdt) - else: - with zipfile.ZipFile(jdtJar, 'r') as zf: - if 'org/eclipse/jdt/internal/compiler/apt/' not in zf.namelist(): - abort('Specified Eclipse compiler does not include annotation processing support. ' + - 'Ensure you are using a stand alone ecj.jar, not org.eclipse.jdt.core_*.jar ' + - 'from within the plugins/ directory of an Eclipse IDE installation.') - - if args.only is not None: - # N.B. This build will not include dependencies including annotation processor dependencies - sortedProjects = [project(name) for name in args.only.split(',')] - else: - if args.projects is not None: - projectNames = args.projects.split(',') - else: - projectNames = None - - projects = _projects_opt_limit_to_suites(projects_from_names(projectNames)) - # N.B. Limiting to a suite only affects the starting set of projects. Dependencies in other suites will still be compiled - sortedProjects = sorted_project_deps(projects, includeAnnotationProcessors=True) - - if args.java and jdtJar: - ideinit([], refreshOnly=True, buildProcessorJars=False) - - tasks = {} - updatedAnnotationProcessorDists = set() - for p in sortedProjects: - if p.native: - if args.native: - log('Calling GNU make {0}...'.format(p.dir)) - - if args.clean: - run([gmake_cmd(), 'clean'], cwd=p.dir) - - run([gmake_cmd()], cwd=p.dir) - continue - else: - if not args.java: - continue - if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project - continue - - # skip building this Java project if its Java compliance level is "higher" than the configured JDK - requiredCompliance = p.javaCompliance if p.javaCompliance else JavaCompliance(args.compliance) if args.compliance else None - jdk = java(requiredCompliance) - - outputDir = p.output_dir() - - sourceDirs = p.source_dirs() - buildReason = None - if args.force: - buildReason = 'forced build' - elif args.clean: - buildReason = 'clean' - - taskDeps = [] - for dep in p.all_deps([], includeLibs=False, includeAnnotationProcessors=True): - taskDep = tasks.get(dep.name) - if taskDep: - if not buildReason: - buildReason = dep.name + ' rebuilt' - taskDeps.append(taskDep) - - javafilelist = [] - nonjavafiletuples = [] - for sourceDir in sourceDirs: - for root, _, files in os.walk(sourceDir): - javafiles = [join(root, name) for name in files if name.endswith('.java')] - javafilelist += javafiles - - nonjavafiletuples += [(sourceDir, [join(root, name) for name in files if not name.endswith('.java')])] - - if not buildReason: - for javafile in javafiles: - classfile = TimeStampFile(outputDir + javafile[len(sourceDir):-len('java')] + 'class') - if not classfile.exists() or classfile.isOlderThan(javafile): - if basename(classfile.path) != 'package-info.class': - buildReason = 'class file(s) out of date (witness: ' + classfile.path + ')' - break - - apsOutOfDate = p.update_current_annotation_processors_file() - if apsOutOfDate: - buildReason = 'annotation processor(s) changed' - - if not buildReason: - logv('[all class files for {0} are up to date - skipping]'.format(p.name)) - _handleNonJavaFiles(outputDir, p, False, nonjavafiletuples) - continue - - _handleNonJavaFiles(outputDir, p, True, nonjavafiletuples) - - if len(javafilelist) == 0: - logv('[no Java sources for {0} - skipping]'.format(p.name)) - continue - - javafilelist = sorted(javafilelist) - - task = JavaCompileTask(args, p, buildReason, javafilelist, jdk, outputDir, jdtJar, taskDeps) - if p.definedAnnotationProcessorsDist: - updatedAnnotationProcessorDists.add(p.definedAnnotationProcessorsDist) - - tasks[p.name] = task - if args.parallelize: - # Best to initialize class paths on main process - jdk.bootclasspath() - task.proc = None - else: - task.execute() - - if args.parallelize: - - def joinTasks(tasks): - failed = [] - for t in tasks: - t.proc.join() - _removeSubprocess(t.sub) - if t.proc.exitcode != 0: - failed.append(t) - return failed - - def checkTasks(tasks): - active = [] - for t in tasks: - if t.proc.is_alive(): - active.append(t) - else: - if t.proc.exitcode != 0: - return ([], joinTasks(tasks)) - return (active, []) - - def remainingDepsDepth(task): - if task._d is None: - incompleteDeps = [d for d in task.deps if d.proc is None or d.proc.is_alive()] - if len(incompleteDeps) == 0: - task._d = 0 - else: - task._d = max([remainingDepsDepth(t) for t in incompleteDeps]) + 1 - return task._d - - def compareTasks(t1, t2): - d = remainingDepsDepth(t1) - remainingDepsDepth(t2) - if d == 0: - t1Work = (1 + len(t1.proj.annotation_processors())) * len(t1.javafilelist) - t2Work = (1 + len(t2.proj.annotation_processors())) * len(t2.javafilelist) - d = t1Work - t2Work - return d - - def sortWorklist(tasks): - for t in tasks: - t._d = None - return sorted(tasks, compareTasks) - - cpus = cpu_count() - worklist = sortWorklist(tasks.values()) - active = [] - failed = [] - while len(worklist) != 0: - while True: - active, failed = checkTasks(active) - if len(failed) != 0: - assert not active, active - break - if len(active) == cpus: - # Sleep for 1 second - time.sleep(1) - else: - break - - if len(failed) != 0: - break - - def executeTask(task): - # Clear sub-process list cloned from parent process - del _currentSubprocesses[:] - task.execute() - - def depsDone(task): - for d in task.deps: - if d.proc is None or d.proc.exitcode is None: - return False - return True - - for task in worklist: - if depsDone(task): - worklist.remove(task) - task.proc = multiprocessing.Process(target=executeTask, args=(task,)) - task.proc.start() - active.append(task) - task.sub = _addSubprocess(task.proc, ['JavaCompileTask', str(task)]) - if len(active) == cpus: - break - - worklist = sortWorklist(worklist) - - failed += joinTasks(active) - if len(failed): - for t in failed: - log('Compiling {0} failed'.format(t.proj.name)) - abort('{0} Java compilation tasks failed'.format(len(failed))) - - if args.java and not args.only: - files = [] - rebuiltProjects = frozenset([t.proj for t in tasks.itervalues()]) - for dist in sorted_dists(): - if not exists(dist.path): - log('Creating jar for {0}'.format(dist.name)) - dist.make_archive() - elif dist not in updatedAnnotationProcessorDists: - projectsInDist = dist.sorted_deps() - n = len(rebuiltProjects.intersection(projectsInDist)) - if n != 0: - log('Updating jar for {0} [{1} constituent projects (re)built]'.format(dist.name, n)) - dist.make_archive() - else: - logv('[all constituent projects for {0} are up to date - skipping jar updating]'.format(dist.name)) - if args.check_distributions and not dist.isProcessorDistribution: - with zipfile.ZipFile(dist.path, 'r') as zf: - files.extend([member for member in zf.namelist() if not member.startswith('META-INF')]) - dups = set([x for x in files if files.count(x) > 1]) - if len(dups) > 0: - abort('Distributions overlap! duplicates: ' + str(dups)) - - if suppliedParser: - return args - return None - -def _handleNonJavaFiles(outputDir, p, clean, nonjavafiletuples): - if exists(outputDir): - if clean: - log('Cleaning {0}...'.format(outputDir)) - shutil.rmtree(outputDir) - os.mkdir(outputDir) - else: - os.mkdir(outputDir) - genDir = p.source_gen_dir() - if genDir != '' and exists(genDir) and clean: - log('Cleaning {0}...'.format(genDir)) - for f in os.listdir(genDir): - shutil.rmtree(join(genDir, f)) - - # Copy all non Java resources or assemble Jasmin files - jasminAvailable = None - for nonjavafiletuple in nonjavafiletuples: - sourceDir = nonjavafiletuple[0] - nonjavafilelist = nonjavafiletuple[1] - - for src in nonjavafilelist: - if src.endswith('.jasm'): - className = None - with open(src) as f: - for line in f: - if line.startswith('.class '): - className = line.split()[-1] - break - - if className is not None: - jasminOutputDir = p.jasmin_output_dir() - classFile = join(jasminOutputDir, className.replace('/', os.sep) + '.class') - if exists(dirname(classFile)) and (not exists(classFile) or os.path.getmtime(classFile) < os.path.getmtime(src)): - if jasminAvailable is None: - try: - with open(os.devnull) as devnull: - subprocess.call('jasmin', stdout=devnull, stderr=subprocess.STDOUT) - jasminAvailable = True - except OSError: - jasminAvailable = False - - if jasminAvailable: - log('Assembling Jasmin file ' + src) - run(['jasmin', '-d', jasminOutputDir, src]) - else: - log('The jasmin executable could not be found - skipping ' + src) - with file(classFile, 'a'): - os.utime(classFile, None) - - else: - log('could not file .class directive in Jasmin source: ' + src) - else: - dst = join(outputDir, src[len(sourceDir) + 1:]) - if not exists(dirname(dst)): - os.makedirs(dirname(dst)) - if exists(dirname(dst)) and (not exists(dst) or os.path.getmtime(dst) < os.path.getmtime(src)): - shutil.copyfile(src, dst) - -def _chunk_files_for_command_line(files, limit=None, pathFunction=lambda f: f): - """ - Returns a generator for splitting up a list of files into chunks such that the - size of the space separated file paths in a chunk is less than a given limit. - This is used to work around system command line length limits. - """ - chunkSize = 0 - chunkStart = 0 - if limit is None: - commandLinePrefixAllowance = 3000 - if get_os() == 'windows': - # The CreateProcess function on Windows limits the length of a command line to - # 32,768 characters (http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx) - limit = 32768 - commandLinePrefixAllowance - else: - # Using just SC_ARG_MAX without extra downwards adjustment - # results in "[Errno 7] Argument list too long" on MacOS. - commandLinePrefixAllowance = 20000 - syslimit = os.sysconf('SC_ARG_MAX') - if syslimit == -1: - syslimit = 262144 # we could use sys.maxint but we prefer a more robust smaller value - limit = syslimit - commandLinePrefixAllowance - assert limit > 0 - for i in range(len(files)): - path = pathFunction(files[i]) - size = len(path) + 1 - assert size < limit - if chunkSize + size < limit: - chunkSize += size - else: - assert i > chunkStart - yield files[chunkStart:i] - chunkStart = i - chunkSize = 0 - if chunkStart == 0: - assert chunkSize < limit - yield files - -def eclipseformat(args): - """run the Eclipse Code Formatter on the Java sources - - The exit code 1 denotes that at least one file was modified.""" - - parser = ArgumentParser(prog='mx eclipseformat') - parser.add_argument('-e', '--eclipse-exe', help='location of the Eclipse executable') - parser.add_argument('-C', '--no-backup', action='store_false', dest='backup', help='do not save backup of modified files') - parser.add_argument('--projects', action='store', help='comma separated projects to process (omit to process all projects)') - - args = parser.parse_args(args) - if args.eclipse_exe is None: - args.eclipse_exe = os.environ.get('ECLIPSE_EXE') - if args.eclipse_exe is None: - abort('Could not find Eclipse executable. Use -e option or ensure ECLIPSE_EXE environment variable is set.') - - # Maybe an Eclipse installation dir was specified - look for the executable in it - if isdir(args.eclipse_exe): - args.eclipse_exe = join(args.eclipse_exe, exe_suffix('eclipse')) - warn("The eclipse-exe was a directory, now using " + args.eclipse_exe) - - if not os.path.isfile(args.eclipse_exe): - abort('File does not exist: ' + args.eclipse_exe) - if not os.access(args.eclipse_exe, os.X_OK): - abort('Not an executable file: ' + args.eclipse_exe) - - eclipseinit([], buildProcessorJars=False) - - # build list of projects to be processed - projects = sorted_deps() - if args.projects is not None: - projects = [project(name) for name in args.projects.split(',')] - - class Batch: - def __init__(self, settingsDir): - self.path = join(settingsDir, 'org.eclipse.jdt.core.prefs') - with open(join(settingsDir, 'org.eclipse.jdt.ui.prefs')) as fp: - jdtUiPrefs = fp.read() - self.removeTrailingWhitespace = 'sp_cleanup.remove_trailing_whitespaces_all=true' in jdtUiPrefs - if self.removeTrailingWhitespace: - assert 'sp_cleanup.remove_trailing_whitespaces=true' in jdtUiPrefs and 'sp_cleanup.remove_trailing_whitespaces_ignore_empty=false' in jdtUiPrefs - self.cachedHash = None - - def __hash__(self): - if not self.cachedHash: - with open(self.path) as fp: - self.cachedHash = (fp.read(), self.removeTrailingWhitespace).__hash__() - return self.cachedHash - - def __eq__(self, other): - if not isinstance(other, Batch): - return False - if self.removeTrailingWhitespace != other.removeTrailingWhitespace: - return False - if self.path == other.path: - return True - with open(self.path) as fp: - with open(other.path) as ofp: - if fp.read() != ofp.read(): - return False - return True - - class FileInfo: - def __init__(self, path): - self.path = path - with open(path) as fp: - self.content = fp.read() - self.times = (os.path.getatime(path), os.path.getmtime(path)) - - def update(self, removeTrailingWhitespace): - with open(self.path) as fp: - content = fp.read() - - if self.content != content: - # Only apply *after* formatting to match the order in which the IDE does it - if removeTrailingWhitespace: - content, n = re.subn(r'[ \t]+$', '', content, flags=re.MULTILINE) - if n != 0 and self.content == content: - # undo on-disk changes made by the Eclipse formatter - with open(self.path, 'w') as fp: - fp.write(content) - - if self.content != content: - self.diff = difflib.unified_diff(self.content.splitlines(1), content.splitlines(1)) - self.content = content - return True - - # reset access and modification time of file - os.utime(self.path, self.times) - - modified = list() - batches = dict() # all sources with the same formatting settings are formatted together - for p in projects: - if p.native: - continue - sourceDirs = p.source_dirs() - - batch = Batch(join(p.dir, '.settings')) - - if not exists(batch.path): - if _opts.verbose: - log('[no Eclipse Code Formatter preferences at {0} - skipping]'.format(batch.path)) - continue - javafiles = [] - for sourceDir in sourceDirs: - for root, _, files in os.walk(sourceDir): - for f in [join(root, name) for name in files if name.endswith('.java')]: - javafiles.append(FileInfo(f)) - if len(javafiles) == 0: - logv('[no Java sources in {0} - skipping]'.format(p.name)) - continue - - res = batches.setdefault(batch, javafiles) - if res is not javafiles: - res.extend(javafiles) - - log("we have: " + str(len(batches)) + " batches") - for batch, javafiles in batches.iteritems(): - for chunk in _chunk_files_for_command_line(javafiles, pathFunction=lambda f: f.path): - run([args.eclipse_exe, - '-nosplash', - '-application', - 'org.eclipse.jdt.core.JavaCodeFormatter', - '-config', batch.path] - + [f.path for f in chunk]) - for fi in chunk: - if fi.update(batch.removeTrailingWhitespace): - modified.append(fi) - - log('{0} files were modified'.format(len(modified))) - - if len(modified) != 0: - arcbase = _primary_suite.dir - if args.backup: - backup = os.path.abspath('eclipseformat.backup.zip') - zf = zipfile.ZipFile(backup, 'w', zipfile.ZIP_DEFLATED) - for fi in modified: - name = os.path.relpath(fi.path, arcbase) - log(' - {0}'.format(name)) - log('Changes:') - log(''.join(fi.diff)) - if args.backup: - arcname = name.replace(os.sep, '/') - zf.writestr(arcname, fi.content) - if args.backup: - zf.close() - log('Wrote backup of {0} modified files to {1}'.format(len(modified), backup)) - return 1 - return 0 - -def processorjars(): - for s in suites(True): - _processorjars_suite(s) - -def _processorjars_suite(s): - projs = [p for p in s.projects if p.definedAnnotationProcessors is not None] - if len(projs) <= 0: - return [] - - pnames = [p.name for p in projs] - build(['--jdt-warning-as-error', '--projects', ",".join(pnames)]) - return [p.definedAnnotationProcessorsDist.path for p in s.projects if p.definedAnnotationProcessorsDist is not None] - -def pylint(args): - """run pylint (if available) over Python source files (found by 'hg locate' or by tree walk with -walk)""" - - parser = ArgumentParser(prog='mx pylint') - parser.add_argument('--walk', action='store_true', help='use tree walk find .py files') - args = parser.parse_args(args) - - rcfile = join(dirname(__file__), '.pylintrc') - if not exists(rcfile): - log('pylint configuration file does not exist: ' + rcfile) - return - - try: - output = subprocess.check_output(['pylint', '--version'], stderr=subprocess.STDOUT) - m = re.match(r'.*pylint (\d+)\.(\d+)\.(\d+).*', output, re.DOTALL) - if not m: - log('could not determine pylint version from ' + output) - return - major, minor, micro = (int(m.group(1)), int(m.group(2)), int(m.group(3))) - if major != 1 or minor != 1: - log('require pylint version = 1.1.x (got {0}.{1}.{2})'.format(major, minor, micro)) - return - except BaseException: - log('pylint is not available') - return - - def findfiles_by_walk(): - result = [] - for suite in suites(True): - for root, dirs, files in os.walk(suite.dir): - for f in files: - if f.endswith('.py'): - pyfile = join(root, f) - result.append(pyfile) - if 'bin' in dirs: - dirs.remove('bin') - if 'lib' in dirs: - # avoids downloaded .py files - dirs.remove('lib') - return result - - def findfiles_by_hg(): - result = [] - for suite in suites(True): - versioned = subprocess.check_output(['hg', 'locate', '-f'], stderr=subprocess.STDOUT, cwd=suite.dir).split(os.linesep) - for f in versioned: - if f.endswith('.py') and exists(f): - result.append(f) - return result - - # Perhaps we should just look in suite.mxDir directories for .py files? - if args.walk: - pyfiles = findfiles_by_walk() - else: - pyfiles = findfiles_by_hg() - - env = os.environ.copy() - - pythonpath = dirname(__file__) - for suite in suites(True): - pythonpath = os.pathsep.join([pythonpath, suite.mxDir]) - - env['PYTHONPATH'] = pythonpath - - for pyfile in pyfiles: - log('Running pylint on ' + pyfile + '...') - run(['pylint', '--reports=n', '--rcfile=' + rcfile, pyfile], env=env) - -""" -Utility for creating and updating a zip file atomically. -""" -class Archiver: - def __init__(self, path): - self.path = path - - def __enter__(self): - if self.path: - if not isdir(dirname(self.path)): - os.makedirs(dirname(self.path)) - fd, tmp = tempfile.mkstemp(suffix='', prefix=basename(self.path) + '.', dir=dirname(self.path)) - self.tmpFd = fd - self.tmpPath = tmp - self.zf = zipfile.ZipFile(tmp, 'w') - else: - self.tmpFd = None - self.tmpPath = None - self.zf = None - return self - - def __exit__(self, exc_type, exc_value, traceback): - if self.zf: - self.zf.close() - os.close(self.tmpFd) - # Correct the permissions on the temporary file which is created with restrictive permissions - os.chmod(self.tmpPath, 0o666 & ~currentUmask) - # Atomic on Unix - shutil.move(self.tmpPath, self.path) - -def _archive(args): - archive(args) - return 0 - -def archive(args): - """create jar files for projects and distributions""" - parser = ArgumentParser(prog='mx archive') - parser.add_argument('--parsable', action='store_true', dest='parsable', help='Outputs results in a stable parsable way (one archive per line, =)') - parser.add_argument('names', nargs=REMAINDER, metavar='[|@]...') - args = parser.parse_args(args) - - archives = [] - for name in args.names: - if name.startswith('@'): - dname = name[1:] - d = distribution(dname) - d.make_archive() - archives.append(d.path) - if args.parsable: - log('{0}={1}'.format(dname, d.path)) - else: - p = project(name) - path = p.make_archive() - archives.append(path) - if args.parsable: - log('{0}={1}'.format(name, path)) - - if not args.parsable: - logv("generated archives: " + str(archives)) - return archives - -def canonicalizeprojects(args): - """check all project specifications for canonical dependencies - - The exit code of this command reflects how many projects have non-canonical dependencies.""" - - nonCanonical = [] - for s in suites(True): - for p in s.projects: - if p.checkPackagePrefix: - for pkg in p.defined_java_packages(): - if not pkg.startswith(p.name): - abort('package in {0} does not have prefix matching project name: {1}'.format(p, pkg)) - - ignoredDeps = set([name for name in p.deps if project(name, False) is not None]) - for pkg in p.imported_java_packages(): - for name in p.deps: - dep = project(name, False) - if dep is None: - ignoredDeps.discard(name) - else: - if pkg in dep.defined_java_packages(): - ignoredDeps.discard(name) - if pkg in dep.extended_java_packages(): - ignoredDeps.discard(name) - if len(ignoredDeps) != 0: - candidates = set() - # Compute dependencies based on projects required by p - for d in sorted_deps(): - if not d.defined_java_packages().isdisjoint(p.imported_java_packages()): - candidates.add(d) - # Remove non-canonical candidates - for c in list(candidates): - candidates.difference_update(c.all_deps([], False, False)) - candidates = [d.name for d in candidates] - - abort('{0} does not use any packages defined in these projects: {1}\nComputed project dependencies: {2}'.format( - p, ', '.join(ignoredDeps), ','.join(candidates))) - - excess = frozenset(p.deps) - set(p.canonical_deps()) - if len(excess) != 0: - nonCanonical.append(p) - if len(nonCanonical) != 0: - for p in nonCanonical: - canonicalDeps = p.canonical_deps() - if len(canonicalDeps) != 0: - log('Canonical dependencies for project ' + p.name + ' are: [') - for d in canonicalDeps: - log(' "' + d + '",') - log(' ],') - else: - log('Canonical dependencies for project ' + p.name + ' are: []') - return len(nonCanonical) - -class TimeStampFile: - def __init__(self, path): - self.path = path - self.timestamp = os.path.getmtime(path) if exists(path) else None - - def isOlderThan(self, arg): - if not self.timestamp: - return True - if isinstance(arg, TimeStampFile): - if arg.timestamp is None: - return False - else: - return arg.timestamp > self.timestamp - elif isinstance(arg, types.ListType): - files = arg - else: - files = [arg] - for f in files: - if os.path.getmtime(f) > self.timestamp: - return True - return False - - def exists(self): - return exists(self.path) - - def touch(self): - if exists(self.path): - os.utime(self.path, None) - else: - if not isdir(dirname(self.path)): - os.makedirs(dirname(self.path)) - file(self.path, 'a') - -def checkstyle(args): - """run Checkstyle on the Java sources - - Run Checkstyle over the Java sources. Any errors or warnings - produced by Checkstyle result in a non-zero exit code.""" - - parser = ArgumentParser(prog='mx checkstyle') - - parser.add_argument('-f', action='store_true', dest='force', help='force checking (disables timestamp checking)') - args = parser.parse_args(args) - - totalErrors = 0 - for p in projects_opt_limit_to_suites(): - if p.native: - continue - sourceDirs = p.source_dirs() - - config = join(project(p.checkstyleProj).dir, '.checkstyle_checks.xml') - if not exists(config): - logv('[No Checkstyle configuration found for {0} - skipping]'.format(p)) - continue - - # skip checking this Java project if its Java compliance level is "higher" than the configured JDK - jdk = java(p.javaCompliance) - assert jdk - - for sourceDir in sourceDirs: - javafilelist = [] - for root, _, files in os.walk(sourceDir): - javafilelist += [join(root, name) for name in files if name.endswith('.java') and name != 'package-info.java'] - if len(javafilelist) == 0: - logv('[no Java sources in {0} - skipping]'.format(sourceDir)) - continue - - timestamp = TimeStampFile(join(p.suite.mxDir, 'checkstyle-timestamps', sourceDir[len(p.suite.dir) + 1:].replace(os.sep, '_') + '.timestamp')) - mustCheck = False - if not args.force and timestamp.exists(): - mustCheck = timestamp.isOlderThan(javafilelist) - else: - mustCheck = True - - if not mustCheck: - if _opts.verbose: - log('[all Java sources in {0} already checked - skipping]'.format(sourceDir)) - continue - - exclude = join(p.dir, '.checkstyle.exclude') - if exists(exclude): - with open(exclude) as f: - # Convert patterns to OS separators - patterns = [name.rstrip().replace('/', os.sep) for name in f.readlines()] - def match(name): - for p in patterns: - if p in name: - if _opts.verbose: - log('excluding: ' + name) - return True - return False - - javafilelist = [name for name in javafilelist if not match(name)] - - auditfileName = join(p.dir, 'checkstyleOutput.txt') - log('Running Checkstyle on {0} using {1}...'.format(sourceDir, config)) - - try: - for chunk in _chunk_files_for_command_line(javafilelist): - try: - run_java(['-Xmx1g', '-jar', library('CHECKSTYLE').get_path(True), '-f', 'xml', '-c', config, '-o', auditfileName] + chunk, nonZeroIsFatal=False) - finally: - if exists(auditfileName): - errors = [] - source = [None] - def start_element(name, attrs): - if name == 'file': - source[0] = attrs['name'] - elif name == 'error': - errors.append('{0}:{1}: {2}'.format(source[0], attrs['line'], attrs['message'])) - - xp = xml.parsers.expat.ParserCreate() - xp.StartElementHandler = start_element - with open(auditfileName) as fp: - xp.ParseFile(fp) - if len(errors) != 0: - map(log, errors) - totalErrors = totalErrors + len(errors) - else: - timestamp.touch() - finally: - if exists(auditfileName): - os.unlink(auditfileName) - return totalErrors - -def clean(args, parser=None): - """remove all class files, images, and executables - - Removes all files created by a build, including Java class files, executables, and - generated images. - """ - - suppliedParser = parser is not None - - parser = parser if suppliedParser else ArgumentParser(prog='mx clean') - parser.add_argument('--no-native', action='store_false', dest='native', help='do not clean native projects') - parser.add_argument('--no-java', action='store_false', dest='java', help='do not clean Java projects') - parser.add_argument('--no-dist', action='store_false', dest='dist', help='do not delete distributions') - - args = parser.parse_args(args) - - def _rmtree(dirPath): - path = dirPath - if get_os() == 'windows': - path = unicode("\\\\?\\" + dirPath) - shutil.rmtree(path) - - def _rmIfExists(name): - if name and os.path.isfile(name): - os.unlink(name) - - for p in projects_opt_limit_to_suites(): - if p.native: - if args.native: - run([gmake_cmd(), '-C', p.dir, 'clean']) - else: - if args.java: - genDir = p.source_gen_dir() - if genDir != '' and exists(genDir): - log('Clearing {0}...'.format(genDir)) - for f in os.listdir(genDir): - _rmtree(join(genDir, f)) - - - outputDir = p.output_dir() - if outputDir != '' and exists(outputDir): - log('Removing {0}...'.format(outputDir)) - _rmtree(outputDir) - - for configName in ['netbeans-config.zip', 'eclipse-config.zip']: - config = TimeStampFile(join(p.suite.mxDir, configName)) - if config.exists(): - os.unlink(config.path) - - if args.java: - if args.dist: - for d in _dists.keys(): - log('Removing distribution {0}...'.format(d)) - _rmIfExists(distribution(d).path) - _rmIfExists(distribution(d).sourcesPath) - - if suppliedParser: - return args - -def about(args): - """show the 'man page' for mx""" - print __doc__ - -def help_(args): - """show help for a given command - -With no arguments, print a list of commands and short help for each command. - -Given a command name, print help for that command.""" - if len(args) == 0: - _argParser.print_help() - return - - name = args[0] - if not _commands.has_key(name): - hits = [c for c in _commands.iterkeys() if c.startswith(name)] - if len(hits) == 1: - name = hits[0] - elif len(hits) == 0: - abort('mx: unknown command \'{0}\'\n{1}use "mx help" for more options'.format(name, _format_commands())) - else: - abort('mx: command \'{0}\' is ambiguous\n {1}'.format(name, ' '.join(hits))) - - value = _commands[name] - (func, usage) = value[:2] - doc = func.__doc__ - if len(value) > 2: - docArgs = value[2:] - fmtArgs = [] - for d in docArgs: - if isinstance(d, Callable): - fmtArgs += [d()] - else: - fmtArgs += [str(d)] - doc = doc.format(*fmtArgs) - print 'mx {0} {1}\n\n{2}\n'.format(name, usage, doc) - -def projectgraph(args, suite=None): - """create graph for project structure ("mx projectgraph | dot -Tpdf -oprojects.pdf" or "mx projectgraph --igv")""" - - parser = ArgumentParser(prog='mx projectgraph') - parser.add_argument('--igv', action='store_true', help='output to IGV listening on 127.0.0.1:4444') - parser.add_argument('--igv-format', action='store_true', help='output graph in IGV format') - - args = parser.parse_args(args) - - if args.igv or args.igv_format: - ids = {} - nextToIndex = {} - igv = XMLDoc() - igv.open('graphDocument') - igv.open('group') - igv.open('properties') - igv.element('p', {'name' : 'name'}, 'GraalProjectDependencies') - igv.close('properties') - igv.open('graph', {'name' : 'dependencies'}) - igv.open('nodes') - for p in sorted_deps(includeLibs=True, includeJreLibs=True): - ident = len(ids) - ids[p.name] = str(ident) - igv.open('node', {'id' : str(ident)}) - igv.open('properties') - igv.element('p', {'name' : 'name'}, p.name) - igv.close('properties') - igv.close('node') - igv.close('nodes') - igv.open('edges') - for p in projects(): - fromIndex = 0 - for dep in p.canonical_deps(): - toIndex = nextToIndex.get(dep, 0) - nextToIndex[dep] = toIndex + 1 - igv.element('edge', {'from' : ids[p.name], 'fromIndex' : str(fromIndex), 'to' : ids[dep], 'toIndex' : str(toIndex), 'label' : 'dependsOn'}) - fromIndex = fromIndex + 1 - igv.close('edges') - igv.close('graph') - igv.close('group') - igv.close('graphDocument') - - if args.igv: - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect(('127.0.0.1', 4444)) - s.send(igv.xml()) - else: - print igv.xml(indent=' ', newl='\n') - return - - print 'digraph projects {' - print 'rankdir=BT;' - print 'node [shape=rect];' - for p in projects(): - for dep in p.canonical_deps(): - print '"' + p.name + '"->"' + dep + '";' - if hasattr(p, '_declaredAnnotationProcessors'): - for ap in p._declaredAnnotationProcessors: - print '"' + p.name + '"->"' + ap + '" [style="dashed"];' - print '}' - -def _source_locator_memento(deps): - slm = XMLDoc() - slm.open('sourceLookupDirector') - slm.open('sourceContainers', {'duplicates' : 'false'}) - - javaCompliance = None - for dep in deps: - if dep.isLibrary(): - if hasattr(dep, 'eclipse.container'): - memento = XMLDoc().element('classpathContainer', {'path' : getattr(dep, 'eclipse.container')}).xml(standalone='no') - slm.element('classpathContainer', {'memento' : memento, 'typeId':'org.eclipse.jdt.launching.sourceContainer.classpathContainer'}) - elif dep.get_source_path(resolve=True): - memento = XMLDoc().element('archive', {'detectRoot' : 'true', 'path' : dep.get_source_path(resolve=True)}).xml(standalone='no') - slm.element('container', {'memento' : memento, 'typeId':'org.eclipse.debug.core.containerType.externalArchive'}) - elif dep.isProject(): - memento = XMLDoc().element('javaProject', {'name' : dep.name}).xml(standalone='no') - slm.element('container', {'memento' : memento, 'typeId':'org.eclipse.jdt.launching.sourceContainer.javaProject'}) - if javaCompliance is None or dep.javaCompliance > javaCompliance: - javaCompliance = dep.javaCompliance - - if javaCompliance: - memento = XMLDoc().element('classpathContainer', {'path' : 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-' + str(javaCompliance)}).xml(standalone='no') - slm.element('classpathContainer', {'memento' : memento, 'typeId':'org.eclipse.jdt.launching.sourceContainer.classpathContainer'}) - else: - memento = XMLDoc().element('classpathContainer', {'path' : 'org.eclipse.jdt.launching.JRE_CONTAINER'}).xml(standalone='no') - slm.element('classpathContainer', {'memento' : memento, 'typeId':'org.eclipse.jdt.launching.sourceContainer.classpathContainer'}) - - slm.close('sourceContainers') - slm.close('sourceLookupDirector') - return slm - -def make_eclipse_attach(suite, hostname, port, name=None, deps=None): - """ - Creates an Eclipse launch configuration file for attaching to a Java process. - """ - if deps is None: - deps = [] - slm = _source_locator_memento(deps) - launch = XMLDoc() - launch.open('launchConfiguration', {'type' : 'org.eclipse.jdt.launching.remoteJavaApplication'}) - launch.element('stringAttribute', {'key' : 'org.eclipse.debug.core.source_locator_id', 'value' : 'org.eclipse.jdt.launching.sourceLocator.JavaSourceLookupDirector'}) - launch.element('stringAttribute', {'key' : 'org.eclipse.debug.core.source_locator_memento', 'value' : '%s'}) - launch.element('booleanAttribute', {'key' : 'org.eclipse.jdt.launching.ALLOW_TERMINATE', 'value' : 'true'}) - launch.open('mapAttribute', {'key' : 'org.eclipse.jdt.launching.CONNECT_MAP'}) - launch.element('mapEntry', {'key' : 'hostname', 'value' : hostname}) - launch.element('mapEntry', {'key' : 'port', 'value' : port}) - launch.close('mapAttribute') - launch.element('stringAttribute', {'key' : 'org.eclipse.jdt.launching.PROJECT_ATTR', 'value' : ''}) - launch.element('stringAttribute', {'key' : 'org.eclipse.jdt.launching.VM_CONNECTOR_ID', 'value' : 'org.eclipse.jdt.launching.socketAttachConnector'}) - launch.close('launchConfiguration') - launch = launch.xml(newl='\n', standalone='no') % slm.xml(escape=True, standalone='no') - - if name is None: - if len(suites()) == 1: - suitePrefix = '' - else: - suitePrefix = suite.name + '-' - name = suitePrefix + 'attach-' + hostname + '-' + port - eclipseLaunches = join(suite.mxDir, 'eclipse-launches') - if not exists(eclipseLaunches): - os.makedirs(eclipseLaunches) - launchFile = join(eclipseLaunches, name + '.launch') - return update_file(launchFile, launch), launchFile - -def make_eclipse_launch(suite, javaArgs, jre, name=None, deps=None): - """ - Creates an Eclipse launch configuration file for running/debugging a Java command. - """ - if deps is None: - deps = [] - mainClass = None - vmArgs = [] - appArgs = [] - cp = None - argsCopy = list(reversed(javaArgs)) - while len(argsCopy) != 0: - a = argsCopy.pop() - if a == '-jar': - mainClass = '-jar' - appArgs = list(reversed(argsCopy)) - break - if a == '-cp' or a == '-classpath': - assert len(argsCopy) != 0 - cp = argsCopy.pop() - vmArgs.append(a) - vmArgs.append(cp) - elif a.startswith('-'): - vmArgs.append(a) - else: - mainClass = a - appArgs = list(reversed(argsCopy)) - break - - if mainClass is None: - log('Cannot create Eclipse launch configuration without main class or jar file: java ' + ' '.join(javaArgs)) - return False - - if name is None: - if mainClass == '-jar': - name = basename(appArgs[0]) - if len(appArgs) > 1 and not appArgs[1].startswith('-'): - name = name + '_' + appArgs[1] - else: - name = mainClass - name = time.strftime('%Y-%m-%d-%H%M%S_' + name) - - if cp is not None: - for e in cp.split(os.pathsep): - for s in suites(): - deps += [p for p in s.projects if e == p.output_dir()] - deps += [l for l in s.libs if e == l.get_path(False)] - - slm = _source_locator_memento(deps) - - launch = XMLDoc() - launch.open('launchConfiguration', {'type' : 'org.eclipse.jdt.launching.localJavaApplication'}) - launch.element('stringAttribute', {'key' : 'org.eclipse.debug.core.source_locator_id', 'value' : 'org.eclipse.jdt.launching.sourceLocator.JavaSourceLookupDirector'}) - launch.element('stringAttribute', {'key' : 'org.eclipse.debug.core.source_locator_memento', 'value' : '%s'}) - launch.element('stringAttribute', {'key' : 'org.eclipse.jdt.launching.JRE_CONTAINER', 'value' : 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/' + jre}) - launch.element('stringAttribute', {'key' : 'org.eclipse.jdt.launching.MAIN_TYPE', 'value' : mainClass}) - launch.element('stringAttribute', {'key' : 'org.eclipse.jdt.launching.PROGRAM_ARGUMENTS', 'value' : ' '.join(appArgs)}) - launch.element('stringAttribute', {'key' : 'org.eclipse.jdt.launching.PROJECT_ATTR', 'value' : ''}) - launch.element('stringAttribute', {'key' : 'org.eclipse.jdt.launching.VM_ARGUMENTS', 'value' : ' '.join(vmArgs)}) - launch.close('launchConfiguration') - launch = launch.xml(newl='\n', standalone='no') % slm.xml(escape=True, standalone='no') - - eclipseLaunches = join(suite.mxDir, 'eclipse-launches') - if not exists(eclipseLaunches): - os.makedirs(eclipseLaunches) - return update_file(join(eclipseLaunches, name + '.launch'), launch) - -def eclipseinit(args, buildProcessorJars=True, refreshOnly=False): - """(re)generate Eclipse project configurations and working sets""" - for s in suites(True): - _eclipseinit_suite(args, s, buildProcessorJars, refreshOnly) - - generate_eclipse_workingsets() - -def _check_ide_timestamp(suite, configZip, ide): - """return True if and only if the projects file, eclipse-settings files, and mx itself are all older than configZip""" - suitePyFiles = [join(suite.mxDir, e) for e in os.listdir(suite.mxDir) if e.startswith('suite') and e.endswith('.py')] - if configZip.isOlderThan(suitePyFiles): - return False - # Assume that any mx change might imply changes to the generated IDE files - if configZip.isOlderThan(__file__): - return False - - if ide == 'eclipse': - for p in suite.projects: - for _, sources in p.eclipse_settings_sources().iteritems(): - for source in sources: - if configZip.isOlderThan(source): - return False - return True - -def _eclipseinit_project(p, files=None, libFiles=None): - assert java(p.javaCompliance) - - if not exists(p.dir): - os.makedirs(p.dir) - - out = XMLDoc() - out.open('classpath') - - for src in p.srcDirs: - srcDir = join(p.dir, src) - if not exists(srcDir): - os.mkdir(srcDir) - out.element('classpathentry', {'kind' : 'src', 'path' : src}) - - processorPath = p.annotation_processors_path() - if processorPath: - genDir = p.source_gen_dir() - if not exists(genDir): - os.mkdir(genDir) - out.open('classpathentry', {'kind' : 'src', 'path' : 'src_gen'}) - if p.uses_annotation_processor_library(): - # ignore warnings produced by third-party annotation processors - out.open('attributes') - out.element('attribute', {'name' : 'ignore_optional_problems', 'value' : 'true'}) - out.close('attributes') - out.close('classpathentry') - - if files: - files.append(genDir) - - # Every Java program depends on a JRE - out.element('classpathentry', {'kind' : 'con', 'path' : 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-' + str(p.javaCompliance)}) - - if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project - out.element('classpathentry', {'kind' : 'con', 'path' : 'org.eclipse.pde.core.requiredPlugins'}) - - containerDeps = set() - libraryDeps = set() - projectDeps = set() - - for dep in p.all_deps([], True): - if dep == p: - continue - if dep.isLibrary(): - if hasattr(dep, 'eclipse.container'): - container = getattr(dep, 'eclipse.container') - containerDeps.add(container) - libraryDeps -= set(dep.all_deps([], True)) - else: - libraryDeps.add(dep) - elif dep.isProject(): - projectDeps.add(dep) - - for dep in sorted(containerDeps): - out.element('classpathentry', {'exported' : 'true', 'kind' : 'con', 'path' : dep}) - - for dep in sorted(libraryDeps): - path = dep.path - dep.get_path(resolve=True) - - # Relative paths for "lib" class path entries have various semantics depending on the Eclipse - # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's - # safest to simply use absolute paths. - path = _make_absolute(path, p.suite.dir) - - attributes = {'exported' : 'true', 'kind' : 'lib', 'path' : path} - - sourcePath = dep.get_source_path(resolve=True) - if sourcePath is not None: - attributes['sourcepath'] = sourcePath - out.element('classpathentry', attributes) - if libFiles: - libFiles.append(path) - - for dep in sorted(projectDeps): - out.element('classpathentry', {'combineaccessrules' : 'false', 'exported' : 'true', 'kind' : 'src', 'path' : '/' + dep.name}) - - out.element('classpathentry', {'kind' : 'output', 'path' : getattr(p, 'eclipse.output', 'bin')}) - out.close('classpath') - classpathFile = join(p.dir, '.classpath') - update_file(classpathFile, out.xml(indent='\t', newl='\n')) - if files: - files.append(classpathFile) - - csConfig = join(project(p.checkstyleProj).dir, '.checkstyle_checks.xml') - if exists(csConfig): - out = XMLDoc() - - dotCheckstyle = join(p.dir, ".checkstyle") - checkstyleConfigPath = '/' + p.checkstyleProj + '/.checkstyle_checks.xml' - out.open('fileset-config', {'file-format-version' : '1.2.0', 'simple-config' : 'true'}) - out.open('local-check-config', {'name' : 'Checks', 'location' : checkstyleConfigPath, 'type' : 'project', 'description' : ''}) - out.element('additional-data', {'name' : 'protect-config-file', 'value' : 'false'}) - out.close('local-check-config') - out.open('fileset', {'name' : 'all', 'enabled' : 'true', 'check-config-name' : 'Checks', 'local' : 'true'}) - out.element('file-match-pattern', {'match-pattern' : '.', 'include-pattern' : 'true'}) - out.close('fileset') - out.open('filter', {'name' : 'all', 'enabled' : 'true', 'check-config-name' : 'Checks', 'local' : 'true'}) - out.element('filter-data', {'value' : 'java'}) - out.close('filter') - - exclude = join(p.dir, '.checkstyle.exclude') - if exists(exclude): - out.open('filter', {'name' : 'FilesFromPackage', 'enabled' : 'true'}) - with open(exclude) as f: - for line in f: - if not line.startswith('#'): - line = line.strip() - exclDir = join(p.dir, line) - assert isdir(exclDir), 'excluded source directory listed in ' + exclude + ' does not exist or is not a directory: ' + exclDir - out.element('filter-data', {'value' : line}) - out.close('filter') - - out.close('fileset-config') - update_file(dotCheckstyle, out.xml(indent=' ', newl='\n')) - if files: - files.append(dotCheckstyle) - else: - # clean up existing .checkstyle file - dotCheckstyle = join(p.dir, ".checkstyle") - if exists(dotCheckstyle): - os.unlink(dotCheckstyle) - - out = XMLDoc() - out.open('projectDescription') - out.element('name', data=p.name) - out.element('comment', data='') - out.element('projects', data='') - out.open('buildSpec') - out.open('buildCommand') - out.element('name', data='org.eclipse.jdt.core.javabuilder') - out.element('arguments', data='') - out.close('buildCommand') - if exists(csConfig): - out.open('buildCommand') - out.element('name', data='net.sf.eclipsecs.core.CheckstyleBuilder') - out.element('arguments', data='') - out.close('buildCommand') - if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project - for buildCommand in ['org.eclipse.pde.ManifestBuilder', 'org.eclipse.pde.SchemaBuilder']: - out.open('buildCommand') - out.element('name', data=buildCommand) - out.element('arguments', data='') - out.close('buildCommand') - - if p.definedAnnotationProcessorsDist: - # Create a launcher that will (re)build the annotation processor - # jar any time one of its sources is modified. - dist = p.definedAnnotationProcessorsDist - - distProjects = [d for d in dist.sorted_deps(transitive=True) if d.isProject()] - relevantResources = [] - for p in distProjects: - for srcDir in p.source_dirs(): - relevantResources.append(join(p.name, os.path.relpath(srcDir, p.dir))) - relevantResources.append(join(p.name, os.path.relpath(p.output_dir(), p.dir))) - - # The path should always be p.name/dir independent of where the workspace actually is. - # So we use the parent folder of the project, whatever that is, to generate such a relative path. - logicalWorkspaceRoot = os.path.dirname(p.dir) - refreshFile = os.path.relpath(p.definedAnnotationProcessorsDist.path, logicalWorkspaceRoot) - _genEclipseBuilder(out, p, 'CreateAnnotationProcessorJar', 'archive @' + dist.name, refresh=True, refreshFile=refreshFile, relevantResources=relevantResources, async=True, xmlIndent='', xmlStandalone='no') - - out.close('buildSpec') - out.open('natures') - out.element('nature', data='org.eclipse.jdt.core.javanature') - if exists(csConfig): - out.element('nature', data='net.sf.eclipsecs.core.CheckstyleNature') - if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project - out.element('nature', data='org.eclipse.pde.PluginNature') - out.close('natures') - out.close('projectDescription') - projectFile = join(p.dir, '.project') - update_file(projectFile, out.xml(indent='\t', newl='\n')) - if files: - files.append(projectFile) - - settingsDir = join(p.dir, ".settings") - if not exists(settingsDir): - os.mkdir(settingsDir) - - # copy a possibly modified file to the project's .settings directory - for name, sources in p.eclipse_settings_sources().iteritems(): - out = StringIO.StringIO() - print >> out, '# GENERATED -- DO NOT EDIT' - for source in sources: - print >> out, '# Source:', source - with open(source) as f: - print >> out, f.read() - content = out.getvalue().replace('${javaCompliance}', str(p.javaCompliance)) - if processorPath: - content = content.replace('org.eclipse.jdt.core.compiler.processAnnotations=disabled', 'org.eclipse.jdt.core.compiler.processAnnotations=enabled') - update_file(join(settingsDir, name), content) - if files: - files.append(join(settingsDir, name)) - - if processorPath: - out = XMLDoc() - out.open('factorypath') - out.element('factorypathentry', {'kind' : 'PLUGIN', 'id' : 'org.eclipse.jst.ws.annotations.core', 'enabled' : 'true', 'runInBatchMode' : 'false'}) - for e in processorPath.split(os.pathsep): - out.element('factorypathentry', {'kind' : 'EXTJAR', 'id' : e, 'enabled' : 'true', 'runInBatchMode' : 'false'}) - out.close('factorypath') - update_file(join(p.dir, '.factorypath'), out.xml(indent='\t', newl='\n')) - if files: - files.append(join(p.dir, '.factorypath')) - -def _eclipseinit_suite(args, suite, buildProcessorJars=True, refreshOnly=False): - configZip = TimeStampFile(join(suite.mxDir, 'eclipse-config.zip')) - configLibsZip = join(suite.mxDir, 'eclipse-config-libs.zip') - if refreshOnly and not configZip.exists(): - return - - if _check_ide_timestamp(suite, configZip, 'eclipse'): - logv('[Eclipse configurations are up to date - skipping]') - return - - files = [] - libFiles = [] - if buildProcessorJars: - files += _processorjars_suite(suite) - - for p in suite.projects: - if p.native: - continue - _eclipseinit_project(p, files, libFiles) - - _, launchFile = make_eclipse_attach(suite, 'localhost', '8000', deps=sorted_deps(projectNames=None, includeLibs=True)) - files.append(launchFile) - - # Create an Eclipse project for each distribution that will create/update the archive - # for the distribution whenever any (transitively) dependent project of the - # distribution is updated. - for dist in suite.dists: - projectDir = dist.get_ide_project_dir() - if not projectDir: - continue - if not exists(projectDir): - os.makedirs(projectDir) - distProjects = [d for d in dist.sorted_deps(transitive=True) if d.isProject()] - relevantResources = [] - for p in distProjects: - for srcDir in p.source_dirs(): - relevantResources.append(join(p.name, os.path.relpath(srcDir, p.dir))) - relevantResources.append(join(p.name, os.path.relpath(p.output_dir(), p.dir))) - out = XMLDoc() - out.open('projectDescription') - out.element('name', data=dist.name) - out.element('comment', data='Updates ' + dist.path + ' if a project dependency of ' + dist.name + ' is updated') - out.open('projects') - for p in distProjects: - out.element('project', data=p.name) - for d in dist.distDependencies: - out.element('project', data=d) - out.close('projects') - out.open('buildSpec') - dist.dir = projectDir - dist.javaCompliance = max([p.javaCompliance for p in distProjects]) - _genEclipseBuilder(out, dist, 'Create' + dist.name + 'Dist', '-v archive @' + dist.name, relevantResources=relevantResources, logToFile=True, refresh=False, async=False, logToConsole=False, appendToLogFile=False) - out.close('buildSpec') - out.open('natures') - out.element('nature', data='org.eclipse.jdt.core.javanature') - out.close('natures') - out.close('projectDescription') - projectFile = join(projectDir, '.project') - update_file(projectFile, out.xml(indent='\t', newl='\n')) - files.append(projectFile) - - _zip_files(files, suite.dir, configZip.path) - _zip_files(libFiles, suite.dir, configLibsZip) - -def _zip_files(files, baseDir, zipPath): - fd, tmp = tempfile.mkstemp(suffix='', prefix=basename(zipPath), dir=baseDir) - try: - zf = zipfile.ZipFile(tmp, 'w') - for f in sorted(set(files)): - relpath = os.path.relpath(f, baseDir) - arcname = relpath.replace(os.sep, '/') - zf.write(f, arcname) - zf.close() - os.close(fd) - # Atomic on Unix - shutil.move(tmp, zipPath) - # Correct the permissions on the temporary file which is created with restrictive permissions - os.chmod(zipPath, 0o666 & ~currentUmask) - finally: - if exists(tmp): - os.remove(tmp) - -def _genEclipseBuilder(dotProjectDoc, p, name, mxCommand, refresh=True, refreshFile=None, relevantResources=None, async=False, logToConsole=False, logToFile=False, appendToLogFile=True, xmlIndent='\t', xmlStandalone=None): - externalToolDir = join(p.dir, '.externalToolBuilders') - launchOut = XMLDoc() - consoleOn = 'true' if logToConsole else 'false' - launchOut.open('launchConfiguration', {'type' : 'org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType'}) - launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.core.capture_output', 'value': consoleOn}) - launchOut.open('mapAttribute', {'key' : 'org.eclipse.debug.core.environmentVariables'}) - launchOut.element('mapEntry', {'key' : 'JAVA_HOME', 'value' : java().jdk}) - launchOut.close('mapAttribute') - - if refresh: - if refreshFile is None: - refreshScope = '${project}' - else: - refreshScope = '${working_set:}' - - launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.core.ATTR_REFRESH_RECURSIVE', 'value': 'false'}) - launchOut.element('stringAttribute', {'key' : 'org.eclipse.debug.core.ATTR_REFRESH_SCOPE', 'value': refreshScope}) - - if relevantResources is not None: - resources = '${working_set:' - for relevantResource in relevantResources: - resources += '' - resources += '}' - launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE', 'value': resources}) - - - launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON', 'value': consoleOn}) - launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND', 'value': 'true' if async else 'false'}) - if logToFile: - logFile = join(externalToolDir, name + '.log') - launchOut.element('stringAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CAPTURE_IN_FILE', 'value': logFile}) - launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_APPEND_TO_FILE', 'value': 'true' if appendToLogFile else 'false'}) - - # expect to find the OS command to invoke mx in the same directory - baseDir = dirname(os.path.abspath(__file__)) - - cmd = 'mx.sh' - if get_os() == 'windows': - cmd = 'mx.cmd' - cmdPath = join(baseDir, cmd) - if not os.path.exists(cmdPath): - # backwards compatibility for when the commands lived in parent of mxtool - cmdPath = join(dirname(baseDir), cmd) - if not os.path.exists(cmdPath): - abort('cannot locate ' + cmd) - - launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_LOCATION', 'value': cmdPath}) - launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS', 'value': 'full,incremental,auto,'}) - launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS', 'value': mxCommand}) - launchOut.element('booleanAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED', 'value': 'true'}) - launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY', 'value': p.suite.dir}) - - - launchOut.close('launchConfiguration') - - if not exists(externalToolDir): - os.makedirs(externalToolDir) - update_file(join(externalToolDir, name + '.launch'), launchOut.xml(indent=xmlIndent, standalone=xmlStandalone, newl='\n')) - - dotProjectDoc.open('buildCommand') - dotProjectDoc.element('name', data='org.eclipse.ui.externaltools.ExternalToolBuilder') - dotProjectDoc.element('triggers', data='auto,full,incremental,') - dotProjectDoc.open('arguments') - dotProjectDoc.open('dictionary') - dotProjectDoc.element('key', data='LaunchConfigHandle') - dotProjectDoc.element('value', data='/.externalToolBuilders/' + name + '.launch') - dotProjectDoc.close('dictionary') - dotProjectDoc.open('dictionary') - dotProjectDoc.element('key', data='incclean') - dotProjectDoc.element('value', data='true') - dotProjectDoc.close('dictionary') - dotProjectDoc.close('arguments') - dotProjectDoc.close('buildCommand') - -def generate_eclipse_workingsets(): - """ - Populate the workspace's working set configuration with working sets generated from project data for the primary suite - If the workspace already contains working set definitions, the existing ones will be retained and extended. - In case mx/env does not contain a WORKSPACE definition pointing to the workspace root directory, a parent search from the primary suite directory is performed. - If no workspace root directory can be identified, the primary suite directory is used and the user has to place the workingsets.xml file by hand. - """ - - # identify the location where to look for workingsets.xml - wsfilename = 'workingsets.xml' - wsloc = '.metadata/.plugins/org.eclipse.ui.workbench' - if os.environ.has_key('WORKSPACE'): - expected_wsroot = os.environ['WORKSPACE'] - else: - expected_wsroot = _primary_suite.dir - - wsroot = _find_eclipse_wsroot(expected_wsroot) - if wsroot is None: - # failed to find it - wsroot = expected_wsroot - - wsdir = join(wsroot, wsloc) - if not exists(wsdir): - wsdir = wsroot - logv('Could not find Eclipse metadata directory. Please place ' + wsfilename + ' in ' + wsloc + ' manually.') - wspath = join(wsdir, wsfilename) - - # gather working set info from project data - workingSets = dict() - for p in projects(): - if p.workingSets is None: - continue - for w in p.workingSets.split(","): - if not workingSets.has_key(w): - workingSets[w] = [p.name] - else: - workingSets[w].append(p.name) - - if exists(wspath): - wsdoc = _copy_workingset_xml(wspath, workingSets) - else: - wsdoc = _make_workingset_xml(workingSets) - - update_file(wspath, wsdoc.xml(newl='\n')) - -def _find_eclipse_wsroot(wsdir): - md = join(wsdir, '.metadata') - if exists(md): - return wsdir - split = os.path.split(wsdir) - if split[0] == wsdir: # root directory - return None - else: - return _find_eclipse_wsroot(split[0]) - -def _make_workingset_xml(workingSets): - wsdoc = XMLDoc() - wsdoc.open('workingSetManager') - - for w in sorted(workingSets.keys()): - _workingset_open(wsdoc, w) - for p in workingSets[w]: - _workingset_element(wsdoc, p) - wsdoc.close('workingSet') - - wsdoc.close('workingSetManager') - return wsdoc - -def _copy_workingset_xml(wspath, workingSets): - target = XMLDoc() - target.open('workingSetManager') - - parser = xml.parsers.expat.ParserCreate() - - class ParserState(object): - def __init__(self): - self.current_ws_name = 'none yet' - self.current_ws = None - self.seen_ws = list() - self.seen_projects = list() - self.aggregate_ws = False - self.nested_ws = False - - ps = ParserState() - - # parsing logic - def _ws_start(name, attributes): - if name == 'workingSet': - if attributes.has_key('name'): - ps.current_ws_name = attributes['name'] - if attributes.has_key('aggregate') and attributes['aggregate'] == 'true': - ps.aggregate_ws = True - ps.current_ws = None - elif workingSets.has_key(ps.current_ws_name): - ps.current_ws = workingSets[ps.current_ws_name] - ps.seen_ws.append(ps.current_ws_name) - ps.seen_projects = list() - else: - ps.current_ws = None - target.open(name, attributes) - parser.StartElementHandler = _ws_item - - def _ws_end(name): - closeAndResetHandler = False - if name == 'workingSet': - if ps.aggregate_ws: - if ps.nested_ws: - ps.nested_ws = False - else: - ps.aggregate_ws = False - closeAndResetHandler = True - else: - if not ps.current_ws is None: - for p in ps.current_ws: - if not p in ps.seen_projects: - _workingset_element(target, p) - closeAndResetHandler = True - if closeAndResetHandler: - target.close('workingSet') - parser.StartElementHandler = _ws_start - elif name == 'workingSetManager': - # process all working sets that are new to the file - for w in sorted(workingSets.keys()): - if not w in ps.seen_ws: - _workingset_open(target, w) - for p in workingSets[w]: - _workingset_element(target, p) - target.close('workingSet') - - def _ws_item(name, attributes): - if name == 'item': - if ps.current_ws is None: - target.element(name, attributes) - elif not attributes.has_key('elementID') and attributes.has_key('factoryID') and attributes.has_key('path') and attributes.has_key('type'): - target.element(name, attributes) - p_name = attributes['path'][1:] # strip off the leading '/' - ps.seen_projects.append(p_name) - else: - p_name = attributes['elementID'][1:] # strip off the leading '=' - _workingset_element(target, p_name) - ps.seen_projects.append(p_name) - elif name == 'workingSet': - ps.nested_ws = True - target.element(name, attributes) - - # process document - parser.StartElementHandler = _ws_start - parser.EndElementHandler = _ws_end - with open(wspath, 'r') as wsfile: - parser.ParseFile(wsfile) - - target.close('workingSetManager') - return target - -def _workingset_open(wsdoc, ws): - wsdoc.open('workingSet', {'editPageID': 'org.eclipse.jdt.ui.JavaWorkingSetPage', 'factoryID': 'org.eclipse.ui.internal.WorkingSetFactory', 'id': 'wsid_' + ws, 'label': ws, 'name': ws}) - -def _workingset_element(wsdoc, p): - wsdoc.element('item', {'elementID': '=' + p, 'factoryID': 'org.eclipse.jdt.ui.PersistableJavaElementFactory'}) - -def netbeansinit(args, refreshOnly=False, buildProcessorJars=True): - """(re)generate NetBeans project configurations""" - - for suite in suites(True): - _netbeansinit_suite(args, suite, refreshOnly, buildProcessorJars) - -def _netbeansinit_project(p, jdks=None, files=None, libFiles=None): - if not exists(join(p.dir, 'nbproject')): - os.makedirs(join(p.dir, 'nbproject')) - - jdk = java(p.javaCompliance) - assert jdk - - if jdks: - jdks.add(jdk) - - out = XMLDoc() - out.open('project', {'name' : p.name, 'default' : 'default', 'basedir' : '.'}) - out.element('description', data='Builds, tests, and runs the project ' + p.name + '.') - out.element('import', {'file' : 'nbproject/build-impl.xml'}) - out.open('target', {'name' : '-post-init'}) - out.open('pathconvert', {'property' : 'comma.javac.classpath', 'pathsep' : ','}) - out.element('path', {'path' : '${javac.classpath}'}) - out.close('pathconvert') - - out.open('restrict', {'id' : 'missing.javac.classpath'}) - out.element('filelist', {'dir' : '${basedir}', 'files' : '${comma.javac.classpath}'}) - out.open('not') - out.element('exists') - out.close('not') - out.close('restrict') - - out.element('property', {'name' : 'missing.javac.classpath', 'refid' : 'missing.javac.classpath'}) - - out.open('condition', {'property' : 'no.dependencies', 'value' : 'true'}) - out.element('equals', {'arg1' : '${missing.javac.classpath}', 'arg2' : ''}) - out.close('condition') - - out.element('property', {'name' : 'no.dependencies', 'value' : 'false'}) - - out.open('condition', {'property' : 'no.deps'}) - out.element('equals', {'arg1' : '${no.dependencies}', 'arg2' : 'true'}) - out.close('condition') - - out.close('target') - out.open('target', {'name' : 'compile'}) - out.open('exec', {'executable' : sys.executable, 'failonerror' : 'true'}) - out.element('env', {'key' : 'JAVA_HOME', 'value' : jdk.jdk}) - out.element('arg', {'value' : os.path.abspath(__file__)}) - out.element('arg', {'value' : 'build'}) - out.element('arg', {'value' : '--only'}) - out.element('arg', {'value' : p.name}) - out.element('arg', {'value' : '--force-javac'}) - out.element('arg', {'value' : '--no-native'}) - out.close('exec') - out.close('target') - out.open('target', {'name' : 'jar', 'depends' : 'compile'}) - out.close('target') - out.close('project') - update_file(join(p.dir, 'build.xml'), out.xml(indent='\t', newl='\n')) - if files: - files.append(join(p.dir, 'build.xml')) - - out = XMLDoc() - out.open('project', {'xmlns' : 'http://www.netbeans.org/ns/project/1'}) - out.element('type', data='org.netbeans.modules.java.j2seproject') - out.open('configuration') - out.open('data', {'xmlns' : 'http://www.netbeans.org/ns/j2se-project/3'}) - out.element('name', data=p.name) - out.element('explicit-platform', {'explicit-source-supported' : 'true'}) - out.open('source-roots') - out.element('root', {'id' : 'src.dir'}) - if len(p.annotation_processors()) > 0: - out.element('root', {'id' : 'src.ap-source-output.dir', 'name' : 'Generated Packages'}) - out.close('source-roots') - out.open('test-roots') - out.close('test-roots') - out.close('data') - - firstDep = True - for dep in p.all_deps([], includeLibs=False, includeAnnotationProcessors=True): - if dep == p: - continue - - if dep.isProject(): - n = dep.name.replace('.', '_') - if firstDep: - out.open('references', {'xmlns' : 'http://www.netbeans.org/ns/ant-project-references/1'}) - firstDep = False - - out.open('reference') - out.element('foreign-project', data=n) - out.element('artifact-type', data='jar') - out.element('script', data='build.xml') - out.element('target', data='jar') - out.element('clean-target', data='clean') - out.element('id', data='jar') - out.close('reference') - - if not firstDep: - out.close('references') - - out.close('configuration') - out.close('project') - update_file(join(p.dir, 'nbproject', 'project.xml'), out.xml(indent=' ', newl='\n')) - if files: - files.append(join(p.dir, 'nbproject', 'project.xml')) - - out = StringIO.StringIO() - jdkPlatform = 'JDK_' + str(jdk.version) - - annotationProcessorEnabled = "false" - annotationProcessorSrcFolder = "" - if len(p.annotation_processors()) > 0: - annotationProcessorEnabled = "true" - genSrcDir = p.source_gen_dir() - if not exists(genSrcDir): - os.makedirs(genSrcDir) - annotationProcessorSrcFolder = "src.ap-source-output.dir=" + genSrcDir - - content = """ -annotation.processing.enabled=""" + annotationProcessorEnabled + """ -annotation.processing.enabled.in.editor=""" + annotationProcessorEnabled + """ -annotation.processing.processors.list= -annotation.processing.run.all.processors=true -application.title=""" + p.name + """ -application.vendor=mx -build.classes.dir=${build.dir} -build.classes.excludes=**/*.java,**/*.form -# This directory is removed when the project is cleaned: -build.dir=bin -build.generated.sources.dir=${build.dir}/generated-sources -# Only compile against the classpath explicitly listed here: -build.sysclasspath=ignore -build.test.classes.dir=${build.dir}/test/classes -build.test.results.dir=${build.dir}/test/results -# Uncomment to specify the preferred debugger connection transport: -#debug.transport=dt_socket -debug.classpath=\\ -${run.classpath} -debug.test.classpath=\\ -${run.test.classpath} -# This directory is removed when the project is cleaned: -dist.dir=dist -dist.jar=${dist.dir}/""" + p.name + """.jar -dist.javadoc.dir=${dist.dir}/javadoc -endorsed.classpath= -excludes= -includes=** -jar.compress=false -# Space-separated list of extra javac options -javac.compilerargs=-XDignore.symbol.file -javac.deprecation=false -javac.source=""" + str(p.javaCompliance) + """ -javac.target=""" + str(p.javaCompliance) + """ -javac.test.classpath=\\ -${javac.classpath}:\\ -${build.classes.dir} -javadoc.additionalparam= -javadoc.author=false -javadoc.encoding=${source.encoding} -javadoc.noindex=false -javadoc.nonavbar=false -javadoc.notree=false -javadoc.private=false -javadoc.splitindex=true -javadoc.use=true -javadoc.version=false -javadoc.windowtitle= -main.class= -manifest.file=manifest.mf -meta.inf.dir=${src.dir}/META-INF -mkdist.disabled=false -platforms.""" + jdkPlatform + """.home=""" + jdk.jdk + """ -platform.active=""" + jdkPlatform + """ -run.classpath=\\ -${javac.classpath}:\\ -${build.classes.dir} -# Space-separated list of JVM arguments used when running the project -# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value -# or test-sys-prop.name=value to set system properties for unit tests): -run.jvmargs= -run.test.classpath=\\ -${javac.test.classpath}:\\ -${build.test.classes.dir} -test.src.dir=./test -""" + annotationProcessorSrcFolder + """ -source.encoding=UTF-8""".replace(':', os.pathsep).replace('/', os.sep) - print >> out, content - - mainSrc = True - for src in p.srcDirs: - srcDir = join(p.dir, src) - if not exists(srcDir): - os.mkdir(srcDir) - ref = 'file.reference.' + p.name + '-' + src - print >> out, ref + '=' + src - if mainSrc: - print >> out, 'src.dir=${' + ref + '}' - mainSrc = False - else: - print >> out, 'src.' + src + '.dir=${' + ref + '}' - - javacClasspath = [] - - deps = p.all_deps([], True) - annotationProcessorOnlyDeps = [] - if len(p.annotation_processors()) > 0: - for ap in p.annotation_processors(): - apDep = dependency(ap) - if not apDep in deps: - deps.append(apDep) - annotationProcessorOnlyDeps.append(apDep) - - annotationProcessorReferences = [] - - for dep in deps: - if dep == p: - continue - - if dep.isLibrary(): - path = dep.get_path(resolve=True) - if path: - if os.sep == '\\': - path = path.replace('\\', '\\\\') - ref = 'file.reference.' + dep.name + '-bin' - print >> out, ref + '=' + path - if libFiles: - libFiles.append(path) - - elif dep.isProject(): - n = dep.name.replace('.', '_') - relDepPath = os.path.relpath(dep.dir, p.dir).replace(os.sep, '/') - ref = 'reference.' + n + '.jar' - print >> out, 'project.' + n + '=' + relDepPath - print >> out, ref + '=${project.' + n + '}/dist/' + dep.name + '.jar' - - if not dep in annotationProcessorOnlyDeps: - javacClasspath.append('${' + ref + '}') - else: - annotationProcessorReferences.append('${' + ref + '}') - - print >> out, 'javac.classpath=\\\n ' + (os.pathsep + '\\\n ').join(javacClasspath) - print >> out, 'javac.processorpath=' + (os.pathsep + '\\\n ').join(['${javac.classpath}'] + annotationProcessorReferences) - print >> out, 'javac.test.processorpath=' + (os.pathsep + '\\\n ').join(['${javac.test.classpath}'] + annotationProcessorReferences) - - update_file(join(p.dir, 'nbproject', 'project.properties'), out.getvalue()) - out.close() - if files: - files.append(join(p.dir, 'nbproject', 'project.properties')) - -def _netbeansinit_suite(args, suite, refreshOnly=False, buildProcessorJars=True): - configZip = TimeStampFile(join(suite.mxDir, 'netbeans-config.zip')) - configLibsZip = join(suite.mxDir, 'eclipse-config-libs.zip') - if refreshOnly and not configZip.exists(): - return - - if _check_ide_timestamp(suite, configZip, 'netbeans'): - logv('[NetBeans configurations are up to date - skipping]') - return - - files = [] - libFiles = [] - jdks = set() - for p in suite.projects: - if p.native: - continue - - if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project - continue - - _netbeansinit_project(p, jdks, files, libFiles) - - log('If using NetBeans:') - # http://stackoverflow.com/questions/24720665/cant-resolve-jdk-internal-package - log(' 1. Edit etc/netbeans.conf in your NetBeans installation and modify netbeans_default_options variable to include "-J-DCachingArchiveProvider.disableCtSym=true"') - log(' 2. Ensure that the following platform(s) are defined (Tools -> Java Platforms):') - for jdk in jdks: - log(' JDK_' + str(jdk.version)) - log(' 3. Open/create a Project Group for the directory containing the projects (File -> Project Group -> New Group... -> Folder of Projects)') - - _zip_files(files, suite.dir, configZip.path) - _zip_files(libFiles, suite.dir, configLibsZip) - -def intellijinit(args, refreshOnly=False): - """(re)generate Intellij project configurations""" - - for suite in suites(True): - _intellij_suite(args, suite, refreshOnly) - -def _intellij_suite(args, suite, refreshOnly=False): - - libraries = set() - - ideaProjectDirectory = join(suite.dir, '.idea') - - if not exists(ideaProjectDirectory): - os.mkdir(ideaProjectDirectory) - nameFile = join(ideaProjectDirectory, '.name') - update_file(nameFile, "Graal") - modulesXml = XMLDoc() - modulesXml.open('project', attributes={'version': '4'}) - modulesXml.open('component', attributes={'name': 'ProjectModuleManager'}) - modulesXml.open('modules') - - - def _intellij_exclude_if_exists(xml, p, name): - path = join(p.dir, name) - if exists(path): - xml.element('excludeFolder', attributes={'url':'file://$MODULE_DIR$/' + name}) - - annotationProcessorProfiles = {} - - def _complianceToIntellijLanguageLevel(compliance): - return 'JDK_1_' + str(compliance.value) - - # create the modules (1 module = 1 Intellij project) - for p in suite.projects: - if p.native: - continue - - assert java(p.javaCompliance) - - if not exists(p.dir): - os.makedirs(p.dir) - - annotationProcessorProfileKey = tuple(p.annotation_processors()) - - if not annotationProcessorProfileKey in annotationProcessorProfiles: - annotationProcessorProfiles[annotationProcessorProfileKey] = [p] - else: - annotationProcessorProfiles[annotationProcessorProfileKey].append(p) - - intellijLanguageLevel = _complianceToIntellijLanguageLevel(p.javaCompliance) - - moduleXml = XMLDoc() - moduleXml.open('module', attributes={'type': 'JAVA_MODULE', 'version': '4'}) - - moduleXml.open('component', attributes={'name': 'NewModuleRootManager', 'LANGUAGE_LEVEL': intellijLanguageLevel, 'inherit-compiler-output': 'false'}) - moduleXml.element('output', attributes={'url': 'file://$MODULE_DIR$/bin'}) - moduleXml.element('exclude-output') - - moduleXml.open('content', attributes={'url': 'file://$MODULE_DIR$'}) - for src in p.srcDirs: - srcDir = join(p.dir, src) - if not exists(srcDir): - os.mkdir(srcDir) - moduleXml.element('sourceFolder', attributes={'url':'file://$MODULE_DIR$/' + src, 'isTestSource': 'false'}) - - if len(p.annotation_processors()) > 0: - genDir = p.source_gen_dir() - if not exists(genDir): - os.mkdir(genDir) - moduleXml.element('sourceFolder', attributes={'url':'file://$MODULE_DIR$/' + os.path.relpath(genDir, p.dir), 'isTestSource': 'false'}) - - for name in ['.externalToolBuilders', '.settings', 'nbproject']: - _intellij_exclude_if_exists(moduleXml, p, name) - moduleXml.close('content') - - moduleXml.element('orderEntry', attributes={'type': 'jdk', 'jdkType': 'JavaSDK', 'jdkName': str(p.javaCompliance)}) - moduleXml.element('orderEntry', attributes={'type': 'sourceFolder', 'forTests': 'false'}) - - deps = p.all_deps([], True, includeAnnotationProcessors=True) - for dep in deps: - if dep == p: - continue - - if dep.isLibrary(): - libraries.add(dep) - moduleXml.element('orderEntry', attributes={'type': 'library', 'name': dep.name, 'level': 'project'}) - elif dep.isProject(): - moduleXml.element('orderEntry', attributes={'type': 'module', 'module-name': dep.name}) - - moduleXml.close('component') - moduleXml.close('module') - moduleFile = join(p.dir, p.name + '.iml') - update_file(moduleFile, moduleXml.xml(indent=' ', newl='\n')) - - moduleFilePath = "$PROJECT_DIR$/" + os.path.relpath(moduleFile, suite.dir) - modulesXml.element('module', attributes={'fileurl': 'file://' + moduleFilePath, 'filepath': moduleFilePath}) - - modulesXml.close('modules') - modulesXml.close('component') - modulesXml.close('project') - moduleXmlFile = join(ideaProjectDirectory, 'modules.xml') - update_file(moduleXmlFile, modulesXml.xml(indent=' ', newl='\n')) - - # TODO What about cross-suite dependencies? - - librariesDirectory = join(ideaProjectDirectory, 'libraries') - - if not exists(librariesDirectory): - os.mkdir(librariesDirectory) - - # Setup the libraries that were used above - # TODO: setup all the libraries from the suite regardless of usage? - for library in libraries: - libraryXml = XMLDoc() - - libraryXml.open('component', attributes={'name': 'libraryTable'}) - libraryXml.open('library', attributes={'name': library.name}) - libraryXml.open('CLASSES') - libraryXml.element('root', attributes={'url': 'jar://$PROJECT_DIR$/' + os.path.relpath(library.get_path(True), suite.dir) + '!/'}) - libraryXml.close('CLASSES') - libraryXml.element('JAVADOC') - if library.sourcePath: - libraryXml.open('SOURCES') - libraryXml.element('root', attributes={'url': 'jar://$PROJECT_DIR$/' + os.path.relpath(library.get_source_path(True), suite.dir) + '!/'}) - libraryXml.close('SOURCES') - else: - libraryXml.element('SOURCES') - libraryXml.close('library') - libraryXml.close('component') - - libraryFile = join(librariesDirectory, library.name + '.xml') - update_file(libraryFile, libraryXml.xml(indent=' ', newl='\n')) - - - - # Set annotation processor profiles up, and link them to modules in compiler.xml - compilerXml = XMLDoc() - compilerXml.open('project', attributes={'version': '4'}) - compilerXml.open('component', attributes={'name': 'CompilerConfiguration'}) - - compilerXml.element('option', attributes={'name': "DEFAULT_COMPILER", 'value': 'Javac'}) - compilerXml.element('resourceExtensions') - compilerXml.open('wildcardResourcePatterns') - compilerXml.element('entry', attributes={'name': '!?*.java'}) - compilerXml.close('wildcardResourcePatterns') - - if annotationProcessorProfiles: - compilerXml.open('annotationProcessing') - for processors, modules in sorted(annotationProcessorProfiles.iteritems()): - compilerXml.open('profile', attributes={'default': 'false', 'name': '-'.join(processors), 'enabled': 'true'}) - compilerXml.element('sourceOutputDir', attributes={'name': 'src_gen'}) # TODO use p.source_gen_dir() ? - compilerXml.element('outputRelativeToContentRoot', attributes={'value': 'true'}) - compilerXml.open('processorPath', attributes={'useClasspath': 'false'}) - for apName in processors: - pDep = dependency(apName) - for entry in pDep.all_deps([], True): - if entry.isLibrary(): - compilerXml.element('entry', attributes={'name': '$PROJECT_DIR$/' + os.path.relpath(entry.path, suite.dir)}) - elif entry.isProject(): - assert entry.isProject() - compilerXml.element('entry', attributes={'name': '$PROJECT_DIR$/' + os.path.relpath(entry.output_dir(), suite.dir)}) - compilerXml.close('processorPath') - for module in modules: - compilerXml.element('module', attributes={'name': module.name}) - compilerXml.close('profile') - compilerXml.close('annotationProcessing') - - compilerXml.close('component') - compilerXml.close('project') - compilerFile = join(ideaProjectDirectory, 'compiler.xml') - update_file(compilerFile, compilerXml.xml(indent=' ', newl='\n')) - - # Wite misc.xml for global JDK config - miscXml = XMLDoc() - miscXml.open('project', attributes={'version': '4'}) - miscXml.element('component', attributes={'name': 'ProjectRootManager', 'version': '2', 'languageLevel': _complianceToIntellijLanguageLevel(java().javaCompliance), 'project-jdk-name': str(java().javaCompliance), 'project-jdk-type': 'JavaSDK'}) - miscXml.close('project') - miscFile = join(ideaProjectDirectory, 'misc.xml') - update_file(miscFile, miscXml.xml(indent=' ', newl='\n')) - - - # TODO look into copyright settings - # TODO should add vcs.xml support - -def ideclean(args): - """remove all Eclipse and NetBeans project configurations""" - def rm(path): - if exists(path): - os.remove(path) - - for s in suites(): - rm(join(s.mxDir, 'eclipse-config.zip')) - rm(join(s.mxDir, 'netbeans-config.zip')) - shutil.rmtree(join(s.dir, '.idea'), ignore_errors=True) - - for p in projects(): - if p.native: - continue - - shutil.rmtree(join(p.dir, '.settings'), ignore_errors=True) - shutil.rmtree(join(p.dir, '.externalToolBuilders'), ignore_errors=True) - shutil.rmtree(join(p.dir, 'nbproject'), ignore_errors=True) - rm(join(p.dir, '.classpath')) - rm(join(p.dir, '.checkstyle')) - rm(join(p.dir, '.project')) - rm(join(p.dir, '.factorypath')) - rm(join(p.dir, p.name + '.iml')) - rm(join(p.dir, 'build.xml')) - rm(join(p.dir, 'eclipse-build.xml')) - try: - rm(join(p.dir, p.name + '.jar')) - except: - log("Error removing {0}".format(p.name + '.jar')) - - for d in _dists.itervalues(): - if d.get_ide_project_dir(): - shutil.rmtree(d.get_ide_project_dir(), ignore_errors=True) - -def ideinit(args, refreshOnly=False, buildProcessorJars=True): - """(re)generate Eclipse, NetBeans and Intellij project configurations""" - eclipseinit(args, refreshOnly=refreshOnly, buildProcessorJars=buildProcessorJars) - netbeansinit(args, refreshOnly=refreshOnly, buildProcessorJars=buildProcessorJars) - intellijinit(args, refreshOnly=refreshOnly) - if not refreshOnly: - fsckprojects([]) - -def fsckprojects(args): - """find directories corresponding to deleted Java projects and delete them""" - if not is_interactive(): - log('fsckprojects command must be run in an interactive shell') - return - hg = HgConfig() - projectDirs = [p.dir for suite in suites() for p in suite.projects] - distIdeDirs = [d.get_ide_project_dir() for suite in suites() for d in suite.dists if d.get_ide_project_dir() is not None] - for suite in suites(True): - for dirpath, dirnames, files in os.walk(suite.dir): - if dirpath == suite.dir: - # no point in traversing .hg, lib, or .workspace - dirnames[:] = [d for d in dirnames if d not in ['.hg', 'lib', '.workspace']] - elif dirpath in projectDirs: - # don't traverse subdirs of an existing project - dirnames[:] = [] - elif dirpath in distIdeDirs: - # don't traverse subdirs of an existing distribution - dirnames[:] = [] - else: - projectConfigFiles = frozenset(['.classpath', '.project', 'nbproject']) - indicators = projectConfigFiles.intersection(files) - if len(indicators) != 0: - indicators = [os.path.relpath(join(dirpath, i), suite.dir) for i in indicators] - indicatorsInHg = hg.locate(suite.dir, indicators) - # Only proceed if there are indicator files that are not under HG - if len(indicators) > len(indicatorsInHg): - if ask_yes_no(dirpath + ' looks like a removed project -- delete it', 'n'): - shutil.rmtree(dirpath) - log('Deleted ' + dirpath) - -def javadoc(args, parser=None, docDir='javadoc', includeDeps=True, stdDoclet=True): - """generate javadoc for some/all Java projects""" - - parser = ArgumentParser(prog='mx javadoc') if parser is None else parser - parser.add_argument('-d', '--base', action='store', help='base directory for output') - parser.add_argument('--unified', action='store_true', help='put javadoc in a single directory instead of one per project') - parser.add_argument('--force', action='store_true', help='(re)generate javadoc even if package-list file exists') - parser.add_argument('--projects', action='store', help='comma separated projects to process (omit to process all projects)') - parser.add_argument('--Wapi', action='store_true', dest='warnAPI', help='show warnings about using internal APIs') - parser.add_argument('--argfile', action='store', help='name of file containing extra javadoc options') - parser.add_argument('--arg', action='append', dest='extra_args', help='extra Javadoc arguments (e.g. --arg @-use)', metavar='@', default=[]) - parser.add_argument('-m', '--memory', action='store', help='-Xmx value to pass to underlying JVM') - parser.add_argument('--packages', action='store', help='comma separated packages to process (omit to process all packages)') - parser.add_argument('--exclude-packages', action='store', help='comma separated packages to exclude') - - args = parser.parse_args(args) - - # build list of projects to be processed - if args.projects is not None: - candidates = [project(name) for name in args.projects.split(',')] - else: - candidates = projects_opt_limit_to_suites() - - # optionally restrict packages within a project - packages = [] - if args.packages is not None: - packages = [name for name in args.packages.split(',')] - - exclude_packages = [] - if args.exclude_packages is not None: - exclude_packages = [name for name in args.exclude_packages.split(',')] - - def outDir(p): - if args.base is None: - return join(p.dir, docDir) - return join(args.base, p.name, docDir) - - def check_package_list(p): - return not exists(join(outDir(p), 'package-list')) - - def assess_candidate(p, projects): - if p in projects: - return False - if args.force or args.unified or check_package_list(p): - projects.append(p) - return True - return False - - projects = [] - for p in candidates: - if not p.native: - if includeDeps: - deps = p.all_deps([], includeLibs=False, includeSelf=False) - for d in deps: - assess_candidate(d, projects) - if not assess_candidate(p, projects): - logv('[package-list file exists - skipping {0}]'.format(p.name)) - - - def find_packages(sourceDirs, pkgs=None): - if pkgs is None: - pkgs = set() - for sourceDir in sourceDirs: - for root, _, files in os.walk(sourceDir): - if len([name for name in files if name.endswith('.java')]) != 0: - pkg = root[len(sourceDir) + 1:].replace(os.sep, '.') - if len(packages) == 0 or pkg in packages: - if len(exclude_packages) == 0 or not pkg in exclude_packages: - pkgs.add(pkg) - return pkgs - - extraArgs = [a.lstrip('@') for a in args.extra_args] - if args.argfile is not None: - extraArgs += ['@' + args.argfile] - memory = '2g' - if args.memory is not None: - memory = args.memory - memory = '-J-Xmx' + memory - - if not args.unified: - for p in projects: - # The project must be built to ensure javadoc can find class files for all referenced classes - build(['--no-native', '--projects', p.name]) - - pkgs = find_packages(p.source_dirs(), set()) - deps = p.all_deps([], includeLibs=False, includeSelf=False) - links = ['-link', 'http://docs.oracle.com/javase/' + str(p.javaCompliance.value) + '/docs/api/'] - out = outDir(p) - for d in deps: - depOut = outDir(d) - links.append('-link') - links.append(os.path.relpath(depOut, out)) - cp = classpath(p.name, includeSelf=True) - sp = os.pathsep.join(p.source_dirs()) - overviewFile = join(p.dir, 'overview.html') - delOverviewFile = False - if not exists(overviewFile): - with open(overviewFile, 'w') as fp: - print >> fp, 'Documentation for the ' + p.name + ' project.' - delOverviewFile = True - nowarnAPI = [] - if not args.warnAPI: - nowarnAPI.append('-XDignore.symbol.file') - - # windowTitle onloy applies to the standard doclet processor - windowTitle = [] - if stdDoclet: - windowTitle = ['-windowtitle', p.name + ' javadoc'] - try: - log('Generating {2} for {0} in {1}'.format(p.name, out, docDir)) - projectJava = java(p.javaCompliance) - - # Once https://bugs.openjdk.java.net/browse/JDK-8041628 is fixed, - # this should be reverted to: - # javadocExe = java().javadoc - # we can then also respect _opts.relatex_compliance - javadocExe = projectJava.javadoc - - run([javadocExe, memory, - '-XDignore.symbol.file', - '-classpath', cp, - '-quiet', - '-d', out, - '-overview', overviewFile, - '-sourcepath', sp, - '-source', str(projectJava.javaCompliance)] + - projectJava.javadocLibOptions([]) + - ([] if projectJava.javaCompliance < JavaCompliance('1.8') else ['-Xdoclint:none']) + - links + - extraArgs + - nowarnAPI + - windowTitle + - list(pkgs)) - log('Generated {2} for {0} in {1}'.format(p.name, out, docDir)) - finally: - if delOverviewFile: - os.remove(overviewFile) - - else: - # The projects must be built to ensure javadoc can find class files for all referenced classes - build(['--no-native']) - - pkgs = set() - sp = [] - names = [] - for p in projects: - find_packages(p.source_dirs(), pkgs) - sp += p.source_dirs() - names.append(p.name) - - links = ['-link', 'http://docs.oracle.com/javase/' + str(java().javaCompliance.value) + '/docs/api/'] - out = join(_primary_suite.dir, docDir) - if args.base is not None: - out = join(args.base, docDir) - cp = classpath() - sp = os.pathsep.join(sp) - nowarnAPI = [] - if not args.warnAPI: - nowarnAPI.append('-XDignore.symbol.file') - log('Generating {2} for {0} in {1}'.format(', '.join(names), out, docDir)) - run([java().javadoc, memory, - '-classpath', cp, - '-quiet', - '-d', out, - '-sourcepath', sp] + - ([] if java().javaCompliance < JavaCompliance('1.8') else ['-Xdoclint:none']) + - links + - extraArgs + - nowarnAPI + - list(pkgs)) - log('Generated {2} for {0} in {1}'.format(', '.join(names), out, docDir)) - -def site(args): - """creates a website containing javadoc and the project dependency graph""" - - parser = ArgumentParser(prog='site') - parser.add_argument('-d', '--base', action='store', help='directory for generated site', required=True, metavar='') - parser.add_argument('--tmp', action='store', help='directory to use for intermediate results', metavar='') - parser.add_argument('--name', action='store', help='name of overall documentation', required=True, metavar='') - parser.add_argument('--overview', action='store', help='path to the overview content for overall documentation', required=True, metavar='') - parser.add_argument('--projects', action='store', help='comma separated projects to process (omit to process all projects)') - parser.add_argument('--jd', action='append', help='extra Javadoc arguments (e.g. --jd @-use)', metavar='@', default=[]) - parser.add_argument('--exclude-packages', action='store', help='comma separated packages to exclude', metavar='') - parser.add_argument('--dot-output-base', action='store', help='base file name (relative to /all) for project dependency graph .svg and .jpg files generated by dot (omit to disable dot generation)', metavar='') - parser.add_argument('--title', action='store', help='value used for -windowtitle and -doctitle javadoc args for overall documentation (default: "")', metavar='') - args = parser.parse_args(args) - - args.base = os.path.abspath(args.base) - tmpbase = args.tmp if args.tmp else tempfile.mkdtemp(prefix=basename(args.base) + '.', dir=dirname(args.base)) - unified = join(tmpbase, 'all') - - exclude_packages_arg = [] - if args.exclude_packages is not None: - exclude_packages_arg = ['--exclude-packages', args.exclude_packages] - - projects = sorted_deps() - projects_arg = [] - if args.projects is not None: - projects_arg = ['--projects', args.projects] - projects = [project(name) for name in args.projects.split(',')] - - extra_javadoc_args = [] - for a in args.jd: - extra_javadoc_args.append('--arg') - extra_javadoc_args.append('@' + a) - - try: - # Create javadoc for each project - javadoc(['--base', tmpbase] + exclude_packages_arg + projects_arg + extra_javadoc_args) - - # Create unified javadoc for all projects - with open(args.overview) as fp: - content = fp.read() - idx = content.rfind('</body>') - if idx != -1: - args.overview = join(tmpbase, 'overview_with_projects.html') - with open(args.overview, 'w') as fp2: - print >> fp2, content[0:idx] - print >> fp2, """<div class="contentContainer"> -<table class="overviewSummary" border="0" cellpadding="3" cellspacing="0" summary="Projects table"> -<caption><span>Projects</span><span class="tabEnd"> </span></caption> -<tr><th class="colFirst" scope="col">Project</th><th class="colLast" scope="col"> </th></tr> -<tbody>""" - color = 'row' - for p in projects: - print >> fp2, '<tr class="{1}Color"><td class="colFirst"><a href="../{0}/javadoc/index.html",target = "_top">{0}</a></td><td class="colLast"> </td></tr>'.format(p.name, color) - color = 'row' if color == 'alt' else 'alt' - - print >> fp2, '</tbody></table></div>' - print >> fp2, content[idx:] - - title = args.title if args.title is not None else args.name - javadoc(['--base', tmpbase, - '--unified', - '--arg', '@-windowtitle', '--arg', '@' + title, - '--arg', '@-doctitle', '--arg', '@' + title, - '--arg', '@-overview', '--arg', '@' + args.overview] + exclude_packages_arg + projects_arg + extra_javadoc_args) - - if exists(unified): - shutil.rmtree(unified) - os.rename(join(tmpbase, 'javadoc'), unified) - - # Generate dependency graph with Graphviz - if args.dot_output_base is not None: - dotErr = None - try: - if not 'version' in subprocess.check_output(['dot', '-V'], stderr=subprocess.STDOUT): - dotErr = 'dot -V does not print a string containing "version"' - except subprocess.CalledProcessError as e: - dotErr = 'error calling "dot -V": {0}'.format(e) - except OSError as e: - dotErr = 'error calling "dot -V": {0}'.format(e) - - if dotErr != None: - abort('cannot generate dependency graph: ' + dotErr) - - dot = join(tmpbase, 'all', str(args.dot_output_base) + '.dot') - svg = join(tmpbase, 'all', str(args.dot_output_base) + '.svg') - jpg = join(tmpbase, 'all', str(args.dot_output_base) + '.jpg') - html = join(tmpbase, 'all', str(args.dot_output_base) + '.html') - with open(dot, 'w') as fp: - dim = len(projects) - print >> fp, 'digraph projects {' - print >> fp, 'rankdir=BT;' - print >> fp, 'size = "' + str(dim) + ',' + str(dim) + '";' - print >> fp, 'node [shape=rect, fontcolor="blue"];' - # print >> fp, 'edge [color="green"];' - for p in projects: - print >> fp, '"' + p.name + '" [URL = "../' + p.name + '/javadoc/index.html", target = "_top"]' - for dep in p.canonical_deps(): - if dep in [proj.name for proj in projects]: - print >> fp, '"' + p.name + '" -> "' + dep + '"' - depths = dict() - for p in projects: - d = p.max_depth() - depths.setdefault(d, list()).append(p.name) - print >> fp, '}' - - run(['dot', '-Tsvg', '-o' + svg, '-Tjpg', '-o' + jpg, dot]) - - # Post-process generated SVG to remove title elements which most browsers - # render as redundant (and annoying) tooltips. - with open(svg, 'r') as fp: - content = fp.read() - content = re.sub('<title>.*', '', content) - content = re.sub('xlink:title="[^"]*"', '', content) - with open(svg, 'w') as fp: - fp.write(content) - - # Create HTML that embeds the svg file in an frame - with open(html, 'w') as fp: - print >> fp, ''.format(args.dot_output_base) - - if exists(args.base): - shutil.rmtree(args.base) - if args.tmp: - shutil.copytree(tmpbase, args.base) - else: - shutil.move(tmpbase, args.base) - - print 'Created website - root is ' + join(args.base, 'all', 'index.html') - - finally: - if not args.tmp and exists(tmpbase): - shutil.rmtree(tmpbase) - -def _kwArg(kwargs): - if len(kwargs) > 0: - return kwargs.pop(0) - return None - -def findclass(args, logToConsole=True, matcher=lambda string, classname: string in classname): - """find all classes matching a given substring""" - matches = [] - for entry, filename in classpath_walk(includeBootClasspath=True): - if filename.endswith('.class'): - if isinstance(entry, zipfile.ZipFile): - classname = filename.replace('/', '.') - else: - classname = filename.replace(os.sep, '.') - classname = classname[:-len('.class')] - for a in args: - if matcher(a, classname): - matches.append(classname) - if logToConsole: - log(classname) - return matches - -def select_items(items, descriptions=None, allowMultiple=True): - """ - Presents a command line interface for selecting one or more (if allowMultiple is true) items. - - """ - if len(items) <= 1: - return items - else: - assert is_interactive() - numlen = str(len(str(len(items)))) - if allowMultiple: - log(('[{0:>' + numlen + '}] ').format(0)) - for i in range(0, len(items)): - if descriptions is None: - log(('[{0:>' + numlen + '}] {1}').format(i + 1, items[i])) - else: - assert len(items) == len(descriptions) - wrapper = textwrap.TextWrapper(subsequent_indent=' ') - log('\n'.join(wrapper.wrap(('[{0:>' + numlen + '}] {1} - {2}').format(i + 1, items[i], descriptions[i])))) - while True: - if allowMultiple: - s = raw_input('Enter number(s) of selection (separate multiple choices with spaces): ').split() - else: - s = [raw_input('Enter number of selection: ')] - try: - s = [int(x) for x in s] - except: - log('Selection contains non-numeric characters: "' + ' '.join(s) + '"') - continue - - if allowMultiple and 0 in s: - return items - - indexes = [] - for n in s: - if n not in range(1, len(items) + 1): - log('Invalid selection: ' + str(n)) - continue - else: - indexes.append(n - 1) - if allowMultiple: - return [items[i] for i in indexes] - if len(indexes) == 1: - return items[indexes[0]] - return None - -def exportlibs(args): - """export libraries to an archive file""" - - parser = ArgumentParser(prog='exportlibs') - parser.add_argument('-b', '--base', action='store', help='base name of archive (default: libs)', default='libs', metavar='') - parser.add_argument('-a', '--include-all', action='store_true', help="include all defined libaries") - parser.add_argument('--arc', action='store', choices=['tgz', 'tbz2', 'tar', 'zip'], default='tgz', help='the type of the archive to create') - parser.add_argument('--no-sha1', action='store_false', dest='sha1', help='do not create SHA1 signature of archive') - parser.add_argument('--no-md5', action='store_false', dest='md5', help='do not create MD5 signature of archive') - parser.add_argument('--include-system-libs', action='store_true', help='include system libraries (i.e., those not downloaded from URLs)') - parser.add_argument('extras', nargs=REMAINDER, help='extra files and directories to add to archive', metavar='files...') - args = parser.parse_args(args) - - def createArchive(addMethod): - entries = {} - def add(path, arcname): - apath = os.path.abspath(path) - if not entries.has_key(arcname): - entries[arcname] = apath - logv('[adding ' + path + ']') - addMethod(path, arcname=arcname) - elif entries[arcname] != apath: - logv('[warning: ' + apath + ' collides with ' + entries[arcname] + ' as ' + arcname + ']') - else: - logv('[already added ' + path + ']') - - libsToExport = set() - if args.include_all: - for lib in _libs.itervalues(): - libsToExport.add(lib) - else: - def isValidLibrary(dep): - if dep in _libs.iterkeys(): - lib = _libs[dep] - if len(lib.urls) != 0 or args.include_system_libs: - return lib - return None - - # iterate over all project dependencies and find used libraries - for p in _projects.itervalues(): - for dep in p.deps: - r = isValidLibrary(dep) - if r: - libsToExport.add(r) - - # a library can have other libraries as dependency - size = 0 - while size != len(libsToExport): - size = len(libsToExport) - for lib in libsToExport.copy(): - for dep in lib.deps: - r = isValidLibrary(dep) - if r: - libsToExport.add(r) - - for lib in libsToExport: - add(lib.get_path(resolve=True), lib.path) - if lib.sha1: - add(lib.get_path(resolve=True) + ".sha1", lib.path + ".sha1") - if lib.sourcePath: - add(lib.get_source_path(resolve=True), lib.sourcePath) - if lib.sourceSha1: - add(lib.get_source_path(resolve=True) + ".sha1", lib.sourcePath + ".sha1") - - if args.extras: - for e in args.extras: - if os.path.isdir(e): - for root, _, filenames in os.walk(e): - for name in filenames: - f = join(root, name) - add(f, f) - else: - add(e, e) - - if args.arc == 'zip': - path = args.base + '.zip' - with zipfile.ZipFile(path, 'w') as zf: - createArchive(zf.write) - else: - path = args.base + '.tar' - mode = 'w' - if args.arc != 'tar': - sfx = args.arc[1:] - mode = mode + ':' + sfx - path = path + '.' + sfx - with tarfile.open(path, mode) as tar: - createArchive(tar.add) - log('created ' + path) - - def digest(enabled, path, factory, suffix): - if enabled: - d = factory() - with open(path, 'rb') as f: - while True: - buf = f.read(4096) - if not buf: - break - d.update(buf) - with open(path + '.' + suffix, 'w') as fp: - print >> fp, d.hexdigest() - log('created ' + path + '.' + suffix) - - digest(args.sha1, path, hashlib.sha1, 'sha1') - digest(args.md5, path, hashlib.md5, 'md5') - -def javap(args): - """disassemble classes matching given pattern with javap""" - - javapExe = java().javap - if not exists(javapExe): - abort('The javap executable does not exists: ' + javapExe) - else: - candidates = findclass(args, logToConsole=False) - if len(candidates) == 0: - log('no matches') - selection = select_items(candidates) - run([javapExe, '-private', '-verbose', '-classpath', classpath()] + selection) - -def show_projects(args): - """show all projects""" - for s in suites(): - if len(s.projects) != 0: - log(join(s.mxDir, 'suite*.py')) - for p in s.projects: - log('\t' + p.name) - -def show_suites(args): - """show all suites""" - def _show_section(name, section): - if len(section) != 0: - log(' ' + name + ':') - for e in section: - log(' ' + e.name) - - for s in suites(): - log(join(s.mxDir, 'suite*.py')) - _show_section('libraries', s.libs) - _show_section('jrelibraries', s.jreLibs) - _show_section('projects', s.projects) - _show_section('distributions', s.dists) - -def _compile_mx_class(javaClassName, classpath=None, jdk=None, myDir=None): - myDir = dirname(__file__) if myDir is None else myDir - binDir = join(myDir, 'bin' if not jdk else '.jdk' + str(jdk.version)) - javaSource = join(myDir, javaClassName + '.java') - javaClass = join(binDir, javaClassName + '.class') - if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource): - if not exists(binDir): - os.mkdir(binDir) - javac = jdk.javac if jdk else java().javac - cmd = [javac, '-d', _cygpathU2W(binDir)] - if classpath: - cmd += ['-cp', _separatedCygpathU2W(binDir + os.pathsep + classpath)] - cmd += [_cygpathU2W(javaSource)] - try: - subprocess.check_call(cmd) - except subprocess.CalledProcessError: - abort('failed to compile:' + javaSource) - - return (myDir, binDir) - -def checkcopyrights(args): - '''run copyright check on the sources''' - class CP(ArgumentParser): - def format_help(self): - return ArgumentParser.format_help(self) + self._get_program_help() - - def _get_program_help(self): - help_output = subprocess.check_output([java().java, '-cp', _cygpathU2W(binDir), 'CheckCopyright', '--help']) - return '\nother argumemnts preceded with --\n' + help_output - - myDir, binDir = _compile_mx_class('CheckCopyright') - - parser = CP(prog='mx checkcopyrights') - - parser.add_argument('--primary', action='store_true', help='limit checks to primary suite') - parser.add_argument('remainder', nargs=REMAINDER, metavar='...') - args = parser.parse_args(args) - remove_doubledash(args.remainder) - - - # ensure compiled form of code is up to date - - result = 0 - # copyright checking is suite specific as each suite may have different overrides - for s in suites(True): - if args.primary and not s.primary: - continue - custom_copyrights = _cygpathU2W(join(s.mxDir, 'copyrights')) - custom_args = [] - if exists(custom_copyrights): - custom_args = ['--custom-copyright-dir', custom_copyrights] - rc = run([java().java, '-cp', _cygpathU2W(binDir), 'CheckCopyright', '--copyright-dir', _cygpathU2W(myDir)] + custom_args + args.remainder, cwd=s.dir, nonZeroIsFatal=False) - result = result if rc == 0 else rc - return result - -def remove_doubledash(args): - if '--' in args: - args.remove('--') - -def ask_yes_no(question, default=None): - """""" - assert not default or default == 'y' or default == 'n' - if not is_interactive(): - if default: - return default - else: - abort("Can not answer '" + question + "?' if stdout is not a tty") - questionMark = '? [yn]: ' - if default: - questionMark = questionMark.replace(default, default.upper()) - if _opts.answer: - answer = str(_opts.answer) - print question + questionMark + answer - else: - answer = raw_input(question + questionMark) or default - while not answer: - answer = raw_input(question + questionMark) - return answer.lower().startswith('y') - -def add_argument(*args, **kwargs): - """ - Define how a single command-line argument. - """ - assert _argParser is not None - _argParser.add_argument(*args, **kwargs) - -def update_commands(suite, new_commands): - for key, value in new_commands.iteritems(): - assert ':' not in key - old = _commands.get(key) - if old is not None: - oldSuite = _commandsToSuite.get(key) - if not oldSuite: - # Core mx command is overridden by first suite - # defining command of same name. The core mx - # command has its name prefixed with ':'. - _commands[':' + key] = old - else: - # Previously specified command from another suite - # is not overridden. Instead, the new command - # has a name qualified by the suite name. - key = suite.name + ':' + key - _commands[key] = value - _commandsToSuite[key] = suite - -def warn(msg): - if _warn: - print 'WARNING: ' + msg - -# Table of commands in alphabetical order. -# Keys are command names, value are lists: [, , ...] -# If any of the format args are instances of Callable, then they are called before being -# used in the call to str.format(). -# Suite extensions should not update this table directly, but use update_commands -_commands = { - 'about': [about, ''], - 'build': [build, '[options]'], - 'checkstyle': [checkstyle, ''], - 'canonicalizeprojects': [canonicalizeprojects, ''], - 'checkcopyrights': [checkcopyrights, '[options]'], - 'clean': [clean, ''], - 'eclipseinit': [eclipseinit, ''], - 'eclipseformat': [eclipseformat, ''], - 'exportlibs': [exportlibs, ''], - 'findbugs': [mx_findbugs.findbugs, ''], - 'findclass': [findclass, ''], - 'fsckprojects': [fsckprojects, ''], - 'help': [help_, '[command]'], - 'ideclean': [ideclean, ''], - 'ideinit': [ideinit, ''], - 'intellijinit': [intellijinit, ''], - 'archive': [_archive, '[options]'], - 'projectgraph': [projectgraph, ''], - 'pylint': [pylint, ''], - 'javap': [javap, ''], - 'javadoc': [javadoc, '[options]'], - 'site': [site, '[options]'], - 'netbeansinit': [netbeansinit, ''], - 'suites': [show_suites, ''], - 'projects': [show_projects, ''], - 'unittest' : [mx_unittest.unittest, '[unittest options] [--] [VM options] [filters...]', mx_unittest.unittestHelpSuffix], -} -_commandsToSuite = {} - -_argParser = ArgParser() - -def _suitename(mxDir): - base = os.path.basename(mxDir) - parts = base.split('.') - assert len(parts) == 2 - assert parts[0] == 'mx' - return parts[1] - -def _is_suite_dir(d, mxDirName=None): - """ - Checks if d contains a suite. - If mxDirName is None, matches any suite name, otherwise checks for exactly that suite. - """ - if os.path.isdir(d): - for f in [mxDirName] if mxDirName else [e for e in os.listdir(d) if e.startswith('mx.')]: - mxDir = join(d, f) - if exists(mxDir) and isdir(mxDir) and (exists(join(mxDir, 'suite.py'))): - return mxDir - -def _check_primary_suite(): - if _primary_suite is None: - abort('no primary suite found') - else: - return _primary_suite - -def _findPrimarySuiteMxDirFrom(d): - """ search for a suite directory upwards from 'd' """ - while d: - mxDir = _is_suite_dir(d) - if mxDir is not None: - return mxDir - parent = dirname(d) - if d == parent: - return None - d = parent - - return None - -def _findPrimarySuiteMxDir(): - # check for explicit setting - if _primary_suite_path is not None: - mxDir = _is_suite_dir(_primary_suite_path) - if mxDir is not None: - return mxDir - else: - abort(_primary_suite_path + ' does not contain an mx suite') - - # try current working directory first - mxDir = _findPrimarySuiteMxDirFrom(os.getcwd()) - if mxDir is not None: - return mxDir - # backwards compatibility: search from path of this file - return _findPrimarySuiteMxDirFrom(dirname(__file__)) - -def main(): - mxMxDir = _is_suite_dir(os.path.abspath(dirname(__file__))) - assert mxMxDir - global _mx_suite - _mx_suite = _loadSuite(mxMxDir) - - primarySuiteMxDir = _findPrimarySuiteMxDir() - if primarySuiteMxDir: - global _primary_suite - _primary_suite = _loadSuite(primarySuiteMxDir, True) - else: - abort('no primary suite found') - - opts, commandAndArgs = _argParser._parse_cmd_line() - assert _opts == opts - - for s in suites(): - s._post_init(opts) - - if len(commandAndArgs) == 0: - _argParser.print_help() - return - - command = commandAndArgs[0] - command_args = commandAndArgs[1:] - - if not _commands.has_key(command): - hits = [c for c in _commands.iterkeys() if c.startswith(command)] - if len(hits) == 1: - command = hits[0] - elif len(hits) == 0: - abort('mx: unknown command \'{0}\'\n{1}use "mx help" for more options'.format(command, _format_commands())) - else: - abort('mx: command \'{0}\' is ambiguous\n {1}'.format(command, ' '.join(hits))) - - c, _ = _commands[command][:2] - def term_handler(signum, frame): - abort(1) - if not is_jython(): - signal.signal(signal.SIGTERM, term_handler) - - def quit_handler(signum, frame): - _send_sigquit() - if not is_jython() and get_os() != 'windows': - signal.signal(signal.SIGQUIT, quit_handler) - - try: - if opts.timeout != 0: - def alarm_handler(signum, frame): - abort('Command timed out after ' + str(opts.timeout) + ' seconds: ' + ' '.join(commandAndArgs)) - signal.signal(signal.SIGALRM, alarm_handler) - signal.alarm(opts.timeout) - retcode = c(command_args) - if retcode is not None and retcode != 0: - abort(retcode) - except KeyboardInterrupt: - # no need to show the stack trace when the user presses CTRL-C - abort(1) - -version = VersionSpec("1.0") - -currentUmask = None - -if __name__ == '__main__': - # Capture the current umask since there's no way to query it without mutating it. - currentUmask = os.umask(0) - os.umask(currentUmask) - - main() diff -r 103f53747955 -r 258eaaa98484 mxtool/mx_findbugs.py --- a/mxtool/mx_findbugs.py Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -#!/usr/bin/env python2.7 -# -# ---------------------------------------------------------------------------------------------------- -# -# Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# -# ---------------------------------------------------------------------------------------------------- -# - -import mx -import os -import tempfile -import zipfile -import shutil -from os.path import join, exists - -def defaultFindbugsArgs(): - args = ['-textui', '-low', '-maxRank', '15'] - if mx.is_interactive(): - args.append('-progress') - return args - -def findbugs(args, fbArgs=None, suite=None, projects=None): - """run FindBugs against non-test Java projects""" - findBugsHome = mx.get_env('FINDBUGS_HOME', None) - if suite is None: - suite = mx._primary_suite - if findBugsHome: - findbugsJar = join(findBugsHome, 'lib', 'findbugs.jar') - else: - findbugsLib = join(mx._mx_suite.dir, 'lib', 'findbugs-3.0.0') - if not exists(findbugsLib): - tmp = tempfile.mkdtemp(prefix='findbugs-download-tmp', dir=mx._mx_suite.dir) - try: - findbugsDist = mx.library('FINDBUGS_DIST').get_path(resolve=True) - with zipfile.ZipFile(findbugsDist) as zf: - candidates = [e for e in zf.namelist() if e.endswith('/lib/findbugs.jar')] - assert len(candidates) == 1, candidates - libDirInZip = os.path.dirname(candidates[0]) - zf.extractall(tmp) - shutil.copytree(join(tmp, libDirInZip), findbugsLib) - finally: - shutil.rmtree(tmp) - findbugsJar = join(findbugsLib, 'findbugs.jar') - assert exists(findbugsJar) - nonTestProjects = [p for p in mx.projects() if not p.name.endswith('.test') and not p.name.endswith('.jtt')] - outputDirs = map(mx._cygpathU2W, [p.output_dir() for p in nonTestProjects]) - javaCompliance = max([p.javaCompliance for p in nonTestProjects]) - findbugsResults = join(suite.dir, 'findbugs.results') - - if fbArgs is None: - fbArgs = defaultFindbugsArgs() - cmd = ['-jar', mx._cygpathU2W(findbugsJar)] + fbArgs - cmd = cmd + ['-auxclasspath', mx._separatedCygpathU2W(mx.classpath([p.name for p in nonTestProjects])), '-output', mx._cygpathU2W(findbugsResults), '-exitcode'] + args + outputDirs - exitcode = mx.run_java(cmd, nonZeroIsFatal=False, javaConfig=mx.java(javaCompliance)) - if exitcode != 0: - with open(findbugsResults) as fp: - mx.log(fp.read()) - os.unlink(findbugsResults) - return exitcode diff -r 103f53747955 -r 258eaaa98484 mxtool/mx_unittest.py --- a/mxtool/mx_unittest.py Thu Jul 02 12:42:20 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,262 +0,0 @@ -#!/usr/bin/env python2.7 -# -# ---------------------------------------------------------------------------------------------------- -# -# Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# -# ---------------------------------------------------------------------------------------------------- -# - -import mx -import os -import re -import tempfile -import fnmatch -from argparse import ArgumentParser, RawDescriptionHelpFormatter - -def _find_classes_with_annotations(p, pkgRoot, annotations, includeInnerClasses=False): - """ - Scan the sources of project 'p' for Java source files containing a line starting with 'annotation' - (ignoring preceding whitespace) and return the fully qualified class name for each Java - source file matched in a list. - """ - - matches = lambda line: len([a for a in annotations if line == a or line.startswith(a + '(')]) != 0 - return p.find_classes_with_matching_source_line(pkgRoot, matches, includeInnerClasses) - -def _run_tests(args, harness, vmLauncher, annotations, testfile, blacklist, whitelist, regex): - - - vmArgs, tests = mx.extract_VM_args(args) - for t in tests: - if t.startswith('-'): - mx.abort('VM option ' + t + ' must precede ' + tests[0]) - - candidates = {} - for p in mx.projects_opt_limit_to_suites(): - if mx.java().javaCompliance < p.javaCompliance: - continue - for c in _find_classes_with_annotations(p, None, annotations).keys(): - candidates[c] = p - - classes = [] - if len(tests) == 0: - classes = candidates.keys() - projectsCp = mx.classpath([pcp.name for pcp in mx.projects_opt_limit_to_suites() if pcp.javaCompliance <= mx.java().javaCompliance]) - else: - projs = set() - found = False - if len(tests) == 1 and '#' in tests[0]: - words = tests[0].split('#') - if len(words) != 2: - mx.abort("Method specification is class#method: " + tests[0]) - t, method = words - - for c, p in candidates.iteritems(): - # prefer exact matches first - if t == c: - found = True - classes.append(c) - projs.add(p.name) - if not found: - for c, p in candidates.iteritems(): - if t in c: - found = True - classes.append(c) - projs.add(p.name) - if not found: - mx.log('warning: no tests matched by substring "' + t) - elif len(classes) != 1: - mx.abort('More than one test matches substring {0} {1}'.format(t, classes)) - - classes = [c + "#" + method for c in classes] - else: - for t in tests: - if '#' in t: - mx.abort('Method specifications can only be used in a single test: ' + t) - for c, p in candidates.iteritems(): - if t in c: - found = True - classes.append(c) - projs.add(p.name) - if not found: - mx.log('warning: no tests matched by substring "' + t) - projectsCp = mx.classpath(projs) - - if blacklist: - classes = [c for c in classes if not any((glob.match(c) for glob in blacklist))] - - if whitelist: - classes = [c for c in classes if any((glob.match(c) for glob in whitelist))] - - if regex: - classes = [c for c in classes if re.search(regex, c)] - - if len(classes) != 0: - f_testfile = open(testfile, 'w') - for c in classes: - f_testfile.write(c + '\n') - f_testfile.close() - harness(projectsCp, vmLauncher, vmArgs) - -def _unittest(args, annotations, vmLauncher=None, prefixCp="", blacklist=None, whitelist=None, verbose=False, fail_fast=False, enable_timing=False, regex=None, color=False, eager_stacktrace=False, gc_after_test=False): - testfile = os.environ.get('MX_TESTFILE', None) - if testfile is None: - (_, testfile) = tempfile.mkstemp(".testclasses", "mxtool") - os.close(_) - - coreCp = mx.classpath(['com.oracle.mxtool.junit', 'HCFDIS']) - - coreArgs = [] - if verbose: - coreArgs.append('-JUnitVerbose') - if fail_fast: - coreArgs.append('-JUnitFailFast') - if enable_timing: - coreArgs.append('-JUnitEnableTiming') - if color: - coreArgs.append('-JUnitColor') - if eager_stacktrace: - coreArgs.append('-JUnitEagerStackTrace') - if gc_after_test: - coreArgs.append('-JUnitGCAfterTest') - - - def harness(projectsCp, vmLauncher, vmArgs): - prefixArgs = ['-esa', '-ea'] - if gc_after_test: - prefixArgs.append('-XX:-DisableExplicitGC') - with open(testfile) as fp: - testclasses = [l.rstrip() for l in fp.readlines()] - - # Run the VM in a mode where application/test classes can - # access classes normally hidden behind the JVMCI class loader - cp = prefixCp + coreCp + os.pathsep + projectsCp - - # suppress menubar and dock when running on Mac - vmArgs = prefixArgs + ['-Djava.awt.headless=true'] + vmArgs + ['-cp', mx._separatedCygpathU2W(cp)] - mainClass = 'com.oracle.mxtool.junit.MxJUnitWrapper' - # Execute Junit directly when one test is being run. This simplifies - # replaying the VM execution in a native debugger (e.g., gdb). - mainClassArgs = coreArgs + (testclasses if len(testclasses) == 1 else ['@' + mx._cygpathU2W(testfile)]) - - vmLauncher(vmArgs, mainClass, mainClassArgs) - - if vmLauncher is None: - vmLauncher = lambda vmArgs, mainClass, mainClassArgs: mx.run_java(vmArgs + [mainClass] + mainClassArgs) - - try: - _run_tests(args, harness, vmLauncher, annotations, testfile, blacklist, whitelist, regex) - finally: - if os.environ.get('MX_TESTFILE') is None: - os.remove(testfile) - -unittestHelpSuffix = """ - Unittest options: - - --blacklist run all testcases not specified in the blacklist - --whitelist run only testcases which are included - in the given whitelist - --verbose enable verbose JUnit output - --fail-fast stop after first JUnit test class that has a failure - --enable-timing enable JUnit test timing - --regex run only testcases matching a regular expression - --color enable colors output - --eager-stacktrace print stacktrace eagerly - --gc-after-test force a GC after each test - - To avoid conflicts with VM options '--' can be used as delimiter. - - If filters are supplied, only tests whose fully qualified name - includes a filter as a substring are run. - - For example, this command line: - - mx unittest -G:Dump= -G:MethodFilter=BC_aload.* -G:+PrintCFG BC_aload - - will run all JUnit test classes that contain 'BC_aload' in their - fully qualified name and will pass these options to the VM: - - -G:Dump= -G:MethodFilter=BC_aload.* -G:+PrintCFG - - To get around command line length limitations on some OSes, the - JUnit class names to be executed are written to a file that a - custom JUnit wrapper reads and passes onto JUnit proper. The - MX_TESTFILE environment variable can be set to specify a - file which will not be deleted once the unittests are done - (unlike the temporary file otherwise used). - - As with all other commands, using the global '-v' before 'unittest' - command will cause mx to show the complete command line - it uses to run the VM. -""" - -def unittest(args, vmLauncher=None): - """run the JUnit tests (all testcases)""" - - parser = ArgumentParser(prog='mx unittest', - description='run the JUnit tests', - add_help=False, - formatter_class=RawDescriptionHelpFormatter, - epilog=unittestHelpSuffix, - ) - parser.add_argument('--blacklist', help='run all testcases not specified in ', metavar='') - parser.add_argument('--whitelist', help='run testcases specified in only', metavar='') - parser.add_argument('--verbose', help='enable verbose JUnit output', action='store_true') - parser.add_argument('--fail-fast', help='stop after first JUnit test class that has a failure', action='store_true') - parser.add_argument('--enable-timing', help='enable JUnit test timing', action='store_true') - parser.add_argument('--regex', help='run only testcases matching a regular expression', metavar='') - parser.add_argument('--color', help='enable color output', action='store_true') - parser.add_argument('--eager-stacktrace', help='print stacktrace eagerly', action='store_true') - parser.add_argument('--gc-after-test', help='force a GC after each test', action='store_true') - - ut_args = [] - delimiter = False - # check for delimiter - while len(args) > 0: - arg = args.pop(0) - if arg == '--': - delimiter = True - break - ut_args.append(arg) - - if delimiter: - # all arguments before '--' must be recognized - parsed_args = parser.parse_args(ut_args) - else: - # parse all know arguments - parsed_args, args = parser.parse_known_args(ut_args) - - if parsed_args.whitelist: - try: - with open(parsed_args.whitelist) as fp: - parsed_args.whitelist = [re.compile(fnmatch.translate(l.rstrip())) for l in fp.readlines() if not l.startswith('#')] - except IOError: - mx.log('warning: could not read whitelist: ' + parsed_args.whitelist) - if parsed_args.blacklist: - try: - with open(parsed_args.blacklist) as fp: - parsed_args.blacklist = [re.compile(fnmatch.translate(l.rstrip())) for l in fp.readlines() if not l.startswith('#')] - except IOError: - mx.log('warning: could not read blacklist: ' + parsed_args.blacklist) - - _unittest(args, ['@Test', '@Parameters'], vmLauncher=vmLauncher, **parsed_args.__dict__)