Merge branch 'develop' into improvement/JAL-3449_add_install4j_installer_getdown_vers... improvement/JAL-3449_add_install4j_installer_getdown_versions_to_jalview_console.2
authorBen Soares <bsoares@dundee.ac.uk>
Wed, 19 Feb 2020 16:40:09 +0000 (16:40 +0000)
committerBen Soares <bsoares@dundee.ac.uk>
Wed, 19 Feb 2020 16:40:09 +0000 (16:40 +0000)
1  2 
build.gradle

diff --combined build.gradle
@@@ -1,15 -1,15 +1,15 @@@
  import org.apache.tools.ant.filters.ReplaceTokens
 -//import org.apache.tools.ant.filters.ReplaceRegexp
  import org.gradle.internal.os.OperatingSystem
 -import org.gradle.plugins.ide.eclipse.model.*
 -
 -
 +import org.gradle.plugins.ide.eclipse.model.Output
 +import org.gradle.plugins.ide.eclipse.model.Library
 +import java.security.MessageDigest
  import groovy.transform.ExternalizeMethods
 +import groovy.util.XmlParser
 +import groovy.xml.XmlUtil
  
  buildscript {
    dependencies {
      classpath 'org.openclover:clover:4.4.1'
 -    classpath 'org.apache.commons:commons-compress:1.18'
    }
  }
  
