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 hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
2023 delete installersOutputTxt
2024 delete installersSha256
2025 delete hugoDataJsonFile
2029 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2030 group = "distribution"
2031 description = "Create the install4j installers"
2033 dependsOn copyInstall4jTemplate
2034 dependsOn cleanInstallersDataFiles
2036 projectFile = install4jConfFile
2038 // create an md5 for the input files to use as version for install4j conf file
2039 def digest = MessageDigest.getInstance("MD5")
2041 (file("${install4jDir}/${install4j_template}").text +
2042 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2043 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2044 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2045 if (filesMd5.length() >= 8) {
2046 filesMd5 = filesMd5.substring(0,8)
2048 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2051 'JALVIEW_NAME': jalview_name,
2052 'JALVIEW_APPLICATION_NAME': install4jApplicationName,
2053 'JALVIEW_DIR': "../..",
2054 'OSX_KEYSTORE': OSX_KEYSTORE,
2055 'OSX_APPLEID': OSX_APPLEID,
2056 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2057 'JSIGN_SH': JSIGN_SH,
2058 'JRE_DIR': getdown_app_dir_java,
2059 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2060 'JALVIEW_VERSION': JALVIEW_VERSION,
2061 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2062 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2063 'JAVA_VERSION': JAVA_VERSION,
2064 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2065 'VERSION': JALVIEW_VERSION,
2066 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2067 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2068 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2069 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2070 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2071 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2072 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2073 'BUNDLE_ID': install4jBundleId,
2074 'INTERNAL_ID': install4jInternalId,
2075 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2076 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2077 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
2078 'WRAPPER_LINK': getdownWrapperLink,
2079 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2080 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2081 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2082 'INSTALLER_NAME': install4jInstallerName,
2083 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2084 'GETDOWN_WEBSITE_DIR': getdown_website_dir,
2085 'GETDOWN_FILES_DIR': getdown_files_dir,
2086 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2087 'GETDOWN_DIST_DIR': getdownAppDistDir,
2088 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2089 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2090 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2091 'BUILD_DIR': install4jBuildDir,
2092 'APPLICATION_CATEGORIES': install4j_application_categories,
2093 'APPLICATION_FOLDER': install4jApplicationFolder,
2094 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2095 'EXECUTABLE_NAME': install4jExecutableName,
2096 'EXTRA_SCHEME': install4jExtraScheme,
2097 'MAC_ICONS_FILE': install4jMacIconsFile,
2098 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2099 'PNG_ICON_FILE': install4jPngIconFile,
2100 'BACKGROUND': install4jBackground,
2104 //println("INSTALL4J VARIABLES:")
2105 //variables.each{k,v->println("${k}=${v}")}
2107 destination = "${jalviewDir}/${install4jBuildDir}"
2108 buildSelected = true
2110 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2112 disableSigning = true
2113 disableNotarization = true
2117 macKeystorePassword = OSX_KEYPASS
2120 if (OSX_ALTOOLPASS) {
2121 appleIdPassword = OSX_ALTOOLPASS
2122 disableNotarization = false
2124 disableNotarization = true
2128 println("Using projectFile "+projectFile)
2129 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2133 inputs.dir(getdownWebsiteDir)
2134 inputs.file(install4jConfFile)
2135 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2136 inputs.dir(macosJavaVMDir)
2137 inputs.dir(windowsJavaVMDir)
2138 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2141 def getDataHash(File myFile) {
2142 HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
2143 return myFile.exists()
2145 "filename" : myFile.getName(),
2146 "filesize" : myFile.length(),
2147 "sha256" : hash.toString()
2152 def writeDataJsonFile(File installersOutputTxt, File installersSha256, File hugoDataJsonFile) {
2153 if (!installersOutputTxt.exists()) {
2154 throw new GradleException("Required input file '${installersOutputTxt.getPath()}' doesn't exist.")
2157 if (install4jCheckSums && (!installersSha256)) {
2158 throw new GradleException("Required input file '${installersSha256.getPath()}' doesn't exist.")
2162 "channel" : getdownChannelName,
2163 "date" : getDate("yyyy-MM-dd HH:mm:ss"),
2164 "git-commit" : "${gitHash} [${gitBranch}]",
2165 "version" : JALVIEW_VERSION
2168 installersOutputTxt.readLines().each { def line ->
2169 if (line.startsWith("#")) {
2172 line.replaceAll("\n","")
2173 def vals = line.split("\t")
2174 def filename = vals[3]
2175 def filesize = file(filename).length()
2176 filename = filename.replaceAll(/^.*\//, "")
2177 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2178 idHash."${filename}" = vals[0]
2180 if (install4jCheckSums) {
2181 installersSha256.readLines().each { def line ->
2182 if (line.startsWith("#")) {
2185 line.replaceAll("\n","")
2186 def vals = line.split(/\s+\*?/)
2187 def filename = vals[1]
2188 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2193 def jarHash = getDataHash(file(shadowJar.archiveFile))
2194 if (jarHash != null) {
2195 hash."JAR" = jarHash;
2199 def jvlHash =getDataHash(file(getdownVersionLaunchJvl))
2200 if (jvlHash != null) {
2201 hash."JVL" = jvlHash;
2205 def tarHash = getDataHash(file(sourceDist.archiveFile))
2206 if (tarHash != null) {
2207 hash."SOURCE" = tarHash;
2210 return hugoDataJsonFile.write(new JsonBuilder(hash).toPrettyString())
2213 task staticMakeInstallersJsonFile {
2215 def output = findProperty("i4j_output")
2216 def sha256 = findProperty("i4j_sha256")
2217 def json = findProperty("i4j_json")
2218 if (output == null || sha256 == null || json == null) {
2219 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2221 writeDataJsonFile(file(output), file(sha256), file(json))
2226 dependsOn installerFiles
2232 eclipse().configFile(eclipse_codestyle_file)
2236 task createSourceReleaseProperties(type: WriteProperties) {
2237 group = "distribution"
2238 description = "Create the source RELEASE properties file"
2240 def sourceTarBuildDir = "${buildDir}/sourceTar"
2241 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2242 outputFile (sourceReleasePropertiesFile)
2245 releaseProps.each{ key, val -> property key, val }
2246 property "git.branch", gitBranch
2247 property "git.hash", gitHash
2250 outputs.file(outputFile)
2253 task sourceDist(type: Tar) {
2254 group "distribution"
2255 description "Create a source .tar.gz file for distribution"
2257 dependsOn createBuildProperties
2258 dependsOn convertMdFiles
2259 dependsOn eclipseAllPreferences
2260 dependsOn createSourceReleaseProperties
2263 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2264 archiveFileName = outputFileName
2266 compression Compression.GZIP
2281 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2283 "utils/InstallAnywhere",
2298 "gradle.properties",
2310 ".settings/org.eclipse.buildship.core.prefs",
2311 ".settings/org.eclipse.jdt.core.prefs"
2315 exclude (EXCLUDE_FILES)
2316 include (PROCESS_FILES)
2317 filter(ReplaceTokens,
2321 'Version-Rel': JALVIEW_VERSION,
2322 'Year-Rel': getDate("yyyy")
2327 exclude (EXCLUDE_FILES)
2328 exclude (PROCESS_FILES)
2329 exclude ("appletlib")
2330 exclude ("**/*locales")
2331 exclude ("*locales/**")
2332 exclude ("utils/InstallAnywhere")
2334 exclude (getdown_files_dir)
2335 exclude (getdown_website_dir)
2337 // exluding these as not using jars as modules yet
2338 exclude ("${j11modDir}/**/*.jar")
2341 include(INCLUDE_FILES)
2343 // from (jalviewDir) {
2344 // // explicit includes for stuff that seemed to not get included
2345 // include(fileTree("test/**/*."))
2346 // exclude(EXCLUDE_FILES)
2347 // exclude(PROCESS_FILES)
2350 from(file(buildProperties).getParent()) {
2351 include(file(buildProperties).getName())
2352 rename(file(buildProperties).getName(), "build_properties")
2354 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2358 def sourceTarBuildDir = "${buildDir}/sourceTar"
2359 from(sourceTarBuildDir) {
2360 // this includes the appended RELEASE properties file
2364 task makeDataJsonFile {
2365 dependsOn installerFiles
2366 dependsOn sourceDist
2367 dependsOn getdownArchive
2370 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2371 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2372 def hugoDataJsonFile = file("${jalviewDir}/${hugo_build_dir}/data/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
2374 inputs.file(installersOutputTxt)
2375 if (install4jCheckSums) {
2376 inputs.file(installersSha256)
2378 outputs.file(hugoDataJsonFile)
2381 writeDataJsonFile(installersOutputTxt, installersSha256, hugoDataJsonFile)
2387 dependsOn pubhtmlhelp
2389 inputs.dir("${helpBuildDir}/${help_dir}")
2390 outputs.dir("${buildDir}/distributions/${help_dir}")
2394 task j2sSetHeadlessBuild {
2401 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2403 description "Enable the alternative J2S Config file for headless build"
2405 outputFile = jalviewjsJ2sSettingsFileName
2406 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2407 def j2sProps = new Properties()
2408 if (j2sPropsFile.exists()) {
2410 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2411 j2sProps.load(j2sPropsFileFIS)
2412 j2sPropsFileFIS.close()
2414 j2sProps.each { prop, val ->
2417 } catch (Exception e) {
2418 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2422 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2423 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2428 task jalviewjsSetEclipseWorkspace {
2429 def propKey = "jalviewjs_eclipse_workspace"
2431 if (project.hasProperty(propKey)) {
2432 propVal = project.getProperty(propKey)
2433 if (propVal.startsWith("~/")) {
2434 propVal = System.getProperty("user.home") + propVal.substring(1)
2437 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2438 def propsFile = file(propsFileName)
2439 def eclipseWsDir = propVal
2440 def props = new Properties()
2442 def writeProps = true
2443 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2444 def ins = new FileInputStream(propsFileName)
2447 if (props.getProperty(propKey, null) != null) {
2448 eclipseWsDir = props.getProperty(propKey)
2453 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2454 def tempDir = File.createTempDir()
2455 eclipseWsDir = tempDir.getAbsolutePath()
2458 eclipseWorkspace = file(eclipseWsDir)
2461 // do not run a headless transpile when we claim to be in Eclipse
2463 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2464 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2466 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2470 props.setProperty(propKey, eclipseWsDir)
2471 propsFile.parentFile.mkdirs()
2472 def bytes = new ByteArrayOutputStream()
2473 props.store(bytes, null)
2474 def propertiesString = bytes.toString()
2475 propsFile.text = propertiesString
2481 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2484 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2485 outputs.file(propsFileName)
2486 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2490 task jalviewjsEclipsePaths {
2493 def eclipseRoot = jalviewjs_eclipse_root
2494 if (eclipseRoot.startsWith("~/")) {
2495 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
2497 if (OperatingSystem.current().isMacOsX()) {
2498 eclipseRoot += "/Eclipse.app"
2499 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
2500 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
2501 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
2502 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2503 eclipseRoot += "/eclipse"
2505 eclipseBinary = "${eclipseRoot}/eclipse.exe"
2506 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2507 } else { // linux or unix
2508 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2509 eclipseRoot += "/eclipse"
2510 println("eclipseDir exists")
2512 eclipseBinary = "${eclipseRoot}/eclipse"
2513 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2516 eclipseVersion = "4.13" // default
2517 def assumedVersion = true
2518 if (file(eclipseProduct).exists()) {
2519 def fis = new FileInputStream(eclipseProduct)
2520 def props = new Properties()
2522 eclipseVersion = props.getProperty("version")
2524 assumedVersion = false
2527 def propKey = "eclipse_debug"
2528 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
2531 // do not run a headless transpile when we claim to be in Eclipse
2533 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2534 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2536 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2539 if (!assumedVersion) {
2540 println("ECLIPSE VERSION=${eclipseVersion}")
2546 task printProperties {
2548 description "Output to console all System.properties"
2550 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
2556 dependsOn eclipseProject
2557 dependsOn eclipseClasspath
2558 dependsOn eclipseJdt
2562 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
2563 task jalviewjsEclipseCopyDropins(type: Copy) {
2564 dependsOn jalviewjsEclipsePaths
2566 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
2567 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
2568 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
2575 // this eclipse -clean doesn't actually work
2576 task jalviewjsCleanEclipse(type: Exec) {
2577 dependsOn eclipseSetup
2578 dependsOn jalviewjsEclipsePaths
2579 dependsOn jalviewjsEclipseCopyDropins
2581 executable(eclipseBinary)
2582 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
2588 def inputString = """exit
2591 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
2592 standardInput = inputByteStream
2595 /* not really working yet
2596 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
2600 task jalviewjsTransferUnzipSwingJs {
2601 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
2605 from zipTree(file_zip)
2606 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2610 inputs.file file_zip
2611 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2615 task jalviewjsTransferUnzipLib {
2616 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
2619 zipFiles.each { file_zip ->
2621 from zipTree(file_zip)
2622 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2627 inputs.files zipFiles
2628 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2632 task jalviewjsTransferUnzipAllLibs {
2633 dependsOn jalviewjsTransferUnzipSwingJs
2634 dependsOn jalviewjsTransferUnzipLib
2638 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
2640 description "Create the alternative j2s file from the j2s.* properties"
2642 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
2643 def siteDirProperty = "j2s.site.directory"
2644 def setSiteDir = false
2645 jalviewjsJ2sProps.each { prop, val ->
2647 if (prop == siteDirProperty) {
2648 if (!(val.startsWith('/') || val.startsWith("file://") )) {
2649 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
2655 if (!setSiteDir) { // default site location, don't override specifically set property
2656 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
2659 outputFile = jalviewjsJ2sAltSettingsFileName
2662 inputs.properties(jalviewjsJ2sProps)
2663 outputs.file(jalviewjsJ2sAltSettingsFileName)
2668 task jalviewjsEclipseSetup {
2669 dependsOn jalviewjsEclipseCopyDropins
2670 dependsOn jalviewjsSetEclipseWorkspace
2671 dependsOn jalviewjsCreateJ2sSettings
2675 task jalviewjsSyncAllLibs (type: Sync) {
2676 dependsOn jalviewjsTransferUnzipAllLibs
2677 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
2678 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
2679 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2683 def outputFiles = []
2684 rename { filename ->
2685 outputFiles += "${outputDir}/${filename}"
2692 // should this be exclude really ?
2693 duplicatesStrategy "INCLUDE"
2695 outputs.files outputFiles
2696 inputs.files inputFiles
2700 task jalviewjsSyncResources (type: Sync) {
2701 dependsOn buildResources
2703 def inputFiles = fileTree(dir: resourcesBuildDir)
2704 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
2708 def outputFiles = []
2709 rename { filename ->
2710 outputFiles += "${outputDir}/${filename}"
2716 outputs.files outputFiles
2717 inputs.files inputFiles
2721 task jalviewjsSyncSiteResources (type: Sync) {
2722 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
2723 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2727 def outputFiles = []
2728 rename { filename ->
2729 outputFiles += "${outputDir}/${filename}"
2735 outputs.files outputFiles
2736 inputs.files inputFiles
2740 task jalviewjsSyncBuildProperties (type: Sync) {
2741 dependsOn createBuildProperties
2742 def inputFiles = [file(buildProperties)]
2743 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
2747 def outputFiles = []
2748 rename { filename ->
2749 outputFiles += "${outputDir}/${filename}"
2755 outputs.files outputFiles
2756 inputs.files inputFiles
2760 task jalviewjsProjectImport(type: Exec) {
2761 dependsOn eclipseSetup
2762 dependsOn jalviewjsEclipsePaths
2763 dependsOn jalviewjsEclipseSetup
2766 // do not run a headless import when we claim to be in Eclipse
2768 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2769 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2771 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2775 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
2776 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
2777 executable(eclipseBinary)
2778 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
2782 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
2784 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
2785 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
2788 inputs.file("${jalviewDir}/.project")
2789 outputs.upToDateWhen {
2790 file(projdir).exists()
2795 task jalviewjsTranspile(type: Exec) {
2796 dependsOn jalviewjsEclipseSetup
2797 dependsOn jalviewjsProjectImport
2798 dependsOn jalviewjsEclipsePaths
2800 dependsOn jalviewjsEnableAltFileProperty
2804 // do not run a headless transpile when we claim to be in Eclipse
2806 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2807 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2809 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2813 executable(eclipseBinary)
2814 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
2818 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
2820 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
2821 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
2827 stdout = new ByteArrayOutputStream()
2828 stderr = new ByteArrayOutputStream()
2830 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
2831 def logOutFile = file(logOutFileName)
2832 logOutFile.createNewFile()
2833 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
2834 BINARY: ${eclipseBinary}
2835 VERSION: ${eclipseVersion}
2836 WORKSPACE: ${eclipseWorkspace}
2837 DEBUG: ${eclipseDebug}
2840 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
2841 // combine stdout and stderr
2842 def logErrFOS = logOutFOS
2844 if (jalviewjs_j2s_to_console.equals("true")) {
2845 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2846 new org.apache.tools.ant.util.TeeOutputStream(
2850 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2851 new org.apache.tools.ant.util.TeeOutputStream(
2856 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2859 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2866 if (stdout.toString().contains("Error processing ")) {
2867 // j2s did not complete transpile
2868 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2869 if (jalviewjs_ignore_transpile_errors.equals("true")) {
2870 println("IGNORING TRANSPILE ERRORS")
2871 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2873 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2878 inputs.dir("${jalviewDir}/${sourceDir}")
2879 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
2880 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
2884 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
2886 def stdout = new ByteArrayOutputStream()
2887 def stderr = new ByteArrayOutputStream()
2889 def coreFile = file(jsfile)
2891 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
2893 logOutFile.createNewFile()
2894 logOutFile.append(msg+"\n")
2896 def coreTop = file(prefixFile)
2897 def coreBottom = file(suffixFile)
2898 coreFile.getParentFile().mkdirs()
2899 coreFile.createNewFile()
2900 coreFile.write( coreTop.getText("UTF-8") )
2904 def t = f.getText("UTF-8")
2905 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
2906 coreFile.append( t )
2908 msg = "...file '"+f.getPath()+"' does not exist, skipping"
2910 logOutFile.append(msg+"\n")
2913 coreFile.append( coreBottom.getText("UTF-8") )
2915 msg = "Generating ${zjsfile}"
2917 logOutFile.append(msg+"\n")
2918 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
2919 def logErrFOS = logOutFOS
2922 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
2923 main = "com.google.javascript.jscomp.CommandLineRunner"
2924 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
2925 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
2928 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
2930 logOutFile.append(msg+"\n")
2932 if (logOutConsole) {
2933 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2934 new org.apache.tools.ant.util.TeeOutputStream(
2938 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2939 new org.apache.tools.ant.util.TeeOutputStream(
2944 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2947 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2954 logOutFile.append(msg+"\n")
2958 task jalviewjsBuildAllCores {
2960 description "Build the core js lib closures listed in the classlists dir"
2961 dependsOn jalviewjsTranspile
2962 dependsOn jalviewjsTransferUnzipSwingJs
2964 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
2965 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
2966 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
2967 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
2968 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
2969 def prefixFile = "${jsDir}/core/coretop2.js"
2970 def suffixFile = "${jsDir}/core/corebottom2.js"
2972 inputs.file prefixFile
2973 inputs.file suffixFile
2975 def classlistFiles = []
2976 // add the classlists found int the jalviewjs_classlists_dir
2977 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
2979 def name = file.getName() - ".txt"
2986 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
2987 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
2988 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
2990 jalviewjsCoreClasslists = []
2992 classlistFiles.each {
2995 def file = hash['file']
2996 if (! file.exists()) {
2997 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
2998 return false // this is a "continue" in groovy .each closure
3000 def name = hash['name']
3002 name = file.getName() - ".txt"
3010 def list = fileTree(dir: j2sDir, includes: filelist)
3012 def jsfile = "${outputDir}/core${name}.js"
3013 def zjsfile = "${outputDir}/core${name}.z.js"
3015 jalviewjsCoreClasslists += [
3024 outputs.file(jsfile)
3025 outputs.file(zjsfile)
3028 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
3029 def stevesoftClasslistName = "_stevesoft"
3030 def stevesoftClasslist = [
3031 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
3032 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
3033 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
3034 'name': stevesoftClasslistName
3036 jalviewjsCoreClasslists += stevesoftClasslist
3037 inputs.files(stevesoftClasslist['list'])
3038 outputs.file(stevesoftClasslist['jsfile'])
3039 outputs.file(stevesoftClasslist['zjsfile'])
3042 def allClasslistName = "_all"
3043 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3044 allJsFiles += fileTree(
3048 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3049 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3050 "**/org/jmol/export/JSExporter.js"
3053 allJsFiles += fileTree(
3057 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3058 "**/sun/misc/Unsafe.js",
3059 "**/swingjs/jquery/jquery-editable-select.js",
3060 "**/swingjs/jquery/j2sComboBox.js",
3061 "**/sun/misc/FloatingDecimal.js"
3064 def allClasslist = [
3065 'jsfile': "${outputDir}/core${allClasslistName}.js",
3066 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
3068 'name': allClasslistName
3070 // not including this version of "all" core at the moment
3071 //jalviewjsCoreClasslists += allClasslist
3072 inputs.files(allClasslist['list'])
3073 outputs.file(allClasslist['jsfile'])
3074 outputs.file(allClasslist['zjsfile'])
3077 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3078 logOutFile.getParentFile().mkdirs()
3079 logOutFile.createNewFile()
3080 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3082 jalviewjsCoreClasslists.each {
3083 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3090 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3093 into file(outputFile).getParentFile()
3094 rename { filename ->
3095 if (filename.equals(inputFile.getName())) {
3096 return file(outputFile).getName()
3100 filter(ReplaceTokens,
3104 'MAIN': '"'+main_class+'"',
3106 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3107 'COREKEY': jalviewjs_core_key,
3108 'CORENAME': coreName
3115 task jalviewjsPublishCoreTemplates {
3116 dependsOn jalviewjsBuildAllCores
3117 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3118 def inputFile = file(inputFileName)
3119 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3121 def outputFiles = []
3122 jalviewjsCoreClasslists.each { cl ->
3123 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3124 cl['outputfile'] = outputFile
3125 outputFiles += outputFile
3129 jalviewjsCoreClasslists.each { cl ->
3130 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3133 inputs.file(inputFile)
3134 outputs.files(outputFiles)
3138 task jalviewjsSyncCore (type: Sync) {
3139 dependsOn jalviewjsBuildAllCores
3140 dependsOn jalviewjsPublishCoreTemplates
3141 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3142 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3146 def outputFiles = []
3147 rename { filename ->
3148 outputFiles += "${outputDir}/${filename}"
3154 outputs.files outputFiles
3155 inputs.files inputFiles
3159 // this Copy version of TransferSiteJs will delete anything else in the target dir
3160 task jalviewjsCopyTransferSiteJs(type: Copy) {
3161 dependsOn jalviewjsTranspile
3162 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3163 into "${jalviewDir}/${jalviewjsSiteDir}"
3167 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3168 task jalviewjsSyncTransferSiteJs(type: Sync) {
3169 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3171 into "${jalviewDir}/${jalviewjsSiteDir}"
3178 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3179 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3180 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3181 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3183 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3184 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3185 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3186 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3189 task jalviewjsPrepareSite {
3191 description "Prepares the website folder including unzipping files and copying resources"
3192 dependsOn jalviewjsSyncAllLibs
3193 dependsOn jalviewjsSyncResources
3194 dependsOn jalviewjsSyncSiteResources
3195 dependsOn jalviewjsSyncBuildProperties
3196 dependsOn jalviewjsSyncCore
3200 task jalviewjsBuildSite {
3202 description "Builds the whole website including transpiled code"
3203 dependsOn jalviewjsCopyTransferSiteJs
3204 dependsOn jalviewjsPrepareSite
3208 task cleanJalviewjsTransferSite {
3210 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3211 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3212 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3213 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3218 task cleanJalviewjsSite {
3219 dependsOn cleanJalviewjsTransferSite
3221 delete "${jalviewDir}/${jalviewjsSiteDir}"
3226 task jalviewjsSiteTar(type: Tar) {
3228 description "Creates a tar.gz file for the website"
3229 dependsOn jalviewjsBuildSite
3230 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3231 archiveFileName = outputFilename
3233 compression Compression.GZIP
3235 from "${jalviewDir}/${jalviewjsSiteDir}"
3236 into jalviewjs_site_dir // this is inside the tar file
3238 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3242 task jalviewjsServer {
3244 def filename = "jalviewjsTest.html"
3245 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3246 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3251 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3252 factory = f.newInstance()
3253 } catch (ClassNotFoundException e) {
3254 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3256 def port = Integer.valueOf(jalviewjs_server_port)
3261 while(port < start+1000 && !running) {
3263 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3264 jalviewjsServer = factory.start(doc_root, port)
3266 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3267 println("SERVER STARTED with document root ${doc_root}.")
3268 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3269 println("For debug: "+url+"?j2sdebug")
3270 println("For verbose: "+url+"?j2sverbose")
3271 } catch (Exception e) {
3276 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3277 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3278 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3280 jalviewjsCoreClasslists.each { cl ->
3281 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3283 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3285 println("For core ${cl.name}: "+urlcore)
3288 file(htmlFile).text = htmlText
3291 outputs.file(htmlFile)
3292 outputs.upToDateWhen({false})
3296 task cleanJalviewjsAll {
3298 description "Delete all configuration and build artifacts to do with JalviewJS build"
3299 dependsOn cleanJalviewjsSite
3300 dependsOn jalviewjsEclipsePaths
3303 delete "${jalviewDir}/${jalviewjsBuildDir}"
3304 delete "${jalviewDir}/${eclipse_bin_dir}"
3305 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3306 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3308 delete jalviewjsJ2sAltSettingsFileName
3311 outputs.upToDateWhen( { false } )
3315 task jalviewjsIDE_checkJ2sPlugin {
3316 group "00 JalviewJS in Eclipse"
3317 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3320 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3321 def j2sPluginFile = file(j2sPlugin)
3322 def eclipseHome = System.properties["eclipse.home.location"]
3323 if (eclipseHome == null || ! IN_ECLIPSE) {
3324 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3326 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3327 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3328 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3329 eclipseJ2sPluginDirs += altPluginsDir
3331 def foundPlugin = false
3332 def j2sPluginFileName = j2sPluginFile.getName()
3333 def eclipseJ2sPlugin
3334 def eclipseJ2sPluginFile
3335 eclipseJ2sPluginDirs.any { dir ->
3336 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3337 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3338 if (eclipseJ2sPluginFile.exists()) {
3344 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3345 System.err.println(msg)
3346 throw new StopExecutionException(msg)
3349 def digest = MessageDigest.getInstance("MD5")
3351 digest.update(j2sPluginFile.text.bytes)
3352 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3354 digest.update(eclipseJ2sPluginFile.text.bytes)
3355 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3357 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3358 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3359 System.err.println(msg)
3360 throw new StopExecutionException(msg)
3362 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3368 task jalviewjsIDE_copyJ2sPlugin {
3369 group "00 JalviewJS in Eclipse"
3370 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3373 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3374 def j2sPluginFile = file(j2sPlugin)
3375 def eclipseHome = System.properties["eclipse.home.location"]
3376 if (eclipseHome == null || ! IN_ECLIPSE) {
3377 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3379 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3380 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3381 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3382 System.err.println(msg)
3385 eclipseJ2sPluginFile.getParentFile().mkdirs()
3386 into eclipseJ2sPluginFile.getParent()
3392 task jalviewjsIDE_j2sFile {
3393 group "00 JalviewJS in Eclipse"
3394 description "Creates the .j2s file"
3395 dependsOn jalviewjsCreateJ2sSettings
3399 task jalviewjsIDE_SyncCore {
3400 group "00 JalviewJS in Eclipse"
3401 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3402 dependsOn jalviewjsSyncCore
3406 task jalviewjsIDE_SyncSiteAll {
3407 dependsOn jalviewjsSyncAllLibs
3408 dependsOn jalviewjsSyncResources
3409 dependsOn jalviewjsSyncSiteResources
3410 dependsOn jalviewjsSyncBuildProperties
3414 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3417 task jalviewjsIDE_PrepareSite {
3418 group "00 JalviewJS in Eclipse"
3419 description "Sync libs and resources to site dir, but not closure cores"
3421 dependsOn jalviewjsIDE_SyncSiteAll
3422 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3426 task jalviewjsIDE_AssembleSite {
3427 group "00 JalviewJS in Eclipse"
3428 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3429 dependsOn jalviewjsPrepareSite
3433 task jalviewjsIDE_SiteClean {
3434 group "00 JalviewJS in Eclipse"
3435 description "Deletes the Eclipse transpiled site"
3436 dependsOn cleanJalviewjsSite
3440 task jalviewjsIDE_Server {
3441 group "00 JalviewJS in Eclipse"
3442 description "Starts a webserver on localhost to test the website"
3443 dependsOn jalviewjsServer
3447 // buildship runs this at import or gradle refresh
3448 task eclipseSynchronizationTask {
3449 //dependsOn eclipseSetup
3450 dependsOn createBuildProperties
3452 dependsOn jalviewjsIDE_j2sFile
3453 dependsOn jalviewjsIDE_checkJ2sPlugin
3454 dependsOn jalviewjsIDE_PrepareSite
3459 // buildship runs this at build time or project refresh
3460 task eclipseAutoBuildTask {
3461 //dependsOn jalviewjsIDE_checkJ2sPlugin
3462 //dependsOn jalviewjsIDE_PrepareSite
3468 description "Build the site"
3469 dependsOn jalviewjsBuildSite