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
50 // id 'org.gradle.crypto.checksum' version '1.4.0'
62 // in ext the values are cast to Object. Ensure string values are cast as String (and not GStringImpl) for later use
63 def string(Object o) {
64 return o == null ? "" : o.toString()
67 def overrideProperties(String propsFileName, boolean output = false) {
68 if (propsFileName == null) {
71 def propsFile = file(propsFileName)
72 if (propsFile != null && propsFile.exists()) {
73 println("Using properties from file '${propsFileName}'")
75 def p = new Properties()
76 def localPropsFIS = new FileInputStream(propsFile)
82 if (project.hasProperty(key)) {
83 oldval = project.findProperty(key)
84 project.setProperty(key, val)
86 println("Overriding property '${key}' ('${oldval}') with ${file(propsFile).getName()} value '${val}'")
89 ext.setProperty(key, val)
91 println("Setting ext property '${key}' with ${file(propsFile).getName()}s value '${val}'")
95 } catch (Exception e) {
96 println("Exception reading local.properties")
103 jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath()
104 jalviewDirRelativePath = jalviewDir
107 getdownChannelName = CHANNEL.toLowerCase()
108 // default to "default". Currently only has different cosmetics for "develop", "release", "default"
109 propertiesChannelName = ["develop", "release", "test-release", "jalviewjs", "jalviewjs-release" ].contains(getdownChannelName) ? getdownChannelName : "default"
110 // Import channel_properties
111 channelDir = string("${jalviewDir}/${channel_properties_dir}/${propertiesChannelName}")
112 channelGradleProperties = string("${channelDir}/channel_gradle.properties")
113 channelPropsFile = string("${channelDir}/${resource_dir}/${channel_props}")
114 overrideProperties(channelGradleProperties, false)
115 // local build environment properties
116 // can be "projectDir/local.properties"
117 overrideProperties("${projectDir}/local.properties", true)
118 // or "../projectDir_local.properties"
119 overrideProperties(projectDir.getParent() + "/" + projectDir.getName() + "_local.properties", true)
122 // Import releaseProps from the RELEASE file
123 // or a file specified via JALVIEW_RELEASE_FILE if defined
124 // Expect jalview.version and target release branch in jalview.release
125 releaseProps = new Properties();
126 def releasePropFile = findProperty("JALVIEW_RELEASE_FILE");
127 def defaultReleasePropFile = "${jalviewDirAbsolutePath}/RELEASE";
129 (new File(releasePropFile!=null ? releasePropFile : defaultReleasePropFile)).withInputStream {
130 releaseProps.load(it)
132 } catch (Exception fileLoadError) {
133 throw new Error("Couldn't load release properties file "+(releasePropFile==null ? defaultReleasePropFile : "from custom location: releasePropFile"),fileLoadError);
136 // Set JALVIEW_VERSION if it is not already set
137 if (findProperty("JALVIEW_VERSION")==null || "".equals(JALVIEW_VERSION)) {
138 JALVIEW_VERSION = releaseProps.get("jalview.version")
141 // this property set when running Eclipse headlessly
142 j2sHeadlessBuildProperty = string("net.sf.j2s.core.headlessbuild")
143 // this property set by Eclipse
144 eclipseApplicationProperty = string("eclipse.application")
145 // CHECK IF RUNNING FROM WITHIN ECLIPSE
146 def eclipseApplicationPropertyVal = System.properties[eclipseApplicationProperty]
147 IN_ECLIPSE = eclipseApplicationPropertyVal != null && eclipseApplicationPropertyVal.startsWith("org.eclipse.ui.")
148 // BUT WITHOUT THE HEADLESS BUILD PROPERTY SET
149 if (System.properties[j2sHeadlessBuildProperty].equals("true")) {
150 println("Setting IN_ECLIPSE to ${IN_ECLIPSE} as System.properties['${j2sHeadlessBuildProperty}'] == '${System.properties[j2sHeadlessBuildProperty]}'")
154 println("WITHIN ECLIPSE IDE")
156 println("HEADLESS BUILD")
159 J2S_ENABLED = (project.hasProperty('j2s.compiler.status') && project['j2s.compiler.status'] != null && project['j2s.compiler.status'] == "enable")
161 println("J2S ENABLED")
164 System.properties.sort { it.key }.each {
165 key, val -> println("SYSTEM PROPERTY ${key}='${val}'")
168 if (false && IN_ECLIPSE) {
169 jalviewDir = jalviewDirAbsolutePath
174 buildDate = new Date().format("yyyyMMdd")
177 bareSourceDir = string(source_dir)
178 sourceDir = string("${jalviewDir}/${bareSourceDir}")
179 resourceDir = string("${jalviewDir}/${resource_dir}")
180 bareTestSourceDir = string(test_source_dir)
181 testDir = string("${jalviewDir}/${bareTestSourceDir}")
183 classesDir = string("${jalviewDir}/${classes_dir}")
186 useClover = clover.equals("true")
187 cloverBuildDir = "${buildDir}/clover"
188 cloverInstrDir = file("${cloverBuildDir}/clover-instr")
189 cloverClassesDir = file("${cloverBuildDir}/clover-classes")
190 cloverReportDir = file("${buildDir}/reports/clover")
191 cloverTestInstrDir = file("${cloverBuildDir}/clover-test-instr")
192 cloverTestClassesDir = file("${cloverBuildDir}/clover-test-classes")
193 //cloverTestClassesDir = cloverClassesDir
194 cloverDb = string("${cloverBuildDir}/clover.db")
196 testSourceDir = useClover ? cloverTestInstrDir : testDir
197 testClassesDir = useClover ? cloverTestClassesDir : "${jalviewDir}/${test_output_dir}"
199 getdownWebsiteDir = string("${jalviewDir}/${getdown_website_dir}/${JAVA_VERSION}")
200 getdownArchiveDir = string("${jalviewDir}/${getdown_archive_dir}")
201 getdownFullArchiveDir = null
202 getdownTextLines = []
203 getdownLaunchJvl = null
204 getdownVersionLaunchJvl = null
206 buildProperties = null
208 // the following values might be overridden by the CHANNEL switch
209 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
210 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
211 getdownArchiveAppBase = null
212 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}")
213 getdownAppDistDir = getdown_app_dir_alt
214 getdownImagesDir = string("${jalviewDir}/${getdown_images_dir}")
215 getdownSetAppBaseProperty = false // whether to pass the appbase and appdistdir to the application
216 reportRsyncCommand = false
217 jvlChannelName = CHANNEL.toLowerCase()
218 install4jSuffix = CHANNEL.substring(0, 1).toUpperCase() + CHANNEL.substring(1).toLowerCase(); // BUILD -> Build
219 install4jDMGDSStore = "${install4j_images_dir}/${install4j_dmg_ds_store}"
220 install4jDMGBackgroundImage = "${install4j_images_dir}/${install4j_dmg_background}"
221 install4jInstallerName = "${jalview_name} Non-Release Installer"
222 install4jExecutableName = install4j_executable_name
223 install4jExtraScheme = "jalviewx"
224 install4jMacIconsFile = string("${install4j_images_dir}/${install4j_mac_icons_file}")
225 install4jWindowsIconsFile = string("${install4j_images_dir}/${install4j_windows_icons_file}")
226 install4jPngIconFile = string("${install4j_images_dir}/${install4j_png_icon_file}")
227 install4jBackground = string("${install4j_images_dir}/${install4j_background}")
228 install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
229 install4jCheckSums = true
233 // TODO: get bamboo build artifact URL for getdown artifacts
234 getdown_channel_base = bamboo_channelbase
235 getdownChannelName = string("${bamboo_planKey}/${JAVA_VERSION}")
236 getdownAppBase = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
237 jvlChannelName += "_${getdownChannelName}"
238 // automatically add the test group Not-bamboo for exclusion
239 if ("".equals(testng_excluded_groups)) {
240 testng_excluded_groups = "Not-bamboo"
242 install4jExtraScheme = "jalviewb"
245 case [ "RELEASE", "JALVIEWJS-RELEASE" ]:
246 getdownAppDistDir = getdown_app_dir_release
247 getdownSetAppBaseProperty = true
248 reportRsyncCommand = true
250 install4jInstallerName = "${jalview_name} Installer"
251 getdownArchiveAppBase = getdown_archive_base
255 getdownChannelName = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
256 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
257 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
258 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
259 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
261 package_dir = string("${ARCHIVEDIR}/${package_dir}")
262 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
265 reportRsyncCommand = true
266 install4jExtraScheme = "jalviewa"
270 getdownChannelName = string("archive/${JALVIEW_VERSION}")
271 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
272 getdownAppBase = file(getdownWebsiteDir).toURI().toString()
273 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
274 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
276 package_dir = string("${ARCHIVEDIR}/${package_dir}")
277 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
280 reportRsyncCommand = true
281 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
282 install4jSuffix = "Archive"
283 install4jExtraScheme = "jalviewa"
287 reportRsyncCommand = true
288 getdownSetAppBaseProperty = true
289 // DEVELOP-RELEASE is usually associated with a Jalview release series so set the version
290 JALVIEW_VERSION=JALVIEW_VERSION+"-d${buildDate}"
292 install4jSuffix = "Develop"
293 install4jExtraScheme = "jalviewd"
294 install4jInstallerName = "${jalview_name} Develop Installer"
298 reportRsyncCommand = true
299 getdownSetAppBaseProperty = true
300 // Don't ignore transpile errors for release build
301 if (jalviewjs_ignore_transpile_errors.equals("true")) {
302 jalviewjs_ignore_transpile_errors = "false"
303 println("Setting jalviewjs_ignore_transpile_errors to 'false'")
305 JALVIEW_VERSION = JALVIEW_VERSION+"-test"
306 install4jSuffix = "Test"
307 install4jExtraScheme = "jalviewt"
308 install4jInstallerName = "${jalview_name} Test Installer"
311 case ~/^SCRATCH(|-[-\w]*)$/:
312 getdownChannelName = CHANNEL
313 JALVIEW_VERSION = JALVIEW_VERSION+"-"+CHANNEL
315 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
316 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
317 reportRsyncCommand = true
318 install4jSuffix = "Scratch"
322 if (!file("${LOCALDIR}").exists()) {
323 throw new GradleException("Must provide a LOCALDIR value to produce a local distribution")
325 getdownAppBase = file(file("${LOCALDIR}").getAbsolutePath()).toURI().toString()
326 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
328 JALVIEW_VERSION = "TEST"
329 install4jSuffix = "Test-Local"
330 install4jExtraScheme = "jalviewt"
331 install4jInstallerName = "${jalview_name} Test Installer"
334 case [ "LOCAL", "JALVIEWJS" ]:
335 JALVIEW_VERSION = "TEST"
336 getdownAppBase = file(getdownWebsiteDir).toURI().toString()
337 getdownArchiveAppBase = file("${jalviewDir}/${getdown_archive_dir}").toURI().toString()
338 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
339 install4jExtraScheme = "jalviewl"
340 install4jCheckSums = false
343 default: // something wrong specified
344 throw new GradleException("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
348 JALVIEW_VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
349 // override getdownAppBase if requested
350 if (findProperty("getdown_appbase_override") != null) {
351 // revert to LOCAL if empty string
352 if (string(getdown_appbase_override) == "") {
353 getdownAppBase = file(getdownWebsiteDir).toURI().toString()
354 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
355 } else if (string(getdown_appbase_override).startsWith("file://")) {
356 getdownAppBase = string(getdown_appbase_override)
357 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
359 getdownAppBase = string(getdown_appbase_override)
361 println("Overriding getdown appbase with '${getdownAppBase}'")
363 // sanitise file name for jalview launcher file for this channel
364 jvlChannelName = jvlChannelName.replaceAll("[^\\w\\-]+", "_")
365 // install4j application and folder names
366 if (install4jSuffix == "") {
367 install4jApplicationName = "${jalview_name}"
368 install4jBundleId = "${install4j_bundle_id}"
369 install4jWinApplicationId = install4j_release_win_application_id
371 install4jApplicationName = "${jalview_name} ${install4jSuffix}"
372 install4jBundleId = "${install4j_bundle_id}-" + install4jSuffix.toLowerCase()
373 // add int hash of install4jSuffix to the last part of the application_id
374 def id = install4j_release_win_application_id
375 def idsplitreverse = id.split("-").reverse()
376 idsplitreverse[0] = idsplitreverse[0].toInteger() + install4jSuffix.hashCode()
377 install4jWinApplicationId = idsplitreverse.reverse().join("-")
379 // sanitise folder and id names
380 // install4jApplicationFolder = e.g. "Jalview Build"
381 install4jApplicationFolder = install4jApplicationName
382 .replaceAll("[\"'~:/\\\\\\s]", "_") // replace all awkward filename chars " ' ~ : / \
383 .replaceAll("_+", "_") // collapse __
384 install4jInternalId = install4jApplicationName
386 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
387 .replaceAll("_+", "") // collapse __
388 //.replaceAll("_*-_*", "-") // collapse _-_
389 install4jUnixApplicationFolder = install4jApplicationName
391 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
392 .replaceAll("_+", "_") // collapse __
393 .replaceAll("_*-_*", "-") // collapse _-_
396 getdownWrapperLink = install4jUnixApplicationFolder // e.g. "jalview_local"
397 getdownAppDir = string("${getdownWebsiteDir}/${getdownAppDistDir}")
398 //getdownJ11libDir = "${getdownWebsiteDir}/${getdown_j11lib_dir}"
399 getdownResourceDir = string("${getdownWebsiteDir}/${getdown_resource_dir}")
400 getdownInstallDir = string("${getdownWebsiteDir}/${getdown_install_dir}")
401 getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
402 getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
403 /* compile without modules -- using classpath libraries
404 modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
405 modules_runtimeClasspath = modules_compileClasspath
411 apply plugin: "com.palantir.git-version"
412 def details = versionDetails()
413 gitHash = details.gitHash
414 gitBranch = details.branchName
415 } catch(org.gradle.api.internal.plugins.PluginApplicationException e) {
416 println("Not in a git repository. Using git values from RELEASE properties file.")
417 gitHash = releaseProps.getProperty("git.hash")
418 gitBranch = releaseProps.getProperty("git.branch")
419 } catch(java.lang.RuntimeException e1) {
420 throw new GradleException("Error with git-version plugin. Directory '.git' exists but versionDetails() cannot be found.")
423 println("Using a ${CHANNEL} profile.")
425 additional_compiler_args = []
426 // configure classpath/args for j8/j11 compilation
427 if (JAVA_VERSION.equals("1.8")) {
428 JAVA_INTEGER_VERSION = string("8")
431 libDistDir = j8libDir
432 compile_source_compatibility = 1.8
433 compile_target_compatibility = 1.8
434 // these are getdown.txt properties defined dependent on the JAVA_VERSION
435 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
436 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
437 // this property is assigned below and expanded to multiple lines in the getdown task
438 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
439 // this property is for the Java library used in eclipse
440 eclipseJavaRuntimeName = string("JavaSE-1.8")
441 } else if (JAVA_VERSION.equals("11")) {
442 JAVA_INTEGER_VERSION = string("11")
444 libDistDir = j11libDir
445 compile_source_compatibility = 11
446 compile_target_compatibility = 11
447 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
448 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
449 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
450 eclipseJavaRuntimeName = string("JavaSE-11")
451 /* compile without modules -- using classpath libraries
452 additional_compiler_args += [
453 '--module-path', modules_compileClasspath.asPath,
454 '--add-modules', j11modules
457 } else if (JAVA_VERSION.equals("17")) {
458 JAVA_INTEGER_VERSION = string("17")
460 libDistDir = j17libDir
461 compile_source_compatibility = 17
462 compile_target_compatibility = 17
463 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
464 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
465 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
466 eclipseJavaRuntimeName = string("JavaSE-17")
467 /* compile without modules -- using classpath libraries
468 additional_compiler_args += [
469 '--module-path', modules_compileClasspath.asPath,
470 '--add-modules', j11modules
474 throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
479 JAVA_MIN_VERSION = JAVA_VERSION
480 JAVA_MAX_VERSION = JAVA_VERSION
481 def jreInstallsDir = string(jre_installs_dir)
482 if (jreInstallsDir.startsWith("~/")) {
483 jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
485 macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
486 windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
487 linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
488 macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_mac_x64.tar.gz")
489 windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_windows_x64.tar.gz")
490 linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_linux_x64.tar.gz")
491 install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
492 install4jConfFileName = string("jalview-install4j-conf.install4j")
493 install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
494 install4jHomeDir = install4j_home_dir
495 if (install4jHomeDir.startsWith("~/")) {
496 install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
499 resourceBuildDir = string("${buildDir}/resources")
500 resourcesBuildDir = string("${resourceBuildDir}/resources_build")
501 helpBuildDir = string("${resourceBuildDir}/help_build")
502 docBuildDir = string("${resourceBuildDir}/doc_build")
504 if (buildProperties == null) {
505 buildProperties = string("${resourcesBuildDir}/${build_properties_file}")
507 buildingHTML = string("${jalviewDir}/${doc_dir}/building.html")
508 helpParentDir = string("${jalviewDir}/${help_parent_dir}")
509 helpSourceDir = string("${helpParentDir}/${help_dir}")
510 helpFile = string("${helpBuildDir}/${help_dir}/help.jhm")
513 relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
514 jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
515 jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
517 jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
519 jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
521 jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
522 jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
523 jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
524 jalviewjsJalviewCoreHtmlFile = string("")
525 jalviewjsJalviewCoreName = string(jalviewjs_core_name)
526 jalviewjsCoreClasslists = []
527 jalviewjsJalviewTemplateName = string(jalviewjs_name)
528 jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
529 jalviewjsJ2sAltSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_alt_settings}")
530 jalviewjsJ2sProps = null
531 jalviewjsJ2sPlugin = jalviewjs_j2s_plugin
533 eclipseWorkspace = null
534 eclipseBinary = string("")
535 eclipseVersion = string("")
545 outputDir = file(classesDir)
549 srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ]
552 compileClasspath = files(sourceSets.main.java.outputDir)
553 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
555 runtimeClasspath = compileClasspath
556 runtimeClasspath += files(sourceSets.main.resources.srcDirs)
561 srcDirs cloverInstrDir
562 outputDir = cloverClassesDir
566 srcDirs = sourceSets.main.resources.srcDirs
569 compileClasspath = files( sourceSets.clover.java.outputDir )
570 //compileClasspath += files( testClassesDir )
571 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
572 compileClasspath += fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
573 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
575 runtimeClasspath = compileClasspath
580 srcDirs testSourceDir
581 outputDir = file(testClassesDir)
585 srcDirs = useClover ? sourceSets.clover.resources.srcDirs : sourceSets.main.resources.srcDirs
588 compileClasspath = files( sourceSets.test.java.outputDir )
589 compileClasspath += useClover ? sourceSets.clover.compileClasspath : sourceSets.main.compileClasspath
590 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
592 runtimeClasspath = compileClasspath
593 runtimeClasspath += files(sourceSets.test.resources.srcDirs)
599 // eclipse project and settings files creation, also used by buildship
602 name = eclipse_project_name
604 natures 'org.eclipse.jdt.core.javanature',
605 'org.eclipse.jdt.groovy.core.groovyNature',
606 'org.eclipse.buildship.core.gradleprojectnature'
608 buildCommand 'org.eclipse.jdt.core.javabuilder'
609 buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
613 //defaultOutputDir = sourceSets.main.java.outputDir
614 configurations.each{ c->
615 if (c.isCanBeResolved()) {
616 minusConfigurations += [c]
620 plusConfigurations = [ ]
624 def removeTheseToo = []
625 HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
626 cp.entries.each { entry ->
627 // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
628 // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
629 // we add the resources and help/help dirs in as libs afterwards (see below)
630 if (entry.kind == 'src') {
631 if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
632 removeTheseToo += entry
634 alreadyAddedSrcPath.putAt(entry.path, true)
639 cp.entries.removeAll(removeTheseToo)
641 //cp.entries += new Output("${eclipse_bin_dir}/main")
642 if (file(helpParentDir).isDirectory()) {
643 cp.entries += new Library(fileReference(helpParentDir))
645 if (file(resourceDir).isDirectory()) {
646 cp.entries += new Library(fileReference(resourceDir))
649 HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
651 sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
652 //don't want to add outputDir as eclipse is using its own output dir in bin/main
653 if (it.isDirectory() || ! it.exists()) {
654 // don't add dirs to classpath, especially if they don't exist
655 return false // groovy "continue" in .any closure
657 def itPath = it.toString()
658 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
659 // make relative path
660 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
662 if (alreadyAddedLibPath.get(itPath)) {
663 //println("Not adding duplicate entry "+itPath)
665 //println("Adding entry "+itPath)
666 cp.entries += new Library(fileReference(itPath))
667 alreadyAddedLibPath.put(itPath, true)
671 sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
672 //no longer want to add outputDir as eclipse is using its own output dir in bin/main
673 if (it.isDirectory() || ! it.exists()) {
674 // don't add dirs to classpath
675 return false // groovy "continue" in .any closure
678 def itPath = it.toString()
679 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
680 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
682 if (alreadyAddedLibPath.get(itPath)) {
685 def lib = new Library(fileReference(itPath))
686 lib.entryAttributes["test"] = "true"
688 alreadyAddedLibPath.put(itPath, true)
696 containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
701 // for the IDE, use java 11 compatibility
702 sourceCompatibility = compile_source_compatibility
703 targetCompatibility = compile_target_compatibility
704 javaRuntimeName = eclipseJavaRuntimeName
706 // add in jalview project specific properties/preferences into eclipse core preferences
708 withProperties { props ->
709 def jalview_prefs = new Properties()
710 def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
711 jalview_prefs.load(ins)
713 jalview_prefs.forEach { t, v ->
714 if (props.getAt(t) == null) {
718 // codestyle file -- overrides previous formatter prefs
719 def csFile = file("${jalviewDirAbsolutePath}/${eclipse_codestyle_file}")
720 if (csFile.exists()) {
721 XmlParser parser = new XmlParser()
722 def profiles = parser.parse(csFile)
723 def profile = profiles.'profile'.find { p -> (p.'@kind' == "CodeFormatterProfile" && p.'@name' == "Jalview") }
724 if (profile != null) {
725 profile.'setting'.each { s ->
727 def value = s.'@value'
728 if (id != null && value != null) {
729 props.putAt(id, value)
740 // Don't want these to be activated if in headless build
741 synchronizationTasks "eclipseSynchronizationTask"
742 //autoBuildTasks "eclipseAutoBuildTask"
748 /* hack to change eclipse prefs in .settings files other than org.eclipse.jdt.core.prefs */
749 // Class to allow updating arbitrary properties files
750 class PropertiesFile extends PropertiesPersistableConfigurationObject {
751 public PropertiesFile(PropertiesTransformer t) { super(t); }
752 @Override protected void load(Properties properties) { }
753 @Override protected void store(Properties properties) { }
754 @Override protected String getDefaultResourceName() { return ""; }
755 // This is necessary, because PropertiesPersistableConfigurationObject fails
756 // if no default properties file exists.
757 @Override public void loadDefaults() { load(new StringBufferInputStream("")); }
760 // Task to update arbitrary properties files (set outputFile)
761 class PropertiesFileTask extends PropertiesGeneratorTask<PropertiesFile> {
762 private final PropertiesFileContentMerger file;
763 public PropertiesFileTask() { file = new PropertiesFileContentMerger(getTransformer()); }
764 protected PropertiesFile create() { return new PropertiesFile(getTransformer()); }
765 protected void configure(PropertiesFile props) {
766 file.getBeforeMerged().execute(props); file.getWhenMerged().execute(props);
768 public void file(Closure closure) { ConfigureUtil.configure(closure, file); }
771 task eclipseUIPreferences(type: PropertiesFileTask) {
772 description = "Generate Eclipse additional settings"
773 def filename = "org.eclipse.jdt.ui.prefs"
774 outputFile = "$projectDir/.settings/${filename}" as File
777 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
782 task eclipseGroovyCorePreferences(type: PropertiesFileTask) {
783 description = "Generate Eclipse additional settings"
784 def filename = "org.eclipse.jdt.groovy.core.prefs"
785 outputFile = "$projectDir/.settings/${filename}" as File
788 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
793 task eclipseAllPreferences {
795 dependsOn eclipseUIPreferences
796 dependsOn eclipseGroovyCorePreferences
799 eclipseUIPreferences.mustRunAfter eclipseJdt
800 eclipseGroovyCorePreferences.mustRunAfter eclipseJdt
802 /* end of eclipse preferences hack */
810 delete cloverBuildDir
811 delete cloverReportDir
816 task cloverInstrJava(type: JavaExec) {
817 group = "Verification"
818 description = "Create clover instrumented source java files"
820 dependsOn cleanClover
822 inputs.files(sourceSets.main.allJava)
823 outputs.dir(cloverInstrDir)
825 //classpath = fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
826 classpath = sourceSets.clover.compileClasspath
827 main = "com.atlassian.clover.CloverInstr"
835 cloverInstrDir.getPath(),
837 def srcFiles = sourceSets.main.allJava.files
840 { file -> file.absolutePath }
843 args argsList.toArray()
846 delete cloverInstrDir
847 println("Clover: About to instrument "+srcFiles.size() +" files")
852 task cloverInstrTests(type: JavaExec) {
853 group = "Verification"
854 description = "Create clover instrumented source test files"
856 dependsOn cleanClover
858 inputs.files(testDir)
859 outputs.dir(cloverTestInstrDir)
861 classpath = sourceSets.clover.compileClasspath
862 main = "com.atlassian.clover.CloverInstr"
872 cloverTestInstrDir.getPath(),
874 args argsList.toArray()
877 delete cloverTestInstrDir
878 println("Clover: About to instrument test files")
884 group = "Verification"
885 description = "Create clover instrumented all source files"
887 dependsOn cloverInstrJava
888 dependsOn cloverInstrTests
892 cloverClasses.dependsOn cloverInstr
895 task cloverConsoleReport(type: JavaExec) {
896 group = "Verification"
897 description = "Creates clover console report"
900 file(cloverDb).exists()
903 inputs.dir cloverClassesDir
905 classpath = sourceSets.clover.runtimeClasspath
906 main = "com.atlassian.clover.reporters.console.ConsoleReporter"
908 if (cloverreport_mem.length() > 0) {
909 maxHeapSize = cloverreport_mem
911 if (cloverreport_jvmargs.length() > 0) {
912 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
922 args argsList.toArray()
926 task cloverHtmlReport(type: JavaExec) {
927 group = "Verification"
928 description = "Creates clover HTML report"
931 file(cloverDb).exists()
934 def cloverHtmlDir = cloverReportDir
935 inputs.dir cloverClassesDir
936 outputs.dir cloverHtmlDir
938 classpath = sourceSets.clover.runtimeClasspath
939 main = "com.atlassian.clover.reporters.html.HtmlReporter"
941 if (cloverreport_mem.length() > 0) {
942 maxHeapSize = cloverreport_mem
944 if (cloverreport_jvmargs.length() > 0) {
945 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
956 if (cloverreport_html_options.length() > 0) {
957 argsList += cloverreport_html_options.split(" ")
960 args argsList.toArray()
964 task cloverXmlReport(type: JavaExec) {
965 group = "Verification"
966 description = "Creates clover XML report"
969 file(cloverDb).exists()
972 def cloverXmlFile = "${cloverReportDir}/clover.xml"
973 inputs.dir cloverClassesDir
974 outputs.file cloverXmlFile
976 classpath = sourceSets.clover.runtimeClasspath
977 main = "com.atlassian.clover.reporters.xml.XMLReporter"
979 if (cloverreport_mem.length() > 0) {
980 maxHeapSize = cloverreport_mem
982 if (cloverreport_jvmargs.length() > 0) {
983 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
994 if (cloverreport_xml_options.length() > 0) {
995 argsList += cloverreport_xml_options.split(" ")
998 args argsList.toArray()
1003 group = "Verification"
1004 description = "Creates clover reports"
1006 dependsOn cloverXmlReport
1007 dependsOn cloverHtmlReport
1014 sourceCompatibility = compile_source_compatibility
1015 targetCompatibility = compile_target_compatibility
1016 options.compilerArgs += additional_compiler_args
1017 print ("Setting target compatibility to "+targetCompatibility+"\n")
1019 //classpath += configurations.cloverRuntime
1025 // JBP->BS should the print statement in doFirst refer to compile_target_compatibility ?
1026 sourceCompatibility = compile_source_compatibility
1027 targetCompatibility = compile_target_compatibility
1028 options.compilerArgs = additional_compiler_args
1029 options.encoding = "UTF-8"
1031 print ("Setting target compatibility to "+compile_target_compatibility+"\n")
1038 sourceCompatibility = compile_source_compatibility
1039 targetCompatibility = compile_target_compatibility
1040 options.compilerArgs = additional_compiler_args
1042 print ("Setting target compatibility to "+targetCompatibility+"\n")
1049 delete sourceSets.main.java.outputDir
1055 dependsOn cleanClover
1057 delete sourceSets.test.java.outputDir
1062 // format is a string like date.format("dd MMMM yyyy")
1063 def getDate(format) {
1064 return date.format(format)
1068 def convertMdToHtml (FileTree mdFiles, File cssFile) {
1069 MutableDataSet options = new MutableDataSet()
1071 def extensions = new ArrayList<>()
1072 extensions.add(AnchorLinkExtension.create())
1073 extensions.add(AutolinkExtension.create())
1074 extensions.add(StrikethroughExtension.create())
1075 extensions.add(TaskListExtension.create())
1076 extensions.add(TablesExtension.create())
1077 extensions.add(TocExtension.create())
1079 options.set(Parser.EXTENSIONS, extensions)
1081 // set GFM table parsing options
1082 options.set(TablesExtension.WITH_CAPTION, false)
1083 options.set(TablesExtension.COLUMN_SPANS, false)
1084 options.set(TablesExtension.MIN_HEADER_ROWS, 1)
1085 options.set(TablesExtension.MAX_HEADER_ROWS, 1)
1086 options.set(TablesExtension.APPEND_MISSING_COLUMNS, true)
1087 options.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
1088 options.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
1090 options.set(AnchorLinkExtension.ANCHORLINKS_SET_ID, false)
1091 options.set(AnchorLinkExtension.ANCHORLINKS_ANCHOR_CLASS, "anchor")
1092 options.set(AnchorLinkExtension.ANCHORLINKS_SET_NAME, true)
1093 options.set(AnchorLinkExtension.ANCHORLINKS_TEXT_PREFIX, "<span class=\"octicon octicon-link\"></span>")
1095 Parser parser = Parser.builder(options).build()
1096 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1098 mdFiles.each { mdFile ->
1099 // add table of contents
1100 def mdText = "[TOC]\n"+mdFile.text
1102 // grab the first top-level title
1104 def titleRegex = /(?m)^#(\s+|([^#]))(.*)/
1105 def matcher = mdText =~ titleRegex
1106 if (matcher.size() > 0) {
1107 // matcher[0][2] is the first character of the title if there wasn't any whitespace after the #
1108 title = (matcher[0][2] != null ? matcher[0][2] : "")+matcher[0][3]
1110 // or use the filename if none found
1111 if (title == null) {
1112 title = mdFile.getName()
1115 Node document = parser.parse(mdText)
1116 String htmlBody = renderer.render(document)
1117 def htmlText = '''<html>
1118 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1119 <html xmlns="http://www.w3.org/1999/xhtml">
1121 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1122 <meta http-equiv="Content-Style-Type" content="text/css" />
1123 <meta name="generator" content="flexmark" />
1125 htmlText += ((title != null) ? " <title>${title}</title>" : '' )
1127 <style type="text/css">code{white-space: pre;}</style>
1129 htmlText += ((cssFile != null) ? cssFile.text : '')
1130 htmlText += '''</head>
1133 htmlText += htmlBody
1139 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1140 def htmlFile = file(htmlFilePath)
1141 println("Creating ${htmlFilePath}")
1142 htmlFile.text = htmlText
1147 task copyDocs(type: Copy) {
1148 def inputDir = "${jalviewDir}/${doc_dir}"
1149 def outputDir = "${docBuildDir}/${doc_dir}"
1153 include('**/*.html')
1155 filter(ReplaceTokens,
1159 'Version-Rel': JALVIEW_VERSION,
1160 'Year-Rel': getDate("yyyy")
1167 exclude('**/*.html')
1172 inputs.dir(inputDir)
1173 outputs.dir(outputDir)
1177 task convertMdFiles {
1179 def mdFiles = fileTree(dir: docBuildDir, include: "**/*.md")
1180 def cssFile = file("${jalviewDir}/${flexmark_css}")
1183 convertMdToHtml(mdFiles, cssFile)
1186 inputs.files(mdFiles)
1187 inputs.file(cssFile)
1190 mdFiles.each { mdFile ->
1191 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1192 htmlFiles.add(file(htmlFilePath))
1194 outputs.files(htmlFiles)
1198 task copyHelp(type: Copy) {
1199 def inputDir = helpSourceDir
1200 def outputDir = "${helpBuildDir}/${help_dir}"
1204 include('**/*.html')
1208 filter(ReplaceTokens,
1212 'Version-Rel': JALVIEW_VERSION,
1213 'Year-Rel': getDate("yyyy")
1220 exclude('**/*.html')
1227 inputs.dir(inputDir)
1228 outputs.files(helpFile)
1229 outputs.dir(outputDir)
1233 task copyResources(type: Copy) {
1235 description = "Copy (and make text substitutions in) the resources dir to the build area"
1237 def inputDir = resourceDir
1238 def outputDir = resourcesBuildDir
1242 include('**/*.html')
1244 filter(ReplaceTokens,
1248 'Version-Rel': JALVIEW_VERSION,
1249 'Year-Rel': getDate("yyyy")
1256 exclude('**/*.html')
1261 inputs.dir(inputDir)
1262 outputs.dir(outputDir)
1265 task copyChannelResources(type: Copy) {
1266 dependsOn copyResources
1268 description = "Copy the channel resources dir to the build resources area"
1270 def inputDir = "${channelDir}/${resource_dir}"
1271 def outputDir = resourcesBuildDir
1275 inputs.dir(inputDir)
1276 outputs.dir(outputDir)
1279 task createBuildProperties(type: WriteProperties) {
1280 dependsOn copyResources
1282 description = "Create the ${buildProperties} file"
1284 inputs.dir(sourceDir)
1285 inputs.dir(resourcesBuildDir)
1286 outputFile (buildProperties)
1287 // taking time specific comment out to allow better incremental builds
1288 comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
1289 //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
1290 property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
1291 property "VERSION", JALVIEW_VERSION
1292 property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
1293 if (getdownSetAppBaseProperty) {
1294 property "GETDOWNAPPBASE", getdownAppBase
1295 property "GETDOWNAPPDISTDIR", getdownAppDistDir
1297 outputs.file(outputFile)
1301 task buildIndices(type: JavaExec) {
1303 classpath = sourceSets.main.compileClasspath
1304 main = "com.sun.java.help.search.Indexer"
1305 workingDir = "${helpBuildDir}/${help_dir}"
1308 inputs.dir("${workingDir}/${argDir}")
1310 outputs.dir("${classesDir}/doc")
1311 outputs.dir("${classesDir}/help")
1312 outputs.file("${workingDir}/JavaHelpSearch/DOCS")
1313 outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
1314 outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
1315 outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
1316 outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
1317 outputs.file("${workingDir}/JavaHelpSearch/TMAP")
1320 task buildResources {
1321 dependsOn copyResources
1322 dependsOn copyChannelResources
1323 dependsOn createBuildProperties
1327 dependsOn buildResources
1330 dependsOn convertMdFiles
1331 dependsOn buildIndices
1335 compileJava.dependsOn prepare
1336 run.dependsOn compileJava
1337 //run.dependsOn prepare
1340 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1345 dependsOn cloverClasses
1347 dependsOn compileJava //?
1351 includeGroups testng_groups
1352 excludeGroups testng_excluded_groups
1354 useDefaultListeners=true
1357 maxHeapSize = "1024m"
1359 workingDir = jalviewDir
1360 def testLaf = project.findProperty("test_laf")
1361 if (testLaf != null) {
1362 println("Setting Test LaF to '${testLaf}'")
1363 systemProperty "laf", testLaf
1365 def testHiDPIScale = project.findProperty("test_HiDPIScale")
1366 if (testHiDPIScale != null) {
1367 println("Setting Test HiDPI Scale to '${testHiDPIScale}'")
1368 systemProperty "sun.java2d.uiScale", testHiDPIScale
1370 sourceCompatibility = compile_source_compatibility
1371 targetCompatibility = compile_target_compatibility
1372 jvmArgs += additional_compiler_args
1376 println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1382 task compileLinkCheck(type: JavaCompile) {
1384 classpath = files("${jalviewDir}/${utils_dir}")
1385 destinationDir = file("${jalviewDir}/${utils_dir}")
1386 source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1388 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1389 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1390 outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1391 outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1395 task linkCheck(type: JavaExec) {
1397 dependsOn compileLinkCheck
1399 def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1400 classpath = files("${jalviewDir}/${utils_dir}")
1401 main = "HelpLinksChecker"
1402 workingDir = jalviewDir
1403 args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1405 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1406 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1409 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1413 inputs.dir(helpBuildDir)
1414 outputs.file(helpLinksCheckerOutFile)
1418 // import the pubhtmlhelp target
1419 ant.properties.basedir = "${jalviewDir}"
1420 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1421 ant.importBuild "${utils_dir}/publishHelp.xml"
1424 task cleanPackageDir(type: Delete) {
1426 delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1436 attributes "Main-Class": main_class,
1437 "Permissions": "all-permissions",
1438 "Application-Name": install4jApplicationName,
1439 "Codebase": application_codebase,
1440 "Implementation-Version": JALVIEW_VERSION
1443 def outputDir = "${jalviewDir}/${package_dir}"
1444 destinationDirectory = file(outputDir)
1445 archiveFileName = rootProject.name+".jar"
1446 duplicatesStrategy "EXCLUDE"
1453 exclude "**/*.jar.*"
1455 inputs.dir(sourceSets.main.java.outputDir)
1456 sourceSets.main.resources.srcDirs.each{ dir ->
1459 outputs.file("${outputDir}/${archiveFileName}")
1463 task copyJars(type: Copy) {
1464 from fileTree(dir: classesDir, include: "**/*.jar").files
1465 into "${jalviewDir}/${package_dir}"
1469 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1470 task syncJars(type: Sync) {
1472 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1473 into "${jalviewDir}/${package_dir}"
1475 include jar.archiveFileName.getOrNull()
1482 description = "Put all required libraries in dist"
1483 // order of "cleanPackageDir", "copyJars", "jar" important!
1484 jar.mustRunAfter cleanPackageDir
1485 syncJars.mustRunAfter cleanPackageDir
1486 dependsOn cleanPackageDir
1489 outputs.dir("${jalviewDir}/${package_dir}")
1494 dependsOn cleanPackageDir
1501 group = "distribution"
1502 description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1506 from ("${jalviewDir}/${libDistDir}") {
1510 attributes "Implementation-Version": JALVIEW_VERSION,
1511 "Application-Name": install4jApplicationName
1514 duplicatesStrategy "INCLUDE"
1516 mainClassName = shadow_jar_main_class
1518 classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1523 task getdownWebsite() {
1524 group = "distribution"
1525 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1530 def getdownWebsiteResourceFilenames = []
1531 def getdownResourceDir = getdownResourceDir
1532 def getdownResourceFilenames = []
1535 // clean the getdown website and files dir before creating getdown folders
1536 delete getdownWebsiteDir
1537 delete getdownFilesDir
1540 from buildProperties
1541 rename(file(buildProperties).getName(), getdown_build_properties)
1544 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1547 from channelPropsFile
1548 into getdownWebsiteDir
1550 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
1552 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
1553 def props = project.properties.sort { it.key }
1554 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
1555 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
1557 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
1558 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
1560 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
1561 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
1563 if (getdownImagesDir != null && file(getdownImagesDir).exists()) {
1564 props.put("getdown_txt_ui.background_image", "${getdownImagesDir}/${getdown_background_image}")
1565 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesDir}/${getdown_instant_background_image}")
1566 props.put("getdown_txt_ui.error_background", "${getdownImagesDir}/${getdown_error_background}")
1567 props.put("getdown_txt_ui.progress_image", "${getdownImagesDir}/${getdown_progress_image}")
1568 props.put("getdown_txt_ui.icon", "${getdownImagesDir}/${getdown_icon}")
1569 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesDir}/${getdown_mac_dock_icon}")
1572 props.put("getdown_txt_title", jalview_name)
1573 props.put("getdown_txt_ui.name", install4jApplicationName)
1575 // start with appbase
1576 getdownTextLines += "appbase = ${getdownAppBase}"
1577 props.each{ prop, val ->
1578 if (prop.startsWith("getdown_txt_") && val != null) {
1579 if (prop.startsWith("getdown_txt_multi_")) {
1580 def key = prop.substring(18)
1581 val.split(",").each{ v ->
1582 def line = "${key} = ${v}"
1583 getdownTextLines += line
1586 // file values rationalised
1587 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
1589 if (val.indexOf('/') == 0) {
1592 } else if (val.indexOf('/') > 0) {
1593 // relative path (relative to jalviewDir)
1594 r = file( "${jalviewDir}/${val}" )
1597 val = "${getdown_resource_dir}/" + r.getName()
1598 getdownWebsiteResourceFilenames += val
1599 getdownResourceFilenames += r.getPath()
1602 if (! prop.startsWith("getdown_txt_resource")) {
1603 def line = prop.substring(12) + " = ${val}"
1604 getdownTextLines += line
1610 getdownWebsiteResourceFilenames.each{ filename ->
1611 getdownTextLines += "resource = ${filename}"
1613 getdownResourceFilenames.each{ filename ->
1616 into getdownResourceDir
1620 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
1621 getdownWrapperScripts.each{ script ->
1622 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
1626 into "${getdownWebsiteDir}/${getdown_wrapper_script_dir}"
1628 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
1633 fileTree(file(package_dir)).each{ f ->
1634 if (f.isDirectory()) {
1635 def files = fileTree(dir: f, include: ["*"]).getFiles()
1637 } else if (f.exists()) {
1641 def jalviewJar = jar.archiveFileName.getOrNull()
1642 // put jalview.jar first for CLASSPATH and .properties files reasons
1643 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
1644 def name = f.getName()
1645 def line = "code = ${getdownAppDistDir}/${name}"
1646 getdownTextLines += line
1653 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
1655 if (JAVA_VERSION.equals("11")) {
1656 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
1657 j11libFiles.sort().each{f ->
1658 def name = f.getName()
1659 def line = "code = ${getdown_j11lib_dir}/${name}"
1660 getdownTextLines += line
1663 into getdownJ11libDir
1669 // 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.
1670 //getdownTextLines += "class = " + file(getdownLauncher).getName()
1671 getdownTextLines += "resource = ${getdown_launcher_new}"
1672 getdownTextLines += "class = ${main_class}"
1673 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
1674 if (getdownSetAppBaseProperty) {
1675 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
1676 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
1679 def getdownTxt = file("${getdownWebsiteDir}/getdown.txt")
1680 getdownTxt.write(getdownTextLines.join("\n"))
1682 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
1683 def launchJvl = file("${getdownWebsiteDir}/${getdownLaunchJvl}")
1684 launchJvl.write("appbase=${getdownAppBase}")
1686 // files going into the getdown website dir: getdown-launcher.jar
1688 from getdownLauncher
1689 rename(file(getdownLauncher).getName(), getdown_launcher_new)
1690 into getdownWebsiteDir
1693 // files going into the getdown website dir: getdown-launcher(-local).jar
1695 from getdownLauncher
1696 if (file(getdownLauncher).getName() != getdown_launcher) {
1697 rename(file(getdownLauncher).getName(), getdown_launcher)
1699 into getdownWebsiteDir
1702 // files going into the getdown website dir: ./install dir and files
1703 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
1706 from getdownLauncher
1707 from "${getdownAppDir}/${getdown_build_properties}"
1708 if (file(getdownLauncher).getName() != getdown_launcher) {
1709 rename(file(getdownLauncher).getName(), getdown_launcher)
1711 into getdownInstallDir
1714 // and make a copy in the getdown files dir (these are not downloaded by getdown)
1716 from getdownInstallDir
1717 into getdownFilesInstallDir
1721 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
1725 from getdownLauncher
1726 from "${getdownWebsiteDir}/${getdown_build_properties}"
1727 from "${getdownWebsiteDir}/${channel_props}"
1728 if (file(getdownLauncher).getName() != getdown_launcher) {
1729 rename(file(getdownLauncher).getName(), getdown_launcher)
1731 into getdownFilesDir
1734 // and ./resource (not all downloaded by getdown)
1736 from getdownResourceDir
1737 into "${getdownFilesDir}/${getdown_resource_dir}"
1742 inputs.dir("${jalviewDir}/${package_dir}")
1744 outputs.dir(getdownWebsiteDir)
1745 outputs.dir(getdownFilesDir)
1749 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
1750 task getdownDigestDir(type: JavaExec) {
1752 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
1754 def digestDirPropertyName = "DIGESTDIR"
1756 classpath = files(getdownLauncher)
1757 def digestDir = findProperty(digestDirPropertyName)
1758 if (digestDir == null) {
1759 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
1763 main = "com.threerings.getdown.tools.Digester"
1767 task getdownDigest(type: JavaExec) {
1768 group = "distribution"
1769 description = "Digest the getdown website folder"
1770 dependsOn getdownWebsite
1772 classpath = files(getdownLauncher)
1774 main = "com.threerings.getdown.tools.Digester"
1775 args getdownWebsiteDir
1776 inputs.dir(getdownWebsiteDir)
1777 outputs.file("${getdownWebsiteDir}/digest2.txt")
1782 group = "distribution"
1783 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
1784 dependsOn getdownDigest
1786 if (reportRsyncCommand) {
1787 def fromDir = getdownWebsiteDir + (getdownWebsiteDir.endsWith('/')?'':'/')
1788 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
1789 println "LIKELY RSYNC COMMAND:"
1790 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
1791 if (RUNRSYNC == "true") {
1793 commandLine "mkdir", "-p", toDir
1796 commandLine "rsync", "-avh", "--delete", fromDir, toDir
1804 task getdownArchiveBuild() {
1805 group = "distribution"
1806 description = "Put files in the archive dir to go on the website"
1808 dependsOn getdownWebsite
1810 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
1811 def vDir = "${getdownArchiveDir}/${v}"
1812 getdownFullArchiveDir = "${vDir}/getdown"
1813 getdownVersionLaunchJvl = "${vDir}/jalview-${v}.jvl"
1815 def vAltDir = "alt_${v}"
1816 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
1819 if (getdownArchiveAppBase == null) {
1820 throw new StopExecutionException("Cannot create getdownArchive for CHANNEL=${CHANNEL}")
1823 // cleanup old "old" dir
1824 delete getdownArchiveDir
1826 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
1827 getdownArchiveTxt.getParentFile().mkdirs()
1828 def getdownArchiveTextLines = []
1829 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
1833 from "${getdownWebsiteDir}/${getdownAppDistDir}"
1834 into "${getdownFullArchiveDir}/${vAltDir}"
1837 getdownTextLines.each { line ->
1838 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
1839 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
1840 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
1841 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
1842 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
1843 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
1844 // remove the existing resource = resource/ or bin/ lines
1845 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
1846 getdownArchiveTextLines += line
1850 // the resource dir -- add these files as resource lines in getdown.txt
1852 from "${archiveImagesDir}"
1853 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
1855 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
1859 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
1861 def vLaunchJvl = file(getdownVersionLaunchJvl)
1862 vLaunchJvl.getParentFile().mkdirs()
1863 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
1864 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
1865 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
1866 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
1867 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
1868 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
1870 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
1872 from getdownLauncher
1873 from "${getdownWebsiteDir}/${getdownLaunchJvl}"
1874 from "${getdownWebsiteDir}/${getdown_launcher_new}"
1875 from "${getdownWebsiteDir}/${channel_props}"
1876 if (file(getdownLauncher).getName() != getdown_launcher) {
1877 rename(file(getdownLauncher).getName(), getdown_launcher)
1879 into getdownFullArchiveDir
1885 task getdownArchiveDigest(type: JavaExec) {
1886 group = "distribution"
1887 description = "Digest the getdown archive folder"
1889 dependsOn getdownArchiveBuild
1892 classpath = files(getdownLauncher)
1893 args getdownFullArchiveDir
1895 main = "com.threerings.getdown.tools.Digester"
1896 inputs.dir(getdownFullArchiveDir)
1897 outputs.file("${getdownFullArchiveDir}/digest2.txt")
1900 task getdownArchive() {
1901 group = "distribution"
1902 description = "Build the website archive dir with getdown digest"
1904 dependsOn getdownArchiveBuild
1905 dependsOn getdownArchiveDigest
1908 tasks.withType(JavaCompile) {
1909 options.encoding = 'UTF-8'
1915 delete getdownWebsiteDir
1916 delete getdownFilesDir
1917 delete getdownArchiveDir
1923 if (file(install4jHomeDir).exists()) {
1925 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
1926 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
1927 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
1928 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
1930 installDir(file(install4jHomeDir))
1932 mediaTypes = Arrays.asList(install4j_media_types.split(","))
1936 task copyInstall4jTemplate {
1937 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
1938 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
1939 inputs.file(install4jTemplateFile)
1940 inputs.file(install4jFileAssociationsFile)
1941 inputs.property("CHANNEL", { CHANNEL })
1942 outputs.file(install4jConfFile)
1945 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
1947 // turn off code signing if no OSX_KEYPASS
1948 if (OSX_KEYPASS == "") {
1949 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
1950 codeSigning.'@macEnabled' = "false"
1952 install4jConfigXml.'**'.windows.each { windows ->
1953 windows.'@runPostProcessor' = "false"
1957 // disable install screen for OSX dmg (for 2.11.2.0)
1958 install4jConfigXml.'**'.macosArchive.each { macosArchive ->
1959 macosArchive.attributes().remove('executeSetupApp')
1960 macosArchive.attributes().remove('setupAppId')
1963 // turn off checksum creation for LOCAL channel
1964 def e = install4jConfigXml.application[0]
1965 e.'@createChecksums' = string(install4jCheckSums)
1967 // put file association actions where placeholder action is
1968 def install4jFileAssociationsText = install4jFileAssociationsFile.text
1969 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
1970 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
1971 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
1972 def parent = a.parent()
1974 fileAssociationActions.each { faa ->
1977 // don't need to continue in .any loop once replacements have been made
1982 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
1983 // NB we're deleting the /other/ one!
1984 // Also remove the examples subdir from non-release versions
1985 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
1986 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
1987 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
1988 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
1990 // remove the examples subdir from Full File Set
1991 def files = install4jConfigXml.files[0]
1992 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
1993 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
1994 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
1995 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
1996 dirEntry.parent().remove(dirEntry)
1998 install4jConfigXml.'**'.action.any { a ->
1999 if (a.'@customizedId' == customizedIdToDelete) {
2000 def parent = a.parent()
2006 // write install4j file
2007 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
2014 delete install4jConfFile
2018 task cleanInstallersDataFiles {
2019 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2020 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2021 def VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
2022 def hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${VERSION_UNDERSCORES}.json")
2024 delete installersOutputTxt
2025 delete installersSha256
2026 delete hugoDataJsonFile
2030 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2031 group = "distribution"
2032 description = "Create the install4j installers"
2034 dependsOn copyInstall4jTemplate
2035 dependsOn cleanInstallersDataFiles
2037 projectFile = install4jConfFile
2039 // create an md5 for the input files to use as version for install4j conf file
2040 def digest = MessageDigest.getInstance("MD5")
2042 (file("${install4jDir}/${install4j_template}").text +
2043 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2044 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2045 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2046 if (filesMd5.length() >= 8) {
2047 filesMd5 = filesMd5.substring(0,8)
2049 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2052 'JALVIEW_NAME': jalview_name,
2053 'JALVIEW_APPLICATION_NAME': install4jApplicationName,
2054 'JALVIEW_DIR': "../..",
2055 'OSX_KEYSTORE': OSX_KEYSTORE,
2056 'OSX_APPLEID': OSX_APPLEID,
2057 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2058 'JSIGN_SH': JSIGN_SH,
2059 'JRE_DIR': getdown_app_dir_java,
2060 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2061 'JALVIEW_VERSION': JALVIEW_VERSION,
2062 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2063 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2064 'JAVA_VERSION': JAVA_VERSION,
2065 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2066 'VERSION': JALVIEW_VERSION,
2067 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2068 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2069 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2070 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2071 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2072 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2073 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2074 'BUNDLE_ID': install4jBundleId,
2075 'INTERNAL_ID': install4jInternalId,
2076 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2077 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2078 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
2079 'WRAPPER_LINK': getdownWrapperLink,
2080 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2081 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2082 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2083 'INSTALLER_NAME': install4jInstallerName,
2084 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2085 'GETDOWN_WEBSITE_DIR': getdown_website_dir,
2086 'GETDOWN_FILES_DIR': getdown_files_dir,
2087 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2088 'GETDOWN_DIST_DIR': getdownAppDistDir,
2089 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2090 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2091 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2092 'BUILD_DIR': install4jBuildDir,
2093 'APPLICATION_CATEGORIES': install4j_application_categories,
2094 'APPLICATION_FOLDER': install4jApplicationFolder,
2095 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2096 'EXECUTABLE_NAME': install4jExecutableName,
2097 'EXTRA_SCHEME': install4jExtraScheme,
2098 'MAC_ICONS_FILE': install4jMacIconsFile,
2099 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2100 'PNG_ICON_FILE': install4jPngIconFile,
2101 'BACKGROUND': install4jBackground,
2105 //println("INSTALL4J VARIABLES:")
2106 //variables.each{k,v->println("${k}=${v}")}
2108 destination = "${jalviewDir}/${install4jBuildDir}"
2109 buildSelected = true
2111 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2113 disableSigning = true
2114 disableNotarization = true
2118 macKeystorePassword = OSX_KEYPASS
2121 if (OSX_ALTOOLPASS) {
2122 appleIdPassword = OSX_ALTOOLPASS
2123 disableNotarization = false
2125 disableNotarization = true
2129 println("Using projectFile "+projectFile)
2130 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2134 inputs.dir(getdownWebsiteDir)
2135 inputs.file(install4jConfFile)
2136 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2137 inputs.dir(macosJavaVMDir)
2138 inputs.dir(windowsJavaVMDir)
2139 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2142 def getDataHash(File myFile) {
2143 HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
2144 return myFile.exists()
2146 "filename" : myFile.getName(),
2147 "filesize" : myFile.length(),
2148 "sha256" : hash.toString()
2153 def writeDataJsonFile(File installersOutputTxt, File installersSha256, File hugoDataJsonFile) {
2154 if (!installersOutputTxt.exists()) {
2155 throw new GradleException("Required input file '${installersOutputTxt.getPath()}' doesn't exist.")
2158 if (install4jCheckSums && (!installersSha256)) {
2159 throw new GradleException("Required input file '${installersSha256.getPath()}' doesn't exist.")
2163 "channel" : getdownChannelName,
2164 "date" : getDate("yyyy-MM-dd HH:mm:ss"),
2165 "git-commit" : "${gitHash} [${gitBranch}]",
2166 "version" : JALVIEW_VERSION
2169 installersOutputTxt.readLines().each { def line ->
2170 if (line.startsWith("#")) {
2173 line.replaceAll("\n","")
2174 def vals = line.split("\t")
2175 def filename = vals[3]
2176 def filesize = file(filename).length()
2177 filename = filename.replaceAll(/^.*\//, "")
2178 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2179 idHash."${filename}" = vals[0]
2181 if (install4jCheckSums) {
2182 installersSha256.readLines().each { def line ->
2183 if (line.startsWith("#")) {
2186 line.replaceAll("\n","")
2187 def vals = line.split(/\s+\*?/)
2188 def filename = vals[1]
2189 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2194 def jarHash = getDataHash(file(shadowJar.archiveFile))
2195 if (jarHash != null) {
2196 hash."JAR" = jarHash;
2200 def jvlHash =getDataHash(file(getdownVersionLaunchJvl))
2201 if (jvlHash != null) {
2202 hash."JVL" = jvlHash;
2206 def tarHash = getDataHash(file(sourceDist.archiveFile))
2207 if (tarHash != null) {
2208 hash."SOURCE" = tarHash;
2211 return hugoDataJsonFile.write(new JsonBuilder(hash).toPrettyString())
2214 task staticMakeInstallersJsonFile {
2216 def output = findProperty("i4j_output")
2217 def sha256 = findProperty("i4j_sha256")
2218 def json = findProperty("i4j_json")
2219 if (output == null || sha256 == null || json == null) {
2220 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2222 writeDataJsonFile(file(output), file(sha256), file(json))
2227 dependsOn installerFiles
2233 eclipse().configFile(eclipse_codestyle_file)
2237 task createSourceReleaseProperties(type: WriteProperties) {
2238 group = "distribution"
2239 description = "Create the source RELEASE properties file"
2241 def sourceTarBuildDir = "${buildDir}/sourceTar"
2242 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2243 outputFile (sourceReleasePropertiesFile)
2246 releaseProps.each{ key, val -> property key, val }
2247 property "git.branch", gitBranch
2248 property "git.hash", gitHash
2251 outputs.file(outputFile)
2254 task sourceDist(type: Tar) {
2255 group "distribution"
2256 description "Create a source .tar.gz file for distribution"
2258 dependsOn createBuildProperties
2259 dependsOn convertMdFiles
2260 dependsOn eclipseAllPreferences
2261 dependsOn createSourceReleaseProperties
2264 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2265 archiveFileName = outputFileName
2267 compression Compression.GZIP
2282 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2284 "utils/InstallAnywhere",
2299 "gradle.properties",
2311 ".settings/org.eclipse.buildship.core.prefs",
2312 ".settings/org.eclipse.jdt.core.prefs"
2316 exclude (EXCLUDE_FILES)
2317 include (PROCESS_FILES)
2318 filter(ReplaceTokens,
2322 'Version-Rel': JALVIEW_VERSION,
2323 'Year-Rel': getDate("yyyy")
2328 exclude (EXCLUDE_FILES)
2329 exclude (PROCESS_FILES)
2330 exclude ("appletlib")
2331 exclude ("**/*locales")
2332 exclude ("*locales/**")
2333 exclude ("utils/InstallAnywhere")
2335 exclude (getdown_files_dir)
2336 exclude (getdown_website_dir)
2338 // exluding these as not using jars as modules yet
2339 exclude ("${j11modDir}/**/*.jar")
2342 include(INCLUDE_FILES)
2344 // from (jalviewDir) {
2345 // // explicit includes for stuff that seemed to not get included
2346 // include(fileTree("test/**/*."))
2347 // exclude(EXCLUDE_FILES)
2348 // exclude(PROCESS_FILES)
2351 from(file(buildProperties).getParent()) {
2352 include(file(buildProperties).getName())
2353 rename(file(buildProperties).getName(), "build_properties")
2355 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2359 def sourceTarBuildDir = "${buildDir}/sourceTar"
2360 from(sourceTarBuildDir) {
2361 // this includes the appended RELEASE properties file
2365 task makeDataJsonFile {
2366 dependsOn installerFiles
2367 dependsOn sourceDist
2368 dependsOn getdownArchive
2371 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2372 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2373 def VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
2374 def hugoDataJsonFile = file("${jalviewDir}/${hugo_build_dir}/data/installers-${VERSION_UNDERSCORES}.json")
2376 inputs.file(installersOutputTxt)
2377 if (install4jCheckSums) {
2378 inputs.file(installersSha256)
2380 outputs.file(hugoDataJsonFile)
2383 writeDataJsonFile(installersOutputTxt, installersSha256, hugoDataJsonFile)
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