+ installDir(file(install4jHomeDir))
+
+ mediaTypes = Arrays.asList(install4j_media_types.split(","))
+}
+
+
+task copyInstall4jTemplate {
+ def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
+ def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
+ inputs.file(install4jTemplateFile)
+ inputs.file(install4jFileAssociationsFile)
+ inputs.property("CHANNEL", { CHANNEL })
+ 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"
+ }
+ }
+
+ // disable install screen for OSX dmg (for 2.11.2.0)
+ install4jConfigXml.'**'.macosArchive.each { macosArchive ->
+ macosArchive.attributes().remove('executeSetupApp')
+ macosArchive.attributes().remove('setupAppId')
+ }
+
+ // turn off checksum creation for LOCAL channel
+ def e = install4jConfigXml.application[0]
+ e.'@createChecksums' = string(install4jCheckSums)
+
+ // put file association actions where placeholder action is
+ def install4jFileAssociationsText = install4jFileAssociationsFile.text
+ def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
+ install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
+ 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
+ }
+ }
+
+ // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
+ // NB we're deleting the /other/ one!
+ // Also remove the examples subdir from non-release versions
+ def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
+ // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
+ if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
+ customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
+ } else {
+ // remove the examples subdir from Full File Set
+ def files = install4jConfigXml.files[0]
+ def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
+ def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
+ def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
+ def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
+ dirEntry.parent().remove(dirEntry)
+ }
+ install4jConfigXml.'**'.action.any { a ->
+ if (a.'@customizedId' == customizedIdToDelete) {
+ def parent = a.parent()
+ parent.remove(a)
+ return true
+ }
+ }
+
+ // write install4j file
+ install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
+ }
+}
+
+
+clean {
+ doFirst {
+ delete install4jConfFile
+ }
+}
+
+task cleanInstallersDataFiles {
+ def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
+ def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
+ def hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
+ doFirst {
+ delete installersOutputTxt
+ delete installersSha256
+ delete hugoDataJsonFile
+ }
+}
+
+task installerFiles(type: com.install4j.gradle.Install4jTask) {
+ group = "distribution"
+ description = "Create the install4j installers"
+ dependsOn getdown
+ dependsOn copyInstall4jTemplate
+ dependsOn cleanInstallersDataFiles
+
+ 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}"
+
+ variables = [
+ 'JALVIEW_NAME': jalview_name,
+ 'JALVIEW_APPLICATION_NAME': applicationName,
+ 'JALVIEW_DIR': "../..",
+ 'OSX_KEYSTORE': OSX_KEYSTORE,
+ 'OSX_APPLEID': OSX_APPLEID,
+ 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
+ '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,
+ 'BUNDLE_ID': install4jBundleId,
+ 'INTERNAL_ID': install4jInternalId,
+ 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
+ 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
+ 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
+ 'WRAPPER_LINK': getdownWrapperLink,
+ 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
+ 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
+ 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
+ 'INSTALLER_NAME': install4jInstallerName,
+ 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
+ 'GETDOWN_CHANNEL_DIR': getdownChannelDir,
+ '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,
+ 'APPLICATION_CATEGORIES': install4j_application_categories,
+ 'APPLICATION_FOLDER': install4jApplicationFolder,
+ 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
+ 'EXECUTABLE_NAME': install4jExecutableName,
+ 'EXTRA_SCHEME': install4jExtraScheme,
+ 'MAC_ICONS_FILE': install4jMacIconsFile,
+ 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
+ 'PNG_ICON_FILE': install4jPngIconFile,
+ 'BACKGROUND': install4jBackground,
+
+ ]
+
+ //println("INSTALL4J VARIABLES:")
+ //variables.each{k,v->println("${k}=${v}")}
+
+ destination = "${jalviewDir}/${install4jBuildDir}"
+ buildSelected = true
+
+ if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
+ faster = true
+ disableSigning = true
+ disableNotarization = true
+ }
+
+ if (OSX_KEYPASS) {
+ macKeystorePassword = OSX_KEYPASS
+ }
+
+ if (OSX_ALTOOLPASS) {
+ appleIdPassword = OSX_ALTOOLPASS
+ disableNotarization = false
+ } else {
+ disableNotarization = true
+ }
+
+ doFirst {
+ println("Using projectFile "+projectFile)
+ if (!disableNotarization) { println("Will notarize OSX App DMG") }
+ }
+ //verbose=true
+
+ inputs.dir(getdownAppBaseDir)
+ inputs.file(install4jConfFile)
+ inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
+ inputs.dir(macosJavaVMDir)
+ inputs.dir(windowsJavaVMDir)
+ outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
+}
+
+def getDataHash(File myFile) {
+ HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
+ return myFile.exists()
+ ? [
+ "file" : myFile.getName(),
+ "filesize" : myFile.length(),
+ "sha256" : hash.toString()
+ ]
+ : null
+}
+
+def writeDataJsonFile(File installersOutputTxt, File installersSha256, File dataJsonFile) {
+ def hash = [
+ "channel" : getdownChannelName,
+ "date" : getDate("yyyy-MM-dd HH:mm:ss"),
+ "git-commit" : "${gitHash} [${gitBranch}]",
+ "version" : JALVIEW_VERSION
+ ]
+ // install4j installer files
+ if (installersOutputTxt.exists()) {
+ def idHash = [:]
+ installersOutputTxt.readLines().each { def line ->
+ if (line.startsWith("#")) {
+ return;
+ }
+ line.replaceAll("\n","")
+ def vals = line.split("\t")
+ def filename = vals[3]
+ def filesize = file(filename).length()
+ filename = filename.replaceAll(/^.*\//, "")
+ hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
+ idHash."${filename}" = vals[0]
+ }
+ if (install4jCheckSums && installersSha256.exists()) {
+ installersSha256.readLines().each { def line ->
+ if (line.startsWith("#")) {
+ return;
+ }
+ line.replaceAll("\n","")
+ def vals = line.split(/\s+\*?/)
+ def filename = vals[1]
+ def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
+ }
+ }
+ }
+
+ [
+ "JAR": shadowJar.archiveFile, // executable JAR
+ "JVL": getdownVersionLaunchJvl, // version JVL
+ "SOURCE": sourceDist.archiveFile // source TGZ
+ ].each { key, value ->
+ def file = file(value)
+ if (file.exists()) {
+ def fileHash = getDataHash(file)
+ if (fileHash != null) {
+ hash."${key}" = fileHash;
+ }
+ }
+ }
+ return dataJsonFile.write(new JsonBuilder(hash).toPrettyString())
+}
+
+task staticMakeInstallersJsonFile {
+ doFirst {
+ def output = findProperty("i4j_output")
+ def sha256 = findProperty("i4j_sha256")
+ def json = findProperty("i4j_json")
+ if (output == null || sha256 == null || json == null) {
+ throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
+ }
+ writeDataJsonFile(file(output), file(sha256), file(json))
+ }
+}
+
+task installers {
+ dependsOn installerFiles
+}
+
+
+spotless {
+ java {
+ eclipse().configFile(eclipse_codestyle_file)
+ }
+}
+
+task createSourceReleaseProperties(type: WriteProperties) {
+ group = "distribution"
+ description = "Create the source RELEASE properties file"
+
+ def sourceTarBuildDir = "${buildDir}/sourceTar"
+ def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
+ outputFile (sourceReleasePropertiesFile)
+
+ doFirst {
+ releaseProps.each{ key, val -> property key, val }
+ property "git.branch", gitBranch
+ property "git.hash", gitHash
+ }
+
+ outputs.file(outputFile)
+}
+
+task sourceDist(type: Tar) {
+ group "distribution"
+ description "Create a source .tar.gz file for distribution"
+
+ dependsOn createBuildProperties
+ dependsOn convertMdFiles
+ dependsOn eclipseAllPreferences
+ dependsOn createSourceReleaseProperties
+
+
+ def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
+ archiveFileName = outputFileName