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
33 classpath "com.vladsch.flexmark:flexmark-all:0.62.0"
42 id "com.diffplug.gradle.spotless" version "3.28.0"
43 id 'com.github.johnrengelman.shadow' version '4.0.3'
44 id 'com.install4j.gradle' version '9.0.6'
45 id 'com.dorongold.task-tree' version '1.5' // only needed to display task dependency tree with gradle task1 [task2 ...] taskTree
46 id 'com.palantir.git-version' version '0.13.0' apply false
57 // in ext the values are cast to Object. Ensure string values are cast as String (and not GStringImpl) for later use
58 def string(Object o) {
59 return o == null ? "" : o.toString()
62 def overrideProperties(String propsFileName, boolean output = false) {
63 if (propsFileName == null) {
66 def propsFile = file(propsFileName)
67 if (propsFile != null && propsFile.exists()) {
68 println("Using properties from file '${propsFileName}'")
70 def p = new Properties()
71 def localPropsFIS = new FileInputStream(propsFile)
77 if (project.hasProperty(key)) {
78 oldval = project.findProperty(key)
79 project.setProperty(key, val)
81 println("Overriding property '${key}' ('${oldval}') with ${file(propsFile).getName()} value '${val}'")
84 ext.setProperty(key, val)
86 println("Setting ext property '${key}' with ${file(propsFile).getName()}s value '${val}'")
90 } catch (Exception e) {
91 println("Exception reading local.properties")
98 jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath()
99 jalviewDirRelativePath = jalviewDir
102 getdownChannelName = CHANNEL.toLowerCase()
103 // default to "default". Currently only has different cosmetics for "develop", "release", "default"
104 propertiesChannelName = ["develop", "release", "test-release", "jalviewjs", "jalviewjs-release" ].contains(getdownChannelName) ? getdownChannelName : "default"
105 // Import channel_properties
106 channelDir = string("${jalviewDir}/${channel_properties_dir}/${propertiesChannelName}")
107 channelGradleProperties = string("${channelDir}/channel_gradle.properties")
108 channelPropsFile = string("${channelDir}/${resource_dir}/${channel_props}")
109 overrideProperties(channelGradleProperties, false)
110 // local build environment properties
111 // can be "projectDir/local.properties"
112 overrideProperties("${projectDir}/local.properties", true)
113 // or "../projectDir_local.properties"
114 overrideProperties(projectDir.getParent() + "/" + projectDir.getName() + "_local.properties", true)
117 // Import releaseProps from the RELEASE file
118 // or a file specified via JALVIEW_RELEASE_FILE if defined
119 // Expect jalview.version and target release branch in jalview.release
120 releaseProps = new Properties();
121 def releasePropFile = findProperty("JALVIEW_RELEASE_FILE");
122 def defaultReleasePropFile = "${jalviewDirAbsolutePath}/RELEASE";
124 (new File(releasePropFile!=null ? releasePropFile : defaultReleasePropFile)).withInputStream {
125 releaseProps.load(it)
127 } catch (Exception fileLoadError) {
128 throw new Error("Couldn't load release properties file "+(releasePropFile==null ? defaultReleasePropFile : "from custom location: releasePropFile"),fileLoadError);
131 // Set JALVIEW_VERSION if it is not already set
132 if (findProperty("JALVIEW_VERSION")==null || "".equals(JALVIEW_VERSION)) {
133 JALVIEW_VERSION = releaseProps.get("jalview.version")
136 // this property set when running Eclipse headlessly
137 j2sHeadlessBuildProperty = string("net.sf.j2s.core.headlessbuild")
138 // this property set by Eclipse
139 eclipseApplicationProperty = string("eclipse.application")
140 // CHECK IF RUNNING FROM WITHIN ECLIPSE
141 def eclipseApplicationPropertyVal = System.properties[eclipseApplicationProperty]
142 IN_ECLIPSE = eclipseApplicationPropertyVal != null && eclipseApplicationPropertyVal.startsWith("org.eclipse.ui.")
143 // BUT WITHOUT THE HEADLESS BUILD PROPERTY SET
144 if (System.properties[j2sHeadlessBuildProperty].equals("true")) {
145 println("Setting IN_ECLIPSE to ${IN_ECLIPSE} as System.properties['${j2sHeadlessBuildProperty}'] == '${System.properties[j2sHeadlessBuildProperty]}'")
149 println("WITHIN ECLIPSE IDE")
151 println("HEADLESS BUILD")
154 J2S_ENABLED = (project.hasProperty('j2s.compiler.status') && project['j2s.compiler.status'] != null && project['j2s.compiler.status'] == "enable")
156 println("J2S ENABLED")
159 System.properties.sort { it.key }.each {
160 key, val -> println("SYSTEM PROPERTY ${key}='${val}'")
163 if (false && IN_ECLIPSE) {
164 jalviewDir = jalviewDirAbsolutePath
169 buildDate = new Date().format("yyyyMMdd")
172 bareSourceDir = string(source_dir)
173 sourceDir = string("${jalviewDir}/${bareSourceDir}")
174 resourceDir = string("${jalviewDir}/${resource_dir}")
175 bareTestSourceDir = string(test_source_dir)
176 testDir = string("${jalviewDir}/${bareTestSourceDir}")
178 classesDir = string("${jalviewDir}/${classes_dir}")
181 useClover = clover.equals("true")
182 cloverBuildDir = "${buildDir}/clover"
183 cloverInstrDir = file("${cloverBuildDir}/clover-instr")
184 cloverClassesDir = file("${cloverBuildDir}/clover-classes")
185 cloverReportDir = file("${buildDir}/reports/clover")
186 cloverTestInstrDir = file("${cloverBuildDir}/clover-test-instr")
187 cloverTestClassesDir = file("${cloverBuildDir}/clover-test-classes")
188 //cloverTestClassesDir = cloverClassesDir
189 cloverDb = string("${cloverBuildDir}/clover.db")
191 testSourceDir = useClover ? cloverTestInstrDir : testDir
192 testClassesDir = useClover ? cloverTestClassesDir : "${jalviewDir}/${test_output_dir}"
194 getdownWebsiteDir = string("${jalviewDir}/${getdown_website_dir}/${JAVA_VERSION}")
195 getdownArchiveDir = string("${jalviewDir}/${getdown_archive_dir}")
196 getdownFullArchiveDir = null
197 getdownTextLines = []
198 getdownLaunchJvl = null
200 buildProperties = null
202 // the following values might be overridden by the CHANNEL switch
203 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
204 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
205 getdownArchiveAppBase = null
206 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}")
207 getdownAppDistDir = getdown_app_dir_alt
208 getdownImagesDir = string("${jalviewDir}/${getdown_images_dir}")
209 getdownSetAppBaseProperty = false // whether to pass the appbase and appdistdir to the application
210 reportRsyncCommand = false
211 jvlChannelName = CHANNEL.toLowerCase()
212 install4jSuffix = CHANNEL.substring(0, 1).toUpperCase() + CHANNEL.substring(1).toLowerCase(); // BUILD -> Build
213 install4jDMGDSStore = "${install4j_images_dir}/${install4j_dmg_ds_store}"
214 install4jDMGBackgroundImage = "${install4j_images_dir}/${install4j_dmg_background}"
215 install4jInstallerName = "${jalview_name} Non-Release Installer"
216 install4jExecutableName = install4j_executable_name
217 install4jExtraScheme = "jalviewx"
218 install4jMacIconsFile = string("${install4j_images_dir}/${install4j_mac_icons_file}")
219 install4jWindowsIconsFile = string("${install4j_images_dir}/${install4j_windows_icons_file}")
220 install4jPngIconFile = string("${install4j_images_dir}/${install4j_png_icon_file}")
221 install4jBackground = string("${install4j_images_dir}/${install4j_background}")
222 install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
223 install4jCheckSums = true
227 // TODO: get bamboo build artifact URL for getdown artifacts
228 getdown_channel_base = bamboo_channelbase
229 getdownChannelName = string("${bamboo_planKey}/${JAVA_VERSION}")
230 getdownAppBase = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
231 jvlChannelName += "_${getdownChannelName}"
232 // automatically add the test group Not-bamboo for exclusion
233 if ("".equals(testng_excluded_groups)) {
234 testng_excluded_groups = "Not-bamboo"
236 install4jExtraScheme = "jalviewb"
239 case [ "RELEASE", "JALVIEWJS-RELEASE" ]:
240 getdownAppDistDir = getdown_app_dir_release
241 getdownSetAppBaseProperty = true
242 reportRsyncCommand = true
244 install4jInstallerName = "${jalview_name} Installer"
245 getdownArchiveAppBase = getdown_archive_base
249 getdownChannelName = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
250 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
251 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
252 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
253 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
255 package_dir = string("${ARCHIVEDIR}/${package_dir}")
256 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
259 reportRsyncCommand = true
260 install4jExtraScheme = "jalviewa"
264 getdownChannelName = string("archive/${JALVIEW_VERSION}")
265 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
266 getdownAppBase = file(getdownWebsiteDir).toURI().toString()
267 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
268 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
270 package_dir = string("${ARCHIVEDIR}/${package_dir}")
271 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
274 reportRsyncCommand = true
275 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
276 install4jSuffix = "Archive"
277 install4jExtraScheme = "jalviewa"
281 reportRsyncCommand = true
282 getdownSetAppBaseProperty = true
283 // DEVELOP-RELEASE is usually associated with a Jalview release series so set the version
284 JALVIEW_VERSION=JALVIEW_VERSION+"-d${buildDate}"
286 install4jSuffix = "Develop"
287 install4jExtraScheme = "jalviewd"
288 install4jInstallerName = "${jalview_name} Develop Installer"
292 reportRsyncCommand = true
293 getdownSetAppBaseProperty = true
294 // Don't ignore transpile errors for release build
295 if (jalviewjs_ignore_transpile_errors.equals("true")) {
296 jalviewjs_ignore_transpile_errors = "false"
297 println("Setting jalviewjs_ignore_transpile_errors to 'false'")
299 JALVIEW_VERSION = JALVIEW_VERSION+"-test"
300 install4jSuffix = "Test"
301 install4jExtraScheme = "jalviewt"
302 install4jInstallerName = "${jalview_name} Test Installer"
305 case ~/^SCRATCH(|-[-\w]*)$/:
306 getdownChannelName = CHANNEL
307 JALVIEW_VERSION = JALVIEW_VERSION+"-"+CHANNEL
309 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
310 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
311 reportRsyncCommand = true
312 install4jSuffix = "Scratch"
316 if (!file("${LOCALDIR}").exists()) {
317 throw new GradleException("Must provide a LOCALDIR value to produce a local distribution")
319 getdownAppBase = file(file("${LOCALDIR}").getAbsolutePath()).toURI().toString()
320 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
322 JALVIEW_VERSION = "TEST"
323 install4jSuffix = "Test-Local"
324 install4jExtraScheme = "jalviewt"
325 install4jInstallerName = "${jalview_name} Test Installer"
328 case [ "LOCAL", "JALVIEWJS" ]:
329 JALVIEW_VERSION = "TEST"
330 getdownAppBase = file(getdownWebsiteDir).toURI().toString()
331 getdownArchiveAppBase = file("${jalviewDir}/${getdown_archive_dir}").toURI().toString()
332 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
333 install4jExtraScheme = "jalviewl"
334 install4jCheckSums = false
337 default: // something wrong specified
338 throw new GradleException("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
342 JALVIEW_VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
343 // override getdownAppBase if requested
344 if (findProperty("getdown_appbase_override") != null) {
345 // revert to LOCAL if empty string
346 if (string(getdown_appbase_override) == "") {
347 getdownAppBase = file(getdownWebsiteDir).toURI().toString()
348 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
349 } else if (string(getdown_appbase_override).startsWith("file://")) {
350 getdownAppBase = string(getdown_appbase_override)
351 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
353 getdownAppBase = string(getdown_appbase_override)
355 println("Overriding getdown appbase with '${getdownAppBase}'")
357 // sanitise file name for jalview launcher file for this channel
358 jvlChannelName = jvlChannelName.replaceAll("[^\\w\\-]+", "_")
359 // install4j application and folder names
360 if (install4jSuffix == "") {
361 install4jApplicationName = "${jalview_name}"
362 install4jBundleId = "${install4j_bundle_id}"
363 install4jWinApplicationId = install4j_release_win_application_id
365 install4jApplicationName = "${jalview_name} ${install4jSuffix}"
366 install4jBundleId = "${install4j_bundle_id}-" + install4jSuffix.toLowerCase()
367 // add int hash of install4jSuffix to the last part of the application_id
368 def id = install4j_release_win_application_id
369 def idsplitreverse = id.split("-").reverse()
370 idsplitreverse[0] = idsplitreverse[0].toInteger() + install4jSuffix.hashCode()
371 install4jWinApplicationId = idsplitreverse.reverse().join("-")
373 // sanitise folder and id names
374 // install4jApplicationFolder = e.g. "Jalview Build"
375 install4jApplicationFolder = install4jApplicationName
376 .replaceAll("[\"'~:/\\\\\\s]", "_") // replace all awkward filename chars " ' ~ : / \
377 .replaceAll("_+", "_") // collapse __
378 install4jInternalId = install4jApplicationName
380 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
381 .replaceAll("_+", "") // collapse __
382 //.replaceAll("_*-_*", "-") // collapse _-_
383 install4jUnixApplicationFolder = install4jApplicationName
385 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
386 .replaceAll("_+", "_") // collapse __
387 .replaceAll("_*-_*", "-") // collapse _-_
390 getdownWrapperLink = install4jUnixApplicationFolder // e.g. "jalview_local"
391 getdownAppDir = string("${getdownWebsiteDir}/${getdownAppDistDir}")
392 //getdownJ11libDir = "${getdownWebsiteDir}/${getdown_j11lib_dir}"
393 getdownResourceDir = string("${getdownWebsiteDir}/${getdown_resource_dir}")
394 getdownInstallDir = string("${getdownWebsiteDir}/${getdown_install_dir}")
395 getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
396 getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
397 /* compile without modules -- using classpath libraries
398 modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
399 modules_runtimeClasspath = modules_compileClasspath
405 apply plugin: "com.palantir.git-version"
406 def details = versionDetails()
407 gitHash = details.gitHash
408 gitBranch = details.branchName
409 } catch(org.gradle.api.internal.plugins.PluginApplicationException e) {
410 println("Not in a git repository. Using git values from RELEASE properties file.")
411 gitHash = releaseProps.getProperty("git.hash")
412 gitBranch = releaseProps.getProperty("git.branch")
413 } catch(java.lang.RuntimeException e1) {
414 throw new GradleException("Error with git-version plugin. Directory '.git' exists but versionDetails() cannot be found.")
417 println("Using a ${CHANNEL} profile.")
419 additional_compiler_args = []
420 // configure classpath/args for j8/j11 compilation
421 if (JAVA_VERSION.equals("1.8")) {
422 JAVA_INTEGER_VERSION = string("8")
425 libDistDir = j8libDir
426 compile_source_compatibility = 1.8
427 compile_target_compatibility = 1.8
428 // these are getdown.txt properties defined dependent on the JAVA_VERSION
429 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
430 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
431 // this property is assigned below and expanded to multiple lines in the getdown task
432 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
433 // this property is for the Java library used in eclipse
434 eclipseJavaRuntimeName = string("JavaSE-1.8")
435 } else if (JAVA_VERSION.equals("11")) {
436 JAVA_INTEGER_VERSION = string("11")
438 libDistDir = j11libDir
439 compile_source_compatibility = 11
440 compile_target_compatibility = 11
441 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
442 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
443 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
444 eclipseJavaRuntimeName = string("JavaSE-11")
445 /* compile without modules -- using classpath libraries
446 additional_compiler_args += [
447 '--module-path', modules_compileClasspath.asPath,
448 '--add-modules', j11modules
451 } else if (JAVA_VERSION.equals("17")) {
452 JAVA_INTEGER_VERSION = string("17")
454 libDistDir = j17libDir
455 compile_source_compatibility = 17
456 compile_target_compatibility = 17
457 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
458 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
459 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
460 eclipseJavaRuntimeName = string("JavaSE-17")
461 /* compile without modules -- using classpath libraries
462 additional_compiler_args += [
463 '--module-path', modules_compileClasspath.asPath,
464 '--add-modules', j11modules
468 throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
473 JAVA_MIN_VERSION = JAVA_VERSION
474 JAVA_MAX_VERSION = JAVA_VERSION
475 def jreInstallsDir = string(jre_installs_dir)
476 if (jreInstallsDir.startsWith("~/")) {
477 jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
479 macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
480 windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
481 linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
482 macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_mac_x64.tar.gz")
483 windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_windows_x64.tar.gz")
484 linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_linux_x64.tar.gz")
485 install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
486 install4jConfFileName = string("jalview-install4j-conf.install4j")
487 install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
488 install4jHomeDir = install4j_home_dir
489 if (install4jHomeDir.startsWith("~/")) {
490 install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
493 resourceBuildDir = string("${buildDir}/resources")
494 resourcesBuildDir = string("${resourceBuildDir}/resources_build")
495 helpBuildDir = string("${resourceBuildDir}/help_build")
496 docBuildDir = string("${resourceBuildDir}/doc_build")
498 if (buildProperties == null) {
499 buildProperties = string("${resourcesBuildDir}/${build_properties_file}")
501 buildingHTML = string("${jalviewDir}/${doc_dir}/building.html")
502 helpParentDir = string("${jalviewDir}/${help_parent_dir}")
503 helpSourceDir = string("${helpParentDir}/${help_dir}")
504 helpFile = string("${helpBuildDir}/${help_dir}/help.jhm")
507 relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
508 jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
509 jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
511 jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
513 jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
515 jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
516 jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
517 jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
518 jalviewjsJalviewCoreHtmlFile = string("")
519 jalviewjsJalviewCoreName = string(jalviewjs_core_name)
520 jalviewjsCoreClasslists = []
521 jalviewjsJalviewTemplateName = string(jalviewjs_name)
522 jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
523 jalviewjsJ2sAltSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_alt_settings}")
524 jalviewjsJ2sProps = null
525 jalviewjsJ2sPlugin = jalviewjs_j2s_plugin
527 eclipseWorkspace = null
528 eclipseBinary = string("")
529 eclipseVersion = string("")
539 outputDir = file(classesDir)
543 srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ]
546 compileClasspath = files(sourceSets.main.java.outputDir)
547 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
549 runtimeClasspath = compileClasspath
550 runtimeClasspath += files(sourceSets.main.resources.srcDirs)
555 srcDirs cloverInstrDir
556 outputDir = cloverClassesDir
560 srcDirs = sourceSets.main.resources.srcDirs
563 compileClasspath = files( sourceSets.clover.java.outputDir )
564 //compileClasspath += files( testClassesDir )
565 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
566 compileClasspath += fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
567 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
569 runtimeClasspath = compileClasspath
574 srcDirs testSourceDir
575 outputDir = file(testClassesDir)
579 srcDirs = useClover ? sourceSets.clover.resources.srcDirs : sourceSets.main.resources.srcDirs
582 compileClasspath = files( sourceSets.test.java.outputDir )
583 compileClasspath += useClover ? sourceSets.clover.compileClasspath : sourceSets.main.compileClasspath
584 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
586 runtimeClasspath = compileClasspath
587 runtimeClasspath += files(sourceSets.test.resources.srcDirs)
593 // eclipse project and settings files creation, also used by buildship
596 name = eclipse_project_name
598 natures 'org.eclipse.jdt.core.javanature',
599 'org.eclipse.jdt.groovy.core.groovyNature',
600 'org.eclipse.buildship.core.gradleprojectnature'
602 buildCommand 'org.eclipse.jdt.core.javabuilder'
603 buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
607 //defaultOutputDir = sourceSets.main.java.outputDir
608 configurations.each{ c->
609 if (c.isCanBeResolved()) {
610 minusConfigurations += [c]
614 plusConfigurations = [ ]
618 def removeTheseToo = []
619 HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
620 cp.entries.each { entry ->
621 // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
622 // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
623 // we add the resources and help/help dirs in as libs afterwards (see below)
624 if (entry.kind == 'src') {
625 if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
626 removeTheseToo += entry
628 alreadyAddedSrcPath.putAt(entry.path, true)
633 cp.entries.removeAll(removeTheseToo)
635 //cp.entries += new Output("${eclipse_bin_dir}/main")
636 if (file(helpParentDir).isDirectory()) {
637 cp.entries += new Library(fileReference(helpParentDir))
639 if (file(resourceDir).isDirectory()) {
640 cp.entries += new Library(fileReference(resourceDir))
643 HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
645 sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
646 //don't want to add outputDir as eclipse is using its own output dir in bin/main
647 if (it.isDirectory() || ! it.exists()) {
648 // don't add dirs to classpath, especially if they don't exist
649 return false // groovy "continue" in .any closure
651 def itPath = it.toString()
652 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
653 // make relative path
654 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
656 if (alreadyAddedLibPath.get(itPath)) {
657 //println("Not adding duplicate entry "+itPath)
659 //println("Adding entry "+itPath)
660 cp.entries += new Library(fileReference(itPath))
661 alreadyAddedLibPath.put(itPath, true)
665 sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
666 //no longer want to add outputDir as eclipse is using its own output dir in bin/main
667 if (it.isDirectory() || ! it.exists()) {
668 // don't add dirs to classpath
669 return false // groovy "continue" in .any closure
672 def itPath = it.toString()
673 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
674 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
676 if (alreadyAddedLibPath.get(itPath)) {
679 def lib = new Library(fileReference(itPath))
680 lib.entryAttributes["test"] = "true"
682 alreadyAddedLibPath.put(itPath, true)
690 containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
695 // for the IDE, use java 11 compatibility
696 sourceCompatibility = compile_source_compatibility
697 targetCompatibility = compile_target_compatibility
698 javaRuntimeName = eclipseJavaRuntimeName
700 // add in jalview project specific properties/preferences into eclipse core preferences
702 withProperties { props ->
703 def jalview_prefs = new Properties()
704 def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
705 jalview_prefs.load(ins)
707 jalview_prefs.forEach { t, v ->
708 if (props.getAt(t) == null) {
712 // codestyle file -- overrides previous formatter prefs
713 def csFile = file("${jalviewDirAbsolutePath}/${eclipse_codestyle_file}")
714 if (csFile.exists()) {
715 XmlParser parser = new XmlParser()
716 def profiles = parser.parse(csFile)
717 def profile = profiles.'profile'.find { p -> (p.'@kind' == "CodeFormatterProfile" && p.'@name' == "Jalview") }
718 if (profile != null) {
719 profile.'setting'.each { s ->
721 def value = s.'@value'
722 if (id != null && value != null) {
723 props.putAt(id, value)
734 // Don't want these to be activated if in headless build
735 synchronizationTasks "eclipseSynchronizationTask"
736 //autoBuildTasks "eclipseAutoBuildTask"
742 /* hack to change eclipse prefs in .settings files other than org.eclipse.jdt.core.prefs */
743 // Class to allow updating arbitrary properties files
744 class PropertiesFile extends PropertiesPersistableConfigurationObject {
745 public PropertiesFile(PropertiesTransformer t) { super(t); }
746 @Override protected void load(Properties properties) { }
747 @Override protected void store(Properties properties) { }
748 @Override protected String getDefaultResourceName() { return ""; }
749 // This is necessary, because PropertiesPersistableConfigurationObject fails
750 // if no default properties file exists.
751 @Override public void loadDefaults() { load(new StringBufferInputStream("")); }
754 // Task to update arbitrary properties files (set outputFile)
755 class PropertiesFileTask extends PropertiesGeneratorTask<PropertiesFile> {
756 private final PropertiesFileContentMerger file;
757 public PropertiesFileTask() { file = new PropertiesFileContentMerger(getTransformer()); }
758 protected PropertiesFile create() { return new PropertiesFile(getTransformer()); }
759 protected void configure(PropertiesFile props) {
760 file.getBeforeMerged().execute(props); file.getWhenMerged().execute(props);
762 public void file(Closure closure) { ConfigureUtil.configure(closure, file); }
765 task eclipseUIPreferences(type: PropertiesFileTask) {
766 description = "Generate Eclipse additional settings"
767 def filename = "org.eclipse.jdt.ui.prefs"
768 outputFile = "$projectDir/.settings/${filename}" as File
771 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
776 task eclipseGroovyCorePreferences(type: PropertiesFileTask) {
777 description = "Generate Eclipse additional settings"
778 def filename = "org.eclipse.jdt.groovy.core.prefs"
779 outputFile = "$projectDir/.settings/${filename}" as File
782 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
787 task eclipseAllPreferences {
789 dependsOn eclipseUIPreferences
790 dependsOn eclipseGroovyCorePreferences
793 eclipseUIPreferences.mustRunAfter eclipseJdt
794 eclipseGroovyCorePreferences.mustRunAfter eclipseJdt
796 /* end of eclipse preferences hack */
804 delete cloverBuildDir
805 delete cloverReportDir
810 task cloverInstrJava(type: JavaExec) {
811 group = "Verification"
812 description = "Create clover instrumented source java files"
814 dependsOn cleanClover
816 inputs.files(sourceSets.main.allJava)
817 outputs.dir(cloverInstrDir)
819 //classpath = fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
820 classpath = sourceSets.clover.compileClasspath
821 main = "com.atlassian.clover.CloverInstr"
829 cloverInstrDir.getPath(),
831 def srcFiles = sourceSets.main.allJava.files
834 { file -> file.absolutePath }
837 args argsList.toArray()
840 delete cloverInstrDir
841 println("Clover: About to instrument "+srcFiles.size() +" files")
846 task cloverInstrTests(type: JavaExec) {
847 group = "Verification"
848 description = "Create clover instrumented source test files"
850 dependsOn cleanClover
852 inputs.files(testDir)
853 outputs.dir(cloverTestInstrDir)
855 classpath = sourceSets.clover.compileClasspath
856 main = "com.atlassian.clover.CloverInstr"
866 cloverTestInstrDir.getPath(),
868 args argsList.toArray()
871 delete cloverTestInstrDir
872 println("Clover: About to instrument test files")
878 group = "Verification"
879 description = "Create clover instrumented all source files"
881 dependsOn cloverInstrJava
882 dependsOn cloverInstrTests
886 cloverClasses.dependsOn cloverInstr
889 task cloverConsoleReport(type: JavaExec) {
890 group = "Verification"
891 description = "Creates clover console report"
894 file(cloverDb).exists()
897 inputs.dir cloverClassesDir
899 classpath = sourceSets.clover.runtimeClasspath
900 main = "com.atlassian.clover.reporters.console.ConsoleReporter"
902 if (cloverreport_mem.length() > 0) {
903 maxHeapSize = cloverreport_mem
905 if (cloverreport_jvmargs.length() > 0) {
906 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
916 args argsList.toArray()
920 task cloverHtmlReport(type: JavaExec) {
921 group = "Verification"
922 description = "Creates clover HTML report"
925 file(cloverDb).exists()
928 def cloverHtmlDir = cloverReportDir
929 inputs.dir cloverClassesDir
930 outputs.dir cloverHtmlDir
932 classpath = sourceSets.clover.runtimeClasspath
933 main = "com.atlassian.clover.reporters.html.HtmlReporter"
935 if (cloverreport_mem.length() > 0) {
936 maxHeapSize = cloverreport_mem
938 if (cloverreport_jvmargs.length() > 0) {
939 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
950 if (cloverreport_html_options.length() > 0) {
951 argsList += cloverreport_html_options.split(" ")
954 args argsList.toArray()
958 task cloverXmlReport(type: JavaExec) {
959 group = "Verification"
960 description = "Creates clover XML report"
963 file(cloverDb).exists()
966 def cloverXmlFile = "${cloverReportDir}/clover.xml"
967 inputs.dir cloverClassesDir
968 outputs.file cloverXmlFile
970 classpath = sourceSets.clover.runtimeClasspath
971 main = "com.atlassian.clover.reporters.xml.XMLReporter"
973 if (cloverreport_mem.length() > 0) {
974 maxHeapSize = cloverreport_mem
976 if (cloverreport_jvmargs.length() > 0) {
977 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
988 if (cloverreport_xml_options.length() > 0) {
989 argsList += cloverreport_xml_options.split(" ")
992 args argsList.toArray()
997 group = "Verification"
998 description = "Creates clover reports"
1000 dependsOn cloverXmlReport
1001 dependsOn cloverHtmlReport
1008 sourceCompatibility = compile_source_compatibility
1009 targetCompatibility = compile_target_compatibility
1010 options.compilerArgs += additional_compiler_args
1011 print ("Setting target compatibility to "+targetCompatibility+"\n")
1013 //classpath += configurations.cloverRuntime
1019 // JBP->BS should the print statement in doFirst refer to compile_target_compatibility ?
1020 sourceCompatibility = compile_source_compatibility
1021 targetCompatibility = compile_target_compatibility
1022 options.compilerArgs = additional_compiler_args
1023 options.encoding = "UTF-8"
1025 print ("Setting target compatibility to "+compile_target_compatibility+"\n")
1032 sourceCompatibility = compile_source_compatibility
1033 targetCompatibility = compile_target_compatibility
1034 options.compilerArgs = additional_compiler_args
1036 print ("Setting target compatibility to "+targetCompatibility+"\n")
1043 delete sourceSets.main.java.outputDir
1049 dependsOn cleanClover
1051 delete sourceSets.test.java.outputDir
1056 // format is a string like date.format("dd MMMM yyyy")
1057 def getDate(format) {
1058 return date.format(format)
1062 def convertMdToHtml (FileTree mdFiles, File cssFile) {
1063 MutableDataSet options = new MutableDataSet()
1065 def extensions = new ArrayList<>()
1066 extensions.add(AnchorLinkExtension.create())
1067 extensions.add(AutolinkExtension.create())
1068 extensions.add(StrikethroughExtension.create())
1069 extensions.add(TaskListExtension.create())
1070 extensions.add(TablesExtension.create())
1071 extensions.add(TocExtension.create())
1073 options.set(Parser.EXTENSIONS, extensions)
1075 // set GFM table parsing options
1076 options.set(TablesExtension.WITH_CAPTION, false)
1077 options.set(TablesExtension.COLUMN_SPANS, false)
1078 options.set(TablesExtension.MIN_HEADER_ROWS, 1)
1079 options.set(TablesExtension.MAX_HEADER_ROWS, 1)
1080 options.set(TablesExtension.APPEND_MISSING_COLUMNS, true)
1081 options.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
1082 options.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
1084 options.set(AnchorLinkExtension.ANCHORLINKS_SET_ID, false)
1085 options.set(AnchorLinkExtension.ANCHORLINKS_ANCHOR_CLASS, "anchor")
1086 options.set(AnchorLinkExtension.ANCHORLINKS_SET_NAME, true)
1087 options.set(AnchorLinkExtension.ANCHORLINKS_TEXT_PREFIX, "<span class=\"octicon octicon-link\"></span>")
1089 Parser parser = Parser.builder(options).build()
1090 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1092 mdFiles.each { mdFile ->
1093 // add table of contents
1094 def mdText = "[TOC]\n"+mdFile.text
1096 // grab the first top-level title
1098 def titleRegex = /(?m)^#(\s+|([^#]))(.*)/
1099 def matcher = mdText =~ titleRegex
1100 if (matcher.size() > 0) {
1101 // matcher[0][2] is the first character of the title if there wasn't any whitespace after the #
1102 title = (matcher[0][2] != null ? matcher[0][2] : "")+matcher[0][3]
1104 // or use the filename if none found
1105 if (title == null) {
1106 title = mdFile.getName()
1109 Node document = parser.parse(mdText)
1110 String htmlBody = renderer.render(document)
1111 def htmlText = '''<html>
1112 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1113 <html xmlns="http://www.w3.org/1999/xhtml">
1115 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1116 <meta http-equiv="Content-Style-Type" content="text/css" />
1117 <meta name="generator" content="flexmark" />
1119 htmlText += ((title != null) ? " <title>${title}</title>" : '' )
1121 <style type="text/css">code{white-space: pre;}</style>
1123 htmlText += ((cssFile != null) ? cssFile.text : '')
1124 htmlText += '''</head>
1127 htmlText += htmlBody
1133 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1134 def htmlFile = file(htmlFilePath)
1135 println("Creating ${htmlFilePath}")
1136 htmlFile.text = htmlText
1141 task copyDocs(type: Copy) {
1142 def inputDir = "${jalviewDir}/${doc_dir}"
1143 def outputDir = "${docBuildDir}/${doc_dir}"
1147 include('**/*.html')
1149 filter(ReplaceTokens,
1153 'Version-Rel': JALVIEW_VERSION,
1154 'Year-Rel': getDate("yyyy")
1161 exclude('**/*.html')
1166 inputs.dir(inputDir)
1167 outputs.dir(outputDir)
1171 task convertMdFiles {
1173 def mdFiles = fileTree(dir: docBuildDir, include: "**/*.md")
1174 def cssFile = file("${jalviewDir}/${flexmark_css}")
1177 convertMdToHtml(mdFiles, cssFile)
1180 inputs.files(mdFiles)
1181 inputs.file(cssFile)
1184 mdFiles.each { mdFile ->
1185 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1186 htmlFiles.add(file(htmlFilePath))
1188 outputs.files(htmlFiles)
1192 task copyHelp(type: Copy) {
1193 def inputDir = helpSourceDir
1194 def outputDir = "${helpBuildDir}/${help_dir}"
1198 include('**/*.html')
1202 filter(ReplaceTokens,
1206 'Version-Rel': JALVIEW_VERSION,
1207 'Year-Rel': getDate("yyyy")
1214 exclude('**/*.html')
1221 inputs.dir(inputDir)
1222 outputs.files(helpFile)
1223 outputs.dir(outputDir)
1227 task copyResources(type: Copy) {
1229 description = "Copy (and make text substitutions in) the resources dir to the build area"
1231 def inputDir = resourceDir
1232 def outputDir = resourcesBuildDir
1236 include('**/*.html')
1238 filter(ReplaceTokens,
1242 'Version-Rel': JALVIEW_VERSION,
1243 'Year-Rel': getDate("yyyy")
1250 exclude('**/*.html')
1255 inputs.dir(inputDir)
1256 outputs.dir(outputDir)
1259 task copyChannelResources(type: Copy) {
1260 dependsOn copyResources
1262 description = "Copy the channel resources dir to the build resources area"
1264 def inputDir = "${channelDir}/${resource_dir}"
1265 def outputDir = resourcesBuildDir
1269 inputs.dir(inputDir)
1270 outputs.dir(outputDir)
1273 task createBuildProperties(type: WriteProperties) {
1274 dependsOn copyResources
1276 description = "Create the ${buildProperties} file"
1278 inputs.dir(sourceDir)
1279 inputs.dir(resourcesBuildDir)
1280 outputFile (buildProperties)
1281 // taking time specific comment out to allow better incremental builds
1282 comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
1283 //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
1284 property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
1285 property "VERSION", JALVIEW_VERSION
1286 property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
1287 if (getdownSetAppBaseProperty) {
1288 property "GETDOWNAPPBASE", getdownAppBase
1289 property "GETDOWNAPPDISTDIR", getdownAppDistDir
1291 outputs.file(outputFile)
1295 task buildIndices(type: JavaExec) {
1297 classpath = sourceSets.main.compileClasspath
1298 main = "com.sun.java.help.search.Indexer"
1299 workingDir = "${helpBuildDir}/${help_dir}"
1302 inputs.dir("${workingDir}/${argDir}")
1304 outputs.dir("${classesDir}/doc")
1305 outputs.dir("${classesDir}/help")
1306 outputs.file("${workingDir}/JavaHelpSearch/DOCS")
1307 outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
1308 outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
1309 outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
1310 outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
1311 outputs.file("${workingDir}/JavaHelpSearch/TMAP")
1314 task buildResources {
1315 dependsOn copyResources
1316 dependsOn copyChannelResources
1317 dependsOn createBuildProperties
1321 dependsOn buildResources
1324 dependsOn convertMdFiles
1325 dependsOn buildIndices
1329 compileJava.dependsOn prepare
1330 run.dependsOn compileJava
1331 //run.dependsOn prepare
1334 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1339 dependsOn cloverClasses
1341 dependsOn compileJava //?
1345 includeGroups testng_groups
1346 excludeGroups testng_excluded_groups
1348 useDefaultListeners=true
1351 maxHeapSize = "1024m"
1353 workingDir = jalviewDir
1354 def testLaf = project.findProperty("test_laf")
1355 if (testLaf != null) {
1356 println("Setting Test LaF to '${testLaf}'")
1357 systemProperty "laf", testLaf
1359 def testHiDPIScale = project.findProperty("test_HiDPIScale")
1360 if (testHiDPIScale != null) {
1361 println("Setting Test HiDPI Scale to '${testHiDPIScale}'")
1362 systemProperty "sun.java2d.uiScale", testHiDPIScale
1364 sourceCompatibility = compile_source_compatibility
1365 targetCompatibility = compile_target_compatibility
1366 jvmArgs += additional_compiler_args
1370 println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1376 task compileLinkCheck(type: JavaCompile) {
1378 classpath = files("${jalviewDir}/${utils_dir}")
1379 destinationDir = file("${jalviewDir}/${utils_dir}")
1380 source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1382 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1383 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1384 outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1385 outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1389 task linkCheck(type: JavaExec) {
1391 dependsOn compileLinkCheck
1393 def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1394 classpath = files("${jalviewDir}/${utils_dir}")
1395 main = "HelpLinksChecker"
1396 workingDir = jalviewDir
1397 args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1399 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1400 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1403 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1407 inputs.dir(helpBuildDir)
1408 outputs.file(helpLinksCheckerOutFile)
1412 // import the pubhtmlhelp target
1413 ant.properties.basedir = "${jalviewDir}"
1414 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1415 ant.importBuild "${utils_dir}/publishHelp.xml"
1418 task cleanPackageDir(type: Delete) {
1420 delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1430 attributes "Main-Class": main_class,
1431 "Permissions": "all-permissions",
1432 "Application-Name": install4jApplicationName,
1433 "Codebase": application_codebase,
1434 "Implementation-Version": JALVIEW_VERSION
1437 def outputDir = "${jalviewDir}/${package_dir}"
1438 destinationDirectory = file(outputDir)
1439 archiveFileName = rootProject.name+".jar"
1440 duplicatesStrategy "EXCLUDE"
1447 exclude "**/*.jar.*"
1449 inputs.dir(sourceSets.main.java.outputDir)
1450 sourceSets.main.resources.srcDirs.each{ dir ->
1453 outputs.file("${outputDir}/${archiveFileName}")
1457 task copyJars(type: Copy) {
1458 from fileTree(dir: classesDir, include: "**/*.jar").files
1459 into "${jalviewDir}/${package_dir}"
1463 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1464 task syncJars(type: Sync) {
1466 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1467 into "${jalviewDir}/${package_dir}"
1469 include jar.archiveFileName.getOrNull()
1476 description = "Put all required libraries in dist"
1477 // order of "cleanPackageDir", "copyJars", "jar" important!
1478 jar.mustRunAfter cleanPackageDir
1479 syncJars.mustRunAfter cleanPackageDir
1480 dependsOn cleanPackageDir
1483 outputs.dir("${jalviewDir}/${package_dir}")
1488 dependsOn cleanPackageDir
1495 group = "distribution"
1496 description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1500 from ("${jalviewDir}/${libDistDir}") {
1504 attributes "Implementation-Version": JALVIEW_VERSION,
1505 "Application-Name": install4jApplicationName
1508 duplicatesStrategy "INCLUDE"
1510 mainClassName = shadow_jar_main_class
1512 classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1517 task getdownWebsite() {
1518 group = "distribution"
1519 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1524 def getdownWebsiteResourceFilenames = []
1525 def getdownResourceDir = getdownResourceDir
1526 def getdownResourceFilenames = []
1529 // clean the getdown website and files dir before creating getdown folders
1530 delete getdownWebsiteDir
1531 delete getdownFilesDir
1534 from buildProperties
1535 rename(file(buildProperties).getName(), getdown_build_properties)
1538 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1541 from channelPropsFile
1542 into getdownWebsiteDir
1544 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
1546 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
1547 def props = project.properties.sort { it.key }
1548 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
1549 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
1551 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
1552 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
1554 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
1555 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
1557 if (getdownImagesDir != null && file(getdownImagesDir).exists()) {
1558 props.put("getdown_txt_ui.background_image", "${getdownImagesDir}/${getdown_background_image}")
1559 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesDir}/${getdown_instant_background_image}")
1560 props.put("getdown_txt_ui.error_background", "${getdownImagesDir}/${getdown_error_background}")
1561 props.put("getdown_txt_ui.progress_image", "${getdownImagesDir}/${getdown_progress_image}")
1562 props.put("getdown_txt_ui.icon", "${getdownImagesDir}/${getdown_icon}")
1563 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesDir}/${getdown_mac_dock_icon}")
1566 props.put("getdown_txt_title", jalview_name)
1567 props.put("getdown_txt_ui.name", install4jApplicationName)
1569 // start with appbase
1570 getdownTextLines += "appbase = ${getdownAppBase}"
1571 props.each{ prop, val ->
1572 if (prop.startsWith("getdown_txt_") && val != null) {
1573 if (prop.startsWith("getdown_txt_multi_")) {
1574 def key = prop.substring(18)
1575 val.split(",").each{ v ->
1576 def line = "${key} = ${v}"
1577 getdownTextLines += line
1580 // file values rationalised
1581 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
1583 if (val.indexOf('/') == 0) {
1586 } else if (val.indexOf('/') > 0) {
1587 // relative path (relative to jalviewDir)
1588 r = file( "${jalviewDir}/${val}" )
1591 val = "${getdown_resource_dir}/" + r.getName()
1592 getdownWebsiteResourceFilenames += val
1593 getdownResourceFilenames += r.getPath()
1596 if (! prop.startsWith("getdown_txt_resource")) {
1597 def line = prop.substring(12) + " = ${val}"
1598 getdownTextLines += line
1604 getdownWebsiteResourceFilenames.each{ filename ->
1605 getdownTextLines += "resource = ${filename}"
1607 getdownResourceFilenames.each{ filename ->
1610 into getdownResourceDir
1614 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
1615 getdownWrapperScripts.each{ script ->
1616 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
1620 into "${getdownWebsiteDir}/${getdown_wrapper_script_dir}"
1622 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
1627 fileTree(file(package_dir)).each{ f ->
1628 if (f.isDirectory()) {
1629 def files = fileTree(dir: f, include: ["*"]).getFiles()
1631 } else if (f.exists()) {
1635 def jalviewJar = jar.archiveFileName.getOrNull()
1636 // put jalview.jar first for CLASSPATH and .properties files reasons
1637 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
1638 def name = f.getName()
1639 def line = "code = ${getdownAppDistDir}/${name}"
1640 getdownTextLines += line
1647 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
1649 if (JAVA_VERSION.equals("11")) {
1650 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
1651 j11libFiles.sort().each{f ->
1652 def name = f.getName()
1653 def line = "code = ${getdown_j11lib_dir}/${name}"
1654 getdownTextLines += line
1657 into getdownJ11libDir
1663 // 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.
1664 //getdownTextLines += "class = " + file(getdownLauncher).getName()
1665 getdownTextLines += "resource = ${getdown_launcher_new}"
1666 getdownTextLines += "class = ${main_class}"
1667 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
1668 if (getdownSetAppBaseProperty) {
1669 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
1670 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
1673 def getdownTxt = file("${getdownWebsiteDir}/getdown.txt")
1674 getdownTxt.write(getdownTextLines.join("\n"))
1676 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
1677 def launchJvl = file("${getdownWebsiteDir}/${getdownLaunchJvl}")
1678 launchJvl.write("appbase=${getdownAppBase}")
1680 // files going into the getdown website dir: getdown-launcher.jar
1682 from getdownLauncher
1683 rename(file(getdownLauncher).getName(), getdown_launcher_new)
1684 into getdownWebsiteDir
1687 // files going into the getdown website dir: getdown-launcher(-local).jar
1689 from getdownLauncher
1690 if (file(getdownLauncher).getName() != getdown_launcher) {
1691 rename(file(getdownLauncher).getName(), getdown_launcher)
1693 into getdownWebsiteDir
1696 // files going into the getdown website dir: ./install dir and files
1697 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
1700 from getdownLauncher
1701 from "${getdownAppDir}/${getdown_build_properties}"
1702 if (file(getdownLauncher).getName() != getdown_launcher) {
1703 rename(file(getdownLauncher).getName(), getdown_launcher)
1705 into getdownInstallDir
1708 // and make a copy in the getdown files dir (these are not downloaded by getdown)
1710 from getdownInstallDir
1711 into getdownFilesInstallDir
1715 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
1719 from getdownLauncher
1720 from "${getdownWebsiteDir}/${getdown_build_properties}"
1721 from "${getdownWebsiteDir}/${channel_props}"
1722 if (file(getdownLauncher).getName() != getdown_launcher) {
1723 rename(file(getdownLauncher).getName(), getdown_launcher)
1725 into getdownFilesDir
1728 // and ./resource (not all downloaded by getdown)
1730 from getdownResourceDir
1731 into "${getdownFilesDir}/${getdown_resource_dir}"
1736 inputs.dir("${jalviewDir}/${package_dir}")
1738 outputs.dir(getdownWebsiteDir)
1739 outputs.dir(getdownFilesDir)
1743 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
1744 task getdownDigestDir(type: JavaExec) {
1746 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
1748 def digestDirPropertyName = "DIGESTDIR"
1750 classpath = files(getdownLauncher)
1751 def digestDir = findProperty(digestDirPropertyName)
1752 if (digestDir == null) {
1753 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
1757 main = "com.threerings.getdown.tools.Digester"
1761 task getdownDigest(type: JavaExec) {
1762 group = "distribution"
1763 description = "Digest the getdown website folder"
1764 dependsOn getdownWebsite
1766 classpath = files(getdownLauncher)
1768 main = "com.threerings.getdown.tools.Digester"
1769 args getdownWebsiteDir
1770 inputs.dir(getdownWebsiteDir)
1771 outputs.file("${getdownWebsiteDir}/digest2.txt")
1776 group = "distribution"
1777 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
1778 dependsOn getdownDigest
1780 if (reportRsyncCommand) {
1781 def fromDir = getdownWebsiteDir + (getdownWebsiteDir.endsWith('/')?'':'/')
1782 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
1783 println "LIKELY RSYNC COMMAND:"
1784 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
1785 if (RUNRSYNC == "true") {
1787 commandLine "mkdir", "-p", toDir
1790 commandLine "rsync", "-avh", "--delete", fromDir, toDir
1798 task getdownArchiveBuild() {
1799 group = "distribution"
1800 description = "Put files in the archive dir to go on the website"
1802 dependsOn getdownWebsite
1804 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
1805 def vDir = "${getdownArchiveDir}/${v}"
1806 getdownFullArchiveDir = "${vDir}/getdown"
1807 def vLaunchVersionJvl = "${vDir}/jalview-${v}.jvl"
1808 def vAltDir = "alt_${v}"
1809 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
1812 if (getdownArchiveAppBase == null) {
1813 throw new StopExecutionException("Cannot create getdownArchive for CHANNEL=${CHANNEL}")
1816 // cleanup old "old" dir
1817 delete getdownArchiveDir
1819 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
1820 getdownArchiveTxt.getParentFile().mkdirs()
1821 def getdownArchiveTextLines = []
1822 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
1826 from "${getdownWebsiteDir}/${getdownAppDistDir}"
1827 into "${getdownFullArchiveDir}/${vAltDir}"
1830 getdownTextLines.each { line ->
1831 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
1832 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
1833 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
1834 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
1835 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
1836 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
1837 // remove the existing resource = resource/ or bin/ lines
1838 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
1839 getdownArchiveTextLines += line
1843 // the resource dir -- add these files as resource lines in getdown.txt
1845 from "${archiveImagesDir}"
1846 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
1848 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
1852 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
1854 def vLaunchJvl = file(vLaunchVersionJvl)
1855 vLaunchJvl.getParentFile().mkdirs()
1856 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
1857 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
1858 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
1859 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
1860 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
1861 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
1863 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
1865 from getdownLauncher
1866 from "${getdownWebsiteDir}/${getdownLaunchJvl}"
1867 from "${getdownWebsiteDir}/${getdown_launcher_new}"
1868 from "${getdownWebsiteDir}/${channel_props}"
1869 if (file(getdownLauncher).getName() != getdown_launcher) {
1870 rename(file(getdownLauncher).getName(), getdown_launcher)
1872 into getdownFullArchiveDir
1878 task getdownArchiveDigest(type: JavaExec) {
1879 group = "distribution"
1880 description = "Digest the getdown archive folder"
1882 dependsOn getdownArchiveBuild
1885 classpath = files(getdownLauncher)
1886 args getdownFullArchiveDir
1888 main = "com.threerings.getdown.tools.Digester"
1889 inputs.dir(getdownFullArchiveDir)
1890 outputs.file("${getdownFullArchiveDir}/digest2.txt")
1893 task getdownArchive() {
1894 group = "distribution"
1895 description = "Build the website archive dir with getdown digest"
1897 dependsOn getdownArchiveBuild
1898 dependsOn getdownArchiveDigest
1901 tasks.withType(JavaCompile) {
1902 options.encoding = 'UTF-8'
1908 delete getdownWebsiteDir
1909 delete getdownFilesDir
1910 delete getdownArchiveDir
1916 if (file(install4jHomeDir).exists()) {
1918 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
1919 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
1920 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
1921 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
1923 installDir(file(install4jHomeDir))
1925 mediaTypes = Arrays.asList(install4j_media_types.split(","))
1929 task copyInstall4jTemplate {
1930 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
1931 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
1932 inputs.file(install4jTemplateFile)
1933 inputs.file(install4jFileAssociationsFile)
1934 inputs.property("CHANNEL", { CHANNEL })
1935 outputs.file(install4jConfFile)
1938 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
1940 // turn off code signing if no OSX_KEYPASS
1941 if (OSX_KEYPASS == "") {
1942 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
1943 codeSigning.'@macEnabled' = "false"
1945 install4jConfigXml.'**'.windows.each { windows ->
1946 windows.'@runPostProcessor' = "false"
1950 // disable install screen for OSX dmg (for 2.11.2.0)
1951 install4jConfigXml.'**'.macosArchive.each { macosArchive ->
1952 macosArchive.attributes().remove('executeSetupApp')
1953 macosArchive.attributes().remove('setupAppId')
1956 // turn off checksum creation for LOCAL channel
1957 def e = install4jConfigXml.application[0]
1958 e.'@createChecksums' = string(install4jCheckSums)
1960 // put file association actions where placeholder action is
1961 def install4jFileAssociationsText = install4jFileAssociationsFile.text
1962 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
1963 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
1964 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
1965 def parent = a.parent()
1967 fileAssociationActions.each { faa ->
1970 // don't need to continue in .any loop once replacements have been made
1975 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
1976 // NB we're deleting the /other/ one!
1977 // Also remove the examples subdir from non-release versions
1978 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
1979 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
1980 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
1981 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
1983 // remove the examples subdir from Full File Set
1984 def files = install4jConfigXml.files[0]
1985 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
1986 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
1987 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
1988 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
1989 dirEntry.parent().remove(dirEntry)
1991 install4jConfigXml.'**'.action.any { a ->
1992 if (a.'@customizedId' == customizedIdToDelete) {
1993 def parent = a.parent()
1999 // write install4j file
2000 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
2007 delete install4jConfFile
2011 task cleanInstallersDataFiles {
2012 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2013 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2014 def VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
2015 def installersJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${VERSION_UNDERSCORES}.json")
2017 delete installersOutputTxt
2018 delete installersSha256
2019 delete installersJsonFile
2023 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2024 group = "distribution"
2025 description = "Create the install4j installers"
2027 dependsOn copyInstall4jTemplate
2028 dependsOn cleanInstallersDataFiles
2030 projectFile = install4jConfFile
2032 // create an md5 for the input files to use as version for install4j conf file
2033 def digest = MessageDigest.getInstance("MD5")
2035 (file("${install4jDir}/${install4j_template}").text +
2036 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2037 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2038 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2039 if (filesMd5.length() >= 8) {
2040 filesMd5 = filesMd5.substring(0,8)
2042 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2045 'JALVIEW_NAME': jalview_name,
2046 'JALVIEW_APPLICATION_NAME': install4jApplicationName,
2047 'JALVIEW_DIR': "../..",
2048 'OSX_KEYSTORE': OSX_KEYSTORE,
2049 'OSX_APPLEID': OSX_APPLEID,
2050 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2051 'JSIGN_SH': JSIGN_SH,
2052 'JRE_DIR': getdown_app_dir_java,
2053 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2054 'JALVIEW_VERSION': JALVIEW_VERSION,
2055 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2056 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2057 'JAVA_VERSION': JAVA_VERSION,
2058 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2059 'VERSION': JALVIEW_VERSION,
2060 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2061 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2062 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2063 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2064 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2065 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2066 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2067 'BUNDLE_ID': install4jBundleId,
2068 'INTERNAL_ID': install4jInternalId,
2069 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2070 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2071 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
2072 'WRAPPER_LINK': getdownWrapperLink,
2073 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2074 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2075 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2076 'INSTALLER_NAME': install4jInstallerName,
2077 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2078 'GETDOWN_WEBSITE_DIR': getdown_website_dir,
2079 'GETDOWN_FILES_DIR': getdown_files_dir,
2080 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2081 'GETDOWN_DIST_DIR': getdownAppDistDir,
2082 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2083 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2084 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2085 'BUILD_DIR': install4jBuildDir,
2086 'APPLICATION_CATEGORIES': install4j_application_categories,
2087 'APPLICATION_FOLDER': install4jApplicationFolder,
2088 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2089 'EXECUTABLE_NAME': install4jExecutableName,
2090 'EXTRA_SCHEME': install4jExtraScheme,
2091 'MAC_ICONS_FILE': install4jMacIconsFile,
2092 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2093 'PNG_ICON_FILE': install4jPngIconFile,
2094 'BACKGROUND': install4jBackground,
2098 //println("INSTALL4J VARIABLES:")
2099 //variables.each{k,v->println("${k}=${v}")}
2101 destination = "${jalviewDir}/${install4jBuildDir}"
2102 buildSelected = true
2104 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2106 disableSigning = true
2107 disableNotarization = true
2111 macKeystorePassword = OSX_KEYPASS
2114 if (OSX_ALTOOLPASS) {
2115 appleIdPassword = OSX_ALTOOLPASS
2116 disableNotarization = false
2118 disableNotarization = true
2122 println("Using projectFile "+projectFile)
2123 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2127 inputs.dir(getdownWebsiteDir)
2128 inputs.file(install4jConfFile)
2129 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2130 inputs.dir(macosJavaVMDir)
2131 inputs.dir(windowsJavaVMDir)
2132 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2135 def writeInstallersJsonFile(File installersOutputTxt, File installersSha256, File installersJsonFile) {
2136 if (!installersOutputTxt.exists()) {
2137 throw new GradleException("Required input file '${installersOutputTxt.getPath()}' doesn't exist.")
2140 if (install4jCheckSums && (!installersSha256)) {
2141 throw new GradleException("Required input file '${installersSha256.getPath()}' doesn't exist.")
2144 def hash = ["channel":getdownChannelName,"date":getDate("yyyy-MM-dd HH:mm:ss")]
2146 installersOutputTxt.readLines().each { def line ->
2147 if (line.startsWith("#")) {
2150 line.replaceAll("\n","")
2151 def vals = line.split("\t")
2152 def filename = vals[3]
2153 def filesize = file(filename).length()
2154 filename = filename.replaceAll(/^.*\//, "")
2155 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2156 idHash."${filename}" = vals[0]
2158 if (install4jCheckSums) {
2159 installersSha256.readLines().each { def line ->
2160 if (line.startsWith("#")) {
2163 line.replaceAll("\n","")
2164 def vals = line.split(/\s+\*?/)
2165 def filename = vals[1]
2166 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2169 return installersJsonFile.write(new JsonBuilder(hash).toPrettyString())
2174 ALSO COMPILE AND ADD IN TO THE JSON FILE INFO FOR EXECUTABLE JAR, VERSION JVL FILE, SOURCE TAR FILE
2182 task makeInstallersJsonFile {
2183 dependsOn installerFiles
2185 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2186 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2187 def VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
2188 def installersJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${VERSION_UNDERSCORES}.json")
2190 inputs.file(installersOutputTxt)
2191 if (install4jCheckSums) {
2192 inputs.file(installersSha256)
2194 outputs.file(installersJsonFile)
2197 writeInstallersJsonFile(installersOutputTxt, installersSha256, installersJsonFile)
2201 task staticMakeInstallersJsonFile {
2203 def output = findProperty("i4j_output")
2204 def sha256 = findProperty("i4j_sha256")
2205 def json = findProperty("i4j_json")
2206 if (output == null || sha256 == null || json == null) {
2207 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2209 writeInstallersJsonFile(file(output), file(sha256), file(json))
2214 dependsOn installerFiles
2215 dependsOn makeInstallersJsonFile
2221 eclipse().configFile(eclipse_codestyle_file)
2225 task createSourceReleaseProperties(type: WriteProperties) {
2226 group = "distribution"
2227 description = "Create the source RELEASE properties file"
2229 def sourceTarBuildDir = "${buildDir}/sourceTar"
2230 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2231 outputFile (sourceReleasePropertiesFile)
2234 releaseProps.each{ key, val -> property key, val }
2235 property "git.branch", gitBranch
2236 property "git.hash", gitHash
2239 outputs.file(outputFile)
2242 task sourceDist(type: Tar) {
2243 group "distribution"
2244 description "Create a source .tar.gz file for distribution"
2246 dependsOn createBuildProperties
2247 dependsOn convertMdFiles
2248 dependsOn eclipseAllPreferences
2249 dependsOn createSourceReleaseProperties
2252 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2253 archiveFileName = outputFileName
2255 compression Compression.GZIP
2270 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2272 "utils/InstallAnywhere",
2287 "gradle.properties",
2299 ".settings/org.eclipse.buildship.core.prefs",
2300 ".settings/org.eclipse.jdt.core.prefs"
2304 exclude (EXCLUDE_FILES)
2305 include (PROCESS_FILES)
2306 filter(ReplaceTokens,
2310 'Version-Rel': JALVIEW_VERSION,
2311 'Year-Rel': getDate("yyyy")
2316 exclude (EXCLUDE_FILES)
2317 exclude (PROCESS_FILES)
2318 exclude ("appletlib")
2319 exclude ("**/*locales")
2320 exclude ("*locales/**")
2321 exclude ("utils/InstallAnywhere")
2323 exclude (getdown_files_dir)
2324 exclude (getdown_website_dir)
2326 // exluding these as not using jars as modules yet
2327 exclude ("${j11modDir}/**/*.jar")
2330 include(INCLUDE_FILES)
2332 // from (jalviewDir) {
2333 // // explicit includes for stuff that seemed to not get included
2334 // include(fileTree("test/**/*."))
2335 // exclude(EXCLUDE_FILES)
2336 // exclude(PROCESS_FILES)
2339 from(file(buildProperties).getParent()) {
2340 include(file(buildProperties).getName())
2341 rename(file(buildProperties).getName(), "build_properties")
2343 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2347 def sourceTarBuildDir = "${buildDir}/sourceTar"
2348 from(sourceTarBuildDir) {
2349 // this includes the appended RELEASE properties file
2356 dependsOn pubhtmlhelp
2358 inputs.dir("${helpBuildDir}/${help_dir}")
2359 outputs.dir("${buildDir}/distributions/${help_dir}")
2363 task j2sSetHeadlessBuild {
2370 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2372 description "Enable the alternative J2S Config file for headless build"
2374 outputFile = jalviewjsJ2sSettingsFileName
2375 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2376 def j2sProps = new Properties()
2377 if (j2sPropsFile.exists()) {
2379 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2380 j2sProps.load(j2sPropsFileFIS)
2381 j2sPropsFileFIS.close()
2383 j2sProps.each { prop, val ->
2386 } catch (Exception e) {
2387 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2391 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2392 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2397 task jalviewjsSetEclipseWorkspace {
2398 def propKey = "jalviewjs_eclipse_workspace"
2400 if (project.hasProperty(propKey)) {
2401 propVal = project.getProperty(propKey)
2402 if (propVal.startsWith("~/")) {
2403 propVal = System.getProperty("user.home") + propVal.substring(1)
2406 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2407 def propsFile = file(propsFileName)
2408 def eclipseWsDir = propVal
2409 def props = new Properties()
2411 def writeProps = true
2412 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2413 def ins = new FileInputStream(propsFileName)
2416 if (props.getProperty(propKey, null) != null) {
2417 eclipseWsDir = props.getProperty(propKey)
2422 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2423 def tempDir = File.createTempDir()
2424 eclipseWsDir = tempDir.getAbsolutePath()
2427 eclipseWorkspace = file(eclipseWsDir)
2430 // do not run a headless transpile when we claim to be in Eclipse
2432 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2433 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2435 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2439 props.setProperty(propKey, eclipseWsDir)
2440 propsFile.parentFile.mkdirs()
2441 def bytes = new ByteArrayOutputStream()
2442 props.store(bytes, null)
2443 def propertiesString = bytes.toString()
2444 propsFile.text = propertiesString
2450 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2453 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2454 outputs.file(propsFileName)
2455 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2459 task jalviewjsEclipsePaths {
2462 def eclipseRoot = jalviewjs_eclipse_root
2463 if (eclipseRoot.startsWith("~/")) {
2464 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
2466 if (OperatingSystem.current().isMacOsX()) {
2467 eclipseRoot += "/Eclipse.app"
2468 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
2469 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
2470 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
2471 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2472 eclipseRoot += "/eclipse"
2474 eclipseBinary = "${eclipseRoot}/eclipse.exe"
2475 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2476 } else { // linux or unix
2477 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2478 eclipseRoot += "/eclipse"
2479 println("eclipseDir exists")
2481 eclipseBinary = "${eclipseRoot}/eclipse"
2482 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2485 eclipseVersion = "4.13" // default
2486 def assumedVersion = true
2487 if (file(eclipseProduct).exists()) {
2488 def fis = new FileInputStream(eclipseProduct)
2489 def props = new Properties()
2491 eclipseVersion = props.getProperty("version")
2493 assumedVersion = false
2496 def propKey = "eclipse_debug"
2497 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
2500 // do not run a headless transpile when we claim to be in Eclipse
2502 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2503 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2505 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2508 if (!assumedVersion) {
2509 println("ECLIPSE VERSION=${eclipseVersion}")
2515 task printProperties {
2517 description "Output to console all System.properties"
2519 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
2525 dependsOn eclipseProject
2526 dependsOn eclipseClasspath
2527 dependsOn eclipseJdt
2531 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
2532 task jalviewjsEclipseCopyDropins(type: Copy) {
2533 dependsOn jalviewjsEclipsePaths
2535 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
2536 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
2537 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
2544 // this eclipse -clean doesn't actually work
2545 task jalviewjsCleanEclipse(type: Exec) {
2546 dependsOn eclipseSetup
2547 dependsOn jalviewjsEclipsePaths
2548 dependsOn jalviewjsEclipseCopyDropins
2550 executable(eclipseBinary)
2551 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
2557 def inputString = """exit
2560 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
2561 standardInput = inputByteStream
2564 /* not really working yet
2565 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
2569 task jalviewjsTransferUnzipSwingJs {
2570 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
2574 from zipTree(file_zip)
2575 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2579 inputs.file file_zip
2580 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2584 task jalviewjsTransferUnzipLib {
2585 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
2588 zipFiles.each { file_zip ->
2590 from zipTree(file_zip)
2591 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2596 inputs.files zipFiles
2597 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2601 task jalviewjsTransferUnzipAllLibs {
2602 dependsOn jalviewjsTransferUnzipSwingJs
2603 dependsOn jalviewjsTransferUnzipLib
2607 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
2609 description "Create the alternative j2s file from the j2s.* properties"
2611 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
2612 def siteDirProperty = "j2s.site.directory"
2613 def setSiteDir = false
2614 jalviewjsJ2sProps.each { prop, val ->
2616 if (prop == siteDirProperty) {
2617 if (!(val.startsWith('/') || val.startsWith("file://") )) {
2618 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
2624 if (!setSiteDir) { // default site location, don't override specifically set property
2625 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
2628 outputFile = jalviewjsJ2sAltSettingsFileName
2631 inputs.properties(jalviewjsJ2sProps)
2632 outputs.file(jalviewjsJ2sAltSettingsFileName)
2637 task jalviewjsEclipseSetup {
2638 dependsOn jalviewjsEclipseCopyDropins
2639 dependsOn jalviewjsSetEclipseWorkspace
2640 dependsOn jalviewjsCreateJ2sSettings
2644 task jalviewjsSyncAllLibs (type: Sync) {
2645 dependsOn jalviewjsTransferUnzipAllLibs
2646 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
2647 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
2648 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2652 def outputFiles = []
2653 rename { filename ->
2654 outputFiles += "${outputDir}/${filename}"
2661 // should this be exclude really ?
2662 duplicatesStrategy "INCLUDE"
2664 outputs.files outputFiles
2665 inputs.files inputFiles
2669 task jalviewjsSyncResources (type: Sync) {
2670 dependsOn buildResources
2672 def inputFiles = fileTree(dir: resourcesBuildDir)
2673 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
2677 def outputFiles = []
2678 rename { filename ->
2679 outputFiles += "${outputDir}/${filename}"
2685 outputs.files outputFiles
2686 inputs.files inputFiles
2690 task jalviewjsSyncSiteResources (type: Sync) {
2691 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
2692 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2696 def outputFiles = []
2697 rename { filename ->
2698 outputFiles += "${outputDir}/${filename}"
2704 outputs.files outputFiles
2705 inputs.files inputFiles
2709 task jalviewjsSyncBuildProperties (type: Sync) {
2710 dependsOn createBuildProperties
2711 def inputFiles = [file(buildProperties)]
2712 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
2716 def outputFiles = []
2717 rename { filename ->
2718 outputFiles += "${outputDir}/${filename}"
2724 outputs.files outputFiles
2725 inputs.files inputFiles
2729 task jalviewjsProjectImport(type: Exec) {
2730 dependsOn eclipseSetup
2731 dependsOn jalviewjsEclipsePaths
2732 dependsOn jalviewjsEclipseSetup
2735 // do not run a headless import when we claim to be in Eclipse
2737 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2738 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2740 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2744 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
2745 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
2746 executable(eclipseBinary)
2747 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
2751 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
2753 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
2754 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
2757 inputs.file("${jalviewDir}/.project")
2758 outputs.upToDateWhen {
2759 file(projdir).exists()
2764 task jalviewjsTranspile(type: Exec) {
2765 dependsOn jalviewjsEclipseSetup
2766 dependsOn jalviewjsProjectImport
2767 dependsOn jalviewjsEclipsePaths
2769 dependsOn jalviewjsEnableAltFileProperty
2773 // do not run a headless transpile when we claim to be in Eclipse
2775 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2776 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2778 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2782 executable(eclipseBinary)
2783 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
2787 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
2789 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
2790 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
2796 stdout = new ByteArrayOutputStream()
2797 stderr = new ByteArrayOutputStream()
2799 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
2800 def logOutFile = file(logOutFileName)
2801 logOutFile.createNewFile()
2802 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
2803 BINARY: ${eclipseBinary}
2804 VERSION: ${eclipseVersion}
2805 WORKSPACE: ${eclipseWorkspace}
2806 DEBUG: ${eclipseDebug}
2809 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
2810 // combine stdout and stderr
2811 def logErrFOS = logOutFOS
2813 if (jalviewjs_j2s_to_console.equals("true")) {
2814 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2815 new org.apache.tools.ant.util.TeeOutputStream(
2819 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2820 new org.apache.tools.ant.util.TeeOutputStream(
2825 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2828 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2835 if (stdout.toString().contains("Error processing ")) {
2836 // j2s did not complete transpile
2837 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2838 if (jalviewjs_ignore_transpile_errors.equals("true")) {
2839 println("IGNORING TRANSPILE ERRORS")
2840 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2842 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2847 inputs.dir("${jalviewDir}/${sourceDir}")
2848 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
2849 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
2853 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
2855 def stdout = new ByteArrayOutputStream()
2856 def stderr = new ByteArrayOutputStream()
2858 def coreFile = file(jsfile)
2860 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
2862 logOutFile.createNewFile()
2863 logOutFile.append(msg+"\n")
2865 def coreTop = file(prefixFile)
2866 def coreBottom = file(suffixFile)
2867 coreFile.getParentFile().mkdirs()
2868 coreFile.createNewFile()
2869 coreFile.write( coreTop.getText("UTF-8") )
2873 def t = f.getText("UTF-8")
2874 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
2875 coreFile.append( t )
2877 msg = "...file '"+f.getPath()+"' does not exist, skipping"
2879 logOutFile.append(msg+"\n")
2882 coreFile.append( coreBottom.getText("UTF-8") )
2884 msg = "Generating ${zjsfile}"
2886 logOutFile.append(msg+"\n")
2887 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
2888 def logErrFOS = logOutFOS
2891 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
2892 main = "com.google.javascript.jscomp.CommandLineRunner"
2893 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
2894 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
2897 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
2899 logOutFile.append(msg+"\n")
2901 if (logOutConsole) {
2902 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2903 new org.apache.tools.ant.util.TeeOutputStream(
2907 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2908 new org.apache.tools.ant.util.TeeOutputStream(
2913 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2916 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2923 logOutFile.append(msg+"\n")
2927 task jalviewjsBuildAllCores {
2929 description "Build the core js lib closures listed in the classlists dir"
2930 dependsOn jalviewjsTranspile
2931 dependsOn jalviewjsTransferUnzipSwingJs
2933 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
2934 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
2935 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
2936 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
2937 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
2938 def prefixFile = "${jsDir}/core/coretop2.js"
2939 def suffixFile = "${jsDir}/core/corebottom2.js"
2941 inputs.file prefixFile
2942 inputs.file suffixFile
2944 def classlistFiles = []
2945 // add the classlists found int the jalviewjs_classlists_dir
2946 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
2948 def name = file.getName() - ".txt"
2955 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
2956 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
2957 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
2959 jalviewjsCoreClasslists = []
2961 classlistFiles.each {
2964 def file = hash['file']
2965 if (! file.exists()) {
2966 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
2967 return false // this is a "continue" in groovy .each closure
2969 def name = hash['name']
2971 name = file.getName() - ".txt"
2979 def list = fileTree(dir: j2sDir, includes: filelist)
2981 def jsfile = "${outputDir}/core${name}.js"
2982 def zjsfile = "${outputDir}/core${name}.z.js"
2984 jalviewjsCoreClasslists += [
2993 outputs.file(jsfile)
2994 outputs.file(zjsfile)
2997 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
2998 def stevesoftClasslistName = "_stevesoft"
2999 def stevesoftClasslist = [
3000 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
3001 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
3002 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
3003 'name': stevesoftClasslistName
3005 jalviewjsCoreClasslists += stevesoftClasslist
3006 inputs.files(stevesoftClasslist['list'])
3007 outputs.file(stevesoftClasslist['jsfile'])
3008 outputs.file(stevesoftClasslist['zjsfile'])
3011 def allClasslistName = "_all"
3012 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3013 allJsFiles += fileTree(
3017 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3018 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3019 "**/org/jmol/export/JSExporter.js"
3022 allJsFiles += fileTree(
3026 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3027 "**/sun/misc/Unsafe.js",
3028 "**/swingjs/jquery/jquery-editable-select.js",
3029 "**/swingjs/jquery/j2sComboBox.js",
3030 "**/sun/misc/FloatingDecimal.js"
3033 def allClasslist = [
3034 'jsfile': "${outputDir}/core${allClasslistName}.js",
3035 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
3037 'name': allClasslistName
3039 // not including this version of "all" core at the moment
3040 //jalviewjsCoreClasslists += allClasslist
3041 inputs.files(allClasslist['list'])
3042 outputs.file(allClasslist['jsfile'])
3043 outputs.file(allClasslist['zjsfile'])
3046 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3047 logOutFile.getParentFile().mkdirs()
3048 logOutFile.createNewFile()
3049 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3051 jalviewjsCoreClasslists.each {
3052 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3059 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3062 into file(outputFile).getParentFile()
3063 rename { filename ->
3064 if (filename.equals(inputFile.getName())) {
3065 return file(outputFile).getName()
3069 filter(ReplaceTokens,
3073 'MAIN': '"'+main_class+'"',
3075 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3076 'COREKEY': jalviewjs_core_key,
3077 'CORENAME': coreName
3084 task jalviewjsPublishCoreTemplates {
3085 dependsOn jalviewjsBuildAllCores
3086 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3087 def inputFile = file(inputFileName)
3088 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3090 def outputFiles = []
3091 jalviewjsCoreClasslists.each { cl ->
3092 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3093 cl['outputfile'] = outputFile
3094 outputFiles += outputFile
3098 jalviewjsCoreClasslists.each { cl ->
3099 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3102 inputs.file(inputFile)
3103 outputs.files(outputFiles)
3107 task jalviewjsSyncCore (type: Sync) {
3108 dependsOn jalviewjsBuildAllCores
3109 dependsOn jalviewjsPublishCoreTemplates
3110 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3111 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3115 def outputFiles = []
3116 rename { filename ->
3117 outputFiles += "${outputDir}/${filename}"
3123 outputs.files outputFiles
3124 inputs.files inputFiles
3128 // this Copy version of TransferSiteJs will delete anything else in the target dir
3129 task jalviewjsCopyTransferSiteJs(type: Copy) {
3130 dependsOn jalviewjsTranspile
3131 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3132 into "${jalviewDir}/${jalviewjsSiteDir}"
3136 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3137 task jalviewjsSyncTransferSiteJs(type: Sync) {
3138 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3140 into "${jalviewDir}/${jalviewjsSiteDir}"
3147 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3148 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3149 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3150 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3152 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3153 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3154 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3155 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3158 task jalviewjsPrepareSite {
3160 description "Prepares the website folder including unzipping files and copying resources"
3161 dependsOn jalviewjsSyncAllLibs
3162 dependsOn jalviewjsSyncResources
3163 dependsOn jalviewjsSyncSiteResources
3164 dependsOn jalviewjsSyncBuildProperties
3165 dependsOn jalviewjsSyncCore
3169 task jalviewjsBuildSite {
3171 description "Builds the whole website including transpiled code"
3172 dependsOn jalviewjsCopyTransferSiteJs
3173 dependsOn jalviewjsPrepareSite
3177 task cleanJalviewjsTransferSite {
3179 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3180 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3181 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3182 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3187 task cleanJalviewjsSite {
3188 dependsOn cleanJalviewjsTransferSite
3190 delete "${jalviewDir}/${jalviewjsSiteDir}"
3195 task jalviewjsSiteTar(type: Tar) {
3197 description "Creates a tar.gz file for the website"
3198 dependsOn jalviewjsBuildSite
3199 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3200 archiveFileName = outputFilename
3202 compression Compression.GZIP
3204 from "${jalviewDir}/${jalviewjsSiteDir}"
3205 into jalviewjs_site_dir // this is inside the tar file
3207 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3211 task jalviewjsServer {
3213 def filename = "jalviewjsTest.html"
3214 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3215 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3220 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3221 factory = f.newInstance()
3222 } catch (ClassNotFoundException e) {
3223 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3225 def port = Integer.valueOf(jalviewjs_server_port)
3230 while(port < start+1000 && !running) {
3232 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3233 jalviewjsServer = factory.start(doc_root, port)
3235 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3236 println("SERVER STARTED with document root ${doc_root}.")
3237 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3238 println("For debug: "+url+"?j2sdebug")
3239 println("For verbose: "+url+"?j2sverbose")
3240 } catch (Exception e) {
3245 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3246 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3247 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3249 jalviewjsCoreClasslists.each { cl ->
3250 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3252 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3254 println("For core ${cl.name}: "+urlcore)
3257 file(htmlFile).text = htmlText
3260 outputs.file(htmlFile)
3261 outputs.upToDateWhen({false})
3265 task cleanJalviewjsAll {
3267 description "Delete all configuration and build artifacts to do with JalviewJS build"
3268 dependsOn cleanJalviewjsSite
3269 dependsOn jalviewjsEclipsePaths
3272 delete "${jalviewDir}/${jalviewjsBuildDir}"
3273 delete "${jalviewDir}/${eclipse_bin_dir}"
3274 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3275 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3277 delete jalviewjsJ2sAltSettingsFileName
3280 outputs.upToDateWhen( { false } )
3284 task jalviewjsIDE_checkJ2sPlugin {
3285 group "00 JalviewJS in Eclipse"
3286 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3289 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3290 def j2sPluginFile = file(j2sPlugin)
3291 def eclipseHome = System.properties["eclipse.home.location"]
3292 if (eclipseHome == null || ! IN_ECLIPSE) {
3293 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3295 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3296 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3297 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3298 eclipseJ2sPluginDirs += altPluginsDir
3300 def foundPlugin = false
3301 def j2sPluginFileName = j2sPluginFile.getName()
3302 def eclipseJ2sPlugin
3303 def eclipseJ2sPluginFile
3304 eclipseJ2sPluginDirs.any { dir ->
3305 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3306 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3307 if (eclipseJ2sPluginFile.exists()) {
3313 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3314 System.err.println(msg)
3315 throw new StopExecutionException(msg)
3318 def digest = MessageDigest.getInstance("MD5")
3320 digest.update(j2sPluginFile.text.bytes)
3321 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3323 digest.update(eclipseJ2sPluginFile.text.bytes)
3324 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3326 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3327 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3328 System.err.println(msg)
3329 throw new StopExecutionException(msg)
3331 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3337 task jalviewjsIDE_copyJ2sPlugin {
3338 group "00 JalviewJS in Eclipse"
3339 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3342 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3343 def j2sPluginFile = file(j2sPlugin)
3344 def eclipseHome = System.properties["eclipse.home.location"]
3345 if (eclipseHome == null || ! IN_ECLIPSE) {
3346 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3348 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3349 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3350 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3351 System.err.println(msg)
3354 eclipseJ2sPluginFile.getParentFile().mkdirs()
3355 into eclipseJ2sPluginFile.getParent()
3361 task jalviewjsIDE_j2sFile {
3362 group "00 JalviewJS in Eclipse"
3363 description "Creates the .j2s file"
3364 dependsOn jalviewjsCreateJ2sSettings
3368 task jalviewjsIDE_SyncCore {
3369 group "00 JalviewJS in Eclipse"
3370 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3371 dependsOn jalviewjsSyncCore
3375 task jalviewjsIDE_SyncSiteAll {
3376 dependsOn jalviewjsSyncAllLibs
3377 dependsOn jalviewjsSyncResources
3378 dependsOn jalviewjsSyncSiteResources
3379 dependsOn jalviewjsSyncBuildProperties
3383 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3386 task jalviewjsIDE_PrepareSite {
3387 group "00 JalviewJS in Eclipse"
3388 description "Sync libs and resources to site dir, but not closure cores"
3390 dependsOn jalviewjsIDE_SyncSiteAll
3391 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3395 task jalviewjsIDE_AssembleSite {
3396 group "00 JalviewJS in Eclipse"
3397 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3398 dependsOn jalviewjsPrepareSite
3402 task jalviewjsIDE_SiteClean {
3403 group "00 JalviewJS in Eclipse"
3404 description "Deletes the Eclipse transpiled site"
3405 dependsOn cleanJalviewjsSite
3409 task jalviewjsIDE_Server {
3410 group "00 JalviewJS in Eclipse"
3411 description "Starts a webserver on localhost to test the website"
3412 dependsOn jalviewjsServer
3416 // buildship runs this at import or gradle refresh
3417 task eclipseSynchronizationTask {
3418 //dependsOn eclipseSetup
3419 dependsOn createBuildProperties
3421 dependsOn jalviewjsIDE_j2sFile
3422 dependsOn jalviewjsIDE_checkJ2sPlugin
3423 dependsOn jalviewjsIDE_PrepareSite
3428 // buildship runs this at build time or project refresh
3429 task eclipseAutoBuildTask {
3430 //dependsOn jalviewjsIDE_checkJ2sPlugin
3431 //dependsOn jalviewjsIDE_PrepareSite
3437 description "Build the site"
3438 dependsOn jalviewjsBuildSite