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 getdownChannelDir = string("${getdown_website_dir}/${propertiesChannelName}")
198 getdownAppBaseDir = string("${jalviewDir}/${getdownChannelDir}/${JAVA_VERSION}")
199 getdownArchiveDir = string("${jalviewDir}/${getdown_archive_dir}")
200 getdownFullArchiveDir = null
201 getdownTextLines = []
202 getdownLaunchJvl = null
203 getdownVersionLaunchJvl = null
205 buildProperties = null
207 // the following values might be overridden by the CHANNEL switch
208 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
209 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
210 getdownArchiveAppBase = getdown_archive_base
211 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}")
212 getdownAppDistDir = getdown_app_dir_alt
213 getdownImagesDir = string("${jalviewDir}/${getdown_images_dir}")
214 getdownSetAppBaseProperty = false // whether to pass the appbase and appdistdir to the application
215 reportRsyncCommand = false
216 jvlChannelName = CHANNEL.toLowerCase()
217 install4jSuffix = CHANNEL.substring(0, 1).toUpperCase() + CHANNEL.substring(1).toLowerCase(); // BUILD -> Build
218 install4jDMGDSStore = "${install4j_images_dir}/${install4j_dmg_ds_store}"
219 install4jDMGBackgroundImage = "${install4j_images_dir}/${install4j_dmg_background}"
220 install4jInstallerName = "${jalview_name} Non-Release Installer"
221 install4jExecutableName = install4j_executable_name
222 install4jExtraScheme = "jalviewx"
223 install4jMacIconsFile = string("${install4j_images_dir}/${install4j_mac_icons_file}")
224 install4jWindowsIconsFile = string("${install4j_images_dir}/${install4j_windows_icons_file}")
225 install4jPngIconFile = string("${install4j_images_dir}/${install4j_png_icon_file}")
226 install4jBackground = string("${install4j_images_dir}/${install4j_background}")
227 install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
228 install4jCheckSums = true
232 // TODO: get bamboo build artifact URL for getdown artifacts
233 getdown_channel_base = bamboo_channelbase
234 getdownChannelName = string("${bamboo_planKey}/${JAVA_VERSION}")
235 getdownAppBase = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
236 jvlChannelName += "_${getdownChannelName}"
237 // automatically add the test group Not-bamboo for exclusion
238 if ("".equals(testng_excluded_groups)) {
239 testng_excluded_groups = "Not-bamboo"
241 install4jExtraScheme = "jalviewb"
244 case [ "RELEASE", "JALVIEWJS-RELEASE" ]:
245 getdownAppDistDir = getdown_app_dir_release
246 getdownSetAppBaseProperty = true
247 reportRsyncCommand = true
249 install4jInstallerName = "${jalview_name} Installer"
253 getdownChannelName = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
254 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
255 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
256 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
257 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
259 package_dir = string("${ARCHIVEDIR}/${package_dir}")
260 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
263 reportRsyncCommand = true
264 install4jExtraScheme = "jalviewa"
268 getdownChannelName = string("archive/${JALVIEW_VERSION}")
269 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
270 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
271 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
272 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
274 package_dir = string("${ARCHIVEDIR}/${package_dir}")
275 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
278 reportRsyncCommand = true
279 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
280 install4jSuffix = "Archive"
281 install4jExtraScheme = "jalviewa"
285 reportRsyncCommand = true
286 getdownSetAppBaseProperty = true
287 // DEVELOP-RELEASE is usually associated with a Jalview release series so set the version
288 JALVIEW_VERSION=JALVIEW_VERSION+"-d${buildDate}"
290 install4jSuffix = "Develop"
291 install4jExtraScheme = "jalviewd"
292 install4jInstallerName = "${jalview_name} Develop Installer"
296 reportRsyncCommand = true
297 getdownSetAppBaseProperty = true
298 // Don't ignore transpile errors for release build
299 if (jalviewjs_ignore_transpile_errors.equals("true")) {
300 jalviewjs_ignore_transpile_errors = "false"
301 println("Setting jalviewjs_ignore_transpile_errors to 'false'")
303 JALVIEW_VERSION = JALVIEW_VERSION+"-test"
304 install4jSuffix = "Test"
305 install4jExtraScheme = "jalviewt"
306 install4jInstallerName = "${jalview_name} Test Installer"
309 case ~/^SCRATCH(|-[-\w]*)$/:
310 getdownChannelName = CHANNEL
311 JALVIEW_VERSION = JALVIEW_VERSION+"-"+CHANNEL
313 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
314 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
315 reportRsyncCommand = true
316 install4jSuffix = "Scratch"
320 if (!file("${LOCALDIR}").exists()) {
321 throw new GradleException("Must provide a LOCALDIR value to produce a local distribution")
323 getdownAppBase = file(file("${LOCALDIR}").getAbsolutePath()).toURI().toString()
324 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
326 JALVIEW_VERSION = "TEST"
327 install4jSuffix = "Test-Local"
328 install4jExtraScheme = "jalviewt"
329 install4jInstallerName = "${jalview_name} Test Installer"
332 case [ "LOCAL", "JALVIEWJS" ]:
333 JALVIEW_VERSION = "TEST"
334 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
335 getdownArchiveAppBase = file("${jalviewDir}/${getdown_archive_dir}").toURI().toString()
336 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
337 install4jExtraScheme = "jalviewl"
338 install4jCheckSums = false
341 default: // something wrong specified
342 throw new GradleException("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
346 JALVIEW_VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
347 hugoDataJsonFile = file("${jalviewDir}/${hugo_build_dir}/data/installers/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
348 // override getdownAppBase if requested
349 if (findProperty("getdown_appbase_override") != null) {
350 // revert to LOCAL if empty string
351 if (string(getdown_appbase_override) == "") {
352 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
353 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
354 } else if (string(getdown_appbase_override).startsWith("file://")) {
355 getdownAppBase = string(getdown_appbase_override)
356 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
358 getdownAppBase = string(getdown_appbase_override)
360 println("Overriding getdown appbase with '${getdownAppBase}'")
362 // sanitise file name for jalview launcher file for this channel
363 jvlChannelName = jvlChannelName.replaceAll("[^\\w\\-]+", "_")
364 // install4j application and folder names
365 if (install4jSuffix == "") {
366 install4jApplicationName = "${jalview_name}"
367 install4jBundleId = "${install4j_bundle_id}"
368 install4jWinApplicationId = install4j_release_win_application_id
370 install4jApplicationName = "${jalview_name} ${install4jSuffix}"
371 install4jBundleId = "${install4j_bundle_id}-" + install4jSuffix.toLowerCase()
372 // add int hash of install4jSuffix to the last part of the application_id
373 def id = install4j_release_win_application_id
374 def idsplitreverse = id.split("-").reverse()
375 idsplitreverse[0] = idsplitreverse[0].toInteger() + install4jSuffix.hashCode()
376 install4jWinApplicationId = idsplitreverse.reverse().join("-")
378 // sanitise folder and id names
379 // install4jApplicationFolder = e.g. "Jalview Build"
380 install4jApplicationFolder = install4jApplicationName
381 .replaceAll("[\"'~:/\\\\\\s]", "_") // replace all awkward filename chars " ' ~ : / \
382 .replaceAll("_+", "_") // collapse __
383 install4jInternalId = install4jApplicationName
385 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
386 .replaceAll("_+", "") // collapse __
387 //.replaceAll("_*-_*", "-") // collapse _-_
388 install4jUnixApplicationFolder = install4jApplicationName
390 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
391 .replaceAll("_+", "_") // collapse __
392 .replaceAll("_*-_*", "-") // collapse _-_
395 getdownWrapperLink = install4jUnixApplicationFolder // e.g. "jalview_local"
396 getdownAppDir = string("${getdownAppBaseDir}/${getdownAppDistDir}")
397 //getdownJ11libDir = "${getdownAppBaseDir}/${getdown_j11lib_dir}"
398 getdownResourceDir = string("${getdownAppBaseDir}/${getdown_resource_dir}")
399 getdownInstallDir = string("${getdownAppBaseDir}/${getdown_install_dir}")
400 getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
401 getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
402 /* compile without modules -- using classpath libraries
403 modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
404 modules_runtimeClasspath = modules_compileClasspath
410 apply plugin: "com.palantir.git-version"
411 def details = versionDetails()
412 gitHash = details.gitHash
413 gitBranch = details.branchName
414 } catch(org.gradle.api.internal.plugins.PluginApplicationException e) {
415 println("Not in a git repository. Using git values from RELEASE properties file.")
416 gitHash = releaseProps.getProperty("git.hash")
417 gitBranch = releaseProps.getProperty("git.branch")
418 } catch(java.lang.RuntimeException e1) {
419 throw new GradleException("Error with git-version plugin. Directory '.git' exists but versionDetails() cannot be found.")
422 println("Using a ${CHANNEL} profile.")
424 additional_compiler_args = []
425 // configure classpath/args for j8/j11 compilation
426 if (JAVA_VERSION.equals("1.8")) {
427 JAVA_INTEGER_VERSION = string("8")
430 libDistDir = j8libDir
431 compile_source_compatibility = 1.8
432 compile_target_compatibility = 1.8
433 // these are getdown.txt properties defined dependent on the JAVA_VERSION
434 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
435 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
436 // this property is assigned below and expanded to multiple lines in the getdown task
437 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
438 // this property is for the Java library used in eclipse
439 eclipseJavaRuntimeName = string("JavaSE-1.8")
440 } else if (JAVA_VERSION.equals("11")) {
441 JAVA_INTEGER_VERSION = string("11")
443 libDistDir = j11libDir
444 compile_source_compatibility = 11
445 compile_target_compatibility = 11
446 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
447 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
448 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
449 eclipseJavaRuntimeName = string("JavaSE-11")
450 /* compile without modules -- using classpath libraries
451 additional_compiler_args += [
452 '--module-path', modules_compileClasspath.asPath,
453 '--add-modules', j11modules
456 } else if (JAVA_VERSION.equals("17")) {
457 JAVA_INTEGER_VERSION = string("17")
459 libDistDir = j17libDir
460 compile_source_compatibility = 17
461 compile_target_compatibility = 17
462 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
463 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
464 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
465 eclipseJavaRuntimeName = string("JavaSE-17")
466 /* compile without modules -- using classpath libraries
467 additional_compiler_args += [
468 '--module-path', modules_compileClasspath.asPath,
469 '--add-modules', j11modules
473 throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
478 JAVA_MIN_VERSION = JAVA_VERSION
479 JAVA_MAX_VERSION = JAVA_VERSION
480 def jreInstallsDir = string(jre_installs_dir)
481 if (jreInstallsDir.startsWith("~/")) {
482 jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
484 macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
485 windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
486 linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
487 macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_mac_x64.tar.gz")
488 windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_windows_x64.tar.gz")
489 linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_linux_x64.tar.gz")
490 install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
491 install4jConfFileName = string("jalview-install4j-conf.install4j")
492 install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
493 install4jHomeDir = install4j_home_dir
494 if (install4jHomeDir.startsWith("~/")) {
495 install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
498 resourceBuildDir = string("${buildDir}/resources")
499 resourcesBuildDir = string("${resourceBuildDir}/resources_build")
500 helpBuildDir = string("${resourceBuildDir}/help_build")
501 docBuildDir = string("${resourceBuildDir}/doc_build")
503 if (buildProperties == null) {
504 buildProperties = string("${resourcesBuildDir}/${build_properties_file}")
506 buildingHTML = string("${jalviewDir}/${doc_dir}/building.html")
507 helpParentDir = string("${jalviewDir}/${help_parent_dir}")
508 helpSourceDir = string("${helpParentDir}/${help_dir}")
509 helpFile = string("${helpBuildDir}/${help_dir}/help.jhm")
512 relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
513 jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
514 jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
516 jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
518 jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
520 jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
521 jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
522 jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
523 jalviewjsJalviewCoreHtmlFile = string("")
524 jalviewjsJalviewCoreName = string(jalviewjs_core_name)
525 jalviewjsCoreClasslists = []
526 jalviewjsJalviewTemplateName = string(jalviewjs_name)
527 jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
528 jalviewjsJ2sAltSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_alt_settings}")
529 jalviewjsJ2sProps = null
530 jalviewjsJ2sPlugin = jalviewjs_j2s_plugin
532 eclipseWorkspace = null
533 eclipseBinary = string("")
534 eclipseVersion = string("")
544 outputDir = file(classesDir)
548 srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ]
551 compileClasspath = files(sourceSets.main.java.outputDir)
552 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
554 runtimeClasspath = compileClasspath
555 runtimeClasspath += files(sourceSets.main.resources.srcDirs)
560 srcDirs cloverInstrDir
561 outputDir = cloverClassesDir
565 srcDirs = sourceSets.main.resources.srcDirs
568 compileClasspath = files( sourceSets.clover.java.outputDir )
569 //compileClasspath += files( testClassesDir )
570 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
571 compileClasspath += fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
572 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
574 runtimeClasspath = compileClasspath
579 srcDirs testSourceDir
580 outputDir = file(testClassesDir)
584 srcDirs = useClover ? sourceSets.clover.resources.srcDirs : sourceSets.main.resources.srcDirs
587 compileClasspath = files( sourceSets.test.java.outputDir )
588 compileClasspath += useClover ? sourceSets.clover.compileClasspath : sourceSets.main.compileClasspath
589 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
591 runtimeClasspath = compileClasspath
592 runtimeClasspath += files(sourceSets.test.resources.srcDirs)
598 // eclipse project and settings files creation, also used by buildship
601 name = eclipse_project_name
603 natures 'org.eclipse.jdt.core.javanature',
604 'org.eclipse.jdt.groovy.core.groovyNature',
605 'org.eclipse.buildship.core.gradleprojectnature'
607 buildCommand 'org.eclipse.jdt.core.javabuilder'
608 buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
612 //defaultOutputDir = sourceSets.main.java.outputDir
613 configurations.each{ c->
614 if (c.isCanBeResolved()) {
615 minusConfigurations += [c]
619 plusConfigurations = [ ]
623 def removeTheseToo = []
624 HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
625 cp.entries.each { entry ->
626 // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
627 // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
628 // we add the resources and help/help dirs in as libs afterwards (see below)
629 if (entry.kind == 'src') {
630 if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
631 removeTheseToo += entry
633 alreadyAddedSrcPath.putAt(entry.path, true)
638 cp.entries.removeAll(removeTheseToo)
640 //cp.entries += new Output("${eclipse_bin_dir}/main")
641 if (file(helpParentDir).isDirectory()) {
642 cp.entries += new Library(fileReference(helpParentDir))
644 if (file(resourceDir).isDirectory()) {
645 cp.entries += new Library(fileReference(resourceDir))
648 HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
650 sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
651 //don't want to add outputDir as eclipse is using its own output dir in bin/main
652 if (it.isDirectory() || ! it.exists()) {
653 // don't add dirs to classpath, especially if they don't exist
654 return false // groovy "continue" in .any closure
656 def itPath = it.toString()
657 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
658 // make relative path
659 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
661 if (alreadyAddedLibPath.get(itPath)) {
662 //println("Not adding duplicate entry "+itPath)
664 //println("Adding entry "+itPath)
665 cp.entries += new Library(fileReference(itPath))
666 alreadyAddedLibPath.put(itPath, true)
670 sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
671 //no longer want to add outputDir as eclipse is using its own output dir in bin/main
672 if (it.isDirectory() || ! it.exists()) {
673 // don't add dirs to classpath
674 return false // groovy "continue" in .any closure
677 def itPath = it.toString()
678 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
679 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
681 if (alreadyAddedLibPath.get(itPath)) {
684 def lib = new Library(fileReference(itPath))
685 lib.entryAttributes["test"] = "true"
687 alreadyAddedLibPath.put(itPath, true)
695 containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
700 // for the IDE, use java 11 compatibility
701 sourceCompatibility = compile_source_compatibility
702 targetCompatibility = compile_target_compatibility
703 javaRuntimeName = eclipseJavaRuntimeName
705 // add in jalview project specific properties/preferences into eclipse core preferences
707 withProperties { props ->
708 def jalview_prefs = new Properties()
709 def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
710 jalview_prefs.load(ins)
712 jalview_prefs.forEach { t, v ->
713 if (props.getAt(t) == null) {
717 // codestyle file -- overrides previous formatter prefs
718 def csFile = file("${jalviewDirAbsolutePath}/${eclipse_codestyle_file}")
719 if (csFile.exists()) {
720 XmlParser parser = new XmlParser()
721 def profiles = parser.parse(csFile)
722 def profile = profiles.'profile'.find { p -> (p.'@kind' == "CodeFormatterProfile" && p.'@name' == "Jalview") }
723 if (profile != null) {
724 profile.'setting'.each { s ->
726 def value = s.'@value'
727 if (id != null && value != null) {
728 props.putAt(id, value)
739 // Don't want these to be activated if in headless build
740 synchronizationTasks "eclipseSynchronizationTask"
741 //autoBuildTasks "eclipseAutoBuildTask"
747 /* hack to change eclipse prefs in .settings files other than org.eclipse.jdt.core.prefs */
748 // Class to allow updating arbitrary properties files
749 class PropertiesFile extends PropertiesPersistableConfigurationObject {
750 public PropertiesFile(PropertiesTransformer t) { super(t); }
751 @Override protected void load(Properties properties) { }
752 @Override protected void store(Properties properties) { }
753 @Override protected String getDefaultResourceName() { return ""; }
754 // This is necessary, because PropertiesPersistableConfigurationObject fails
755 // if no default properties file exists.
756 @Override public void loadDefaults() { load(new StringBufferInputStream("")); }
759 // Task to update arbitrary properties files (set outputFile)
760 class PropertiesFileTask extends PropertiesGeneratorTask<PropertiesFile> {
761 private final PropertiesFileContentMerger file;
762 public PropertiesFileTask() { file = new PropertiesFileContentMerger(getTransformer()); }
763 protected PropertiesFile create() { return new PropertiesFile(getTransformer()); }
764 protected void configure(PropertiesFile props) {
765 file.getBeforeMerged().execute(props); file.getWhenMerged().execute(props);
767 public void file(Closure closure) { ConfigureUtil.configure(closure, file); }
770 task eclipseUIPreferences(type: PropertiesFileTask) {
771 description = "Generate Eclipse additional settings"
772 def filename = "org.eclipse.jdt.ui.prefs"
773 outputFile = "$projectDir/.settings/${filename}" as File
776 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
781 task eclipseGroovyCorePreferences(type: PropertiesFileTask) {
782 description = "Generate Eclipse additional settings"
783 def filename = "org.eclipse.jdt.groovy.core.prefs"
784 outputFile = "$projectDir/.settings/${filename}" as File
787 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
792 task eclipseAllPreferences {
794 dependsOn eclipseUIPreferences
795 dependsOn eclipseGroovyCorePreferences
798 eclipseUIPreferences.mustRunAfter eclipseJdt
799 eclipseGroovyCorePreferences.mustRunAfter eclipseJdt
801 /* end of eclipse preferences hack */
809 delete cloverBuildDir
810 delete cloverReportDir
815 task cloverInstrJava(type: JavaExec) {
816 group = "Verification"
817 description = "Create clover instrumented source java files"
819 dependsOn cleanClover
821 inputs.files(sourceSets.main.allJava)
822 outputs.dir(cloverInstrDir)
824 //classpath = fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
825 classpath = sourceSets.clover.compileClasspath
826 main = "com.atlassian.clover.CloverInstr"
834 cloverInstrDir.getPath(),
836 def srcFiles = sourceSets.main.allJava.files
839 { file -> file.absolutePath }
842 args argsList.toArray()
845 delete cloverInstrDir
846 println("Clover: About to instrument "+srcFiles.size() +" files")
851 task cloverInstrTests(type: JavaExec) {
852 group = "Verification"
853 description = "Create clover instrumented source test files"
855 dependsOn cleanClover
857 inputs.files(testDir)
858 outputs.dir(cloverTestInstrDir)
860 classpath = sourceSets.clover.compileClasspath
861 main = "com.atlassian.clover.CloverInstr"
871 cloverTestInstrDir.getPath(),
873 args argsList.toArray()
876 delete cloverTestInstrDir
877 println("Clover: About to instrument test files")
883 group = "Verification"
884 description = "Create clover instrumented all source files"
886 dependsOn cloverInstrJava
887 dependsOn cloverInstrTests
891 cloverClasses.dependsOn cloverInstr
894 task cloverConsoleReport(type: JavaExec) {
895 group = "Verification"
896 description = "Creates clover console report"
899 file(cloverDb).exists()
902 inputs.dir cloverClassesDir
904 classpath = sourceSets.clover.runtimeClasspath
905 main = "com.atlassian.clover.reporters.console.ConsoleReporter"
907 if (cloverreport_mem.length() > 0) {
908 maxHeapSize = cloverreport_mem
910 if (cloverreport_jvmargs.length() > 0) {
911 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
921 args argsList.toArray()
925 task cloverHtmlReport(type: JavaExec) {
926 group = "Verification"
927 description = "Creates clover HTML report"
930 file(cloverDb).exists()
933 def cloverHtmlDir = cloverReportDir
934 inputs.dir cloverClassesDir
935 outputs.dir cloverHtmlDir
937 classpath = sourceSets.clover.runtimeClasspath
938 main = "com.atlassian.clover.reporters.html.HtmlReporter"
940 if (cloverreport_mem.length() > 0) {
941 maxHeapSize = cloverreport_mem
943 if (cloverreport_jvmargs.length() > 0) {
944 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
955 if (cloverreport_html_options.length() > 0) {
956 argsList += cloverreport_html_options.split(" ")
959 args argsList.toArray()
963 task cloverXmlReport(type: JavaExec) {
964 group = "Verification"
965 description = "Creates clover XML report"
968 file(cloverDb).exists()
971 def cloverXmlFile = "${cloverReportDir}/clover.xml"
972 inputs.dir cloverClassesDir
973 outputs.file cloverXmlFile
975 classpath = sourceSets.clover.runtimeClasspath
976 main = "com.atlassian.clover.reporters.xml.XMLReporter"
978 if (cloverreport_mem.length() > 0) {
979 maxHeapSize = cloverreport_mem
981 if (cloverreport_jvmargs.length() > 0) {
982 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
993 if (cloverreport_xml_options.length() > 0) {
994 argsList += cloverreport_xml_options.split(" ")
997 args argsList.toArray()
1002 group = "Verification"
1003 description = "Creates clover reports"
1005 dependsOn cloverXmlReport
1006 dependsOn cloverHtmlReport
1013 sourceCompatibility = compile_source_compatibility
1014 targetCompatibility = compile_target_compatibility
1015 options.compilerArgs += additional_compiler_args
1016 print ("Setting target compatibility to "+targetCompatibility+"\n")
1018 //classpath += configurations.cloverRuntime
1024 // JBP->BS should the print statement in doFirst refer to compile_target_compatibility ?
1025 sourceCompatibility = compile_source_compatibility
1026 targetCompatibility = compile_target_compatibility
1027 options.compilerArgs = additional_compiler_args
1028 options.encoding = "UTF-8"
1030 print ("Setting target compatibility to "+compile_target_compatibility+"\n")
1037 sourceCompatibility = compile_source_compatibility
1038 targetCompatibility = compile_target_compatibility
1039 options.compilerArgs = additional_compiler_args
1041 print ("Setting target compatibility to "+targetCompatibility+"\n")
1048 delete sourceSets.main.java.outputDir
1054 dependsOn cleanClover
1056 delete sourceSets.test.java.outputDir
1061 // format is a string like date.format("dd MMMM yyyy")
1062 def getDate(format) {
1063 return date.format(format)
1067 def convertMdToHtml (FileTree mdFiles, File cssFile) {
1068 MutableDataSet options = new MutableDataSet()
1070 def extensions = new ArrayList<>()
1071 extensions.add(AnchorLinkExtension.create())
1072 extensions.add(AutolinkExtension.create())
1073 extensions.add(StrikethroughExtension.create())
1074 extensions.add(TaskListExtension.create())
1075 extensions.add(TablesExtension.create())
1076 extensions.add(TocExtension.create())
1078 options.set(Parser.EXTENSIONS, extensions)
1080 // set GFM table parsing options
1081 options.set(TablesExtension.WITH_CAPTION, false)
1082 options.set(TablesExtension.COLUMN_SPANS, false)
1083 options.set(TablesExtension.MIN_HEADER_ROWS, 1)
1084 options.set(TablesExtension.MAX_HEADER_ROWS, 1)
1085 options.set(TablesExtension.APPEND_MISSING_COLUMNS, true)
1086 options.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
1087 options.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
1089 options.set(AnchorLinkExtension.ANCHORLINKS_SET_ID, false)
1090 options.set(AnchorLinkExtension.ANCHORLINKS_ANCHOR_CLASS, "anchor")
1091 options.set(AnchorLinkExtension.ANCHORLINKS_SET_NAME, true)
1092 options.set(AnchorLinkExtension.ANCHORLINKS_TEXT_PREFIX, "<span class=\"octicon octicon-link\"></span>")
1094 Parser parser = Parser.builder(options).build()
1095 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1097 mdFiles.each { mdFile ->
1098 // add table of contents
1099 def mdText = "[TOC]\n"+mdFile.text
1101 // grab the first top-level title
1103 def titleRegex = /(?m)^#(\s+|([^#]))(.*)/
1104 def matcher = mdText =~ titleRegex
1105 if (matcher.size() > 0) {
1106 // matcher[0][2] is the first character of the title if there wasn't any whitespace after the #
1107 title = (matcher[0][2] != null ? matcher[0][2] : "")+matcher[0][3]
1109 // or use the filename if none found
1110 if (title == null) {
1111 title = mdFile.getName()
1114 Node document = parser.parse(mdText)
1115 String htmlBody = renderer.render(document)
1116 def htmlText = '''<html>
1117 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1118 <html xmlns="http://www.w3.org/1999/xhtml">
1120 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1121 <meta http-equiv="Content-Style-Type" content="text/css" />
1122 <meta name="generator" content="flexmark" />
1124 htmlText += ((title != null) ? " <title>${title}</title>" : '' )
1126 <style type="text/css">code{white-space: pre;}</style>
1128 htmlText += ((cssFile != null) ? cssFile.text : '')
1129 htmlText += '''</head>
1132 htmlText += htmlBody
1138 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1139 def htmlFile = file(htmlFilePath)
1140 println("Creating ${htmlFilePath}")
1141 htmlFile.text = htmlText
1146 task copyDocs(type: Copy) {
1147 def inputDir = "${jalviewDir}/${doc_dir}"
1148 def outputDir = "${docBuildDir}/${doc_dir}"
1152 include('**/*.html')
1154 filter(ReplaceTokens,
1158 'Version-Rel': JALVIEW_VERSION,
1159 'Year-Rel': getDate("yyyy")
1166 exclude('**/*.html')
1171 inputs.dir(inputDir)
1172 outputs.dir(outputDir)
1176 task convertMdFiles {
1178 def mdFiles = fileTree(dir: docBuildDir, include: "**/*.md")
1179 def cssFile = file("${jalviewDir}/${flexmark_css}")
1182 convertMdToHtml(mdFiles, cssFile)
1185 inputs.files(mdFiles)
1186 inputs.file(cssFile)
1189 mdFiles.each { mdFile ->
1190 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1191 htmlFiles.add(file(htmlFilePath))
1193 outputs.files(htmlFiles)
1197 task copyHelp(type: Copy) {
1198 def inputDir = helpSourceDir
1199 def outputDir = "${helpBuildDir}/${help_dir}"
1203 include('**/*.html')
1207 filter(ReplaceTokens,
1211 'Version-Rel': JALVIEW_VERSION,
1212 'Year-Rel': getDate("yyyy")
1219 exclude('**/*.html')
1226 inputs.dir(inputDir)
1227 outputs.files(helpFile)
1228 outputs.dir(outputDir)
1232 task copyResources(type: Copy) {
1234 description = "Copy (and make text substitutions in) the resources dir to the build area"
1236 def inputDir = resourceDir
1237 def outputDir = resourcesBuildDir
1241 include('**/*.html')
1243 filter(ReplaceTokens,
1247 'Version-Rel': JALVIEW_VERSION,
1248 'Year-Rel': getDate("yyyy")
1255 exclude('**/*.html')
1260 inputs.dir(inputDir)
1261 outputs.dir(outputDir)
1264 task copyChannelResources(type: Copy) {
1265 dependsOn copyResources
1267 description = "Copy the channel resources dir to the build resources area"
1269 def inputDir = "${channelDir}/${resource_dir}"
1270 def outputDir = resourcesBuildDir
1274 inputs.dir(inputDir)
1275 outputs.dir(outputDir)
1278 task createBuildProperties(type: WriteProperties) {
1279 dependsOn copyResources
1281 description = "Create the ${buildProperties} file"
1283 inputs.dir(sourceDir)
1284 inputs.dir(resourcesBuildDir)
1285 outputFile (buildProperties)
1286 // taking time specific comment out to allow better incremental builds
1287 comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
1288 //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
1289 property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
1290 property "VERSION", JALVIEW_VERSION
1291 property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
1292 if (getdownSetAppBaseProperty) {
1293 property "GETDOWNAPPBASE", getdownAppBase
1294 property "GETDOWNAPPDISTDIR", getdownAppDistDir
1296 outputs.file(outputFile)
1300 task buildIndices(type: JavaExec) {
1302 classpath = sourceSets.main.compileClasspath
1303 main = "com.sun.java.help.search.Indexer"
1304 workingDir = "${helpBuildDir}/${help_dir}"
1307 inputs.dir("${workingDir}/${argDir}")
1309 outputs.dir("${classesDir}/doc")
1310 outputs.dir("${classesDir}/help")
1311 outputs.file("${workingDir}/JavaHelpSearch/DOCS")
1312 outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
1313 outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
1314 outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
1315 outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
1316 outputs.file("${workingDir}/JavaHelpSearch/TMAP")
1319 task buildResources {
1320 dependsOn copyResources
1321 dependsOn copyChannelResources
1322 dependsOn createBuildProperties
1326 dependsOn buildResources
1329 dependsOn convertMdFiles
1330 dependsOn buildIndices
1334 compileJava.dependsOn prepare
1335 run.dependsOn compileJava
1336 //run.dependsOn prepare
1339 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1344 dependsOn cloverClasses
1346 dependsOn compileJava //?
1350 includeGroups testng_groups
1351 excludeGroups testng_excluded_groups
1353 useDefaultListeners=true
1356 maxHeapSize = "1024m"
1358 workingDir = jalviewDir
1359 def testLaf = project.findProperty("test_laf")
1360 if (testLaf != null) {
1361 println("Setting Test LaF to '${testLaf}'")
1362 systemProperty "laf", testLaf
1364 def testHiDPIScale = project.findProperty("test_HiDPIScale")
1365 if (testHiDPIScale != null) {
1366 println("Setting Test HiDPI Scale to '${testHiDPIScale}'")
1367 systemProperty "sun.java2d.uiScale", testHiDPIScale
1369 sourceCompatibility = compile_source_compatibility
1370 targetCompatibility = compile_target_compatibility
1371 jvmArgs += additional_compiler_args
1375 println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1381 task compileLinkCheck(type: JavaCompile) {
1383 classpath = files("${jalviewDir}/${utils_dir}")
1384 destinationDir = file("${jalviewDir}/${utils_dir}")
1385 source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1387 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1388 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1389 outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1390 outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1394 task linkCheck(type: JavaExec) {
1396 dependsOn compileLinkCheck
1398 def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1399 classpath = files("${jalviewDir}/${utils_dir}")
1400 main = "HelpLinksChecker"
1401 workingDir = jalviewDir
1402 args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1404 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1405 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1408 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1412 inputs.dir(helpBuildDir)
1413 outputs.file(helpLinksCheckerOutFile)
1417 // import the pubhtmlhelp target
1418 ant.properties.basedir = "${jalviewDir}"
1419 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1420 ant.importBuild "${utils_dir}/publishHelp.xml"
1423 task cleanPackageDir(type: Delete) {
1425 delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1435 attributes "Main-Class": main_class,
1436 "Permissions": "all-permissions",
1437 "Application-Name": install4jApplicationName,
1438 "Codebase": application_codebase,
1439 "Implementation-Version": JALVIEW_VERSION
1442 def outputDir = "${jalviewDir}/${package_dir}"
1443 destinationDirectory = file(outputDir)
1444 archiveFileName = rootProject.name+".jar"
1445 duplicatesStrategy "EXCLUDE"
1452 exclude "**/*.jar.*"
1454 inputs.dir(sourceSets.main.java.outputDir)
1455 sourceSets.main.resources.srcDirs.each{ dir ->
1458 outputs.file("${outputDir}/${archiveFileName}")
1462 task copyJars(type: Copy) {
1463 from fileTree(dir: classesDir, include: "**/*.jar").files
1464 into "${jalviewDir}/${package_dir}"
1468 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1469 task syncJars(type: Sync) {
1471 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1472 into "${jalviewDir}/${package_dir}"
1474 include jar.archiveFileName.getOrNull()
1481 description = "Put all required libraries in dist"
1482 // order of "cleanPackageDir", "copyJars", "jar" important!
1483 jar.mustRunAfter cleanPackageDir
1484 syncJars.mustRunAfter cleanPackageDir
1485 dependsOn cleanPackageDir
1488 outputs.dir("${jalviewDir}/${package_dir}")
1493 dependsOn cleanPackageDir
1500 group = "distribution"
1501 description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1505 from ("${jalviewDir}/${libDistDir}") {
1509 attributes "Implementation-Version": JALVIEW_VERSION,
1510 "Application-Name": install4jApplicationName
1513 duplicatesStrategy "INCLUDE"
1515 mainClassName = shadow_jar_main_class
1517 classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1522 task getdownWebsite() {
1523 group = "distribution"
1524 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1529 def getdownWebsiteResourceFilenames = []
1530 def getdownResourceDir = getdownResourceDir
1531 def getdownResourceFilenames = []
1534 // clean the getdown website and files dir before creating getdown folders
1535 delete getdownAppBaseDir
1536 delete getdownFilesDir
1539 from buildProperties
1540 rename(file(buildProperties).getName(), getdown_build_properties)
1543 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1546 from channelPropsFile
1547 into getdownAppBaseDir
1549 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
1551 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
1552 def props = project.properties.sort { it.key }
1553 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
1554 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
1556 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
1557 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
1559 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
1560 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
1562 if (getdownImagesDir != null && file(getdownImagesDir).exists()) {
1563 props.put("getdown_txt_ui.background_image", "${getdownImagesDir}/${getdown_background_image}")
1564 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesDir}/${getdown_instant_background_image}")
1565 props.put("getdown_txt_ui.error_background", "${getdownImagesDir}/${getdown_error_background}")
1566 props.put("getdown_txt_ui.progress_image", "${getdownImagesDir}/${getdown_progress_image}")
1567 props.put("getdown_txt_ui.icon", "${getdownImagesDir}/${getdown_icon}")
1568 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesDir}/${getdown_mac_dock_icon}")
1571 props.put("getdown_txt_title", jalview_name)
1572 props.put("getdown_txt_ui.name", install4jApplicationName)
1574 // start with appbase
1575 getdownTextLines += "appbase = ${getdownAppBase}"
1576 props.each{ prop, val ->
1577 if (prop.startsWith("getdown_txt_") && val != null) {
1578 if (prop.startsWith("getdown_txt_multi_")) {
1579 def key = prop.substring(18)
1580 val.split(",").each{ v ->
1581 def line = "${key} = ${v}"
1582 getdownTextLines += line
1585 // file values rationalised
1586 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
1588 if (val.indexOf('/') == 0) {
1591 } else if (val.indexOf('/') > 0) {
1592 // relative path (relative to jalviewDir)
1593 r = file( "${jalviewDir}/${val}" )
1596 val = "${getdown_resource_dir}/" + r.getName()
1597 getdownWebsiteResourceFilenames += val
1598 getdownResourceFilenames += r.getPath()
1601 if (! prop.startsWith("getdown_txt_resource")) {
1602 def line = prop.substring(12) + " = ${val}"
1603 getdownTextLines += line
1609 getdownWebsiteResourceFilenames.each{ filename ->
1610 getdownTextLines += "resource = ${filename}"
1612 getdownResourceFilenames.each{ filename ->
1615 into getdownResourceDir
1619 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
1620 getdownWrapperScripts.each{ script ->
1621 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
1625 into "${getdownAppBaseDir}/${getdown_wrapper_script_dir}"
1627 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
1632 fileTree(file(package_dir)).each{ f ->
1633 if (f.isDirectory()) {
1634 def files = fileTree(dir: f, include: ["*"]).getFiles()
1636 } else if (f.exists()) {
1640 def jalviewJar = jar.archiveFileName.getOrNull()
1641 // put jalview.jar first for CLASSPATH and .properties files reasons
1642 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
1643 def name = f.getName()
1644 def line = "code = ${getdownAppDistDir}/${name}"
1645 getdownTextLines += line
1652 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
1654 if (JAVA_VERSION.equals("11")) {
1655 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
1656 j11libFiles.sort().each{f ->
1657 def name = f.getName()
1658 def line = "code = ${getdown_j11lib_dir}/${name}"
1659 getdownTextLines += line
1662 into getdownJ11libDir
1668 // 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.
1669 //getdownTextLines += "class = " + file(getdownLauncher).getName()
1670 getdownTextLines += "resource = ${getdown_launcher_new}"
1671 getdownTextLines += "class = ${main_class}"
1672 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
1673 if (getdownSetAppBaseProperty) {
1674 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
1675 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
1678 def getdownTxt = file("${getdownAppBaseDir}/getdown.txt")
1679 getdownTxt.write(getdownTextLines.join("\n"))
1681 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
1682 def launchJvl = file("${getdownAppBaseDir}/${getdownLaunchJvl}")
1683 launchJvl.write("appbase=${getdownAppBase}")
1685 // files going into the getdown website dir: getdown-launcher.jar
1687 from getdownLauncher
1688 rename(file(getdownLauncher).getName(), getdown_launcher_new)
1689 into getdownAppBaseDir
1692 // files going into the getdown website dir: getdown-launcher(-local).jar
1694 from getdownLauncher
1695 if (file(getdownLauncher).getName() != getdown_launcher) {
1696 rename(file(getdownLauncher).getName(), getdown_launcher)
1698 into getdownAppBaseDir
1701 // files going into the getdown website dir: ./install dir and files
1702 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
1705 from getdownLauncher
1706 from "${getdownAppDir}/${getdown_build_properties}"
1707 if (file(getdownLauncher).getName() != getdown_launcher) {
1708 rename(file(getdownLauncher).getName(), getdown_launcher)
1710 into getdownInstallDir
1713 // and make a copy in the getdown files dir (these are not downloaded by getdown)
1715 from getdownInstallDir
1716 into getdownFilesInstallDir
1720 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
1724 from getdownLauncher
1725 from "${getdownAppBaseDir}/${getdown_build_properties}"
1726 from "${getdownAppBaseDir}/${channel_props}"
1727 if (file(getdownLauncher).getName() != getdown_launcher) {
1728 rename(file(getdownLauncher).getName(), getdown_launcher)
1730 into getdownFilesDir
1733 // and ./resource (not all downloaded by getdown)
1735 from getdownResourceDir
1736 into "${getdownFilesDir}/${getdown_resource_dir}"
1741 inputs.dir("${jalviewDir}/${package_dir}")
1743 outputs.dir(getdownAppBaseDir)
1744 outputs.dir(getdownFilesDir)
1748 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
1749 task getdownDigestDir(type: JavaExec) {
1751 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
1753 def digestDirPropertyName = "DIGESTDIR"
1755 classpath = files(getdownLauncher)
1756 def digestDir = findProperty(digestDirPropertyName)
1757 if (digestDir == null) {
1758 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
1762 main = "com.threerings.getdown.tools.Digester"
1766 task getdownDigest(type: JavaExec) {
1767 group = "distribution"
1768 description = "Digest the getdown website folder"
1769 dependsOn getdownWebsite
1771 classpath = files(getdownLauncher)
1773 main = "com.threerings.getdown.tools.Digester"
1774 args getdownAppBaseDir
1775 inputs.dir(getdownAppBaseDir)
1776 outputs.file("${getdownAppBaseDir}/digest2.txt")
1781 group = "distribution"
1782 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
1783 dependsOn getdownDigest
1785 if (reportRsyncCommand) {
1786 def fromDir = getdownAppBaseDir + (getdownAppBaseDir.endsWith('/')?'':'/')
1787 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
1788 println "LIKELY RSYNC COMMAND:"
1789 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
1790 if (RUNRSYNC == "true") {
1792 commandLine "mkdir", "-p", toDir
1795 commandLine "rsync", "-avh", "--delete", fromDir, toDir
1803 task getdownArchiveBuild() {
1804 group = "distribution"
1805 description = "Put files in the archive dir to go on the website"
1807 dependsOn getdownWebsite
1809 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
1810 def vDir = "${getdownArchiveDir}/${v}"
1811 getdownFullArchiveDir = "${vDir}/getdown"
1812 getdownVersionLaunchJvl = "${vDir}/jalview-${v}.jvl"
1814 def vAltDir = "alt_${v}"
1815 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
1818 // cleanup old "old" dir
1819 delete getdownArchiveDir
1821 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
1822 getdownArchiveTxt.getParentFile().mkdirs()
1823 def getdownArchiveTextLines = []
1824 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
1828 from "${getdownAppBaseDir}/${getdownAppDistDir}"
1829 into "${getdownFullArchiveDir}/${vAltDir}"
1832 getdownTextLines.each { line ->
1833 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
1834 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
1835 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
1836 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
1837 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
1838 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
1839 // remove the existing resource = resource/ or bin/ lines
1840 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
1841 getdownArchiveTextLines += line
1845 // the resource dir -- add these files as resource lines in getdown.txt
1847 from "${archiveImagesDir}"
1848 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
1850 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
1854 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
1856 def vLaunchJvl = file(getdownVersionLaunchJvl)
1857 vLaunchJvl.getParentFile().mkdirs()
1858 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
1859 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
1860 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
1861 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
1862 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
1863 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
1865 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
1867 from getdownLauncher
1868 from "${getdownAppBaseDir}/${getdownLaunchJvl}"
1869 from "${getdownAppBaseDir}/${getdown_launcher_new}"
1870 from "${getdownAppBaseDir}/${channel_props}"
1871 if (file(getdownLauncher).getName() != getdown_launcher) {
1872 rename(file(getdownLauncher).getName(), getdown_launcher)
1874 into getdownFullArchiveDir
1880 task getdownArchiveDigest(type: JavaExec) {
1881 group = "distribution"
1882 description = "Digest the getdown archive folder"
1884 dependsOn getdownArchiveBuild
1887 classpath = files(getdownLauncher)
1888 args getdownFullArchiveDir
1890 main = "com.threerings.getdown.tools.Digester"
1891 inputs.dir(getdownFullArchiveDir)
1892 outputs.file("${getdownFullArchiveDir}/digest2.txt")
1895 task getdownArchive() {
1896 group = "distribution"
1897 description = "Build the website archive dir with getdown digest"
1899 dependsOn getdownArchiveBuild
1900 dependsOn getdownArchiveDigest
1903 tasks.withType(JavaCompile) {
1904 options.encoding = 'UTF-8'
1910 delete getdownAppBaseDir
1911 delete getdownFilesDir
1912 delete getdownArchiveDir
1918 if (file(install4jHomeDir).exists()) {
1920 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
1921 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
1922 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
1923 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
1925 installDir(file(install4jHomeDir))
1927 mediaTypes = Arrays.asList(install4j_media_types.split(","))
1931 task copyInstall4jTemplate {
1932 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
1933 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
1934 inputs.file(install4jTemplateFile)
1935 inputs.file(install4jFileAssociationsFile)
1936 inputs.property("CHANNEL", { CHANNEL })
1937 outputs.file(install4jConfFile)
1940 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
1942 // turn off code signing if no OSX_KEYPASS
1943 if (OSX_KEYPASS == "") {
1944 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
1945 codeSigning.'@macEnabled' = "false"
1947 install4jConfigXml.'**'.windows.each { windows ->
1948 windows.'@runPostProcessor' = "false"
1952 // disable install screen for OSX dmg (for 2.11.2.0)
1953 install4jConfigXml.'**'.macosArchive.each { macosArchive ->
1954 macosArchive.attributes().remove('executeSetupApp')
1955 macosArchive.attributes().remove('setupAppId')
1958 // turn off checksum creation for LOCAL channel
1959 def e = install4jConfigXml.application[0]
1960 e.'@createChecksums' = string(install4jCheckSums)
1962 // put file association actions where placeholder action is
1963 def install4jFileAssociationsText = install4jFileAssociationsFile.text
1964 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
1965 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
1966 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
1967 def parent = a.parent()
1969 fileAssociationActions.each { faa ->
1972 // don't need to continue in .any loop once replacements have been made
1977 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
1978 // NB we're deleting the /other/ one!
1979 // Also remove the examples subdir from non-release versions
1980 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
1981 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
1982 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
1983 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
1985 // remove the examples subdir from Full File Set
1986 def files = install4jConfigXml.files[0]
1987 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
1988 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
1989 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
1990 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
1991 dirEntry.parent().remove(dirEntry)
1993 install4jConfigXml.'**'.action.any { a ->
1994 if (a.'@customizedId' == customizedIdToDelete) {
1995 def parent = a.parent()
2001 // write install4j file
2002 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
2009 delete install4jConfFile
2013 task cleanInstallersDataFiles {
2014 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2015 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2016 def hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
2018 delete installersOutputTxt
2019 delete installersSha256
2020 delete hugoDataJsonFile
2024 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2025 group = "distribution"
2026 description = "Create the install4j installers"
2028 dependsOn copyInstall4jTemplate
2029 dependsOn cleanInstallersDataFiles
2031 projectFile = install4jConfFile
2033 // create an md5 for the input files to use as version for install4j conf file
2034 def digest = MessageDigest.getInstance("MD5")
2036 (file("${install4jDir}/${install4j_template}").text +
2037 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2038 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2039 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2040 if (filesMd5.length() >= 8) {
2041 filesMd5 = filesMd5.substring(0,8)
2043 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2046 'JALVIEW_NAME': jalview_name,
2047 'JALVIEW_APPLICATION_NAME': install4jApplicationName,
2048 'JALVIEW_DIR': "../..",
2049 'OSX_KEYSTORE': OSX_KEYSTORE,
2050 'OSX_APPLEID': OSX_APPLEID,
2051 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2052 'JSIGN_SH': JSIGN_SH,
2053 'JRE_DIR': getdown_app_dir_java,
2054 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2055 'JALVIEW_VERSION': JALVIEW_VERSION,
2056 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2057 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2058 'JAVA_VERSION': JAVA_VERSION,
2059 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2060 'VERSION': JALVIEW_VERSION,
2061 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2062 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2063 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2064 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2065 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2066 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2067 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2068 'BUNDLE_ID': install4jBundleId,
2069 'INTERNAL_ID': install4jInternalId,
2070 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2071 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2072 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
2073 'WRAPPER_LINK': getdownWrapperLink,
2074 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2075 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2076 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2077 'INSTALLER_NAME': install4jInstallerName,
2078 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2079 'GETDOWN_CHANNEL_DIR': getdownChannelDir,
2080 'GETDOWN_FILES_DIR': getdown_files_dir,
2081 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2082 'GETDOWN_DIST_DIR': getdownAppDistDir,
2083 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2084 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2085 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2086 'BUILD_DIR': install4jBuildDir,
2087 'APPLICATION_CATEGORIES': install4j_application_categories,
2088 'APPLICATION_FOLDER': install4jApplicationFolder,
2089 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2090 'EXECUTABLE_NAME': install4jExecutableName,
2091 'EXTRA_SCHEME': install4jExtraScheme,
2092 'MAC_ICONS_FILE': install4jMacIconsFile,
2093 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2094 'PNG_ICON_FILE': install4jPngIconFile,
2095 'BACKGROUND': install4jBackground,
2099 //println("INSTALL4J VARIABLES:")
2100 //variables.each{k,v->println("${k}=${v}")}
2102 destination = "${jalviewDir}/${install4jBuildDir}"
2103 buildSelected = true
2105 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2107 disableSigning = true
2108 disableNotarization = true
2112 macKeystorePassword = OSX_KEYPASS
2115 if (OSX_ALTOOLPASS) {
2116 appleIdPassword = OSX_ALTOOLPASS
2117 disableNotarization = false
2119 disableNotarization = true
2123 println("Using projectFile "+projectFile)
2124 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2128 inputs.dir(getdownAppBaseDir)
2129 inputs.file(install4jConfFile)
2130 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2131 inputs.dir(macosJavaVMDir)
2132 inputs.dir(windowsJavaVMDir)
2133 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2136 def getDataHash(File myFile) {
2137 HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
2138 return myFile.exists()
2140 "file" : myFile.getName(),
2141 "filesize" : myFile.length(),
2142 "sha256" : hash.toString()
2147 def writeDataJsonFile(File installersOutputTxt, File installersSha256, File dataJsonFile) {
2149 "channel" : getdownChannelName,
2150 "date" : getDate("yyyy-MM-dd HH:mm:ss"),
2151 "git-commit" : "${gitHash} [${gitBranch}]",
2152 "version" : JALVIEW_VERSION
2154 // install4j installer files
2155 if (installersOutputTxt.exists()) {
2157 installersOutputTxt.readLines().each { def line ->
2158 if (line.startsWith("#")) {
2161 line.replaceAll("\n","")
2162 def vals = line.split("\t")
2163 def filename = vals[3]
2164 def filesize = file(filename).length()
2165 filename = filename.replaceAll(/^.*\//, "")
2166 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2167 idHash."${filename}" = vals[0]
2169 if (install4jCheckSums && installersSha256.exists()) {
2170 installersSha256.readLines().each { def line ->
2171 if (line.startsWith("#")) {
2174 line.replaceAll("\n","")
2175 def vals = line.split(/\s+\*?/)
2176 def filename = vals[1]
2177 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2183 "JAR": shadowJar.archiveFile, // executable JAR
2184 "JVL": getdownVersionLaunchJvl, // version JVL
2185 "SOURCE": sourceDist.archiveFile // source TGZ
2186 ].each { key, value ->
2187 def file = file(value)
2188 if (file.exists()) {
2189 def fileHash = getDataHash(file)
2190 if (fileHash != null) {
2191 hash."${key}" = fileHash;
2195 return dataJsonFile.write(new JsonBuilder(hash).toPrettyString())
2198 task staticMakeInstallersJsonFile {
2200 def output = findProperty("i4j_output")
2201 def sha256 = findProperty("i4j_sha256")
2202 def json = findProperty("i4j_json")
2203 if (output == null || sha256 == null || json == null) {
2204 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2206 writeDataJsonFile(file(output), file(sha256), file(json))
2211 dependsOn installerFiles
2217 eclipse().configFile(eclipse_codestyle_file)
2221 task createSourceReleaseProperties(type: WriteProperties) {
2222 group = "distribution"
2223 description = "Create the source RELEASE properties file"
2225 def sourceTarBuildDir = "${buildDir}/sourceTar"
2226 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2227 outputFile (sourceReleasePropertiesFile)
2230 releaseProps.each{ key, val -> property key, val }
2231 property "git.branch", gitBranch
2232 property "git.hash", gitHash
2235 outputs.file(outputFile)
2238 task sourceDist(type: Tar) {
2239 group "distribution"
2240 description "Create a source .tar.gz file for distribution"
2242 dependsOn createBuildProperties
2243 dependsOn convertMdFiles
2244 dependsOn eclipseAllPreferences
2245 dependsOn createSourceReleaseProperties
2248 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2249 archiveFileName = outputFileName
2251 compression Compression.GZIP
2266 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2268 "utils/InstallAnywhere",
2283 "gradle.properties",
2295 ".settings/org.eclipse.buildship.core.prefs",
2296 ".settings/org.eclipse.jdt.core.prefs"
2300 exclude (EXCLUDE_FILES)
2301 include (PROCESS_FILES)
2302 filter(ReplaceTokens,
2306 'Version-Rel': JALVIEW_VERSION,
2307 'Year-Rel': getDate("yyyy")
2312 exclude (EXCLUDE_FILES)
2313 exclude (PROCESS_FILES)
2314 exclude ("appletlib")
2315 exclude ("**/*locales")
2316 exclude ("*locales/**")
2317 exclude ("utils/InstallAnywhere")
2319 exclude (getdown_files_dir)
2320 // getdown_website_dir and getdown_archive_dir moved to build/website/docroot/getdown
2321 //exclude (getdown_website_dir)
2322 //exclude (getdown_archive_dir)
2324 // exluding these as not using jars as modules yet
2325 exclude ("${j11modDir}/**/*.jar")
2328 include(INCLUDE_FILES)
2330 // from (jalviewDir) {
2331 // // explicit includes for stuff that seemed to not get included
2332 // include(fileTree("test/**/*."))
2333 // exclude(EXCLUDE_FILES)
2334 // exclude(PROCESS_FILES)
2337 from(file(buildProperties).getParent()) {
2338 include(file(buildProperties).getName())
2339 rename(file(buildProperties).getName(), "build_properties")
2341 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2345 def sourceTarBuildDir = "${buildDir}/sourceTar"
2346 from(sourceTarBuildDir) {
2347 // this includes the appended RELEASE properties file
2351 task dataInstallersJson {
2353 description "Create the installers-VERSION.json data file for installer files created"
2355 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2356 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2358 if (installersOutputTxt.exists()) {
2359 inputs.file(installersOutputTxt)
2361 if (install4jCheckSums && installersSha256.exists()) {
2362 inputs.file(installersSha256)
2365 shadowJar.archiveFile, // executable JAR
2366 getdownVersionLaunchJvl, // version JVL
2367 sourceDist.archiveFile // source TGZ
2368 ].each { fileName ->
2369 if (file(fileName).exists()) {
2370 inputs.file(fileName)
2374 outputs.file(hugoDataJsonFile)
2377 writeDataJsonFile(installersOutputTxt, installersSha256, hugoDataJsonFile)
2381 dataInstallersJson.mustRunAfter installers
2382 dataInstallersJson.mustRunAfter shadowJar
2383 dataInstallersJson.mustRunAfter sourceDist
2384 dataInstallersJson.mustRunAfter getdownArchive
2389 dependsOn pubhtmlhelp
2391 inputs.dir("${helpBuildDir}/${help_dir}")
2392 outputs.dir("${buildDir}/distributions/${help_dir}")
2396 task j2sSetHeadlessBuild {
2403 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2405 description "Enable the alternative J2S Config file for headless build"
2407 outputFile = jalviewjsJ2sSettingsFileName
2408 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2409 def j2sProps = new Properties()
2410 if (j2sPropsFile.exists()) {
2412 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2413 j2sProps.load(j2sPropsFileFIS)
2414 j2sPropsFileFIS.close()
2416 j2sProps.each { prop, val ->
2419 } catch (Exception e) {
2420 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2424 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2425 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2430 task jalviewjsSetEclipseWorkspace {
2431 def propKey = "jalviewjs_eclipse_workspace"
2433 if (project.hasProperty(propKey)) {
2434 propVal = project.getProperty(propKey)
2435 if (propVal.startsWith("~/")) {
2436 propVal = System.getProperty("user.home") + propVal.substring(1)
2439 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2440 def propsFile = file(propsFileName)
2441 def eclipseWsDir = propVal
2442 def props = new Properties()
2444 def writeProps = true
2445 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2446 def ins = new FileInputStream(propsFileName)
2449 if (props.getProperty(propKey, null) != null) {
2450 eclipseWsDir = props.getProperty(propKey)
2455 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2456 def tempDir = File.createTempDir()
2457 eclipseWsDir = tempDir.getAbsolutePath()
2460 eclipseWorkspace = file(eclipseWsDir)
2463 // do not run a headless transpile when we claim to be in Eclipse
2465 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2466 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2468 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2472 props.setProperty(propKey, eclipseWsDir)
2473 propsFile.parentFile.mkdirs()
2474 def bytes = new ByteArrayOutputStream()
2475 props.store(bytes, null)
2476 def propertiesString = bytes.toString()
2477 propsFile.text = propertiesString
2483 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2486 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2487 outputs.file(propsFileName)
2488 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2492 task jalviewjsEclipsePaths {
2495 def eclipseRoot = jalviewjs_eclipse_root
2496 if (eclipseRoot.startsWith("~/")) {
2497 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
2499 if (OperatingSystem.current().isMacOsX()) {
2500 eclipseRoot += "/Eclipse.app"
2501 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
2502 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
2503 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
2504 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2505 eclipseRoot += "/eclipse"
2507 eclipseBinary = "${eclipseRoot}/eclipse.exe"
2508 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2509 } else { // linux or unix
2510 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2511 eclipseRoot += "/eclipse"
2512 println("eclipseDir exists")
2514 eclipseBinary = "${eclipseRoot}/eclipse"
2515 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2518 eclipseVersion = "4.13" // default
2519 def assumedVersion = true
2520 if (file(eclipseProduct).exists()) {
2521 def fis = new FileInputStream(eclipseProduct)
2522 def props = new Properties()
2524 eclipseVersion = props.getProperty("version")
2526 assumedVersion = false
2529 def propKey = "eclipse_debug"
2530 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
2533 // do not run a headless transpile when we claim to be in Eclipse
2535 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2536 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2538 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2541 if (!assumedVersion) {
2542 println("ECLIPSE VERSION=${eclipseVersion}")
2548 task printProperties {
2550 description "Output to console all System.properties"
2552 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
2558 dependsOn eclipseProject
2559 dependsOn eclipseClasspath
2560 dependsOn eclipseJdt
2564 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
2565 task jalviewjsEclipseCopyDropins(type: Copy) {
2566 dependsOn jalviewjsEclipsePaths
2568 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
2569 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
2570 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
2577 // this eclipse -clean doesn't actually work
2578 task jalviewjsCleanEclipse(type: Exec) {
2579 dependsOn eclipseSetup
2580 dependsOn jalviewjsEclipsePaths
2581 dependsOn jalviewjsEclipseCopyDropins
2583 executable(eclipseBinary)
2584 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
2590 def inputString = """exit
2593 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
2594 standardInput = inputByteStream
2597 /* not really working yet
2598 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
2602 task jalviewjsTransferUnzipSwingJs {
2603 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
2607 from zipTree(file_zip)
2608 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2612 inputs.file file_zip
2613 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2617 task jalviewjsTransferUnzipLib {
2618 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
2621 zipFiles.each { file_zip ->
2623 from zipTree(file_zip)
2624 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2629 inputs.files zipFiles
2630 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2634 task jalviewjsTransferUnzipAllLibs {
2635 dependsOn jalviewjsTransferUnzipSwingJs
2636 dependsOn jalviewjsTransferUnzipLib
2640 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
2642 description "Create the alternative j2s file from the j2s.* properties"
2644 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
2645 def siteDirProperty = "j2s.site.directory"
2646 def setSiteDir = false
2647 jalviewjsJ2sProps.each { prop, val ->
2649 if (prop == siteDirProperty) {
2650 if (!(val.startsWith('/') || val.startsWith("file://") )) {
2651 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
2657 if (!setSiteDir) { // default site location, don't override specifically set property
2658 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
2661 outputFile = jalviewjsJ2sAltSettingsFileName
2664 inputs.properties(jalviewjsJ2sProps)
2665 outputs.file(jalviewjsJ2sAltSettingsFileName)
2670 task jalviewjsEclipseSetup {
2671 dependsOn jalviewjsEclipseCopyDropins
2672 dependsOn jalviewjsSetEclipseWorkspace
2673 dependsOn jalviewjsCreateJ2sSettings
2677 task jalviewjsSyncAllLibs (type: Sync) {
2678 dependsOn jalviewjsTransferUnzipAllLibs
2679 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
2680 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
2681 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2685 def outputFiles = []
2686 rename { filename ->
2687 outputFiles += "${outputDir}/${filename}"
2694 // should this be exclude really ?
2695 duplicatesStrategy "INCLUDE"
2697 outputs.files outputFiles
2698 inputs.files inputFiles
2702 task jalviewjsSyncResources (type: Sync) {
2703 dependsOn buildResources
2705 def inputFiles = fileTree(dir: resourcesBuildDir)
2706 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
2710 def outputFiles = []
2711 rename { filename ->
2712 outputFiles += "${outputDir}/${filename}"
2718 outputs.files outputFiles
2719 inputs.files inputFiles
2723 task jalviewjsSyncSiteResources (type: Sync) {
2724 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
2725 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2729 def outputFiles = []
2730 rename { filename ->
2731 outputFiles += "${outputDir}/${filename}"
2737 outputs.files outputFiles
2738 inputs.files inputFiles
2742 task jalviewjsSyncBuildProperties (type: Sync) {
2743 dependsOn createBuildProperties
2744 def inputFiles = [file(buildProperties)]
2745 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
2749 def outputFiles = []
2750 rename { filename ->
2751 outputFiles += "${outputDir}/${filename}"
2757 outputs.files outputFiles
2758 inputs.files inputFiles
2762 task jalviewjsProjectImport(type: Exec) {
2763 dependsOn eclipseSetup
2764 dependsOn jalviewjsEclipsePaths
2765 dependsOn jalviewjsEclipseSetup
2768 // do not run a headless import when we claim to be in Eclipse
2770 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2771 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2773 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2777 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
2778 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
2779 executable(eclipseBinary)
2780 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
2784 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
2786 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
2787 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
2790 inputs.file("${jalviewDir}/.project")
2791 outputs.upToDateWhen {
2792 file(projdir).exists()
2797 task jalviewjsTranspile(type: Exec) {
2798 dependsOn jalviewjsEclipseSetup
2799 dependsOn jalviewjsProjectImport
2800 dependsOn jalviewjsEclipsePaths
2802 dependsOn jalviewjsEnableAltFileProperty
2806 // do not run a headless transpile when we claim to be in Eclipse
2808 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2809 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2811 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2815 executable(eclipseBinary)
2816 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
2820 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
2822 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
2823 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
2829 stdout = new ByteArrayOutputStream()
2830 stderr = new ByteArrayOutputStream()
2832 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
2833 def logOutFile = file(logOutFileName)
2834 logOutFile.createNewFile()
2835 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
2836 BINARY: ${eclipseBinary}
2837 VERSION: ${eclipseVersion}
2838 WORKSPACE: ${eclipseWorkspace}
2839 DEBUG: ${eclipseDebug}
2842 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
2843 // combine stdout and stderr
2844 def logErrFOS = logOutFOS
2846 if (jalviewjs_j2s_to_console.equals("true")) {
2847 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2848 new org.apache.tools.ant.util.TeeOutputStream(
2852 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2853 new org.apache.tools.ant.util.TeeOutputStream(
2858 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2861 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2868 if (stdout.toString().contains("Error processing ")) {
2869 // j2s did not complete transpile
2870 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2871 if (jalviewjs_ignore_transpile_errors.equals("true")) {
2872 println("IGNORING TRANSPILE ERRORS")
2873 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2875 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2880 inputs.dir("${jalviewDir}/${sourceDir}")
2881 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
2882 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
2886 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
2888 def stdout = new ByteArrayOutputStream()
2889 def stderr = new ByteArrayOutputStream()
2891 def coreFile = file(jsfile)
2893 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
2895 logOutFile.createNewFile()
2896 logOutFile.append(msg+"\n")
2898 def coreTop = file(prefixFile)
2899 def coreBottom = file(suffixFile)
2900 coreFile.getParentFile().mkdirs()
2901 coreFile.createNewFile()
2902 coreFile.write( coreTop.getText("UTF-8") )
2906 def t = f.getText("UTF-8")
2907 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
2908 coreFile.append( t )
2910 msg = "...file '"+f.getPath()+"' does not exist, skipping"
2912 logOutFile.append(msg+"\n")
2915 coreFile.append( coreBottom.getText("UTF-8") )
2917 msg = "Generating ${zjsfile}"
2919 logOutFile.append(msg+"\n")
2920 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
2921 def logErrFOS = logOutFOS
2924 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
2925 main = "com.google.javascript.jscomp.CommandLineRunner"
2926 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
2927 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
2930 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
2932 logOutFile.append(msg+"\n")
2934 if (logOutConsole) {
2935 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2936 new org.apache.tools.ant.util.TeeOutputStream(
2940 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2941 new org.apache.tools.ant.util.TeeOutputStream(
2946 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2949 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2956 logOutFile.append(msg+"\n")
2960 task jalviewjsBuildAllCores {
2962 description "Build the core js lib closures listed in the classlists dir"
2963 dependsOn jalviewjsTranspile
2964 dependsOn jalviewjsTransferUnzipSwingJs
2966 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
2967 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
2968 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
2969 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
2970 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
2971 def prefixFile = "${jsDir}/core/coretop2.js"
2972 def suffixFile = "${jsDir}/core/corebottom2.js"
2974 inputs.file prefixFile
2975 inputs.file suffixFile
2977 def classlistFiles = []
2978 // add the classlists found int the jalviewjs_classlists_dir
2979 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
2981 def name = file.getName() - ".txt"
2988 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
2989 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
2990 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
2992 jalviewjsCoreClasslists = []
2994 classlistFiles.each {
2997 def file = hash['file']
2998 if (! file.exists()) {
2999 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
3000 return false // this is a "continue" in groovy .each closure
3002 def name = hash['name']
3004 name = file.getName() - ".txt"
3012 def list = fileTree(dir: j2sDir, includes: filelist)
3014 def jsfile = "${outputDir}/core${name}.js"
3015 def zjsfile = "${outputDir}/core${name}.z.js"
3017 jalviewjsCoreClasslists += [
3026 outputs.file(jsfile)
3027 outputs.file(zjsfile)
3030 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
3031 def stevesoftClasslistName = "_stevesoft"
3032 def stevesoftClasslist = [
3033 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
3034 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
3035 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
3036 'name': stevesoftClasslistName
3038 jalviewjsCoreClasslists += stevesoftClasslist
3039 inputs.files(stevesoftClasslist['list'])
3040 outputs.file(stevesoftClasslist['jsfile'])
3041 outputs.file(stevesoftClasslist['zjsfile'])
3044 def allClasslistName = "_all"
3045 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3046 allJsFiles += fileTree(
3050 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3051 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3052 "**/org/jmol/export/JSExporter.js"
3055 allJsFiles += fileTree(
3059 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3060 "**/sun/misc/Unsafe.js",
3061 "**/swingjs/jquery/jquery-editable-select.js",
3062 "**/swingjs/jquery/j2sComboBox.js",
3063 "**/sun/misc/FloatingDecimal.js"
3066 def allClasslist = [
3067 'jsfile': "${outputDir}/core${allClasslistName}.js",
3068 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
3070 'name': allClasslistName
3072 // not including this version of "all" core at the moment
3073 //jalviewjsCoreClasslists += allClasslist
3074 inputs.files(allClasslist['list'])
3075 outputs.file(allClasslist['jsfile'])
3076 outputs.file(allClasslist['zjsfile'])
3079 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3080 logOutFile.getParentFile().mkdirs()
3081 logOutFile.createNewFile()
3082 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3084 jalviewjsCoreClasslists.each {
3085 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3092 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3095 into file(outputFile).getParentFile()
3096 rename { filename ->
3097 if (filename.equals(inputFile.getName())) {
3098 return file(outputFile).getName()
3102 filter(ReplaceTokens,
3106 'MAIN': '"'+main_class+'"',
3108 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3109 'COREKEY': jalviewjs_core_key,
3110 'CORENAME': coreName
3117 task jalviewjsPublishCoreTemplates {
3118 dependsOn jalviewjsBuildAllCores
3119 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3120 def inputFile = file(inputFileName)
3121 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3123 def outputFiles = []
3124 jalviewjsCoreClasslists.each { cl ->
3125 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3126 cl['outputfile'] = outputFile
3127 outputFiles += outputFile
3131 jalviewjsCoreClasslists.each { cl ->
3132 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3135 inputs.file(inputFile)
3136 outputs.files(outputFiles)
3140 task jalviewjsSyncCore (type: Sync) {
3141 dependsOn jalviewjsBuildAllCores
3142 dependsOn jalviewjsPublishCoreTemplates
3143 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3144 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3148 def outputFiles = []
3149 rename { filename ->
3150 outputFiles += "${outputDir}/${filename}"
3156 outputs.files outputFiles
3157 inputs.files inputFiles
3161 // this Copy version of TransferSiteJs will delete anything else in the target dir
3162 task jalviewjsCopyTransferSiteJs(type: Copy) {
3163 dependsOn jalviewjsTranspile
3164 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3165 into "${jalviewDir}/${jalviewjsSiteDir}"
3169 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3170 task jalviewjsSyncTransferSiteJs(type: Sync) {
3171 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3173 into "${jalviewDir}/${jalviewjsSiteDir}"
3180 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3181 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3182 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3183 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3185 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3186 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3187 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3188 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3191 task jalviewjsPrepareSite {
3193 description "Prepares the website folder including unzipping files and copying resources"
3194 dependsOn jalviewjsSyncAllLibs
3195 dependsOn jalviewjsSyncResources
3196 dependsOn jalviewjsSyncSiteResources
3197 dependsOn jalviewjsSyncBuildProperties
3198 dependsOn jalviewjsSyncCore
3202 task jalviewjsBuildSite {
3204 description "Builds the whole website including transpiled code"
3205 dependsOn jalviewjsCopyTransferSiteJs
3206 dependsOn jalviewjsPrepareSite
3210 task cleanJalviewjsTransferSite {
3212 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3213 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3214 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3215 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3220 task cleanJalviewjsSite {
3221 dependsOn cleanJalviewjsTransferSite
3223 delete "${jalviewDir}/${jalviewjsSiteDir}"
3228 task jalviewjsSiteTar(type: Tar) {
3230 description "Creates a tar.gz file for the website"
3231 dependsOn jalviewjsBuildSite
3232 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3233 archiveFileName = outputFilename
3235 compression Compression.GZIP
3237 from "${jalviewDir}/${jalviewjsSiteDir}"
3238 into jalviewjs_site_dir // this is inside the tar file
3240 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3244 task jalviewjsServer {
3246 def filename = "jalviewjsTest.html"
3247 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3248 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3253 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3254 factory = f.newInstance()
3255 } catch (ClassNotFoundException e) {
3256 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3258 def port = Integer.valueOf(jalviewjs_server_port)
3263 while(port < start+1000 && !running) {
3265 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3266 jalviewjsServer = factory.start(doc_root, port)
3268 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3269 println("SERVER STARTED with document root ${doc_root}.")
3270 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3271 println("For debug: "+url+"?j2sdebug")
3272 println("For verbose: "+url+"?j2sverbose")
3273 } catch (Exception e) {
3278 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3279 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3280 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3282 jalviewjsCoreClasslists.each { cl ->
3283 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3285 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3287 println("For core ${cl.name}: "+urlcore)
3290 file(htmlFile).text = htmlText
3293 outputs.file(htmlFile)
3294 outputs.upToDateWhen({false})
3298 task cleanJalviewjsAll {
3300 description "Delete all configuration and build artifacts to do with JalviewJS build"
3301 dependsOn cleanJalviewjsSite
3302 dependsOn jalviewjsEclipsePaths
3305 delete "${jalviewDir}/${jalviewjsBuildDir}"
3306 delete "${jalviewDir}/${eclipse_bin_dir}"
3307 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3308 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3310 delete jalviewjsJ2sAltSettingsFileName
3313 outputs.upToDateWhen( { false } )
3317 task jalviewjsIDE_checkJ2sPlugin {
3318 group "00 JalviewJS in Eclipse"
3319 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3322 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3323 def j2sPluginFile = file(j2sPlugin)
3324 def eclipseHome = System.properties["eclipse.home.location"]
3325 if (eclipseHome == null || ! IN_ECLIPSE) {
3326 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3328 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3329 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3330 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3331 eclipseJ2sPluginDirs += altPluginsDir
3333 def foundPlugin = false
3334 def j2sPluginFileName = j2sPluginFile.getName()
3335 def eclipseJ2sPlugin
3336 def eclipseJ2sPluginFile
3337 eclipseJ2sPluginDirs.any { dir ->
3338 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3339 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3340 if (eclipseJ2sPluginFile.exists()) {
3346 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3347 System.err.println(msg)
3348 throw new StopExecutionException(msg)
3351 def digest = MessageDigest.getInstance("MD5")
3353 digest.update(j2sPluginFile.text.bytes)
3354 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3356 digest.update(eclipseJ2sPluginFile.text.bytes)
3357 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3359 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3360 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3361 System.err.println(msg)
3362 throw new StopExecutionException(msg)
3364 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3370 task jalviewjsIDE_copyJ2sPlugin {
3371 group "00 JalviewJS in Eclipse"
3372 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3375 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3376 def j2sPluginFile = file(j2sPlugin)
3377 def eclipseHome = System.properties["eclipse.home.location"]
3378 if (eclipseHome == null || ! IN_ECLIPSE) {
3379 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3381 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3382 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3383 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3384 System.err.println(msg)
3387 eclipseJ2sPluginFile.getParentFile().mkdirs()
3388 into eclipseJ2sPluginFile.getParent()
3394 task jalviewjsIDE_j2sFile {
3395 group "00 JalviewJS in Eclipse"
3396 description "Creates the .j2s file"
3397 dependsOn jalviewjsCreateJ2sSettings
3401 task jalviewjsIDE_SyncCore {
3402 group "00 JalviewJS in Eclipse"
3403 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3404 dependsOn jalviewjsSyncCore
3408 task jalviewjsIDE_SyncSiteAll {
3409 dependsOn jalviewjsSyncAllLibs
3410 dependsOn jalviewjsSyncResources
3411 dependsOn jalviewjsSyncSiteResources
3412 dependsOn jalviewjsSyncBuildProperties
3416 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3419 task jalviewjsIDE_PrepareSite {
3420 group "00 JalviewJS in Eclipse"
3421 description "Sync libs and resources to site dir, but not closure cores"
3423 dependsOn jalviewjsIDE_SyncSiteAll
3424 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3428 task jalviewjsIDE_AssembleSite {
3429 group "00 JalviewJS in Eclipse"
3430 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3431 dependsOn jalviewjsPrepareSite
3435 task jalviewjsIDE_SiteClean {
3436 group "00 JalviewJS in Eclipse"
3437 description "Deletes the Eclipse transpiled site"
3438 dependsOn cleanJalviewjsSite
3442 task jalviewjsIDE_Server {
3443 group "00 JalviewJS in Eclipse"
3444 description "Starts a webserver on localhost to test the website"
3445 dependsOn jalviewjsServer
3449 // buildship runs this at import or gradle refresh
3450 task eclipseSynchronizationTask {
3451 //dependsOn eclipseSetup
3452 dependsOn createBuildProperties
3454 dependsOn jalviewjsIDE_j2sFile
3455 dependsOn jalviewjsIDE_checkJ2sPlugin
3456 dependsOn jalviewjsIDE_PrepareSite
3461 // buildship runs this at build time or project refresh
3462 task eclipseAutoBuildTask {
3463 //dependsOn jalviewjsIDE_checkJ2sPlugin
3464 //dependsOn jalviewjsIDE_PrepareSite
3470 description "Build the site"
3471 dependsOn jalviewjsBuildSite