1 /* Convention for properties. Read from gradle.properties, use lower_case_underlines for property names.
2 * For properties set within build.gradle, use camelCaseNoSpace.
4 import org.apache.tools.ant.filters.ReplaceTokens
5 import org.gradle.internal.os.OperatingSystem
6 import org.gradle.plugins.ide.internal.generator.PropertiesPersistableConfigurationObject
7 import org.gradle.api.internal.PropertiesTransformer
8 import org.gradle.util.ConfigureUtil
9 import org.gradle.plugins.ide.eclipse.model.Output
10 import org.gradle.plugins.ide.eclipse.model.Library
11 import java.security.MessageDigest
12 import groovy.transform.ExternalizeMethods
13 import groovy.util.XmlParser
14 import groovy.xml.XmlUtil
15 import groovy.json.JsonBuilder
16 import com.vladsch.flexmark.util.ast.Node
17 import com.vladsch.flexmark.html.HtmlRenderer
18 import com.vladsch.flexmark.parser.Parser
19 import com.vladsch.flexmark.util.data.MutableDataSet
20 import com.vladsch.flexmark.ext.gfm.tasklist.TaskListExtension
21 import com.vladsch.flexmark.ext.tables.TablesExtension
22 import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension
23 import com.vladsch.flexmark.ext.autolink.AutolinkExtension
24 import com.vladsch.flexmark.ext.anchorlink.AnchorLinkExtension
25 import com.vladsch.flexmark.ext.toc.TocExtension
26 import com.google.common.hash.HashCode
27 import com.google.common.hash.Hashing
28 import com.google.common.io.Files
36 classpath "com.vladsch.flexmark:flexmark-all:0.62.0"
45 id "com.diffplug.gradle.spotless" version "3.28.0"
46 id 'com.github.johnrengelman.shadow' version '4.0.3'
47 id 'com.install4j.gradle' version '9.0.6'
48 id 'com.dorongold.task-tree' version '1.5' // only needed to display task dependency tree with gradle task1 [task2 ...] taskTree
49 id 'com.palantir.git-version' version '0.13.0' apply false
60 // in ext the values are cast to Object. Ensure string values are cast as String (and not GStringImpl) for later use
61 def string(Object o) {
62 return o == null ? "" : o.toString()
65 def overrideProperties(String propsFileName, boolean output = false) {
66 if (propsFileName == null) {
69 def propsFile = file(propsFileName)
70 if (propsFile != null && propsFile.exists()) {
71 println("Using properties from file '${propsFileName}'")
73 def p = new Properties()
74 def localPropsFIS = new FileInputStream(propsFile)
80 if (project.hasProperty(key)) {
81 oldval = project.findProperty(key)
82 project.setProperty(key, val)
84 println("Overriding property '${key}' ('${oldval}') with ${file(propsFile).getName()} value '${val}'")
87 ext.setProperty(key, val)
89 println("Setting ext property '${key}' with ${file(propsFile).getName()}s value '${val}'")
93 } catch (Exception e) {
94 println("Exception reading local.properties")
101 jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath()
102 jalviewDirRelativePath = jalviewDir
105 getdownChannelName = CHANNEL.toLowerCase()
106 // default to "default". Currently only has different cosmetics for "develop", "release", "default"
107 propertiesChannelName = ["develop", "release", "test-release", "jalviewjs", "jalviewjs-release" ].contains(getdownChannelName) ? getdownChannelName : "default"
108 // Import channel_properties
109 channelDir = string("${jalviewDir}/${channel_properties_dir}/${propertiesChannelName}")
110 channelGradleProperties = string("${channelDir}/channel_gradle.properties")
111 channelPropsFile = string("${channelDir}/${resource_dir}/${channel_props}")
112 overrideProperties(channelGradleProperties, false)
113 // local build environment properties
114 // can be "projectDir/local.properties"
115 overrideProperties("${projectDir}/local.properties", true)
116 // or "../projectDir_local.properties"
117 overrideProperties(projectDir.getParent() + "/" + projectDir.getName() + "_local.properties", true)
120 // Import releaseProps from the RELEASE file
121 // or a file specified via JALVIEW_RELEASE_FILE if defined
122 // Expect jalview.version and target release branch in jalview.release
123 releaseProps = new Properties();
124 def releasePropFile = findProperty("JALVIEW_RELEASE_FILE");
125 def defaultReleasePropFile = "${jalviewDirAbsolutePath}/RELEASE";
127 (new File(releasePropFile!=null ? releasePropFile : defaultReleasePropFile)).withInputStream {
128 releaseProps.load(it)
130 } catch (Exception fileLoadError) {
131 throw new Error("Couldn't load release properties file "+(releasePropFile==null ? defaultReleasePropFile : "from custom location: releasePropFile"),fileLoadError);
134 // Set JALVIEW_VERSION if it is not already set
135 if (findProperty("JALVIEW_VERSION")==null || "".equals(JALVIEW_VERSION)) {
136 JALVIEW_VERSION = releaseProps.get("jalview.version")
139 // this property set when running Eclipse headlessly
140 j2sHeadlessBuildProperty = string("net.sf.j2s.core.headlessbuild")
141 // this property set by Eclipse
142 eclipseApplicationProperty = string("eclipse.application")
143 // CHECK IF RUNNING FROM WITHIN ECLIPSE
144 def eclipseApplicationPropertyVal = System.properties[eclipseApplicationProperty]
145 IN_ECLIPSE = eclipseApplicationPropertyVal != null && eclipseApplicationPropertyVal.startsWith("org.eclipse.ui.")
146 // BUT WITHOUT THE HEADLESS BUILD PROPERTY SET
147 if (System.properties[j2sHeadlessBuildProperty].equals("true")) {
148 println("Setting IN_ECLIPSE to ${IN_ECLIPSE} as System.properties['${j2sHeadlessBuildProperty}'] == '${System.properties[j2sHeadlessBuildProperty]}'")
152 println("WITHIN ECLIPSE IDE")
154 println("HEADLESS BUILD")
157 J2S_ENABLED = (project.hasProperty('j2s.compiler.status') && project['j2s.compiler.status'] != null && project['j2s.compiler.status'] == "enable")
159 println("J2S ENABLED")
162 System.properties.sort { it.key }.each {
163 key, val -> println("SYSTEM PROPERTY ${key}='${val}'")
166 if (false && IN_ECLIPSE) {
167 jalviewDir = jalviewDirAbsolutePath
172 buildDate = new Date().format("yyyyMMdd")
175 bareSourceDir = string(source_dir)
176 sourceDir = string("${jalviewDir}/${bareSourceDir}")
177 resourceDir = string("${jalviewDir}/${resource_dir}")
178 bareTestSourceDir = string(test_source_dir)
179 testDir = string("${jalviewDir}/${bareTestSourceDir}")
181 classesDir = string("${jalviewDir}/${classes_dir}")
184 useClover = clover.equals("true")
185 cloverBuildDir = "${buildDir}/clover"
186 cloverInstrDir = file("${cloverBuildDir}/clover-instr")
187 cloverClassesDir = file("${cloverBuildDir}/clover-classes")
188 cloverReportDir = file("${buildDir}/reports/clover")
189 cloverTestInstrDir = file("${cloverBuildDir}/clover-test-instr")
190 cloverTestClassesDir = file("${cloverBuildDir}/clover-test-classes")
191 //cloverTestClassesDir = cloverClassesDir
192 cloverDb = string("${cloverBuildDir}/clover.db")
194 testSourceDir = useClover ? cloverTestInstrDir : testDir
195 testClassesDir = useClover ? cloverTestClassesDir : "${jalviewDir}/${test_output_dir}"
197 getdownWebsiteDir = string("${jalviewDir}/${getdown_website_dir}/${JAVA_VERSION}")
198 getdownArchiveDir = string("${jalviewDir}/${getdown_archive_dir}")
199 getdownFullArchiveDir = null
200 getdownTextLines = []
201 getdownLaunchJvl = null
202 getdownVersionLaunchJvl = null
204 buildProperties = null
206 // the following values might be overridden by the CHANNEL switch
207 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
208 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
209 getdownArchiveAppBase = getdown_archive_base
210 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}")
211 getdownAppDistDir = getdown_app_dir_alt
212 getdownImagesDir = string("${jalviewDir}/${getdown_images_dir}")
213 getdownSetAppBaseProperty = false // whether to pass the appbase and appdistdir to the application
214 reportRsyncCommand = false
215 jvlChannelName = CHANNEL.toLowerCase()
216 install4jSuffix = CHANNEL.substring(0, 1).toUpperCase() + CHANNEL.substring(1).toLowerCase(); // BUILD -> Build
217 install4jDMGDSStore = "${install4j_images_dir}/${install4j_dmg_ds_store}"
218 install4jDMGBackgroundImage = "${install4j_images_dir}/${install4j_dmg_background}"
219 install4jInstallerName = "${jalview_name} Non-Release Installer"
220 install4jExecutableName = install4j_executable_name
221 install4jExtraScheme = "jalviewx"
222 install4jMacIconsFile = string("${install4j_images_dir}/${install4j_mac_icons_file}")
223 install4jWindowsIconsFile = string("${install4j_images_dir}/${install4j_windows_icons_file}")
224 install4jPngIconFile = string("${install4j_images_dir}/${install4j_png_icon_file}")
225 install4jBackground = string("${install4j_images_dir}/${install4j_background}")
226 install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
227 install4jCheckSums = true
231 // TODO: get bamboo build artifact URL for getdown artifacts
232 getdown_channel_base = bamboo_channelbase
233 getdownChannelName = string("${bamboo_planKey}/${JAVA_VERSION}")
234 getdownAppBase = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
235 jvlChannelName += "_${getdownChannelName}"
236 // automatically add the test group Not-bamboo for exclusion
237 if ("".equals(testng_excluded_groups)) {
238 testng_excluded_groups = "Not-bamboo"
240 install4jExtraScheme = "jalviewb"
243 case [ "RELEASE", "JALVIEWJS-RELEASE" ]:
244 getdownAppDistDir = getdown_app_dir_release
245 getdownSetAppBaseProperty = true
246 reportRsyncCommand = true
248 install4jInstallerName = "${jalview_name} Installer"
252 getdownChannelName = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
253 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
254 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
255 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
256 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
258 package_dir = string("${ARCHIVEDIR}/${package_dir}")
259 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
262 reportRsyncCommand = true
263 install4jExtraScheme = "jalviewa"
267 getdownChannelName = string("archive/${JALVIEW_VERSION}")
268 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
269 getdownAppBase = file(getdownWebsiteDir).toURI().toString()
270 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
271 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
273 package_dir = string("${ARCHIVEDIR}/${package_dir}")
274 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
277 reportRsyncCommand = true
278 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
279 install4jSuffix = "Archive"
280 install4jExtraScheme = "jalviewa"
284 reportRsyncCommand = true
285 getdownSetAppBaseProperty = true
286 // DEVELOP-RELEASE is usually associated with a Jalview release series so set the version
287 JALVIEW_VERSION=JALVIEW_VERSION+"-d${buildDate}"
289 install4jSuffix = "Develop"
290 install4jExtraScheme = "jalviewd"
291 install4jInstallerName = "${jalview_name} Develop Installer"
295 reportRsyncCommand = true
296 getdownSetAppBaseProperty = true
297 // Don't ignore transpile errors for release build
298 if (jalviewjs_ignore_transpile_errors.equals("true")) {
299 jalviewjs_ignore_transpile_errors = "false"
300 println("Setting jalviewjs_ignore_transpile_errors to 'false'")
302 JALVIEW_VERSION = JALVIEW_VERSION+"-test"
303 install4jSuffix = "Test"
304 install4jExtraScheme = "jalviewt"
305 install4jInstallerName = "${jalview_name} Test Installer"
308 case ~/^SCRATCH(|-[-\w]*)$/:
309 getdownChannelName = CHANNEL
310 JALVIEW_VERSION = JALVIEW_VERSION+"-"+CHANNEL
312 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
313 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
314 reportRsyncCommand = true
315 install4jSuffix = "Scratch"
319 if (!file("${LOCALDIR}").exists()) {
320 throw new GradleException("Must provide a LOCALDIR value to produce a local distribution")
322 getdownAppBase = file(file("${LOCALDIR}").getAbsolutePath()).toURI().toString()
323 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
325 JALVIEW_VERSION = "TEST"
326 install4jSuffix = "Test-Local"
327 install4jExtraScheme = "jalviewt"
328 install4jInstallerName = "${jalview_name} Test Installer"
331 case [ "LOCAL", "JALVIEWJS" ]:
332 JALVIEW_VERSION = "TEST"
333 getdownAppBase = file(getdownWebsiteDir).toURI().toString()
334 getdownArchiveAppBase = file("${jalviewDir}/${getdown_archive_dir}").toURI().toString()
335 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
336 install4jExtraScheme = "jalviewl"
337 install4jCheckSums = false
340 default: // something wrong specified
341 throw new GradleException("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
345 JALVIEW_VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
346 hugoDataJsonFile = file("${jalviewDir}/${hugo_build_dir}/data/installers/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
347 // override getdownAppBase if requested
348 if (findProperty("getdown_appbase_override") != null) {
349 // revert to LOCAL if empty string
350 if (string(getdown_appbase_override) == "") {
351 getdownAppBase = file(getdownWebsiteDir).toURI().toString()
352 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
353 } else if (string(getdown_appbase_override).startsWith("file://")) {
354 getdownAppBase = string(getdown_appbase_override)
355 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
357 getdownAppBase = string(getdown_appbase_override)
359 println("Overriding getdown appbase with '${getdownAppBase}'")
361 // sanitise file name for jalview launcher file for this channel
362 jvlChannelName = jvlChannelName.replaceAll("[^\\w\\-]+", "_")
363 // install4j application and folder names
364 if (install4jSuffix == "") {
365 install4jApplicationName = "${jalview_name}"
366 install4jBundleId = "${install4j_bundle_id}"
367 install4jWinApplicationId = install4j_release_win_application_id
369 install4jApplicationName = "${jalview_name} ${install4jSuffix}"
370 install4jBundleId = "${install4j_bundle_id}-" + install4jSuffix.toLowerCase()
371 // add int hash of install4jSuffix to the last part of the application_id
372 def id = install4j_release_win_application_id
373 def idsplitreverse = id.split("-").reverse()
374 idsplitreverse[0] = idsplitreverse[0].toInteger() + install4jSuffix.hashCode()
375 install4jWinApplicationId = idsplitreverse.reverse().join("-")
377 // sanitise folder and id names
378 // install4jApplicationFolder = e.g. "Jalview Build"
379 install4jApplicationFolder = install4jApplicationName
380 .replaceAll("[\"'~:/\\\\\\s]", "_") // replace all awkward filename chars " ' ~ : / \
381 .replaceAll("_+", "_") // collapse __
382 install4jInternalId = install4jApplicationName
384 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
385 .replaceAll("_+", "") // collapse __
386 //.replaceAll("_*-_*", "-") // collapse _-_
387 install4jUnixApplicationFolder = install4jApplicationName
389 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
390 .replaceAll("_+", "_") // collapse __
391 .replaceAll("_*-_*", "-") // collapse _-_
394 getdownWrapperLink = install4jUnixApplicationFolder // e.g. "jalview_local"
395 getdownAppDir = string("${getdownWebsiteDir}/${getdownAppDistDir}")
396 //getdownJ11libDir = "${getdownWebsiteDir}/${getdown_j11lib_dir}"
397 getdownResourceDir = string("${getdownWebsiteDir}/${getdown_resource_dir}")
398 getdownInstallDir = string("${getdownWebsiteDir}/${getdown_install_dir}")
399 getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
400 getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
401 /* compile without modules -- using classpath libraries
402 modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
403 modules_runtimeClasspath = modules_compileClasspath
409 apply plugin: "com.palantir.git-version"
410 def details = versionDetails()
411 gitHash = details.gitHash
412 gitBranch = details.branchName
413 } catch(org.gradle.api.internal.plugins.PluginApplicationException e) {
414 println("Not in a git repository. Using git values from RELEASE properties file.")
415 gitHash = releaseProps.getProperty("git.hash")
416 gitBranch = releaseProps.getProperty("git.branch")
417 } catch(java.lang.RuntimeException e1) {
418 throw new GradleException("Error with git-version plugin. Directory '.git' exists but versionDetails() cannot be found.")
421 println("Using a ${CHANNEL} profile.")
423 additional_compiler_args = []
424 // configure classpath/args for j8/j11 compilation
425 if (JAVA_VERSION.equals("1.8")) {
426 JAVA_INTEGER_VERSION = string("8")
429 libDistDir = j8libDir
430 compile_source_compatibility = 1.8
431 compile_target_compatibility = 1.8
432 // these are getdown.txt properties defined dependent on the JAVA_VERSION
433 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
434 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
435 // this property is assigned below and expanded to multiple lines in the getdown task
436 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
437 // this property is for the Java library used in eclipse
438 eclipseJavaRuntimeName = string("JavaSE-1.8")
439 } else if (JAVA_VERSION.equals("11")) {
440 JAVA_INTEGER_VERSION = string("11")
442 libDistDir = j11libDir
443 compile_source_compatibility = 11
444 compile_target_compatibility = 11
445 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
446 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
447 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
448 eclipseJavaRuntimeName = string("JavaSE-11")
449 /* compile without modules -- using classpath libraries
450 additional_compiler_args += [
451 '--module-path', modules_compileClasspath.asPath,
452 '--add-modules', j11modules
455 } else if (JAVA_VERSION.equals("17")) {
456 JAVA_INTEGER_VERSION = string("17")
458 libDistDir = j17libDir
459 compile_source_compatibility = 17
460 compile_target_compatibility = 17
461 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
462 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
463 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
464 eclipseJavaRuntimeName = string("JavaSE-17")
465 /* compile without modules -- using classpath libraries
466 additional_compiler_args += [
467 '--module-path', modules_compileClasspath.asPath,
468 '--add-modules', j11modules
472 throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
477 JAVA_MIN_VERSION = JAVA_VERSION
478 JAVA_MAX_VERSION = JAVA_VERSION
479 def jreInstallsDir = string(jre_installs_dir)
480 if (jreInstallsDir.startsWith("~/")) {
481 jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
483 macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
484 windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
485 linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
486 macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_mac_x64.tar.gz")
487 windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_windows_x64.tar.gz")
488 linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_linux_x64.tar.gz")
489 install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
490 install4jConfFileName = string("jalview-install4j-conf.install4j")
491 install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
492 install4jHomeDir = install4j_home_dir
493 if (install4jHomeDir.startsWith("~/")) {
494 install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
497 resourceBuildDir = string("${buildDir}/resources")
498 resourcesBuildDir = string("${resourceBuildDir}/resources_build")
499 helpBuildDir = string("${resourceBuildDir}/help_build")
500 docBuildDir = string("${resourceBuildDir}/doc_build")
502 if (buildProperties == null) {
503 buildProperties = string("${resourcesBuildDir}/${build_properties_file}")
505 buildingHTML = string("${jalviewDir}/${doc_dir}/building.html")
506 helpParentDir = string("${jalviewDir}/${help_parent_dir}")
507 helpSourceDir = string("${helpParentDir}/${help_dir}")
508 helpFile = string("${helpBuildDir}/${help_dir}/help.jhm")
511 relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
512 jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
513 jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
515 jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
517 jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
519 jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
520 jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
521 jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
522 jalviewjsJalviewCoreHtmlFile = string("")
523 jalviewjsJalviewCoreName = string(jalviewjs_core_name)
524 jalviewjsCoreClasslists = []
525 jalviewjsJalviewTemplateName = string(jalviewjs_name)
526 jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
527 jalviewjsJ2sAltSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_alt_settings}")
528 jalviewjsJ2sProps = null
529 jalviewjsJ2sPlugin = jalviewjs_j2s_plugin
531 eclipseWorkspace = null
532 eclipseBinary = string("")
533 eclipseVersion = string("")
543 outputDir = file(classesDir)
547 srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ]
550 compileClasspath = files(sourceSets.main.java.outputDir)
551 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
553 runtimeClasspath = compileClasspath
554 runtimeClasspath += files(sourceSets.main.resources.srcDirs)
559 srcDirs cloverInstrDir
560 outputDir = cloverClassesDir
564 srcDirs = sourceSets.main.resources.srcDirs
567 compileClasspath = files( sourceSets.clover.java.outputDir )
568 //compileClasspath += files( testClassesDir )
569 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
570 compileClasspath += fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
571 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
573 runtimeClasspath = compileClasspath
578 srcDirs testSourceDir
579 outputDir = file(testClassesDir)
583 srcDirs = useClover ? sourceSets.clover.resources.srcDirs : sourceSets.main.resources.srcDirs
586 compileClasspath = files( sourceSets.test.java.outputDir )
587 compileClasspath += useClover ? sourceSets.clover.compileClasspath : sourceSets.main.compileClasspath
588 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
590 runtimeClasspath = compileClasspath
591 runtimeClasspath += files(sourceSets.test.resources.srcDirs)
597 // eclipse project and settings files creation, also used by buildship
600 name = eclipse_project_name
602 natures 'org.eclipse.jdt.core.javanature',
603 'org.eclipse.jdt.groovy.core.groovyNature',
604 'org.eclipse.buildship.core.gradleprojectnature'
606 buildCommand 'org.eclipse.jdt.core.javabuilder'
607 buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
611 //defaultOutputDir = sourceSets.main.java.outputDir
612 configurations.each{ c->
613 if (c.isCanBeResolved()) {
614 minusConfigurations += [c]
618 plusConfigurations = [ ]
622 def removeTheseToo = []
623 HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
624 cp.entries.each { entry ->
625 // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
626 // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
627 // we add the resources and help/help dirs in as libs afterwards (see below)
628 if (entry.kind == 'src') {
629 if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
630 removeTheseToo += entry
632 alreadyAddedSrcPath.putAt(entry.path, true)
637 cp.entries.removeAll(removeTheseToo)
639 //cp.entries += new Output("${eclipse_bin_dir}/main")
640 if (file(helpParentDir).isDirectory()) {
641 cp.entries += new Library(fileReference(helpParentDir))
643 if (file(resourceDir).isDirectory()) {
644 cp.entries += new Library(fileReference(resourceDir))
647 HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
649 sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
650 //don't want to add outputDir as eclipse is using its own output dir in bin/main
651 if (it.isDirectory() || ! it.exists()) {
652 // don't add dirs to classpath, especially if they don't exist
653 return false // groovy "continue" in .any closure
655 def itPath = it.toString()
656 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
657 // make relative path
658 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
660 if (alreadyAddedLibPath.get(itPath)) {
661 //println("Not adding duplicate entry "+itPath)
663 //println("Adding entry "+itPath)
664 cp.entries += new Library(fileReference(itPath))
665 alreadyAddedLibPath.put(itPath, true)
669 sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
670 //no longer want to add outputDir as eclipse is using its own output dir in bin/main
671 if (it.isDirectory() || ! it.exists()) {
672 // don't add dirs to classpath
673 return false // groovy "continue" in .any closure
676 def itPath = it.toString()
677 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
678 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
680 if (alreadyAddedLibPath.get(itPath)) {
683 def lib = new Library(fileReference(itPath))
684 lib.entryAttributes["test"] = "true"
686 alreadyAddedLibPath.put(itPath, true)
694 containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
699 // for the IDE, use java 11 compatibility
700 sourceCompatibility = compile_source_compatibility
701 targetCompatibility = compile_target_compatibility
702 javaRuntimeName = eclipseJavaRuntimeName
704 // add in jalview project specific properties/preferences into eclipse core preferences
706 withProperties { props ->
707 def jalview_prefs = new Properties()
708 def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
709 jalview_prefs.load(ins)
711 jalview_prefs.forEach { t, v ->
712 if (props.getAt(t) == null) {
716 // codestyle file -- overrides previous formatter prefs
717 def csFile = file("${jalviewDirAbsolutePath}/${eclipse_codestyle_file}")
718 if (csFile.exists()) {
719 XmlParser parser = new XmlParser()
720 def profiles = parser.parse(csFile)
721 def profile = profiles.'profile'.find { p -> (p.'@kind' == "CodeFormatterProfile" && p.'@name' == "Jalview") }
722 if (profile != null) {
723 profile.'setting'.each { s ->
725 def value = s.'@value'
726 if (id != null && value != null) {
727 props.putAt(id, value)
738 // Don't want these to be activated if in headless build
739 synchronizationTasks "eclipseSynchronizationTask"
740 //autoBuildTasks "eclipseAutoBuildTask"
746 /* hack to change eclipse prefs in .settings files other than org.eclipse.jdt.core.prefs */
747 // Class to allow updating arbitrary properties files
748 class PropertiesFile extends PropertiesPersistableConfigurationObject {
749 public PropertiesFile(PropertiesTransformer t) { super(t); }
750 @Override protected void load(Properties properties) { }
751 @Override protected void store(Properties properties) { }
752 @Override protected String getDefaultResourceName() { return ""; }
753 // This is necessary, because PropertiesPersistableConfigurationObject fails
754 // if no default properties file exists.
755 @Override public void loadDefaults() { load(new StringBufferInputStream("")); }
758 // Task to update arbitrary properties files (set outputFile)
759 class PropertiesFileTask extends PropertiesGeneratorTask<PropertiesFile> {
760 private final PropertiesFileContentMerger file;
761 public PropertiesFileTask() { file = new PropertiesFileContentMerger(getTransformer()); }
762 protected PropertiesFile create() { return new PropertiesFile(getTransformer()); }
763 protected void configure(PropertiesFile props) {
764 file.getBeforeMerged().execute(props); file.getWhenMerged().execute(props);
766 public void file(Closure closure) { ConfigureUtil.configure(closure, file); }
769 task eclipseUIPreferences(type: PropertiesFileTask) {
770 description = "Generate Eclipse additional settings"
771 def filename = "org.eclipse.jdt.ui.prefs"
772 outputFile = "$projectDir/.settings/${filename}" as File
775 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
780 task eclipseGroovyCorePreferences(type: PropertiesFileTask) {
781 description = "Generate Eclipse additional settings"
782 def filename = "org.eclipse.jdt.groovy.core.prefs"
783 outputFile = "$projectDir/.settings/${filename}" as File
786 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
791 task eclipseAllPreferences {
793 dependsOn eclipseUIPreferences
794 dependsOn eclipseGroovyCorePreferences
797 eclipseUIPreferences.mustRunAfter eclipseJdt
798 eclipseGroovyCorePreferences.mustRunAfter eclipseJdt
800 /* end of eclipse preferences hack */
808 delete cloverBuildDir
809 delete cloverReportDir
814 task cloverInstrJava(type: JavaExec) {
815 group = "Verification"
816 description = "Create clover instrumented source java files"
818 dependsOn cleanClover
820 inputs.files(sourceSets.main.allJava)
821 outputs.dir(cloverInstrDir)
823 //classpath = fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
824 classpath = sourceSets.clover.compileClasspath
825 main = "com.atlassian.clover.CloverInstr"
833 cloverInstrDir.getPath(),
835 def srcFiles = sourceSets.main.allJava.files
838 { file -> file.absolutePath }
841 args argsList.toArray()
844 delete cloverInstrDir
845 println("Clover: About to instrument "+srcFiles.size() +" files")
850 task cloverInstrTests(type: JavaExec) {
851 group = "Verification"
852 description = "Create clover instrumented source test files"
854 dependsOn cleanClover
856 inputs.files(testDir)
857 outputs.dir(cloverTestInstrDir)
859 classpath = sourceSets.clover.compileClasspath
860 main = "com.atlassian.clover.CloverInstr"
870 cloverTestInstrDir.getPath(),
872 args argsList.toArray()
875 delete cloverTestInstrDir
876 println("Clover: About to instrument test files")
882 group = "Verification"
883 description = "Create clover instrumented all source files"
885 dependsOn cloverInstrJava
886 dependsOn cloverInstrTests
890 cloverClasses.dependsOn cloverInstr
893 task cloverConsoleReport(type: JavaExec) {
894 group = "Verification"
895 description = "Creates clover console report"
898 file(cloverDb).exists()
901 inputs.dir cloverClassesDir
903 classpath = sourceSets.clover.runtimeClasspath
904 main = "com.atlassian.clover.reporters.console.ConsoleReporter"
906 if (cloverreport_mem.length() > 0) {
907 maxHeapSize = cloverreport_mem
909 if (cloverreport_jvmargs.length() > 0) {
910 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
920 args argsList.toArray()
924 task cloverHtmlReport(type: JavaExec) {
925 group = "Verification"
926 description = "Creates clover HTML report"
929 file(cloverDb).exists()
932 def cloverHtmlDir = cloverReportDir
933 inputs.dir cloverClassesDir
934 outputs.dir cloverHtmlDir
936 classpath = sourceSets.clover.runtimeClasspath
937 main = "com.atlassian.clover.reporters.html.HtmlReporter"
939 if (cloverreport_mem.length() > 0) {
940 maxHeapSize = cloverreport_mem
942 if (cloverreport_jvmargs.length() > 0) {
943 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
954 if (cloverreport_html_options.length() > 0) {
955 argsList += cloverreport_html_options.split(" ")
958 args argsList.toArray()
962 task cloverXmlReport(type: JavaExec) {
963 group = "Verification"
964 description = "Creates clover XML report"
967 file(cloverDb).exists()
970 def cloverXmlFile = "${cloverReportDir}/clover.xml"
971 inputs.dir cloverClassesDir
972 outputs.file cloverXmlFile
974 classpath = sourceSets.clover.runtimeClasspath
975 main = "com.atlassian.clover.reporters.xml.XMLReporter"
977 if (cloverreport_mem.length() > 0) {
978 maxHeapSize = cloverreport_mem
980 if (cloverreport_jvmargs.length() > 0) {
981 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
992 if (cloverreport_xml_options.length() > 0) {
993 argsList += cloverreport_xml_options.split(" ")
996 args argsList.toArray()
1001 group = "Verification"
1002 description = "Creates clover reports"
1004 dependsOn cloverXmlReport
1005 dependsOn cloverHtmlReport
1012 sourceCompatibility = compile_source_compatibility
1013 targetCompatibility = compile_target_compatibility
1014 options.compilerArgs += additional_compiler_args
1015 print ("Setting target compatibility to "+targetCompatibility+"\n")
1017 //classpath += configurations.cloverRuntime
1023 // JBP->BS should the print statement in doFirst refer to compile_target_compatibility ?
1024 sourceCompatibility = compile_source_compatibility
1025 targetCompatibility = compile_target_compatibility
1026 options.compilerArgs = additional_compiler_args
1027 options.encoding = "UTF-8"
1029 print ("Setting target compatibility to "+compile_target_compatibility+"\n")
1036 sourceCompatibility = compile_source_compatibility
1037 targetCompatibility = compile_target_compatibility
1038 options.compilerArgs = additional_compiler_args
1040 print ("Setting target compatibility to "+targetCompatibility+"\n")
1047 delete sourceSets.main.java.outputDir
1053 dependsOn cleanClover
1055 delete sourceSets.test.java.outputDir
1060 // format is a string like date.format("dd MMMM yyyy")
1061 def getDate(format) {
1062 return date.format(format)
1066 def convertMdToHtml (FileTree mdFiles, File cssFile) {
1067 MutableDataSet options = new MutableDataSet()
1069 def extensions = new ArrayList<>()
1070 extensions.add(AnchorLinkExtension.create())
1071 extensions.add(AutolinkExtension.create())
1072 extensions.add(StrikethroughExtension.create())
1073 extensions.add(TaskListExtension.create())
1074 extensions.add(TablesExtension.create())
1075 extensions.add(TocExtension.create())
1077 options.set(Parser.EXTENSIONS, extensions)
1079 // set GFM table parsing options
1080 options.set(TablesExtension.WITH_CAPTION, false)
1081 options.set(TablesExtension.COLUMN_SPANS, false)
1082 options.set(TablesExtension.MIN_HEADER_ROWS, 1)
1083 options.set(TablesExtension.MAX_HEADER_ROWS, 1)
1084 options.set(TablesExtension.APPEND_MISSING_COLUMNS, true)
1085 options.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
1086 options.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
1088 options.set(AnchorLinkExtension.ANCHORLINKS_SET_ID, false)
1089 options.set(AnchorLinkExtension.ANCHORLINKS_ANCHOR_CLASS, "anchor")
1090 options.set(AnchorLinkExtension.ANCHORLINKS_SET_NAME, true)
1091 options.set(AnchorLinkExtension.ANCHORLINKS_TEXT_PREFIX, "<span class=\"octicon octicon-link\"></span>")
1093 Parser parser = Parser.builder(options).build()
1094 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1096 mdFiles.each { mdFile ->
1097 // add table of contents
1098 def mdText = "[TOC]\n"+mdFile.text
1100 // grab the first top-level title
1102 def titleRegex = /(?m)^#(\s+|([^#]))(.*)/
1103 def matcher = mdText =~ titleRegex
1104 if (matcher.size() > 0) {
1105 // matcher[0][2] is the first character of the title if there wasn't any whitespace after the #
1106 title = (matcher[0][2] != null ? matcher[0][2] : "")+matcher[0][3]
1108 // or use the filename if none found
1109 if (title == null) {
1110 title = mdFile.getName()
1113 Node document = parser.parse(mdText)
1114 String htmlBody = renderer.render(document)
1115 def htmlText = '''<html>
1116 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1117 <html xmlns="http://www.w3.org/1999/xhtml">
1119 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1120 <meta http-equiv="Content-Style-Type" content="text/css" />
1121 <meta name="generator" content="flexmark" />
1123 htmlText += ((title != null) ? " <title>${title}</title>" : '' )
1125 <style type="text/css">code{white-space: pre;}</style>
1127 htmlText += ((cssFile != null) ? cssFile.text : '')
1128 htmlText += '''</head>
1131 htmlText += htmlBody
1137 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1138 def htmlFile = file(htmlFilePath)
1139 println("Creating ${htmlFilePath}")
1140 htmlFile.text = htmlText
1145 task copyDocs(type: Copy) {
1146 def inputDir = "${jalviewDir}/${doc_dir}"
1147 def outputDir = "${docBuildDir}/${doc_dir}"
1151 include('**/*.html')
1153 filter(ReplaceTokens,
1157 'Version-Rel': JALVIEW_VERSION,
1158 'Year-Rel': getDate("yyyy")
1165 exclude('**/*.html')
1170 inputs.dir(inputDir)
1171 outputs.dir(outputDir)
1175 task convertMdFiles {
1177 def mdFiles = fileTree(dir: docBuildDir, include: "**/*.md")
1178 def cssFile = file("${jalviewDir}/${flexmark_css}")
1181 convertMdToHtml(mdFiles, cssFile)
1184 inputs.files(mdFiles)
1185 inputs.file(cssFile)
1188 mdFiles.each { mdFile ->
1189 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1190 htmlFiles.add(file(htmlFilePath))
1192 outputs.files(htmlFiles)
1196 task copyHelp(type: Copy) {
1197 def inputDir = helpSourceDir
1198 def outputDir = "${helpBuildDir}/${help_dir}"
1202 include('**/*.html')
1206 filter(ReplaceTokens,
1210 'Version-Rel': JALVIEW_VERSION,
1211 'Year-Rel': getDate("yyyy")
1218 exclude('**/*.html')
1225 inputs.dir(inputDir)
1226 outputs.files(helpFile)
1227 outputs.dir(outputDir)
1231 task copyResources(type: Copy) {
1233 description = "Copy (and make text substitutions in) the resources dir to the build area"
1235 def inputDir = resourceDir
1236 def outputDir = resourcesBuildDir
1240 include('**/*.html')
1242 filter(ReplaceTokens,
1246 'Version-Rel': JALVIEW_VERSION,
1247 'Year-Rel': getDate("yyyy")
1254 exclude('**/*.html')
1259 inputs.dir(inputDir)
1260 outputs.dir(outputDir)
1263 task copyChannelResources(type: Copy) {
1264 dependsOn copyResources
1266 description = "Copy the channel resources dir to the build resources area"
1268 def inputDir = "${channelDir}/${resource_dir}"
1269 def outputDir = resourcesBuildDir
1273 inputs.dir(inputDir)
1274 outputs.dir(outputDir)
1277 task createBuildProperties(type: WriteProperties) {
1278 dependsOn copyResources
1280 description = "Create the ${buildProperties} file"
1282 inputs.dir(sourceDir)
1283 inputs.dir(resourcesBuildDir)
1284 outputFile (buildProperties)
1285 // taking time specific comment out to allow better incremental builds
1286 comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
1287 //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
1288 property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
1289 property "VERSION", JALVIEW_VERSION
1290 property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
1291 if (getdownSetAppBaseProperty) {
1292 property "GETDOWNAPPBASE", getdownAppBase
1293 property "GETDOWNAPPDISTDIR", getdownAppDistDir
1295 outputs.file(outputFile)
1299 task buildIndices(type: JavaExec) {
1301 classpath = sourceSets.main.compileClasspath
1302 main = "com.sun.java.help.search.Indexer"
1303 workingDir = "${helpBuildDir}/${help_dir}"
1306 inputs.dir("${workingDir}/${argDir}")
1308 outputs.dir("${classesDir}/doc")
1309 outputs.dir("${classesDir}/help")
1310 outputs.file("${workingDir}/JavaHelpSearch/DOCS")
1311 outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
1312 outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
1313 outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
1314 outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
1315 outputs.file("${workingDir}/JavaHelpSearch/TMAP")
1318 task buildResources {
1319 dependsOn copyResources
1320 dependsOn copyChannelResources
1321 dependsOn createBuildProperties
1325 dependsOn buildResources
1328 dependsOn convertMdFiles
1329 dependsOn buildIndices
1333 compileJava.dependsOn prepare
1334 run.dependsOn compileJava
1335 //run.dependsOn prepare
1338 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1343 dependsOn cloverClasses
1345 dependsOn compileJava //?
1349 includeGroups testng_groups
1350 excludeGroups testng_excluded_groups
1352 useDefaultListeners=true
1355 maxHeapSize = "1024m"
1357 workingDir = jalviewDir
1358 def testLaf = project.findProperty("test_laf")
1359 if (testLaf != null) {
1360 println("Setting Test LaF to '${testLaf}'")
1361 systemProperty "laf", testLaf
1363 def testHiDPIScale = project.findProperty("test_HiDPIScale")
1364 if (testHiDPIScale != null) {
1365 println("Setting Test HiDPI Scale to '${testHiDPIScale}'")
1366 systemProperty "sun.java2d.uiScale", testHiDPIScale
1368 sourceCompatibility = compile_source_compatibility
1369 targetCompatibility = compile_target_compatibility
1370 jvmArgs += additional_compiler_args
1374 println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1380 task compileLinkCheck(type: JavaCompile) {
1382 classpath = files("${jalviewDir}/${utils_dir}")
1383 destinationDir = file("${jalviewDir}/${utils_dir}")
1384 source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1386 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1387 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1388 outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1389 outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1393 task linkCheck(type: JavaExec) {
1395 dependsOn compileLinkCheck
1397 def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1398 classpath = files("${jalviewDir}/${utils_dir}")
1399 main = "HelpLinksChecker"
1400 workingDir = jalviewDir
1401 args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1403 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1404 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1407 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1411 inputs.dir(helpBuildDir)
1412 outputs.file(helpLinksCheckerOutFile)
1416 // import the pubhtmlhelp target
1417 ant.properties.basedir = "${jalviewDir}"
1418 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1419 ant.importBuild "${utils_dir}/publishHelp.xml"
1422 task cleanPackageDir(type: Delete) {
1424 delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1434 attributes "Main-Class": main_class,
1435 "Permissions": "all-permissions",
1436 "Application-Name": install4jApplicationName,
1437 "Codebase": application_codebase,
1438 "Implementation-Version": JALVIEW_VERSION
1441 def outputDir = "${jalviewDir}/${package_dir}"
1442 destinationDirectory = file(outputDir)
1443 archiveFileName = rootProject.name+".jar"
1444 duplicatesStrategy "EXCLUDE"
1451 exclude "**/*.jar.*"
1453 inputs.dir(sourceSets.main.java.outputDir)
1454 sourceSets.main.resources.srcDirs.each{ dir ->
1457 outputs.file("${outputDir}/${archiveFileName}")
1461 task copyJars(type: Copy) {
1462 from fileTree(dir: classesDir, include: "**/*.jar").files
1463 into "${jalviewDir}/${package_dir}"
1467 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1468 task syncJars(type: Sync) {
1470 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1471 into "${jalviewDir}/${package_dir}"
1473 include jar.archiveFileName.getOrNull()
1480 description = "Put all required libraries in dist"
1481 // order of "cleanPackageDir", "copyJars", "jar" important!
1482 jar.mustRunAfter cleanPackageDir
1483 syncJars.mustRunAfter cleanPackageDir
1484 dependsOn cleanPackageDir
1487 outputs.dir("${jalviewDir}/${package_dir}")
1492 dependsOn cleanPackageDir
1499 group = "distribution"
1500 description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1504 from ("${jalviewDir}/${libDistDir}") {
1508 attributes "Implementation-Version": JALVIEW_VERSION,
1509 "Application-Name": install4jApplicationName
1512 duplicatesStrategy "INCLUDE"
1514 mainClassName = shadow_jar_main_class
1516 classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1521 task getdownWebsite() {
1522 group = "distribution"
1523 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1528 def getdownWebsiteResourceFilenames = []
1529 def getdownResourceDir = getdownResourceDir
1530 def getdownResourceFilenames = []
1533 // clean the getdown website and files dir before creating getdown folders
1534 delete getdownWebsiteDir
1535 delete getdownFilesDir
1538 from buildProperties
1539 rename(file(buildProperties).getName(), getdown_build_properties)
1542 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1545 from channelPropsFile
1546 into getdownWebsiteDir
1548 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
1550 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
1551 def props = project.properties.sort { it.key }
1552 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
1553 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
1555 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
1556 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
1558 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
1559 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
1561 if (getdownImagesDir != null && file(getdownImagesDir).exists()) {
1562 props.put("getdown_txt_ui.background_image", "${getdownImagesDir}/${getdown_background_image}")
1563 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesDir}/${getdown_instant_background_image}")
1564 props.put("getdown_txt_ui.error_background", "${getdownImagesDir}/${getdown_error_background}")
1565 props.put("getdown_txt_ui.progress_image", "${getdownImagesDir}/${getdown_progress_image}")
1566 props.put("getdown_txt_ui.icon", "${getdownImagesDir}/${getdown_icon}")
1567 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesDir}/${getdown_mac_dock_icon}")
1570 props.put("getdown_txt_title", jalview_name)
1571 props.put("getdown_txt_ui.name", install4jApplicationName)
1573 // start with appbase
1574 getdownTextLines += "appbase = ${getdownAppBase}"
1575 props.each{ prop, val ->
1576 if (prop.startsWith("getdown_txt_") && val != null) {
1577 if (prop.startsWith("getdown_txt_multi_")) {
1578 def key = prop.substring(18)
1579 val.split(",").each{ v ->
1580 def line = "${key} = ${v}"
1581 getdownTextLines += line
1584 // file values rationalised
1585 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
1587 if (val.indexOf('/') == 0) {
1590 } else if (val.indexOf('/') > 0) {
1591 // relative path (relative to jalviewDir)
1592 r = file( "${jalviewDir}/${val}" )
1595 val = "${getdown_resource_dir}/" + r.getName()
1596 getdownWebsiteResourceFilenames += val
1597 getdownResourceFilenames += r.getPath()
1600 if (! prop.startsWith("getdown_txt_resource")) {
1601 def line = prop.substring(12) + " = ${val}"
1602 getdownTextLines += line
1608 getdownWebsiteResourceFilenames.each{ filename ->
1609 getdownTextLines += "resource = ${filename}"
1611 getdownResourceFilenames.each{ filename ->
1614 into getdownResourceDir
1618 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
1619 getdownWrapperScripts.each{ script ->
1620 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
1624 into "${getdownWebsiteDir}/${getdown_wrapper_script_dir}"
1626 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
1631 fileTree(file(package_dir)).each{ f ->
1632 if (f.isDirectory()) {
1633 def files = fileTree(dir: f, include: ["*"]).getFiles()
1635 } else if (f.exists()) {
1639 def jalviewJar = jar.archiveFileName.getOrNull()
1640 // put jalview.jar first for CLASSPATH and .properties files reasons
1641 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
1642 def name = f.getName()
1643 def line = "code = ${getdownAppDistDir}/${name}"
1644 getdownTextLines += line
1651 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
1653 if (JAVA_VERSION.equals("11")) {
1654 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
1655 j11libFiles.sort().each{f ->
1656 def name = f.getName()
1657 def line = "code = ${getdown_j11lib_dir}/${name}"
1658 getdownTextLines += line
1661 into getdownJ11libDir
1667 // 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.
1668 //getdownTextLines += "class = " + file(getdownLauncher).getName()
1669 getdownTextLines += "resource = ${getdown_launcher_new}"
1670 getdownTextLines += "class = ${main_class}"
1671 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
1672 if (getdownSetAppBaseProperty) {
1673 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
1674 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
1677 def getdownTxt = file("${getdownWebsiteDir}/getdown.txt")
1678 getdownTxt.write(getdownTextLines.join("\n"))
1680 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
1681 def launchJvl = file("${getdownWebsiteDir}/${getdownLaunchJvl}")
1682 launchJvl.write("appbase=${getdownAppBase}")
1684 // files going into the getdown website dir: getdown-launcher.jar
1686 from getdownLauncher
1687 rename(file(getdownLauncher).getName(), getdown_launcher_new)
1688 into getdownWebsiteDir
1691 // files going into the getdown website dir: getdown-launcher(-local).jar
1693 from getdownLauncher
1694 if (file(getdownLauncher).getName() != getdown_launcher) {
1695 rename(file(getdownLauncher).getName(), getdown_launcher)
1697 into getdownWebsiteDir
1700 // files going into the getdown website dir: ./install dir and files
1701 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
1704 from getdownLauncher
1705 from "${getdownAppDir}/${getdown_build_properties}"
1706 if (file(getdownLauncher).getName() != getdown_launcher) {
1707 rename(file(getdownLauncher).getName(), getdown_launcher)
1709 into getdownInstallDir
1712 // and make a copy in the getdown files dir (these are not downloaded by getdown)
1714 from getdownInstallDir
1715 into getdownFilesInstallDir
1719 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
1723 from getdownLauncher
1724 from "${getdownWebsiteDir}/${getdown_build_properties}"
1725 from "${getdownWebsiteDir}/${channel_props}"
1726 if (file(getdownLauncher).getName() != getdown_launcher) {
1727 rename(file(getdownLauncher).getName(), getdown_launcher)
1729 into getdownFilesDir
1732 // and ./resource (not all downloaded by getdown)
1734 from getdownResourceDir
1735 into "${getdownFilesDir}/${getdown_resource_dir}"
1740 inputs.dir("${jalviewDir}/${package_dir}")
1742 outputs.dir(getdownWebsiteDir)
1743 outputs.dir(getdownFilesDir)
1747 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
1748 task getdownDigestDir(type: JavaExec) {
1750 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
1752 def digestDirPropertyName = "DIGESTDIR"
1754 classpath = files(getdownLauncher)
1755 def digestDir = findProperty(digestDirPropertyName)
1756 if (digestDir == null) {
1757 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
1761 main = "com.threerings.getdown.tools.Digester"
1765 task getdownDigest(type: JavaExec) {
1766 group = "distribution"
1767 description = "Digest the getdown website folder"
1768 dependsOn getdownWebsite
1770 classpath = files(getdownLauncher)
1772 main = "com.threerings.getdown.tools.Digester"
1773 args getdownWebsiteDir
1774 inputs.dir(getdownWebsiteDir)
1775 outputs.file("${getdownWebsiteDir}/digest2.txt")
1780 group = "distribution"
1781 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
1782 dependsOn getdownDigest
1784 if (reportRsyncCommand) {
1785 def fromDir = getdownWebsiteDir + (getdownWebsiteDir.endsWith('/')?'':'/')
1786 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
1787 println "LIKELY RSYNC COMMAND:"
1788 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
1789 if (RUNRSYNC == "true") {
1791 commandLine "mkdir", "-p", toDir
1794 commandLine "rsync", "-avh", "--delete", fromDir, toDir
1802 task getdownArchiveBuild() {
1803 group = "distribution"
1804 description = "Put files in the archive dir to go on the website"
1806 dependsOn getdownWebsite
1808 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
1809 def vDir = "${getdownArchiveDir}/${v}"
1810 getdownFullArchiveDir = "${vDir}/getdown"
1811 getdownVersionLaunchJvl = "${vDir}/jalview-${v}.jvl"
1813 def vAltDir = "alt_${v}"
1814 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
1817 // cleanup old "old" dir
1818 delete getdownArchiveDir
1820 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
1821 getdownArchiveTxt.getParentFile().mkdirs()
1822 def getdownArchiveTextLines = []
1823 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
1827 from "${getdownWebsiteDir}/${getdownAppDistDir}"
1828 into "${getdownFullArchiveDir}/${vAltDir}"
1831 getdownTextLines.each { line ->
1832 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
1833 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
1834 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
1835 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
1836 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
1837 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
1838 // remove the existing resource = resource/ or bin/ lines
1839 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
1840 getdownArchiveTextLines += line
1844 // the resource dir -- add these files as resource lines in getdown.txt
1846 from "${archiveImagesDir}"
1847 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
1849 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
1853 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
1855 def vLaunchJvl = file(getdownVersionLaunchJvl)
1856 vLaunchJvl.getParentFile().mkdirs()
1857 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
1858 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
1859 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
1860 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
1861 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
1862 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
1864 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
1866 from getdownLauncher
1867 from "${getdownWebsiteDir}/${getdownLaunchJvl}"
1868 from "${getdownWebsiteDir}/${getdown_launcher_new}"
1869 from "${getdownWebsiteDir}/${channel_props}"
1870 if (file(getdownLauncher).getName() != getdown_launcher) {
1871 rename(file(getdownLauncher).getName(), getdown_launcher)
1873 into getdownFullArchiveDir
1879 task getdownArchiveDigest(type: JavaExec) {
1880 group = "distribution"
1881 description = "Digest the getdown archive folder"
1883 dependsOn getdownArchiveBuild
1886 classpath = files(getdownLauncher)
1887 args getdownFullArchiveDir
1889 main = "com.threerings.getdown.tools.Digester"
1890 inputs.dir(getdownFullArchiveDir)
1891 outputs.file("${getdownFullArchiveDir}/digest2.txt")
1894 task getdownArchive() {
1895 group = "distribution"
1896 description = "Build the website archive dir with getdown digest"
1898 dependsOn getdownArchiveBuild
1899 dependsOn getdownArchiveDigest
1902 tasks.withType(JavaCompile) {
1903 options.encoding = 'UTF-8'
1909 delete getdownWebsiteDir
1910 delete getdownFilesDir
1911 delete getdownArchiveDir
1917 if (file(install4jHomeDir).exists()) {
1919 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
1920 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
1921 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
1922 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
1924 installDir(file(install4jHomeDir))
1926 mediaTypes = Arrays.asList(install4j_media_types.split(","))
1930 task copyInstall4jTemplate {
1931 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
1932 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
1933 inputs.file(install4jTemplateFile)
1934 inputs.file(install4jFileAssociationsFile)
1935 inputs.property("CHANNEL", { CHANNEL })
1936 outputs.file(install4jConfFile)
1939 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
1941 // turn off code signing if no OSX_KEYPASS
1942 if (OSX_KEYPASS == "") {
1943 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
1944 codeSigning.'@macEnabled' = "false"
1946 install4jConfigXml.'**'.windows.each { windows ->
1947 windows.'@runPostProcessor' = "false"
1951 // disable install screen for OSX dmg (for 2.11.2.0)
1952 install4jConfigXml.'**'.macosArchive.each { macosArchive ->
1953 macosArchive.attributes().remove('executeSetupApp')
1954 macosArchive.attributes().remove('setupAppId')
1957 // turn off checksum creation for LOCAL channel
1958 def e = install4jConfigXml.application[0]
1959 e.'@createChecksums' = string(install4jCheckSums)
1961 // put file association actions where placeholder action is
1962 def install4jFileAssociationsText = install4jFileAssociationsFile.text
1963 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
1964 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
1965 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
1966 def parent = a.parent()
1968 fileAssociationActions.each { faa ->
1971 // don't need to continue in .any loop once replacements have been made
1976 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
1977 // NB we're deleting the /other/ one!
1978 // Also remove the examples subdir from non-release versions
1979 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
1980 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
1981 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
1982 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
1984 // remove the examples subdir from Full File Set
1985 def files = install4jConfigXml.files[0]
1986 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
1987 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
1988 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
1989 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
1990 dirEntry.parent().remove(dirEntry)
1992 install4jConfigXml.'**'.action.any { a ->
1993 if (a.'@customizedId' == customizedIdToDelete) {
1994 def parent = a.parent()
2000 // write install4j file
2001 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
2008 delete install4jConfFile
2012 task cleanInstallersDataFiles {
2013 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2014 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2015 def hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
2017 delete installersOutputTxt
2018 delete installersSha256
2019 delete hugoDataJsonFile
2023 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2024 group = "distribution"
2025 description = "Create the install4j installers"
2027 dependsOn copyInstall4jTemplate
2028 dependsOn cleanInstallersDataFiles
2030 projectFile = install4jConfFile
2032 // create an md5 for the input files to use as version for install4j conf file
2033 def digest = MessageDigest.getInstance("MD5")
2035 (file("${install4jDir}/${install4j_template}").text +
2036 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2037 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2038 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2039 if (filesMd5.length() >= 8) {
2040 filesMd5 = filesMd5.substring(0,8)
2042 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2045 'JALVIEW_NAME': jalview_name,
2046 'JALVIEW_APPLICATION_NAME': install4jApplicationName,
2047 'JALVIEW_DIR': "../..",
2048 'OSX_KEYSTORE': OSX_KEYSTORE,
2049 'OSX_APPLEID': OSX_APPLEID,
2050 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2051 'JSIGN_SH': JSIGN_SH,
2052 'JRE_DIR': getdown_app_dir_java,
2053 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2054 'JALVIEW_VERSION': JALVIEW_VERSION,
2055 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2056 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2057 'JAVA_VERSION': JAVA_VERSION,
2058 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2059 'VERSION': JALVIEW_VERSION,
2060 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2061 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2062 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2063 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2064 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2065 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2066 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2067 'BUNDLE_ID': install4jBundleId,
2068 'INTERNAL_ID': install4jInternalId,
2069 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2070 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2071 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
2072 'WRAPPER_LINK': getdownWrapperLink,
2073 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2074 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2075 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2076 'INSTALLER_NAME': install4jInstallerName,
2077 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2078 'GETDOWN_WEBSITE_DIR': getdown_website_dir,
2079 'GETDOWN_FILES_DIR': getdown_files_dir,
2080 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2081 'GETDOWN_DIST_DIR': getdownAppDistDir,
2082 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2083 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2084 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2085 'BUILD_DIR': install4jBuildDir,
2086 'APPLICATION_CATEGORIES': install4j_application_categories,
2087 'APPLICATION_FOLDER': install4jApplicationFolder,
2088 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2089 'EXECUTABLE_NAME': install4jExecutableName,
2090 'EXTRA_SCHEME': install4jExtraScheme,
2091 'MAC_ICONS_FILE': install4jMacIconsFile,
2092 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2093 'PNG_ICON_FILE': install4jPngIconFile,
2094 'BACKGROUND': install4jBackground,
2098 //println("INSTALL4J VARIABLES:")
2099 //variables.each{k,v->println("${k}=${v}")}
2101 destination = "${jalviewDir}/${install4jBuildDir}"
2102 buildSelected = true
2104 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2106 disableSigning = true
2107 disableNotarization = true
2111 macKeystorePassword = OSX_KEYPASS
2114 if (OSX_ALTOOLPASS) {
2115 appleIdPassword = OSX_ALTOOLPASS
2116 disableNotarization = false
2118 disableNotarization = true
2122 println("Using projectFile "+projectFile)
2123 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2127 inputs.dir(getdownWebsiteDir)
2128 inputs.file(install4jConfFile)
2129 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2130 inputs.dir(macosJavaVMDir)
2131 inputs.dir(windowsJavaVMDir)
2132 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2135 def getDataHash(File myFile) {
2136 HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
2137 return myFile.exists()
2139 "file" : myFile.getName(),
2140 "filesize" : myFile.length(),
2141 "sha256" : hash.toString()
2146 def writeDataJsonFile(File installersOutputTxt, File installersSha256, File dataJsonFile) {
2148 "channel" : getdownChannelName,
2149 "date" : getDate("yyyy-MM-dd HH:mm:ss"),
2150 "git-commit" : "${gitHash} [${gitBranch}]",
2151 "version" : JALVIEW_VERSION
2153 // install4j installer files
2154 if (installersOutputTxt.exists()) {
2156 installersOutputTxt.readLines().each { def line ->
2157 if (line.startsWith("#")) {
2160 line.replaceAll("\n","")
2161 def vals = line.split("\t")
2162 def filename = vals[3]
2163 def filesize = file(filename).length()
2164 filename = filename.replaceAll(/^.*\//, "")
2165 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2166 idHash."${filename}" = vals[0]
2168 if (install4jCheckSums && installersSha256.exists()) {
2169 installersSha256.readLines().each { def line ->
2170 if (line.startsWith("#")) {
2173 line.replaceAll("\n","")
2174 def vals = line.split(/\s+\*?/)
2175 def filename = vals[1]
2176 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2182 "JAR": shadowJar.archiveFile, // executable JAR
2183 "JVL": getdownVersionLaunchJvl, // version JVL
2184 "SOURCE": sourceDist.archiveFile // source TGZ
2185 ].each { key, value ->
2186 def file = file(value)
2187 if (file.exists()) {
2188 def fileHash = getDataHash(file)
2189 if (fileHash != null) {
2190 hash."${key}" = fileHash;
2194 return dataJsonFile.write(new JsonBuilder(hash).toPrettyString())
2197 task staticMakeInstallersJsonFile {
2199 def output = findProperty("i4j_output")
2200 def sha256 = findProperty("i4j_sha256")
2201 def json = findProperty("i4j_json")
2202 if (output == null || sha256 == null || json == null) {
2203 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2205 writeDataJsonFile(file(output), file(sha256), file(json))
2210 dependsOn installerFiles
2216 eclipse().configFile(eclipse_codestyle_file)
2220 task createSourceReleaseProperties(type: WriteProperties) {
2221 group = "distribution"
2222 description = "Create the source RELEASE properties file"
2224 def sourceTarBuildDir = "${buildDir}/sourceTar"
2225 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2226 outputFile (sourceReleasePropertiesFile)
2229 releaseProps.each{ key, val -> property key, val }
2230 property "git.branch", gitBranch
2231 property "git.hash", gitHash
2234 outputs.file(outputFile)
2237 task sourceDist(type: Tar) {
2238 group "distribution"
2239 description "Create a source .tar.gz file for distribution"
2241 dependsOn createBuildProperties
2242 dependsOn convertMdFiles
2243 dependsOn eclipseAllPreferences
2244 dependsOn createSourceReleaseProperties
2247 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2248 archiveFileName = outputFileName
2250 compression Compression.GZIP
2265 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2267 "utils/InstallAnywhere",
2282 "gradle.properties",
2294 ".settings/org.eclipse.buildship.core.prefs",
2295 ".settings/org.eclipse.jdt.core.prefs"
2299 exclude (EXCLUDE_FILES)
2300 include (PROCESS_FILES)
2301 filter(ReplaceTokens,
2305 'Version-Rel': JALVIEW_VERSION,
2306 'Year-Rel': getDate("yyyy")
2311 exclude (EXCLUDE_FILES)
2312 exclude (PROCESS_FILES)
2313 exclude ("appletlib")
2314 exclude ("**/*locales")
2315 exclude ("*locales/**")
2316 exclude ("utils/InstallAnywhere")
2318 exclude (getdown_files_dir)
2319 exclude (getdown_website_dir)
2321 // exluding these as not using jars as modules yet
2322 exclude ("${j11modDir}/**/*.jar")
2325 include(INCLUDE_FILES)
2327 // from (jalviewDir) {
2328 // // explicit includes for stuff that seemed to not get included
2329 // include(fileTree("test/**/*."))
2330 // exclude(EXCLUDE_FILES)
2331 // exclude(PROCESS_FILES)
2334 from(file(buildProperties).getParent()) {
2335 include(file(buildProperties).getName())
2336 rename(file(buildProperties).getName(), "build_properties")
2338 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2342 def sourceTarBuildDir = "${buildDir}/sourceTar"
2343 from(sourceTarBuildDir) {
2344 // this includes the appended RELEASE properties file
2348 task makeDataJsonFile {
2350 description "Create the installers-VERSION.json data file for installer files created"
2352 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2353 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2355 if (installersOutputTxt.exists()) {
2356 inputs.file(installersOutputTxt)
2358 if (install4jCheckSums && installersSha256.exists()) {
2359 inputs.file(installersSha256)
2362 shadowJar.archiveFile, // executable JAR
2363 getdownVersionLaunchJvl, // version JVL
2364 sourceDist.archiveFile // source TGZ
2365 ].each { fileName ->
2366 if (file(fileName).exists()) {
2367 inputs.file(fileName)
2371 outputs.file(hugoDataJsonFile)
2374 writeDataJsonFile(installersOutputTxt, installersSha256, hugoDataJsonFile)
2378 makeDataJsonFile.mustRunAfter installers
2379 makeDataJsonFile.mustRunAfter shadowJar
2380 makeDataJsonFile.mustRunAfter sourceDist
2381 makeDataJsonFile.mustRunAfter getdownArchive
2386 dependsOn pubhtmlhelp
2388 inputs.dir("${helpBuildDir}/${help_dir}")
2389 outputs.dir("${buildDir}/distributions/${help_dir}")
2393 task j2sSetHeadlessBuild {
2400 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2402 description "Enable the alternative J2S Config file for headless build"
2404 outputFile = jalviewjsJ2sSettingsFileName
2405 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2406 def j2sProps = new Properties()
2407 if (j2sPropsFile.exists()) {
2409 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2410 j2sProps.load(j2sPropsFileFIS)
2411 j2sPropsFileFIS.close()
2413 j2sProps.each { prop, val ->
2416 } catch (Exception e) {
2417 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2421 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2422 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2427 task jalviewjsSetEclipseWorkspace {
2428 def propKey = "jalviewjs_eclipse_workspace"
2430 if (project.hasProperty(propKey)) {
2431 propVal = project.getProperty(propKey)
2432 if (propVal.startsWith("~/")) {
2433 propVal = System.getProperty("user.home") + propVal.substring(1)
2436 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2437 def propsFile = file(propsFileName)
2438 def eclipseWsDir = propVal
2439 def props = new Properties()
2441 def writeProps = true
2442 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2443 def ins = new FileInputStream(propsFileName)
2446 if (props.getProperty(propKey, null) != null) {
2447 eclipseWsDir = props.getProperty(propKey)
2452 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2453 def tempDir = File.createTempDir()
2454 eclipseWsDir = tempDir.getAbsolutePath()
2457 eclipseWorkspace = file(eclipseWsDir)
2460 // do not run a headless transpile when we claim to be in Eclipse
2462 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2463 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2465 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2469 props.setProperty(propKey, eclipseWsDir)
2470 propsFile.parentFile.mkdirs()
2471 def bytes = new ByteArrayOutputStream()
2472 props.store(bytes, null)
2473 def propertiesString = bytes.toString()
2474 propsFile.text = propertiesString
2480 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2483 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2484 outputs.file(propsFileName)
2485 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2489 task jalviewjsEclipsePaths {
2492 def eclipseRoot = jalviewjs_eclipse_root
2493 if (eclipseRoot.startsWith("~/")) {
2494 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
2496 if (OperatingSystem.current().isMacOsX()) {
2497 eclipseRoot += "/Eclipse.app"
2498 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
2499 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
2500 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
2501 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2502 eclipseRoot += "/eclipse"
2504 eclipseBinary = "${eclipseRoot}/eclipse.exe"
2505 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2506 } else { // linux or unix
2507 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2508 eclipseRoot += "/eclipse"
2509 println("eclipseDir exists")
2511 eclipseBinary = "${eclipseRoot}/eclipse"
2512 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2515 eclipseVersion = "4.13" // default
2516 def assumedVersion = true
2517 if (file(eclipseProduct).exists()) {
2518 def fis = new FileInputStream(eclipseProduct)
2519 def props = new Properties()
2521 eclipseVersion = props.getProperty("version")
2523 assumedVersion = false
2526 def propKey = "eclipse_debug"
2527 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
2530 // do not run a headless transpile when we claim to be in Eclipse
2532 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2533 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2535 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2538 if (!assumedVersion) {
2539 println("ECLIPSE VERSION=${eclipseVersion}")
2545 task printProperties {
2547 description "Output to console all System.properties"
2549 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
2555 dependsOn eclipseProject
2556 dependsOn eclipseClasspath
2557 dependsOn eclipseJdt
2561 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
2562 task jalviewjsEclipseCopyDropins(type: Copy) {
2563 dependsOn jalviewjsEclipsePaths
2565 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
2566 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
2567 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
2574 // this eclipse -clean doesn't actually work
2575 task jalviewjsCleanEclipse(type: Exec) {
2576 dependsOn eclipseSetup
2577 dependsOn jalviewjsEclipsePaths
2578 dependsOn jalviewjsEclipseCopyDropins
2580 executable(eclipseBinary)
2581 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
2587 def inputString = """exit
2590 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
2591 standardInput = inputByteStream
2594 /* not really working yet
2595 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
2599 task jalviewjsTransferUnzipSwingJs {
2600 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
2604 from zipTree(file_zip)
2605 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2609 inputs.file file_zip
2610 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2614 task jalviewjsTransferUnzipLib {
2615 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
2618 zipFiles.each { file_zip ->
2620 from zipTree(file_zip)
2621 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2626 inputs.files zipFiles
2627 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2631 task jalviewjsTransferUnzipAllLibs {
2632 dependsOn jalviewjsTransferUnzipSwingJs
2633 dependsOn jalviewjsTransferUnzipLib
2637 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
2639 description "Create the alternative j2s file from the j2s.* properties"
2641 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
2642 def siteDirProperty = "j2s.site.directory"
2643 def setSiteDir = false
2644 jalviewjsJ2sProps.each { prop, val ->
2646 if (prop == siteDirProperty) {
2647 if (!(val.startsWith('/') || val.startsWith("file://") )) {
2648 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
2654 if (!setSiteDir) { // default site location, don't override specifically set property
2655 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
2658 outputFile = jalviewjsJ2sAltSettingsFileName
2661 inputs.properties(jalviewjsJ2sProps)
2662 outputs.file(jalviewjsJ2sAltSettingsFileName)
2667 task jalviewjsEclipseSetup {
2668 dependsOn jalviewjsEclipseCopyDropins
2669 dependsOn jalviewjsSetEclipseWorkspace
2670 dependsOn jalviewjsCreateJ2sSettings
2674 task jalviewjsSyncAllLibs (type: Sync) {
2675 dependsOn jalviewjsTransferUnzipAllLibs
2676 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
2677 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
2678 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2682 def outputFiles = []
2683 rename { filename ->
2684 outputFiles += "${outputDir}/${filename}"
2691 // should this be exclude really ?
2692 duplicatesStrategy "INCLUDE"
2694 outputs.files outputFiles
2695 inputs.files inputFiles
2699 task jalviewjsSyncResources (type: Sync) {
2700 dependsOn buildResources
2702 def inputFiles = fileTree(dir: resourcesBuildDir)
2703 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
2707 def outputFiles = []
2708 rename { filename ->
2709 outputFiles += "${outputDir}/${filename}"
2715 outputs.files outputFiles
2716 inputs.files inputFiles
2720 task jalviewjsSyncSiteResources (type: Sync) {
2721 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
2722 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2726 def outputFiles = []
2727 rename { filename ->
2728 outputFiles += "${outputDir}/${filename}"
2734 outputs.files outputFiles
2735 inputs.files inputFiles
2739 task jalviewjsSyncBuildProperties (type: Sync) {
2740 dependsOn createBuildProperties
2741 def inputFiles = [file(buildProperties)]
2742 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
2746 def outputFiles = []
2747 rename { filename ->
2748 outputFiles += "${outputDir}/${filename}"
2754 outputs.files outputFiles
2755 inputs.files inputFiles
2759 task jalviewjsProjectImport(type: Exec) {
2760 dependsOn eclipseSetup
2761 dependsOn jalviewjsEclipsePaths
2762 dependsOn jalviewjsEclipseSetup
2765 // do not run a headless import when we claim to be in Eclipse
2767 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2768 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2770 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2774 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
2775 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
2776 executable(eclipseBinary)
2777 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
2781 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
2783 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
2784 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
2787 inputs.file("${jalviewDir}/.project")
2788 outputs.upToDateWhen {
2789 file(projdir).exists()
2794 task jalviewjsTranspile(type: Exec) {
2795 dependsOn jalviewjsEclipseSetup
2796 dependsOn jalviewjsProjectImport
2797 dependsOn jalviewjsEclipsePaths
2799 dependsOn jalviewjsEnableAltFileProperty
2803 // do not run a headless transpile when we claim to be in Eclipse
2805 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2806 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2808 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2812 executable(eclipseBinary)
2813 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
2817 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
2819 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
2820 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
2826 stdout = new ByteArrayOutputStream()
2827 stderr = new ByteArrayOutputStream()
2829 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
2830 def logOutFile = file(logOutFileName)
2831 logOutFile.createNewFile()
2832 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
2833 BINARY: ${eclipseBinary}
2834 VERSION: ${eclipseVersion}
2835 WORKSPACE: ${eclipseWorkspace}
2836 DEBUG: ${eclipseDebug}
2839 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
2840 // combine stdout and stderr
2841 def logErrFOS = logOutFOS
2843 if (jalviewjs_j2s_to_console.equals("true")) {
2844 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2845 new org.apache.tools.ant.util.TeeOutputStream(
2849 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2850 new org.apache.tools.ant.util.TeeOutputStream(
2855 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2858 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2865 if (stdout.toString().contains("Error processing ")) {
2866 // j2s did not complete transpile
2867 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2868 if (jalviewjs_ignore_transpile_errors.equals("true")) {
2869 println("IGNORING TRANSPILE ERRORS")
2870 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2872 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2877 inputs.dir("${jalviewDir}/${sourceDir}")
2878 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
2879 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
2883 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
2885 def stdout = new ByteArrayOutputStream()
2886 def stderr = new ByteArrayOutputStream()
2888 def coreFile = file(jsfile)
2890 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
2892 logOutFile.createNewFile()
2893 logOutFile.append(msg+"\n")
2895 def coreTop = file(prefixFile)
2896 def coreBottom = file(suffixFile)
2897 coreFile.getParentFile().mkdirs()
2898 coreFile.createNewFile()
2899 coreFile.write( coreTop.getText("UTF-8") )
2903 def t = f.getText("UTF-8")
2904 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
2905 coreFile.append( t )
2907 msg = "...file '"+f.getPath()+"' does not exist, skipping"
2909 logOutFile.append(msg+"\n")
2912 coreFile.append( coreBottom.getText("UTF-8") )
2914 msg = "Generating ${zjsfile}"
2916 logOutFile.append(msg+"\n")
2917 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
2918 def logErrFOS = logOutFOS
2921 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
2922 main = "com.google.javascript.jscomp.CommandLineRunner"
2923 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
2924 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
2927 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
2929 logOutFile.append(msg+"\n")
2931 if (logOutConsole) {
2932 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2933 new org.apache.tools.ant.util.TeeOutputStream(
2937 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2938 new org.apache.tools.ant.util.TeeOutputStream(
2943 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2946 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2953 logOutFile.append(msg+"\n")
2957 task jalviewjsBuildAllCores {
2959 description "Build the core js lib closures listed in the classlists dir"
2960 dependsOn jalviewjsTranspile
2961 dependsOn jalviewjsTransferUnzipSwingJs
2963 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
2964 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
2965 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
2966 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
2967 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
2968 def prefixFile = "${jsDir}/core/coretop2.js"
2969 def suffixFile = "${jsDir}/core/corebottom2.js"
2971 inputs.file prefixFile
2972 inputs.file suffixFile
2974 def classlistFiles = []
2975 // add the classlists found int the jalviewjs_classlists_dir
2976 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
2978 def name = file.getName() - ".txt"
2985 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
2986 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
2987 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
2989 jalviewjsCoreClasslists = []
2991 classlistFiles.each {
2994 def file = hash['file']
2995 if (! file.exists()) {
2996 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
2997 return false // this is a "continue" in groovy .each closure
2999 def name = hash['name']
3001 name = file.getName() - ".txt"
3009 def list = fileTree(dir: j2sDir, includes: filelist)
3011 def jsfile = "${outputDir}/core${name}.js"
3012 def zjsfile = "${outputDir}/core${name}.z.js"
3014 jalviewjsCoreClasslists += [
3023 outputs.file(jsfile)
3024 outputs.file(zjsfile)
3027 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
3028 def stevesoftClasslistName = "_stevesoft"
3029 def stevesoftClasslist = [
3030 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
3031 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
3032 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
3033 'name': stevesoftClasslistName
3035 jalviewjsCoreClasslists += stevesoftClasslist
3036 inputs.files(stevesoftClasslist['list'])
3037 outputs.file(stevesoftClasslist['jsfile'])
3038 outputs.file(stevesoftClasslist['zjsfile'])
3041 def allClasslistName = "_all"
3042 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3043 allJsFiles += fileTree(
3047 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3048 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3049 "**/org/jmol/export/JSExporter.js"
3052 allJsFiles += fileTree(
3056 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3057 "**/sun/misc/Unsafe.js",
3058 "**/swingjs/jquery/jquery-editable-select.js",
3059 "**/swingjs/jquery/j2sComboBox.js",
3060 "**/sun/misc/FloatingDecimal.js"
3063 def allClasslist = [
3064 'jsfile': "${outputDir}/core${allClasslistName}.js",
3065 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
3067 'name': allClasslistName
3069 // not including this version of "all" core at the moment
3070 //jalviewjsCoreClasslists += allClasslist
3071 inputs.files(allClasslist['list'])
3072 outputs.file(allClasslist['jsfile'])
3073 outputs.file(allClasslist['zjsfile'])
3076 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3077 logOutFile.getParentFile().mkdirs()
3078 logOutFile.createNewFile()
3079 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3081 jalviewjsCoreClasslists.each {
3082 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3089 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3092 into file(outputFile).getParentFile()
3093 rename { filename ->
3094 if (filename.equals(inputFile.getName())) {
3095 return file(outputFile).getName()
3099 filter(ReplaceTokens,
3103 'MAIN': '"'+main_class+'"',
3105 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3106 'COREKEY': jalviewjs_core_key,
3107 'CORENAME': coreName
3114 task jalviewjsPublishCoreTemplates {
3115 dependsOn jalviewjsBuildAllCores
3116 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3117 def inputFile = file(inputFileName)
3118 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3120 def outputFiles = []
3121 jalviewjsCoreClasslists.each { cl ->
3122 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3123 cl['outputfile'] = outputFile
3124 outputFiles += outputFile
3128 jalviewjsCoreClasslists.each { cl ->
3129 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3132 inputs.file(inputFile)
3133 outputs.files(outputFiles)
3137 task jalviewjsSyncCore (type: Sync) {
3138 dependsOn jalviewjsBuildAllCores
3139 dependsOn jalviewjsPublishCoreTemplates
3140 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3141 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3145 def outputFiles = []
3146 rename { filename ->
3147 outputFiles += "${outputDir}/${filename}"
3153 outputs.files outputFiles
3154 inputs.files inputFiles
3158 // this Copy version of TransferSiteJs will delete anything else in the target dir
3159 task jalviewjsCopyTransferSiteJs(type: Copy) {
3160 dependsOn jalviewjsTranspile
3161 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3162 into "${jalviewDir}/${jalviewjsSiteDir}"
3166 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3167 task jalviewjsSyncTransferSiteJs(type: Sync) {
3168 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3170 into "${jalviewDir}/${jalviewjsSiteDir}"
3177 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3178 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3179 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3180 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3182 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3183 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3184 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3185 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3188 task jalviewjsPrepareSite {
3190 description "Prepares the website folder including unzipping files and copying resources"
3191 dependsOn jalviewjsSyncAllLibs
3192 dependsOn jalviewjsSyncResources
3193 dependsOn jalviewjsSyncSiteResources
3194 dependsOn jalviewjsSyncBuildProperties
3195 dependsOn jalviewjsSyncCore
3199 task jalviewjsBuildSite {
3201 description "Builds the whole website including transpiled code"
3202 dependsOn jalviewjsCopyTransferSiteJs
3203 dependsOn jalviewjsPrepareSite
3207 task cleanJalviewjsTransferSite {
3209 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3210 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3211 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3212 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3217 task cleanJalviewjsSite {
3218 dependsOn cleanJalviewjsTransferSite
3220 delete "${jalviewDir}/${jalviewjsSiteDir}"
3225 task jalviewjsSiteTar(type: Tar) {
3227 description "Creates a tar.gz file for the website"
3228 dependsOn jalviewjsBuildSite
3229 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3230 archiveFileName = outputFilename
3232 compression Compression.GZIP
3234 from "${jalviewDir}/${jalviewjsSiteDir}"
3235 into jalviewjs_site_dir // this is inside the tar file
3237 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3241 task jalviewjsServer {
3243 def filename = "jalviewjsTest.html"
3244 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3245 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3250 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3251 factory = f.newInstance()
3252 } catch (ClassNotFoundException e) {
3253 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3255 def port = Integer.valueOf(jalviewjs_server_port)
3260 while(port < start+1000 && !running) {
3262 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3263 jalviewjsServer = factory.start(doc_root, port)
3265 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3266 println("SERVER STARTED with document root ${doc_root}.")
3267 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3268 println("For debug: "+url+"?j2sdebug")
3269 println("For verbose: "+url+"?j2sverbose")
3270 } catch (Exception e) {
3275 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3276 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3277 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3279 jalviewjsCoreClasslists.each { cl ->
3280 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3282 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3284 println("For core ${cl.name}: "+urlcore)
3287 file(htmlFile).text = htmlText
3290 outputs.file(htmlFile)
3291 outputs.upToDateWhen({false})
3295 task cleanJalviewjsAll {
3297 description "Delete all configuration and build artifacts to do with JalviewJS build"
3298 dependsOn cleanJalviewjsSite
3299 dependsOn jalviewjsEclipsePaths
3302 delete "${jalviewDir}/${jalviewjsBuildDir}"
3303 delete "${jalviewDir}/${eclipse_bin_dir}"
3304 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3305 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3307 delete jalviewjsJ2sAltSettingsFileName
3310 outputs.upToDateWhen( { false } )
3314 task jalviewjsIDE_checkJ2sPlugin {
3315 group "00 JalviewJS in Eclipse"
3316 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3319 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3320 def j2sPluginFile = file(j2sPlugin)
3321 def eclipseHome = System.properties["eclipse.home.location"]
3322 if (eclipseHome == null || ! IN_ECLIPSE) {
3323 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3325 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3326 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3327 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3328 eclipseJ2sPluginDirs += altPluginsDir
3330 def foundPlugin = false
3331 def j2sPluginFileName = j2sPluginFile.getName()
3332 def eclipseJ2sPlugin
3333 def eclipseJ2sPluginFile
3334 eclipseJ2sPluginDirs.any { dir ->
3335 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3336 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3337 if (eclipseJ2sPluginFile.exists()) {
3343 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3344 System.err.println(msg)
3345 throw new StopExecutionException(msg)
3348 def digest = MessageDigest.getInstance("MD5")
3350 digest.update(j2sPluginFile.text.bytes)
3351 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3353 digest.update(eclipseJ2sPluginFile.text.bytes)
3354 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3356 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3357 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3358 System.err.println(msg)
3359 throw new StopExecutionException(msg)
3361 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3367 task jalviewjsIDE_copyJ2sPlugin {
3368 group "00 JalviewJS in Eclipse"
3369 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3372 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3373 def j2sPluginFile = file(j2sPlugin)
3374 def eclipseHome = System.properties["eclipse.home.location"]
3375 if (eclipseHome == null || ! IN_ECLIPSE) {
3376 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3378 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3379 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3380 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3381 System.err.println(msg)
3384 eclipseJ2sPluginFile.getParentFile().mkdirs()
3385 into eclipseJ2sPluginFile.getParent()
3391 task jalviewjsIDE_j2sFile {
3392 group "00 JalviewJS in Eclipse"
3393 description "Creates the .j2s file"
3394 dependsOn jalviewjsCreateJ2sSettings
3398 task jalviewjsIDE_SyncCore {
3399 group "00 JalviewJS in Eclipse"
3400 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3401 dependsOn jalviewjsSyncCore
3405 task jalviewjsIDE_SyncSiteAll {
3406 dependsOn jalviewjsSyncAllLibs
3407 dependsOn jalviewjsSyncResources
3408 dependsOn jalviewjsSyncSiteResources
3409 dependsOn jalviewjsSyncBuildProperties
3413 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3416 task jalviewjsIDE_PrepareSite {
3417 group "00 JalviewJS in Eclipse"
3418 description "Sync libs and resources to site dir, but not closure cores"
3420 dependsOn jalviewjsIDE_SyncSiteAll
3421 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3425 task jalviewjsIDE_AssembleSite {
3426 group "00 JalviewJS in Eclipse"
3427 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3428 dependsOn jalviewjsPrepareSite
3432 task jalviewjsIDE_SiteClean {
3433 group "00 JalviewJS in Eclipse"
3434 description "Deletes the Eclipse transpiled site"
3435 dependsOn cleanJalviewjsSite
3439 task jalviewjsIDE_Server {
3440 group "00 JalviewJS in Eclipse"
3441 description "Starts a webserver on localhost to test the website"
3442 dependsOn jalviewjsServer
3446 // buildship runs this at import or gradle refresh
3447 task eclipseSynchronizationTask {
3448 //dependsOn eclipseSetup
3449 dependsOn createBuildProperties
3451 dependsOn jalviewjsIDE_j2sFile
3452 dependsOn jalviewjsIDE_checkJ2sPlugin
3453 dependsOn jalviewjsIDE_PrepareSite
3458 // buildship runs this at build time or project refresh
3459 task eclipseAutoBuildTask {
3460 //dependsOn jalviewjsIDE_checkJ2sPlugin
3461 //dependsOn jalviewjsIDE_PrepareSite
3467 description "Build the site"
3468 dependsOn jalviewjsBuildSite