@@@ -18,8 -18,7 +18,8 @@@ plugins 
    id 'application'
    id 'eclipse'
    id 'com.github.johnrengelman.shadow' version '4.0.3'
 -  id 'com.install4j.gradle' version '7.0.9'
 +  id 'com.install4j.gradle' version '8.0.2'
 +  id 'com.dorongold.task-tree' version '1.5' // only needed to display task dependency tree with  gradle task1 [task2 ...] taskTree
  }
  
  repositories {
    }
  }
  
 -mainClassName = launcherClass
 -def cloverInstrDir = file("$buildDir/$cloverSourcesInstrDir")
 -def classes = "$jalviewDir/$classesDir"
 -
 -if (clover.equals("true")) {
 -  use_clover = true
 -  classes = "$buildDir/$cloverClassesDir"
 -} else {
 -  use_clover = false
 -  classes = "$jalviewDir/$classesDir"
 +dependencies {
  }
  
 -// configure classpath/args for j8/j11 compilation
  
 -def jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath()
 -def libDir
 -def libDistDir
 -def compile_source_compatibility
 -def compile_target_compatibility
 +// in ext the values are cast to Object. Ensure string values are cast as String (and not GStringImpl) for later use
 +def string(Object o) {
 +  return o == null ? "" : o.toString()
 +}
 +
  
  ext {
 -  getdownWebsiteDir = jalviewDir + '/' + getdown_website_dir + '/' + JAVA_VERSION
 -  getdownDir = ""
 -  reportRsyncCmd = false
 +  jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath()
 +  jalviewDirRelativePath = jalviewDir
 +
 +  // local build environment properties
 +  def localProps = "${jalviewDirAbsolutePath}/local.properties"
 +  if (file(localProps).exists()) {
 +    try {
 +      def p = new Properties()
 +      def localPropsFIS = new FileInputStream(localProps)
 +      p.load(localPropsFIS)
 +      localPropsFIS.close()
 +      p.each {
 +        key, val -> 
 +          def oldval = findProperty(key)
 +          setProperty(key, val)
 +          if (oldval != null) {
 +            println("Overriding property '${key}' ('${oldval}') with local.properties value '${val}'")
 +          } else {
 +            println("Setting unknown property '${key}' with local.properties value '${val}'")
 +          }
 +      }
 +    } catch (Exception e) {
 +      System.out.println("Exception reading local.properties")
 +    }
 +  }
 +
 +  // this property set when running Eclipse headlessly
 +  j2sHeadlessBuildProperty = string("net.sf.j2s.core.headlessbuild")
 +  // this property set by Eclipse
 +  eclipseApplicationProperty = string("eclipse.application")
 +  // CHECK IF RUNNING FROM WITHIN ECLIPSE
 +  def eclipseApplicationPropertyVal = System.properties[eclipseApplicationProperty]
 +  IN_ECLIPSE = eclipseApplicationPropertyVal != null && eclipseApplicationPropertyVal.startsWith("org.eclipse.ui.")
 +  // BUT WITHOUT THE HEADLESS BUILD PROPERTY SET
 +  if (System.properties[j2sHeadlessBuildProperty].equals("true")) {
 +    println("Setting IN_ECLIPSE to ${IN_ECLIPSE} as System.properties['${j2sHeadlessBuildProperty}'] == '${System.properties[j2sHeadlessBuildProperty]}'")
 +    IN_ECLIPSE = false
 +  }
 +  if (IN_ECLIPSE) {
 +    println("WITHIN ECLIPSE IDE")
 +  } else {
 +    println("HEADLESS BUILD")
 +  }
 +  /* *-/
 +  System.properties.sort { it.key }.each {
 +    key, val -> println("SYSTEM PROPERTY ${key}='${val}'")
 +  }
 +  /-* *-/
 +  if (false && IN_ECLIPSE) {
 +    jalviewDir = jalviewDirAbsolutePath
 +  }
 +  */
 +
 +  // essentials
 +  bareSourceDir = string(source_dir)
 +  sourceDir = string("${jalviewDir}/${bareSourceDir}")
 +  resourceDir = string("${jalviewDir}/${resource_dir}")
 +  bareTestSourceDir = string(test_source_dir)
 +  testSourceDir = string("${jalviewDir}/${bareTestSourceDir}")
 +
 +  // clover
 +  cloverInstrDir = file("${buildDir}/${cloverSourcesInstrDir}")
 +  classesDir = string("${jalviewDir}/${classes_dir}")
 +  if (clover.equals("true")) {
 +    use_clover = true
 +    classesDir = string("${buildDir}/${cloverClassesDir}")
 +  } else {
 +    use_clover = false
 +    classesDir = string("${jalviewDir}/${classes_dir}")
 +  }
 +
 +  classes = classesDir
 +
 +  getdownWebsiteDir = string("${jalviewDir}/${getdown_website_dir}/${JAVA_VERSION}")
    buildDist = true
 -  buildProperties = buildPropertiesFile
 -  getdownLauncher = jalviewDir + '/' + getdown_lib_dir + '/' + getdown_launcher
 +
 +  // the following values might be overridden by the CHANNEL switch
 +  getdownChannelName = CHANNEL.toLowerCase()
 +  getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
 +  getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
 +  getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}")
 +  getdownAppDistDir = getdown_app_dir_alt
 +  buildProperties = string("${classesDir}/${build_properties_file}")
 +  reportRsyncCmd = false
 +  jvlChannelName = CHANNEL.toLowerCase()
    switch (CHANNEL) {
  
      case "BUILD":
      // TODO: get bamboo build artifact URL for getdown artifacts
      getdown_channel_base = bamboo_channelbase
 -    getdown_channel_name = bamboo_planKey + '/'+JAVA_VERSION
 -    getdown_app_base = bamboo_channelbase + '/'+ bamboo_planKey + bamboo_getdown_channel_suffix + '/'+JAVA_VERSION
 -    getdown_app_dir = getdown_app_dir_alt
 -    buildProperties = jalviewDir + "/" + classesDir +"/" + buildPropertiesFile
 +    getdownChannelName = string("${bamboo_planKey}/${JAVA_VERSION}")
 +    getdownAppBase = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
 +    jvlChannelName += "_${getdownChannelName}"
      break
  
      case "RELEASE":
 -    getdown_channel_name = CHANNEL.toLowerCase()
 -    getdownDir = getdown_channel_name + "/" + JAVA_VERSION
 -    getdown_app_base = getdown_channel_base + "/" + getdownDir
 -    getdown_app_dir = getdown_app_dir_release
 -    buildProperties = jalviewDir + "/" + classesDir +"/" + buildPropertiesFile
 +    getdownAppDistDir = getdown_app_dir_release
      reportRsyncCommand = true
      break
  
      case "ARCHIVE":
 -    getdown_channel_name = CHANNEL.toLowerCase()+"/"+JALVIEW_VERSION
 -    getdownDir = getdown_channel_name + "/" + JAVA_VERSION
 -    getdown_app_base = getdown_channel_base + "/" + getdownDir
 -    getdown_app_dir = getdown_app_dir_alt
 -    if (!file(ARCHIVEDIR+"/"+packageDir).exists()) {
 -      print "Must provide an ARCHIVEDIR value to produce an archive distribution"
 -      exit
 +    getdownChannelName = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
 +    getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
 +    getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
 +    if (!file("${ARCHIVEDIR}/${packageDir}").exists()) {
 +      throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
      } else {
 -      packageDir = ARCHIVEDIR + "/" + packageDir
 -      buildProperties = ARCHIVEDIR +"/" + classesDir + "/" + buildPropertiesFile
 +      packageDir = string("${ARCHIVEDIR}/${packageDir}")
 +      buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
        buildDist = false
      }
      reportRsyncCommand = true
      break
  
      case "ARCHIVELOCAL":
 -    getdown_channel_name = "archive" + "/" + JALVIEW_VERSION
 -    getdownDir = getdown_channel_name + "/" + JAVA_VERSION
 -    getdown_app_base = file(getdownWebsiteDir).toURI().toString()
 -    getdown_app_dir = getdown_app_dir_alt
 -    if (!file(ARCHIVEDIR+"/"+packageDir).exists()) {
 -      print "Must provide an ARCHIVEDIR value to produce an archive distribution"
 -      exit
 +    getdownChannelName = string("archive/${JALVIEW_VERSION}")
 +    getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
 +    getdownAppBase = file(getdownWebsiteDir).toURI().toString()
 +    if (!file("${ARCHIVEDIR}/${packageDir}").exists()) {
 +      throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
      } else {
 -      packageDir = ARCHIVEDIR + "/" + packageDir
 -      buildProperties = ARCHIVEDIR +"/" + classesDir + "/" + buildPropertiesFile
 +      packageDir = string("${ARCHIVEDIR}/${packageDir}")
 +      buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
        buildDist = false
      }
      reportRsyncCommand = true
 -    getdownLauncher = jalviewDir + '/' + getdown_lib_dir + '/' + getdown_launcher_local
 +    getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
      break
  
      case "DEVELOP":
 -    getdown_channel_name = CHANNEL.toLowerCase()
 -    getdownDir = getdown_channel_name + "/" + JAVA_VERSION
 -    getdown_app_base = getdown_channel_base + "/" + getdownDir
 -    getdown_app_dir = getdown_app_dir_alt
 -    buildProperties = jalviewDir + "/" + classesDir +"/" + buildPropertiesFile
      reportRsyncCommand = true
      break
  
      case "TEST-RELEASE":
 -    getdown_channel_name = CHANNEL.toLowerCase()
 -    getdownDir = getdown_channel_name + "/" + JAVA_VERSION
 -    getdown_app_base = getdown_channel_base + "/" + getdownDir
 -    getdown_app_dir = getdown_app_dir_alt
 -    buildProperties = jalviewDir + "/" + classesDir +"/" + buildPropertiesFile
      reportRsyncCommand = true
      break
  
      case ~/^SCRATCH(|-[-\w]*)$/:
 -    getdown_channel_name = CHANNEL
 -    getdownDir = getdown_channel_name + "/" + JAVA_VERSION
 -    getdown_app_base = getdown_channel_base + "/" + getdownDir
 -    getdown_app_dir = getdown_app_dir_alt
 -    buildProperties = jalviewDir + "/" + classesDir +"/" + buildPropertiesFile
 +    getdownChannelName = CHANNEL
 +    getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
 +    getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
      reportRsyncCommand = true
      break
  
 +    case "TEST-LOCAL":
 +    if (!file("${LOCALDIR}").exists()) {
 +      throw new GradleException("Must provide a LOCALDIR value to produce a local distribution")
 +    } else {
 +      getdownAppBase = file(file("${LOCALDIR}").getAbsolutePath()).toURI().toString()
 +      getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
 +    }
 +    break
 +
      case "LOCAL":
 -    getdown_app_base = file(getdownWebsiteDir).toURI().toString()
 -    getdown_app_dir = getdown_app_dir_alt
 -    buildProperties = jalviewDir + "/" + classesDir +"/" + buildPropertiesFile
 -    getdownLauncher = jalviewDir + '/' + getdown_lib_dir + '/' + getdown_launcher_local
 +    getdownAppBase = file(getdownWebsiteDir).toURI().toString()
 +    getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
      break
  
      default: // something wrong specified
 -    print("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
 -    exit
 +    throw new GradleException("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
      break
  
    }
 -
 -  println("Using a "+CHANNEL+" profile. appbase="+getdown_app_base)
 -  getdownAppDir = getdownWebsiteDir + '/' + getdown_app_dir
 -  //getdownJ11libDir = getdownWebsiteDir + '/' + getdown_j11lib_dir
 -  getdownResourceDir = getdownWebsiteDir + '/' + getdown_resource_dir
 -  getdownInstallDir = getdownWebsiteDir + '/' + getdown_install_dir
 -  getdownFilesDir = jalviewDir + '/' + getdown_files_dir + '/' + JAVA_VERSION + '/'
 -  getdownFilesInstallDir = getdownFilesDir+"/"+getdown_install_dir
 +  // override getdownAppBase if requested
 +  if (findProperty("getdown_appbase_override") != null) {
 +    getdownAppBase = string(getProperty("getdown_appbase_override"))
 +    println("Overriding getdown appbase with '${getdownAppBase}'")
 +  }
 +  // sanitise file name for jalview launcher file for this channel
 +  jvlChannelName = jvlChannelName.replaceAll(/[^\w\-]/,"_")
 +
 +  getdownAppDir = string("${getdownWebsiteDir}/${getdownAppDistDir}")
 +  //getdownJ11libDir = "${getdownWebsiteDir}/${getdown_j11lib_dir}"
 +  getdownResourceDir = string("${getdownWebsiteDir}/${getdown_resource_dir}")
 +  getdownInstallDir = string("${getdownWebsiteDir}/${getdown_install_dir}")
 +  getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
 +  getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
    /* compile without modules -- using classpath libraries
 -  modules_compileClasspath = fileTree(dir: "$jalviewDir/$j11modDir", include: ["*.jar"])
 +  modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
    modules_runtimeClasspath = modules_compileClasspath
    */
 -  gitHash = ""
 -  gitBranch = ""
 -}
 +  gitHash = string("")
 +  gitBranch = string("")
 +
 +  println("Using a ${CHANNEL} profile.")
 +
 +  additional_compiler_args = []
 +  // configure classpath/args for j8/j11 compilation
 +  if (JAVA_VERSION.equals("1.8")) {
 +    JAVA_INTEGER_VERSION = string("8")
 +    //libDir = j8libDir
 +    libDir = j11libDir
 +    libDistDir = j8libDir
 +    compile_source_compatibility = 1.8
 +    compile_target_compatibility = 1.8
 +    // these are getdown.txt properties defined dependent on the JAVA_VERSION
 +    getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
 +    getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
 +    // this property is assigned below and expanded to multiple lines in the getdown task
 +    getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
 +    // this property is for the Java library used in eclipse
 +    eclipseJavaRuntimeName = string("JavaSE-1.8")
 +  } else if (JAVA_VERSION.equals("11")) {
 +    JAVA_INTEGER_VERSION = string("11")
 +    libDir = j11libDir
 +    libDistDir = j11libDir
 +    compile_source_compatibility = 11
 +    compile_target_compatibility = 11
 +    getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
 +    getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
 +    getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
 +    eclipseJavaRuntimeName = string("JavaSE-11")
 +    /* compile without modules -- using classpath libraries
 +    additional_compiler_args += [
 +    '--module-path', modules_compileClasspath.asPath,
 +    '--add-modules', j11modules
 +    ]
 +     */
 +  } else if (JAVA_VERSION.equals("12") || JAVA_VERSION.equals("13")) {
 +    JAVA_INTEGER_VERSION = JAVA_VERSION
 +    libDir = j11libDir
 +    libDistDir = j11libDir
 +    compile_source_compatibility = JAVA_VERSION
 +    compile_target_compatibility = JAVA_VERSION
 +    getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
 +    getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
 +    getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
 +    eclipseJavaRuntimeName = string("JavaSE-11")
 +    /* compile without modules -- using classpath libraries
 +    additional_compiler_args += [
 +    '--module-path', modules_compileClasspath.asPath,
 +    '--add-modules', j11modules
 +    ]
 +     */
 +  } else {
 +    throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
 +  }
  
 -def JAVA_INTEGER_VERSION
 -def additional_compiler_args = []
 -// these are getdown.txt properties defined dependent on the JAVA_VERSION
 -def getdown_alt_java_min_version
 -def getdown_alt_java_max_version
 -// this property is assigned below and expanded to multiple lines in the getdown task
 -def getdown_alt_multi_java_location
 -// this property is for the Java library used in eclipse
 -def eclipse_java_runtime_name
 -if (JAVA_VERSION.equals("1.8")) {
 -  JAVA_INTEGER_VERSION = "8"
 -  //libDir = j8libDir
 -  libDir = j11libDir
 -  libDistDir = j8libDir
 -  compile_source_compatibility = 1.8
 -  compile_target_compatibility = 1.8
 -  getdown_alt_java_min_version = getdown_alt_java8_min_version
 -  getdown_alt_java_max_version = getdown_alt_java8_max_version
 -  getdown_alt_multi_java_location = getdown_alt_java8_txt_multi_java_location
 -  eclipse_java_runtime_name = "JavaSE-1.8"
 -} else if (JAVA_VERSION.equals("11")) {
 -  JAVA_INTEGER_VERSION = "11"
 -  libDir = j11libDir
 -  libDistDir = j11libDir
 -  compile_source_compatibility = 11
 -  compile_target_compatibility = 11
 -  getdown_alt_java_min_version = getdown_alt_java11_min_version
 -  getdown_alt_java_max_version = getdown_alt_java11_max_version
 -  getdown_alt_multi_java_location = getdown_alt_java11_txt_multi_java_location
 -  eclipse_java_runtime_name = "JavaSE-11"
 -  /* compile without modules -- using classpath libraries
 -  additional_compiler_args += [
 -  '--module-path', ext.modules_compileClasspath.asPath,
 -  '--add-modules', j11modules
 -  ]
 -  */
 -} else if (JAVA_VERSION.equals("12") || JAVA_VERSION.equals("13")) {
 -  JAVA_INTEGER_VERSION = JAVA_VERSION
 -  libDir = j11libDir
 -  libDistDir = j11libDir
 -  compile_source_compatibility = JAVA_VERSION
 -  compile_target_compatibility = JAVA_VERSION
 -  getdown_alt_java_min_version = getdown_alt_java11_min_version
 -  getdown_alt_java_max_version = getdown_alt_java11_max_version
 -  getdown_alt_multi_java_location = getdown_alt_java11_txt_multi_java_location
 -  eclipse_java_runtime_name = "JavaSE-11"
 -  /* compile without modules -- using classpath libraries
 -  additional_compiler_args += [
 -  '--module-path', ext.modules_compileClasspath.asPath,
 -  '--add-modules', j11modules
 -  ]
 -  */
 -} else {
 -  throw new GradleException("JAVA_VERSION=$JAVA_VERSION not currently supported by Jalview")
 +
 +  // for install4j
 +  JAVA_MIN_VERSION = JAVA_VERSION
 +  JAVA_MAX_VERSION = JAVA_VERSION
 +  def jreInstallsDir = string(jre_installs_dir)
 +  if (jreInstallsDir.startsWith("~/")) {
 +    jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
 +  }
 +  macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
 +  macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre-${JAVA_INTEGER_VERSION}-mac-x64.tar.gz")
 +  windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
 +  windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre-${JAVA_INTEGER_VERSION}-windows-x64.tar.gz")
 +  linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
 +  linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre-${JAVA_INTEGER_VERSION}-linux-x64.tar.gz")
 +  install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
 +  install4jConfFileName = string("jalview-install4j-conf.install4j")
 +  install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
 +  install4jHomeDir = install4j_home_dir
 +  if (install4jHomeDir.startsWith("~/")) {
 +    install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
 +  }
 +
 +
 +
 +  buildingHTML = string("${jalviewDir}/${docDir}/building.html")
 +  helpFile = string("${classesDir}/${help_dir}/help.jhm")
 +  helpParentDir = string("${jalviewDir}/${help_parent_dir}")
 +  helpSourceDir = string("${helpParentDir}/${help_dir}")
 +
 +
 +  relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
 +  jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
 +  jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
 +  if (IN_ECLIPSE) {
 +    jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
 +  } else {
 +    jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
 +  }
 +  jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
 +  jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
 +  jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
 +  jalviewjsJalviewCoreHtmlFile = string("")
 +  jalviewjsJalviewCoreName = string(jalviewjs_core_name)
 +  jalviewjsCoreClasslists = []
 +  jalviewjsJalviewTemplateName = string(jalviewjs_name)
 +  jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
 +  jalviewjsJ2sProps = null
 +
 +  eclipseWorkspace = null
 +  eclipseBinary = string("")
 +  eclipseVersion = string("")
 +  eclipseDebug = false
 +  // ENDEXT
  }
  
 -sourceSets {
  
 +sourceSets {
    main {
      java {
 -      srcDirs "$jalviewDir/$sourceDir"
 -      outputDir = file("$classes")
 +      srcDirs sourceDir
 +      outputDir = file(classesDir)
      }
  
      resources {
 -      srcDirs "$jalviewDir/$resourceDir"
 +      srcDirs resourceDir
 +      srcDirs += helpParentDir
      }
  
 -    jar.destinationDir = file("$jalviewDir/$packageDir")
 +    jar.destinationDir = file("${jalviewDir}/${packageDir}")
  
      compileClasspath = files(sourceSets.main.java.outputDir)
 -    compileClasspath += fileTree(dir: "$jalviewDir/$libDir", include: ["*.jar"])
 +    //compileClasspath += files(sourceSets.main.resources.srcDirs)
 +    compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
  
      runtimeClasspath = compileClasspath
    }
 +
    clover {
      java {
        srcDirs = [ cloverInstrDir ]
      compileClasspath = configurations.cloverRuntime + files( sourceSets.clover.java.outputDir )
      compileClasspath += files(sourceSets.main.java.outputDir)
      compileClasspath += sourceSets.main.compileClasspath
 -    compileClasspath += fileTree(dir: "$jalviewDir/$utilsDir", include: ["**/*.jar"])
 -    compileClasspath += fileTree(dir: "$jalviewDir/$libDir", include: ["*.jar"])
 +    compileClasspath += fileTree(dir: "${jalviewDir}/${utilsDir}", include: ["**/*.jar"])
 +    compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
  
      runtimeClasspath = compileClasspath
    }
  
    test {
      java {
 -      srcDirs "$jalviewDir/$testSourceDir"
 -      outputDir = file("$jalviewDir/$testOutputDir")
 +      srcDirs testSourceDir
 +      outputDir = file("${jalviewDir}/${testOutputDir}")
      }
  
      resources {
        compileClasspath += files(sourceSets.main.java.outputDir)
      }
  
 -    compileClasspath += fileTree(dir: "$jalviewDir/$utilsDir", include: ["**/*.jar"])
 -    compileClasspath += fileTree(dir: "$jalviewDir/$libDir", include: ["*.jar"])
 +    compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
 +    compileClasspath += fileTree(dir: "${jalviewDir}/${utilsDir}/testnglibs", include: ["**/*.jar"])
 +    compileClasspath += fileTree(dir: "${jalviewDir}/${utilsDir}/testlibs", include: ["**/*.jar"])
  
      runtimeClasspath = compileClasspath
    }
  }
  
 +
  // clover bits
  dependencies {
    if (use_clover) {
    }
  }
  
 +
  configurations {
    cloverRuntime
    cloverRuntime.extendsFrom cloverCompile
  
  eclipse {
    project {
 -    name = "Jalview with gradle build"
 +    name = eclipse_project_name
  
      natures 'org.eclipse.jdt.core.javanature',
      'org.eclipse.jdt.groovy.core.groovyNature',
    classpath {
      //defaultOutputDir = sourceSets.main.java.outputDir
      def removeThese = []
 -    configurations.each{ if (it.isCanBeResolved()) {
 -      removeThese += it
 +    configurations.each{
 +      if (it.isCanBeResolved()) {
 +        removeThese += it
 +      }
      }
 -  }
  
 -  minusConfigurations += removeThese
 -  plusConfigurations = [ ]
 -  file {
 +    minusConfigurations += removeThese
 +    plusConfigurations = [ ]
 +    file {
  
 -    whenMerged { cp ->
 -      def removeTheseToo = []
 -      HashMap<String, Boolean> addedSrcPath = new HashMap<>();
 -      cp.entries.each { entry ->
 -        if (entry.kind == 'src') {
 -          if (addedSrcPath.getAt(entry.path) || !(entry.path == "src" || entry.path == "test")) {
 -            removeTheseToo += entry
 -          } else {
 -            addedSrcPath.putAt(entry.path, true)
 +      whenMerged { cp ->
 +        def removeTheseToo = []
 +        HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
 +        cp.entries.each { entry ->
 +          // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
 +          // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
 +          // we add the resources and help/help dirs in as libs afterwards (see below)
 +          if (entry.kind == 'src') {
 +            if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
 +              removeTheseToo += entry
 +            } else {
 +              alreadyAddedSrcPath.putAt(entry.path, true)
 +            }
            }
 -        }
 -      }
 -      cp.entries.removeAll(removeTheseToo)
 -
 -      print ("CP="+cp.inspect())
 -
 -      cp.entries += new Output("bin/main")
 -      cp.entries += new Library(fileReference(helpParentDir))
 -      cp.entries += new Library(fileReference(resourceDir))
  
 -      HashMap<String, Boolean> addedLibPath = new HashMap<>();
 -
 -      // changing from sourcesets.main.classpath to specific Java version lib
 -      //sourceSets.main.compileClasspath.each{
 -      fileTree("$jalviewDir/$libDistDir").include("**/*.jar").include("*.jar").each {
 -        //don't want to add outputDir as eclipse is using its own output dir in bin/main
 -        if (it.isDirectory() || ! it.exists()) {
 -          // don't add dirs to classpath
 -          return
 -        }
 -        def itPath = it.toString()
 -        if (itPath.startsWith(jalviewDirAbsolutePath+"/")) {
 -          itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
 -        }
 -        if (addedLibPath.get(itPath)) {
 -          //println("Not adding duplicate entry "+itPath)
 -        } else {
 -          //println("Adding entry "+itPath)
 -          cp.entries += new Library(fileReference(itPath))
 -          addedLibPath.put(itPath, true)
          }
 -      }
 +        cp.entries.removeAll(removeTheseToo)
  
 -      // changing from sourcesets.main.classpath to specific Java version lib
 -      //sourceSets.test.compileClasspath.each{
 -      fileTree(dir: "$jalviewDir/$utilsDir", include: ["**/*.jar"]).each {
 -        //if ((it.isDirectory() || ! it.exists()) && ! (it.equals(sourceSets.main.java.outputDir))) {
 -        //no longer want to add outputDir as eclipse is using its own output dir in bin/main
 -        if (it.isDirectory() || ! it.exists()) {
 -          // don't add dirs to classpath
 -          return false // groovy "break" in .each loop
 -        }
 -        def itPath = it.toString()
 -        if (itPath.startsWith(jalviewDirAbsolutePath+"/")) {
 -          itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
 -        }
 -        if (addedLibPath.get(itPath)) {
 -          // don't duplicate
 -        } else {
 -          def lib = new Library(fileReference(itPath))
 -          // this doesn't work... yet.  Adding test=true attribute using withXml below
 -          //def attrs = new Node(null, 'attributes', ["test":"true"])
 -          //lib.appendNode(attrs) //
 -          cp.entries += lib
 -          addedLibPath.put(itPath, true)
 +        //cp.entries += new Output("${eclipse_bin_dir}/main")
 +        if (file(helpParentDir).isDirectory()) {
 +          cp.entries += new Library(fileReference(helpParentDir))
          }
 +        if (file(resourceDir).isDirectory()) {
 +          cp.entries += new Library(fileReference(resourceDir))
          }
 -      }
  
 -      // withXml changes ignored by buildship, these add the "test=true" attribute
 -      withXml {
 -        def node = it.asNode()
 +        HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
  
 -        def srcTestAttributes
 -        node.children().each{ cpe ->
 -          def attributes = cpe.attributes()
 -          if (attributes.get("kind") == "src" && attributes.get("path") == "test") {
 -            srcTestAttributes = cpe.find { a -> a.name() == "attributes" }
 -            return
 +        sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
 +          //don't want to add outputDir as eclipse is using its own output dir in bin/main
 +          if (it.isDirectory() || ! it.exists()) {
 +            // don't add dirs to classpath, especially if they don't exist
 +            return false // groovy "continue" in .any closure
            }
 -        }
 -        def addTestAttribute = true
 -        srcTestAttributes.each{a ->
 -          if (a.name() == "attribute" && a.attributes().getAt("name") == "test") {
 -            addTestAttribute = false
 +          def itPath = it.toString()
 +          if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
 +            // make relative path
 +            itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
 +          }
 +          if (alreadyAddedLibPath.get(itPath)) {
 +            //println("Not adding duplicate entry "+itPath)
 +          } else {
 +            //println("Adding entry "+itPath)
 +            cp.entries += new Library(fileReference(itPath))
 +            alreadyAddedLibPath.put(itPath, true)
            }
 -        }
 -        if (addTestAttribute) {
 -          srcTestAttributes.append(new Node(null, "attribute", [name:"test", value:"true"]))
          }
  
 -        node.children().each{ cpe ->
 -          def attributes = cpe.attributes()
 -          if (attributes.get("kind") == "lib" && attributes.get("path").startsWith("utils/")) {
 -            cpe.appendNode('attributes')
 -            .appendNode('attribute', [name:"test", value:"true"])
 +        sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
 +          //no longer want to add outputDir as eclipse is using its own output dir in bin/main
 +          if (it.isDirectory() || ! it.exists()) {
 +            // don't add dirs to classpath
 +            return false // groovy "continue" in .any closure
 +          }
 +
 +          def itPath = it.toString()
 +          if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
 +            itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
 +          }
 +          if (alreadyAddedLibPath.get(itPath)) {
 +            // don't duplicate
 +          } else {
 +            def lib = new Library(fileReference(itPath))
 +            lib.entryAttributes["test"] = "true"
 +            cp.entries += lib
 +            alreadyAddedLibPath.put(itPath, true)
            }
          }
 -      } // withXML
 +
 +      } // whenMerged
 +
      } // file
  
      containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
 +
    } // classpath
  
    jdt {
      // for the IDE, use java 11 compatibility
      sourceCompatibility = compile_source_compatibility
      targetCompatibility = compile_target_compatibility
 -    javaRuntimeName = eclipse_java_runtime_name
 +    javaRuntimeName = eclipseJavaRuntimeName
  
 +    // add in jalview project specific properties/preferences into eclipse core preferences
      file {
        withProperties { props ->
          def jalview_prefs = new Properties()
 -        def ins = new FileInputStream(jalviewDirAbsolutePath+"/"+eclipse_extra_jdt_prefs_file)
 +        def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
          jalview_prefs.load(ins)
          ins.close()
          jalview_prefs.forEach { t, v ->
          }
        }
      }
 -  }
  
 -  //synchronizationTasks eclipseClasspath
 -  //autoBuildTasks eclipseClasspath
 +  } // jdt
 +
 +  if (IN_ECLIPSE) {
 +    // Don't want these to be activated if in headless build
 +    synchronizationTasks "eclipseSynchronizationTask"
 +    autoBuildTasks "eclipseAutoBuildTask"
 +
 +  }
  }
  
 +
  task cloverInstr() {
    // only instrument source, we build test classes as normal
    inputs.files files (sourceSets.main.allJava,sourceSets.test.allJava) // , fileTree(dir:"$jalviewDir/$testSourceDir", include: ["**/*.java"]))
@@@ -589,6 -489,7 +589,6 @@@ task cloverReport 
      com.atlassian.clover.reporters.xml.XMLReporter.runReport(args)
    }
  }
 -
  // end clover bits
  
  
@@@ -603,7 -504,6 +603,7 @@@ compileJava 
  
  }
  
 +
  compileTestJava {
    if (use_clover) {
      dependsOn compileCloverJava
@@@ -631,29 -531,21 +631,29 @@@ compileCloverJava 
    classpath += configurations.cloverRuntime
  }
  
 +
  clean {
 -  delete sourceSets.main.java.outputDir
 +  doFirst {
 +    delete sourceSets.main.java.outputDir
 +  }
  }
  
 +
  cleanTest {
 -  delete sourceSets.test.java.outputDir
 -  delete cloverInstrDir
 +  doFirst {
 +    delete sourceSets.test.java.outputDir
 +    delete cloverInstrDir
 +  }
  }
  
 +
  // format is a string like date.format("dd MMMM yyyy")
  def getDate(format) {
    def date = new Date()
    return date.format(format)
  }
  
 +
  task setGitVals {
    def hashStdOut = new ByteArrayOutputStream()
    exec {
      ignoreExitValue true
    }
  
 -  project.ext.gitHash = hashStdOut.toString().trim()
 -  project.ext.gitBranch = branchStdOut.toString().trim()
 +  gitHash = hashStdOut.toString().trim()
 +  gitBranch = branchStdOut.toString().trim()
  
    outputs.upToDateWhen { false }
  }
  
 +
  task createBuildProperties(type: WriteProperties) {
    dependsOn setGitVals
 -  inputs.dir("$jalviewDir/$sourceDir")
 -  inputs.dir("$classes")
 -  inputs.dir("$jalviewDir/$resourceDir")
 +  inputs.dir(sourceDir)
 +  inputs.dir(resourceDir)
 +  file(buildProperties).getParentFile().mkdirs()
    outputFile (buildProperties)
    // taking time specific comment out to allow better incremental builds
    comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
    //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
    property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
    property "VERSION", JALVIEW_VERSION
 -  property "INSTALLATION", INSTALLATION+" git-commit:"+project.ext.gitHash+" ["+project.ext.gitBranch+"]"
 +  property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
    outputs.file(outputFile)
  }
  
 -def buildingHTML = "$jalviewDir/$docDir/building.html"
 -task deleteBuildingHTML(type: Delete) {
 -  delete buildingHTML
 +
 +task cleanBuildingHTML(type: Delete) {
 +  doFirst {
 +    delete buildingHTML
 +  }
  }
  
 +
  task convertBuildingMD(type: Exec) {
 -  dependsOn deleteBuildingHTML
 -  def buildingMD = "$jalviewDir/$docDir/building.md"
 -  def css = "$jalviewDir/$docDir/github.css"
 +  dependsOn cleanBuildingHTML
 +  def buildingMD = "${jalviewDir}/${docDir}/building.md"
 +  def css = "${jalviewDir}/${docDir}/github.css"
  
    def pandoc = null
    pandoc_exec.split(",").each {
    }
  
    def hostname = "hostname".execute().text.trim()
 -  if ((pandoc == null || ! file(pandoc).exists()) && hostname.equals("jv-bamboo")) {
 +  def buildtoolsPandoc = System.getProperty("user.home")+"/buildtools/pandoc/bin/pandoc"
 +  if ((pandoc == null || ! file(pandoc).exists()) && file(buildtoolsPandoc).exists()) {
      pandoc = System.getProperty("user.home")+"/buildtools/pandoc/bin/pandoc"
    }
  
          commandLine pandoc, '-s', '-o', buildingHTML, '--metadata', 'pagetitle="Building Jalview from Source"', '--toc', '-H', css, buildingMD
      } else {
          println("Cannot find pandoc. Skipping convert building.md to HTML")
 -        throw new StopExecutionException()
 +        throw new StopExecutionException("Cannot find pandoc. Skipping convert building.md to HTML")
      }
    }
  
    inputs.file(css)
    outputs.file(buildingHTML)
  }
 +
 +
  clean {
 -  delete buildingHTML
 +  doFirst {
 +    delete buildingHTML
 +  }
  }
  
 +
  task syncDocs(type: Sync) {
    dependsOn convertBuildingMD
 -  def syncDir = "$classes/$docDir"
 -  from fileTree("$jalviewDir/$docDir")
 +  def syncDir = "${classesDir}/${docDir}"
 +  from fileTree("${jalviewDir}/${docDir}")
    into syncDir
  
  }
  
 -def helpFile = "$classes/$helpDir/help.jhm"
  
  task copyHelp(type: Copy) {
 -  def inputDir = "$jalviewDir/$helpParentDir/$helpDir"
 -  def outputDir = "$classes/$helpDir"
 +  def inputDir = helpSourceDir
 +  def outputDir = "${classesDir}/${help_dir}"
    from(inputDir) {
      exclude '**/*.gif'
 -      exclude '**/*.jpg'
 -      exclude '**/*.png'
 -      filter(ReplaceTokens, beginToken: '$$', endToken: '$$', tokens: ['Version-Rel': JALVIEW_VERSION,'Year-Rel': getDate("yyyy")])
 +    exclude '**/*.jpg'
 +    exclude '**/*.png'
 +    filter(ReplaceTokens,
 +      beginToken: '$$',
 +      endToken: '$$',
 +      tokens: [
 +        'Version-Rel': JALVIEW_VERSION,
 +        'Year-Rel': getDate("yyyy")
 +      ]
 +    )
    }
    from(inputDir) {
      include '**/*.gif'
 -      include '**/*.jpg'
 -      include '**/*.png'
 +    include '**/*.jpg'
 +    include '**/*.png'
    }
    into outputDir
  
    outputs.dir(outputDir)
  }
  
 +
  task syncLib(type: Sync) {
 -  def syncDir = "$classes/$libDistDir"
 -  from fileTree("$jalviewDir/$libDistDir")
 +  def syncDir = "${classesDir}/${libDistDir}"
 +  from fileTree("${jalviewDir}/${libDistDir}")
    into syncDir
  }
  
 +
  task syncResources(type: Sync) {
 -  from "$jalviewDir/$resourceDir"
 +  from resourceDir
    include "**/*.*"
 -  exclude "install4j"
 -  into "$classes"
 +  into "${classesDir}"
    preserve {
      include "**"
    }
  }
  
 +
  task prepare {
    dependsOn syncResources
    dependsOn syncDocs
@@@ -827,75 -701,65 +827,75 @@@ test 
    sourceCompatibility = compile_source_compatibility
    targetCompatibility = compile_target_compatibility
    jvmArgs += additional_compiler_args
 -  print ("Setting target compatibility to "+targetCompatibility+"\n")
 +
  }
  
 +
  task buildIndices(type: JavaExec) {
    dependsOn copyHelp
    classpath = sourceSets.main.compileClasspath
    main = "com.sun.java.help.search.Indexer"
 -  workingDir = "$classes/$helpDir"
 +  workingDir = "${classesDir}/${help_dir}"
    def argDir = "html"
    args = [ argDir ]
 -  inputs.dir("$workingDir/$argDir")
 -
 -  outputs.dir("$classes/doc")
 -  outputs.dir("$classes/help")
 -  outputs.file("$workingDir/JavaHelpSearch/DOCS")
 -  outputs.file("$workingDir/JavaHelpSearch/DOCS.TAB")
 -  outputs.file("$workingDir/JavaHelpSearch/OFFSETS")
 -  outputs.file("$workingDir/JavaHelpSearch/POSITIONS")
 -  outputs.file("$workingDir/JavaHelpSearch/SCHEMA")
 -  outputs.file("$workingDir/JavaHelpSearch/TMAP")
 +  inputs.dir("${workingDir}/${argDir}")
 +
 +  outputs.dir("${classesDir}/doc")
 +  outputs.dir("${classesDir}/help")
 +  outputs.file("${workingDir}/JavaHelpSearch/DOCS")
 +  outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
 +  outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
 +  outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
 +  outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
 +  outputs.file("${workingDir}/JavaHelpSearch/TMAP")
  }
  
 +
  task compileLinkCheck(type: JavaCompile) {
    options.fork = true
 -  classpath = files("$jalviewDir/$utilsDir")
 -  destinationDir = file("$jalviewDir/$utilsDir")
 -  source = fileTree(dir: "$jalviewDir/$utilsDir", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
 -
 -  inputs.file("$jalviewDir/$utilsDir/HelpLinksChecker.java")
 -  inputs.file("$jalviewDir/$utilsDir/HelpLinksChecker.java")
 -  outputs.file("$jalviewDir/$utilsDir/HelpLinksChecker.class")
 -  outputs.file("$jalviewDir/$utilsDir/BufferedLineReader.class")
 +  classpath = files("${jalviewDir}/${utilsDir}")
 +  destinationDir = file("${jalviewDir}/${utilsDir}")
 +  source = fileTree(dir: "${jalviewDir}/${utilsDir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
 +
 +  inputs.file("${jalviewDir}/${utilsDir}/HelpLinksChecker.java")
 +  inputs.file("${jalviewDir}/${utilsDir}/HelpLinksChecker.java")
 +  outputs.file("${jalviewDir}/${utilsDir}/HelpLinksChecker.class")
 +  outputs.file("${jalviewDir}/${utilsDir}/BufferedLineReader.class")
  }
  
 -def helplinkscheckertouchfile = file("$jalviewDir/$utilsDir/HelpLinksChecker.touch")
 +
  task linkCheck(type: JavaExec) {
    dependsOn prepare, compileLinkCheck
 -  classpath = files("$jalviewDir/$utilsDir")
 +
 +  def helpLinksCheckerOutFile = file("${jalviewDir}/${utilsDir}/HelpLinksChecker.out")
 +  classpath = files("${jalviewDir}/${utilsDir}")
    main = "HelpLinksChecker"
    workingDir = jalviewDir
 -  def help = "$classes/$helpDir"
 -  args = [ "$classes/$helpDir", "-nointernet" ]
 -
 -  doLast {
 -    helplinkscheckertouchfile.createNewFile()
 -  }
 -
 -  inputs.dir("$classes/$helpDir")
 -  outputs.file(helplinkscheckertouchfile)
 +  args = [ "${classesDir}/${help_dir}", "-nointernet" ]
 +
 +  def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
 +  def errFOS = outFOS
 +  standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
 +    outFOS,
 +    standardOutput)
 +  errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
 +    outFOS,
 +    errorOutput)
 +
 +  inputs.dir("${classesDir}/${help_dir}")
 +  outputs.file(helpLinksCheckerOutFile)
  }
  
  // import the pubhtmlhelp target
 -ant.properties.basedir = "$jalviewDir"
 -ant.properties.helpBuildDir = jalviewDirAbsolutePath+"/$classes/$helpDir"
 -ant.importBuild "$utilsDir/publishHelp.xml"
 +ant.properties.basedir = "${jalviewDir}"
 +ant.properties.helpBuildDir = "${jalviewDirAbsolutePath}/${classes_dir}/${help_dir}"
 +ant.importBuild "${utilsDir}/publishHelp.xml"
  
  
  task cleanPackageDir(type: Delete) {
 -  delete fileTree("$jalviewDir/$packageDir").include("*.jar")
 +  doFirst {
 +    delete fileTree(dir: "${jalviewDir}/${packageDir}", include: "*.jar")
 +  }
  }
  
  jar {
      "Codebase": application_codebase
    }
  
 -  destinationDir = file("$jalviewDir/$packageDir")
 +  destinationDir = file("${jalviewDir}/${packageDir}")
    archiveName = rootProject.name+".jar"
  
    exclude "cache*/**"
    exclude "**/*.jar"
    exclude "**/*.jar.*"
  
 -  inputs.dir("$classes")
 -  outputs.file("$jalviewDir/$packageDir/$archiveName")
 +  inputs.dir(classesDir)
 +  outputs.file("${jalviewDir}/${packageDir}/${archiveName}")
  }
  
 +
  task copyJars(type: Copy) {
 -  from fileTree("$classes").include("**/*.jar").include("*.jar").files
 -  into "$jalviewDir/$packageDir"
 +  from fileTree(dir: classesDir, include: "**/*.jar").files
 +  into "${jalviewDir}/${packageDir}"
  }
  
 +
  // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
  task syncJars(type: Sync) {
 -  from fileTree("$jalviewDir/$libDistDir").include("**/*.jar").include("*.jar").files
 -  into "$jalviewDir/$packageDir"
 +  from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
 +  into "${jalviewDir}/${packageDir}"
    preserve {
      include jar.archiveName
    }
  }
  
 +
  task makeDist {
    group = "build"
    description = "Put all required libraries in dist"
    dependsOn cleanPackageDir
    dependsOn syncJars
    dependsOn jar
 -  outputs.dir("$jalviewDir/$packageDir")
 +  outputs.dir("${jalviewDir}/${packageDir}")
  }
  
 +
  task cleanDist {
    dependsOn cleanPackageDir
    dependsOn cleanTest
@@@ -964,7 -824,7 +964,7 @@@ shadowJar 
    if (buildDist) {
      dependsOn makeDist
    }
 -  from ("$jalviewDir/$libDistDir") {
 +  from ("${jalviewDir}/${libDistDir}") {
      include("*.jar")
    }
    manifest {
    minimize()
  }
  
 +
  task getdownWebsite() {
    group = "distribution"
    description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
      dependsOn makeDist
    }
  
 -      // clean the getdown website and files dir before creating getdown folders
 -      delete project.ext.getdownWebsiteDir
 -      delete project.ext.getdownFilesDir
 -
    def getdownWebsiteResourceFilenames = []
    def getdownTextString = ""
 -  def getdownResourceDir = project.ext.getdownResourceDir
 -  def getdownAppDir = project.ext.getdownAppDir
 +  def getdownResourceDir = getdownResourceDir
    def getdownResourceFilenames = []
  
    doFirst {
 +    // clean the getdown website and files dir before creating getdown folders
 +    delete getdownWebsiteDir
 +    delete getdownFilesDir
 +
      copy {
        from buildProperties
 -      rename(buildPropertiesFile, getdown_build_properties)
 -      into project.ext.getdownAppDir
 +      rename(build_properties_file, getdown_build_properties)
 +      into getdownAppDir
      }
 -    getdownWebsiteResourceFilenames += getdown_app_dir+"/"+getdown_build_properties
 +    getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
  
      // go through properties looking for getdown_txt_...
      def props = project.properties.sort { it.key }
 -      if (getdown_alt_java_min_version.length() > 0) {
 -              props.put("getdown_txt_java_min_version", getdown_alt_java_min_version)
 -      }
 -      if (getdown_alt_java_max_version.length() > 0) {
 -              props.put("getdown_txt_java_max_version", getdown_alt_java_max_version)
 -      }
 -      props.put("getdown_txt_multi_java_location", getdown_alt_multi_java_location)
 -
 -    props.put("getdown_txt_appbase", getdown_app_base)
 +    if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
 +      props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
 +    }
 +    if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
 +      props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
 +    }
 +    if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
 +      props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
 +    }
 +
 +    props.put("getdown_txt_appbase", getdownAppBase)
      props.each{ prop, val ->
        if (prop.startsWith("getdown_txt_") && val != null) {
          if (prop.startsWith("getdown_txt_multi_")) {
            def key = prop.substring(18)
            val.split(",").each{ v ->
 -            def line = key + " = " + v + "\n"
 +            def line = "${key} = ${v}\n"
              getdownTextString += line
            }
          } else {
                r = file(val)
              } else if (val.indexOf('/') > 0) {
                // relative path (relative to jalviewDir)
 -              r = file( jalviewDir + '/' + val )
 +              r = file( "${jalviewDir}/${val}" )
              }
              if (r.exists()) {
 -              val = getdown_resource_dir + '/' + r.getName()
 +              val = "${getdown_resource_dir}/" + r.getName()
                getdownWebsiteResourceFilenames += val
                getdownResourceFilenames += r.getPath()
              }
            }
            if (! prop.startsWith("getdown_txt_resource")) {
 -            def line = prop.substring(12) + " = " + val + "\n"
 +            def line = prop.substring(12) + " = ${val}\n"
              getdownTextString += line
            }
          }
      }
  
      getdownWebsiteResourceFilenames.each{ filename ->
 -      getdownTextString += "resource = "+filename+"\n"
 +      getdownTextString += "resource = ${filename}\n"
      }
      getdownResourceFilenames.each{ filename ->
        copy {
          from filename
 -        into project.ext.getdownResourceDir
 +        into getdownResourceDir
        }
      }
  
        }
      }
      codeFiles.sort().each{f ->
 -      def line = "code = " + getdown_app_dir + '/' + f.getName() + "\n"
 +      def name = f.getName()
 +      def line = "code = ${getdownAppDistDir}/${name}\n"
        getdownTextString += line
        copy {
          from f.getPath()
 -        into project.ext.getdownAppDir
 +        into getdownAppDir
        }
      }
  
      // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
      /*
      if (JAVA_VERSION.equals("11")) {
 -    def j11libFiles = fileTree(dir: "$jalviewDir/$j11libDir", include: ["*.jar"]).getFiles()
 +    def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
      j11libFiles.sort().each{f ->
 -    def line = "code = " + getdown_j11lib_dir + '/' + f.getName() + "\n"
 +    def name = f.getName()
 +    def line = "code = ${getdown_j11lib_dir}/${name}\n"
      getdownTextString += line
      copy {
      from f.getPath()
 -    into project.ext.getdownJ11libDir
 +    into getdownJ11libDir
      }
      }
      }
  
      // getdown-launcher.jar should not be in main application class path so the main application can move it when updated.  Listed as a resource so it gets updated.
      //getdownTextString += "class = " + file(getdownLauncher).getName() + "\n"
 -    getdownTextString += "resource = " + getdown_launcher_new + "\n"
 -    getdownTextString += "class = " + mainClass + "\n"
 +    getdownTextString += "resource = ${getdown_launcher_new}\n"
 +    getdownTextString += "class = ${mainClass}\n"
  
 -    def getdown_txt = file(project.ext.getdownWebsiteDir + "/getdown.txt")
 +    def getdown_txt = file("${getdownWebsiteDir}/getdown.txt")
      getdown_txt.write(getdownTextString)
  
 -    def launch_jvl = file(project.ext.getdownWebsiteDir + "/" + getdown_launch_jvl)
 -    launch_jvl.write("appbase="+props.get("getdown_txt_appbase"))
 +    def getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
 +    def launchJvl = file("${getdownWebsiteDir}/${getdownLaunchJvl}")
 +    launchJvl.write("appbase="+props.get("getdown_txt_appbase"))
  
      copy {
        from getdownLauncher
        rename(file(getdownLauncher).getName(), getdown_launcher_new)
 -      into project.ext.getdownWebsiteDir
 +      into getdownWebsiteDir
      }
  
      copy {
        if (file(getdownLauncher).getName() != getdown_launcher) {
          rename(file(getdownLauncher).getName(), getdown_launcher)
        }
 -      into project.ext.getdownWebsiteDir
 +      into getdownWebsiteDir
      }
  
      if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
        copy {
          from getdown_txt
          from getdownLauncher
 -        from getdownWebsiteDir+"/"+getdown_build_properties
 +        from "${getdownWebsiteDir}/${getdown_build_properties}"
          if (file(getdownLauncher).getName() != getdown_launcher) {
            rename(file(getdownLauncher).getName(), getdown_launcher)
          }
  
      copy {
        from getdown_txt
 -      from launch_jvl
 +      from launchJvl
        from getdownLauncher
 -      from getdownWebsiteDir+"/"+getdown_build_properties
 +      from "${getdownWebsiteDir}/${getdown_build_properties}"
        if (file(getdownLauncher).getName() != getdown_launcher) {
          rename(file(getdownLauncher).getName(), getdown_launcher)
        }
      }
  
      copy {
 -        from getdownResourceDir
 -      into project.ext.getdownFilesDir + '/' + getdown_resource_dir
 +      from getdownResourceDir
 +      into "${getdownFilesDir}/${getdown_resource_dir}"
      }
    }
  
    if (buildDist) {
 -    inputs.dir(jalviewDir + '/' + packageDir)
 +    inputs.dir("${jalviewDir}/${packageDir}")
 +  }
 +  outputs.dir(getdownWebsiteDir)
 +  outputs.dir(getdownFilesDir)
 +}
 +
 +
 +// a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
 +task getdownDigestDir(type: JavaExec) {
 +  def digestDirPropertyName = "DIGESTDIR"
 +  description = "Digest a local dir (-P${digestDirPropertyName}=...) for getdown"
 +  doFirst {
 +    classpath = files(getdownLauncher)
 +    def digestDir = findProperty(digestDirPropertyName)
 +    if (digestDir == null) {
 +      throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
 +    }
 +    args digestDir
    }
 -  outputs.dir(project.ext.getdownWebsiteDir)
 -  outputs.dir(project.ext.getdownFilesDir)
 +  main = "com.threerings.getdown.tools.Digester"
  }
  
 +
  task getdownDigest(type: JavaExec) {
    group = "distribution"
    description = "Digest the getdown website folder"
    dependsOn getdownWebsite
    doFirst {
 -    classpath = files(getdownWebsiteDir + '/' + getdown_launcher)
 +    classpath = files(getdownLauncher)
    }
    main = "com.threerings.getdown.tools.Digester"
 -  args project.ext.getdownWebsiteDir
 -  inputs.dir(project.ext.getdownWebsiteDir)
 -  outputs.file(project.ext.getdownWebsiteDir + '/' + "digest2.txt")
 +  args getdownWebsiteDir
 +  inputs.dir(getdownWebsiteDir)
 +  outputs.file("${getdownWebsiteDir}/digest2.txt")
  }
  
 +
  task getdown() {
    group = "distribution"
    description = "Create the minimal and full getdown app folder for installers and website and create digest file"
    dependsOn getdownDigest
    doLast {
      if (reportRsyncCommand) {
 -      def fromDir = getdownWebsiteDir + (getdownWebsiteDir.endsWith("/")?"":"/")
 -      def toDir = getdown_rsync_dest + "/" + getdownDir + (getdownDir.endsWith("/")?"":"/")
 +      def fromDir = getdownWebsiteDir + (getdownWebsiteDir.endsWith('/')?'':'/')
 +      def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
        println "LIKELY RSYNC COMMAND:"
        println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
        if (RUNRSYNC == "true") {
    }
  }
  
 +
  clean {
 -  delete project.ext.getdownWebsiteDir
 -  delete project.ext.getdownFilesDir
 +  doFirst {
 +    delete getdownWebsiteDir
 +    delete getdownFilesDir
 +  }
  }
  
 +
  install4j {
 -  def install4jHomeDir = "/opt/install4j"
 -  def hostname = "hostname".execute().text.trim()
 -  if (hostname.equals("jv-bamboo")) {
 +  if (file(install4jHomeDir).exists()) {
 +    // good to go!
 +  } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
      install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
 -  } else if (OperatingSystem.current().isMacOsX()) {
 -    install4jHomeDir = '/Applications/install4j.app/Contents/Resources/app'
 -    if (! file(install4jHomeDir).exists()) {
 -      install4jHomeDir = System.getProperty("user.home")+install4jHomeDir
 -    }
 -  } else if (OperatingSystem.current().isLinux()) {
 -    install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
 -  }
 -  installDir = file(install4jHomeDir)
 -  mediaTypes = Arrays.asList(install4jMediaTypes.split(","))
 -  if (install4jFaster.equals("true")) {
 -    faster = true
 +  } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
 +    install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
    }
 +  installDir(file(install4jHomeDir))
 +
 +  mediaTypes = Arrays.asList(install4j_media_types.split(","))
  }
  
 -def install4jConf
 -def macosJavaVMDir
 -def macosJavaVMTgz
 -def windowsJavaVMDir
 -def windowsJavaVMTgz
 -def install4jDir = "$jalviewDir/$install4jResourceDir"
 -def install4jConfFile = "jalview-installers-java"+JAVA_VERSION+".install4j"
 -install4jConf = "$install4jDir/$install4jConfFile"
 -
 -task copyInstall4jTemplate(type: Copy) {
 -  macosJavaVMDir = System.env.HOME+"/buildtools/jre/openjdk-java_vm/getdown/macos-jre"+JAVA_VERSION+"/jre"
 -  macosJavaVMTgz = System.env.HOME+"/buildtools/jre/openjdk-java_vm/install4j/tgz/macos-jre"+JAVA_VERSION+".tar.gz"
 -  windowsJavaVMDir = System.env.HOME+"/buildtools/jre/openjdk-java_vm/getdown/windows-jre"+JAVA_VERSION+"/jre"
 -  windowsJavaVMTgz = System.env.HOME+"/buildtools/jre/openjdk-java_vm/install4j/tgz/windows-jre"+JAVA_VERSION+".tar.gz"
 -  from (install4jDir) {
 -    include install4jTemplate
 -    rename (install4jTemplate, install4jConfFile)
 -    filter(ReplaceTokens, beginToken: '', endToken: '', tokens: ['9999999999': JAVA_VERSION])
 -    filter(ReplaceTokens, beginToken: '$$', endToken: '$$',
 -    tokens: [
 -    'JAVA_VERSION': JAVA_VERSION,
 -    'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
 -    'VERSION': JALVIEW_VERSION,
 -    'MACOS_JAVA_VM_DIR': macosJavaVMDir,
 -    'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
 -    'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
 -    'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
 -    'INSTALL4JINFOPLISTFILEASSOCIATIONS': install4jInfoPlistFileAssociations,
 -    'COPYRIGHT_MESSAGE': install4jCopyrightMessage,
 -    'MACOS_BUNDLE_ID': install4jMacOSBundleId,
 -    'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
 -    'GETDOWN_DIST_DIR': getdown_app_dir,
 -    'GETDOWN_ALT_DIR': getdown_app_dir_alt,
 -    'GETDOWN_INSTALL_DIR': getdown_install_dir
 -    ]
 -    )
 -    if (OSX_KEYPASS=="") {
 -      filter(ReplaceTokens, beginToken: 'codeSigning macEnabled="', endToken: '"', tokens: ['true':'codeSigning macEnabled="false"'])
 -      filter(ReplaceTokens, beginToken: 'runPostProcessor="true" ',endToken: 'Processor', tokens: ['post':'runPostProcessor="false" postProcessor'])
 +
 +task copyInstall4jTemplate {
 +  def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
 +  def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
 +  inputs.file(install4jTemplateFile)
 +  inputs.file(install4jFileAssociationsFile)
 +  outputs.file(install4jConfFile)
 +
 +  doLast {
 +    def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
 +
 +    // turn off code signing if no OSX_KEYPASS
 +    if (OSX_KEYPASS == "") {
 +      install4jConfigXml.'**'.codeSigning.each { codeSigning ->
 +        codeSigning.'@macEnabled' = "false"
 +      }
 +      install4jConfigXml.'**'.windows.each { windows ->
 +        windows.'@runPostProcessor' = "false"
 +      }
 +    }
 +
 +    // turn off checksum creation for LOCAL channel
 +    def e = install4jConfigXml.application[0]
 +    if (CHANNEL == "LOCAL") {
 +      e.'@createChecksums' = "false"
 +    } else {
 +      e.'@createChecksums' = "true"
      }
 +
 +    // put file association actions where placeholder action is
 +    def install4jFileAssociationsText = install4jFileAssociationsFile.text
 +    def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
 +    install4jConfigXml.'**'.action.any { a ->
 +      if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
 +        def parent = a.parent()
 +        parent.remove(a)
 +        fileAssociationActions.each { faa ->
 +            parent.append(faa)
 +        }
 +        // don't need to continue in .any loop once replacements have been made
 +        return true
 +      }
 +    }
 +
 +    // write install4j file
 +    install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
    }
 -  into install4jDir
 -  outputs.files(install4jConf)
 +}
  
 -  doLast {
 -    // include file associations in installer
 -    def installerFileAssociationsXml = file("$install4jDir/$install4jInstallerFileAssociations").text
 -    ant.replaceregexp(
 -      byline: false,
 -      flags: "s",
 -      match: '<action name="EXTENSIONS_REPLACED_BY_GRADLE".*?</action>',
 -      replace: installerFileAssociationsXml,
 -      file: install4jConf
 -    )
 -    /*
 -    // include uninstaller applescript app files in dmg
 -    def installerDMGUninstallerXml = file("$install4jDir/$install4jDMGUninstallerAppFiles").text
 -    ant.replaceregexp(
 -    byline: false,
 -    flags: "s",
 -    match: '<file name="UNINSTALL_OLD_JALVIEW_APP_REPLACED_IN_GRADLE" file=.*?>',
 -    replace: installerDMGUninstallerXml,
 -    file: install4jConf
 -    )
 -     */
 +
 +clean {
 +  doFirst {
 +    delete install4jConfFile
    }
  }
  
 +
  task installers(type: com.install4j.gradle.Install4jTask) {
    group = "distribution"
    description = "Create the install4j installers"
 +  dependsOn setGitVals
    dependsOn getdown
    dependsOn copyInstall4jTemplate
 -  projectFile = file(install4jConf)
 -  println("Using projectFile "+projectFile)
 -  variables = [majorVersion: version.substring(2, 11), build: 001, OSX_KEYSTORE: OSX_KEYSTORE, JSIGN_SH: JSIGN_SH]
 -  destination = "$jalviewDir/$install4jBuildDir/$JAVA_VERSION"
 +
 +  projectFile = install4jConfFile
 +
 +  // create an md5 for the input files to use as version for install4j conf file
 +  def digest = MessageDigest.getInstance("MD5")
 +  digest.update(
 +    (file("${install4jDir}/${install4j_template}").text + 
 +    file("${install4jDir}/${install4j_info_plist_file_associations}").text +
 +    file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
 +  def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
 +  if (filesMd5.length() >= 8) {
 +    filesMd5 = filesMd5.substring(0,8)
 +  }
 +  def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
 +  // make install4jBuildDir relative to jalviewDir
 +  def install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
 +
 +  variables = [
 +    'JALVIEW_NAME': getdown_txt_title,
 +    'JALVIEW_DIR': "../..",
 +    'OSX_KEYSTORE': OSX_KEYSTORE,
 +    'JSIGN_SH': JSIGN_SH,
 +    'JRE_DIR': getdown_app_dir_java,
 +    'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
 +    'JALVIEW_VERSION': JALVIEW_VERSION,
 +    'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
 +    'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
 +    'JAVA_VERSION': JAVA_VERSION,
 +    'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
 +    'VERSION': JALVIEW_VERSION,
 +    'MACOS_JAVA_VM_DIR': macosJavaVMDir,
 +    'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
 +    'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
 +    'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
 +    'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
 +    'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
 +    'COPYRIGHT_MESSAGE': install4j_copyright_message,
 +    'MACOS_BUNDLE_ID': install4j_macOS_bundle_id,
 +    'INSTALLER_NAME': install4j_installer_name,
 +    'INSTALL4J_UTILS_DIR': install4j_utils_dir,
 +    'GETDOWN_WEBSITE_DIR': getdown_website_dir,
 +    'GETDOWN_FILES_DIR': getdown_files_dir,
 +    'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
 +    'GETDOWN_DIST_DIR': getdownAppDistDir,
 +    'GETDOWN_ALT_DIR': getdown_app_dir_alt,
 +    'GETDOWN_INSTALL_DIR': getdown_install_dir,
 +    'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
 +    'BUILD_DIR': install4jBuildDir,
 +  ]
 +
 +  destination = "${jalviewDir}/${install4jBuildDir}"
    buildSelected = true
  
 +  if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
 +    faster = true
 +    disableSigning = true
 +  }
 +
    if (OSX_KEYPASS) {
 -    macKeystorePassword=OSX_KEYPASS
 +    macKeystorePassword = OSX_KEYPASS
 +  }
  
 +  doFirst {
 +    println("Using projectFile "+projectFile)
    }
  
 -  inputs.dir(project.ext.getdownWebsiteDir)
 -  inputs.file(install4jConf)
 +  inputs.dir(getdownWebsiteDir)
 +  inputs.file(install4jConfFile)
 +  inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
    inputs.dir(macosJavaVMDir)
    inputs.dir(windowsJavaVMDir)
 -  outputs.dir("$jalviewDir/$install4jBuildDir/$JAVA_VERSION")
 -
 +  outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
  }
  
 -clean {
 -  delete install4jConf
 -}
  
 -task sourceDist (type: Tar) {
 +task sourceDist(type: Tar) {
    
    def VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
 -  def outputFileName = project.name + "_" + VERSION_UNDERSCORES + ".tar.gz"
 +  def outputFileName = "${project.name}_${VERSION_UNDERSCORES}.tar.gz"
    // cater for buildship < 3.1 [3.0.1 is max version in eclipse 2018-09]
    try {
      archiveFileName = outputFileName
    
    into project.name
  
-   def EXCLUDE_FILES=["build/*","bin/*","test-output/","test-reports","tests","clover*/*"
-   ,".*"
-   ,"benchmarking/*"
-   ,"**/.*"
-   ,"*.class"
-   ,"**/*.class","${j11modDir}/**/*.jar","appletlib","**/*locales"
-   ,"*locales/**",
-   ,"utils/InstallAnywhere"] 
-   def PROCESS_FILES=[   "AUTHORS",
-   "CITATION",
-   "FEATURETODO",
-   "JAVA-11-README",
-   "FEATURETODO",
-   "LICENSE",
-   "**/README",
-   "RELEASE",
-   "THIRDPARTYLIBS","TESTNG",
-   "build.gradle",
-   "gradle.properties",
-   "**/*.java",
-   "**/*.html",
-   "**/*.xml",
-   "**/*.gradle",
-   "**/*.groovy",
-   "**/*.properties",
-   "**/*.perl",
-   "**/*.sh"]
+   def EXCLUDE_FILES=[
+     "build/*",
+     "bin/*",
+     "test-output/",
+     "test-reports",
+     "tests",
+     "clover*/*",
+     ".*",
+     "benchmarking/*",
+     "**/.*",
+     "*.class",
+     "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
+     "*locales/**",
+     "utils/InstallAnywhere",
+     "**/*.log",
+   ] 
+   def PROCESS_FILES=[
+     "AUTHORS",
+     "CITATION",
+     "FEATURETODO",
+     "JAVA-11-README",
+     "FEATURETODO",
+     "LICENSE",
+     "**/README",
+     "RELEASE",
+     "THIRDPARTYLIBS",
+     "TESTNG",
+     "build.gradle",
+     "gradle.properties",
+     "**/*.java",
+     "**/*.html",
+     "**/*.xml",
+     "**/*.gradle",
+     "**/*.groovy",
+     "**/*.properties",
+     "**/*.perl",
+     "**/*.sh",
+   ]
+   def INCLUDE_FILES=[
+     ".settings/org.eclipse.jdt.core.jalview.prefs",
+   ]
  
    from(jalviewDir) {
      exclude (EXCLUDE_FILES)
      include (PROCESS_FILES)
 -    filter(ReplaceTokens, beginToken: '$$', endToken: '$$', tokens: ['Version-Rel': JALVIEW_VERSION,'Year-Rel': getDate("yyyy")])
 +    filter(ReplaceTokens,
 +      beginToken: '$$',
 +      endToken: '$$',
 +      tokens: [
 +        'Version-Rel': JALVIEW_VERSION,
 +        'Year-Rel': getDate("yyyy")
 +      ]
 +    )
    }
    from(jalviewDir) {
      exclude (EXCLUDE_FILES)
      exclude (getdown_website_dir)
  
      // exluding these as not using jars as modules yet
-     exclude ("${j11modDir}/**/*.jar")
-   }
-   //  from (jalviewDir) {
-   //    // explicit includes for stuff that seemed to not get included
-   //    include(fileTree("test/**/*."))
-   //    exclude(EXCLUDE_FILES)
-   //    exclude(PROCESS_FILES)
-   //  }
+     exclude ("$j11modDir/**/*.jar")
+   }
+   from(jalviewDir) {
+     include(INCLUDE_FILES)
+   }
+ //  from (jalviewDir) {
+ //    // explicit includes for stuff that seemed to not get included
+ //    include(fileTree("test/**/*."))
+ //    exclude(EXCLUDE_FILES)
+ //    exclude(PROCESS_FILES)
+ //  }
  }
  
 -task helppages  {
 +
 +task helppages {
    dependsOn copyHelp
    dependsOn pubhtmlhelp
    
 -  inputs.dir("$classes/$helpDir")
 -  outputs.dir("$helpOutputDir")
 +  inputs.dir("${classesDir}/${help_dir}")
 +  outputs.dir("${buildDir}/distributions/${help_dir}")
  }
 +
 +// LARGE AMOUNT OF JALVIEWJS STUFF DELETED HERE
 +task eclipseAutoBuildTask {}
 +task eclipseSynchronizationTask {}