1 /* Convention for properties. Read from gradle.properties, use lower_case_underlines for property names.
2 * For properties set within build.gradle, use camelCaseNoSpace.
4 import org.apache.tools.ant.filters.ReplaceTokens
5 import org.gradle.internal.os.OperatingSystem
6 import org.gradle.plugins.ide.internal.generator.PropertiesPersistableConfigurationObject
7 import org.gradle.api.internal.PropertiesTransformer
8 import org.gradle.util.ConfigureUtil
9 import org.gradle.plugins.ide.eclipse.model.Output
10 import org.gradle.plugins.ide.eclipse.model.Library
11 import java.security.MessageDigest
12 import groovy.transform.ExternalizeMethods
13 import groovy.util.XmlParser
14 import groovy.xml.XmlUtil
15 import groovy.json.JsonBuilder
16 import com.vladsch.flexmark.util.ast.Node
17 import com.vladsch.flexmark.html.HtmlRenderer
18 import com.vladsch.flexmark.parser.Parser
19 import com.vladsch.flexmark.util.data.MutableDataSet
20 import com.vladsch.flexmark.ext.gfm.tasklist.TaskListExtension
21 import com.vladsch.flexmark.ext.tables.TablesExtension
22 import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension
23 import com.vladsch.flexmark.ext.autolink.AutolinkExtension
24 import com.vladsch.flexmark.ext.anchorlink.AnchorLinkExtension
25 import com.vladsch.flexmark.ext.toc.TocExtension
26 import com.google.common.hash.HashCode
27 import com.google.common.hash.Hashing
28 import com.google.common.io.Files
29 import org.jsoup.Jsoup
30 import org.jsoup.nodes.Element
38 classpath "com.vladsch.flexmark:flexmark-all:0.62.0"
39 classpath "org.jsoup:jsoup:1.14.3"
48 id "com.diffplug.gradle.spotless" version "3.28.0"
49 id 'com.github.johnrengelman.shadow' version '4.0.3'
50 id 'com.install4j.gradle' version '9.0.6'
51 id 'com.dorongold.task-tree' version '2.1.0' // only needed to display task dependency tree with gradle task1 [task2 ...] taskTree
52 id 'com.palantir.git-version' version '0.13.0' apply false
63 // in ext the values are cast to Object. Ensure string values are cast as String (and not GStringImpl) for later use
64 def string(Object o) {
65 return o == null ? "" : o.toString()
68 def overrideProperties(String propsFileName, boolean output = false) {
69 if (propsFileName == null) {
72 def propsFile = file(propsFileName)
73 if (propsFile != null && propsFile.exists()) {
74 println("Using properties from file '${propsFileName}'")
76 def p = new Properties()
77 def localPropsFIS = new FileInputStream(propsFile)
83 if (project.hasProperty(key)) {
84 oldval = project.findProperty(key)
85 project.setProperty(key, val)
87 println("Overriding property '${key}' ('${oldval}') with ${file(propsFile).getName()} value '${val}'")
90 ext.setProperty(key, val)
92 println("Setting ext property '${key}' with ${file(propsFile).getName()}s value '${val}'")
96 } catch (Exception e) {
97 println("Exception reading local.properties")
104 jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath()
105 jalviewDirRelativePath = jalviewDir
108 getdownChannelName = CHANNEL.toLowerCase()
109 // default to "default". Currently only has different cosmetics for "develop", "release", "default"
110 propertiesChannelName = ["develop", "release", "test-release", "jalviewjs", "jalviewjs-release" ].contains(getdownChannelName) ? getdownChannelName : "default"
111 // Import channel_properties
112 channelDir = string("${jalviewDir}/${channel_properties_dir}/${propertiesChannelName}")
113 channelGradleProperties = string("${channelDir}/channel_gradle.properties")
114 channelPropsFile = string("${channelDir}/${resource_dir}/${channel_props}")
115 overrideProperties(channelGradleProperties, false)
116 // local build environment properties
117 // can be "projectDir/local.properties"
118 overrideProperties("${projectDir}/local.properties", true)
119 // or "../projectDir_local.properties"
120 overrideProperties(projectDir.getParent() + "/" + projectDir.getName() + "_local.properties", true)
123 // Import releaseProps from the RELEASE file
124 // or a file specified via JALVIEW_RELEASE_FILE if defined
125 // Expect jalview.version and target release branch in jalview.release
126 releaseProps = new Properties();
127 def releasePropFile = findProperty("JALVIEW_RELEASE_FILE");
128 def defaultReleasePropFile = "${jalviewDirAbsolutePath}/RELEASE";
130 (new File(releasePropFile!=null ? releasePropFile : defaultReleasePropFile)).withInputStream {
131 releaseProps.load(it)
133 } catch (Exception fileLoadError) {
134 throw new Error("Couldn't load release properties file "+(releasePropFile==null ? defaultReleasePropFile : "from custom location: releasePropFile"),fileLoadError);
137 // Set JALVIEW_VERSION if it is not already set
138 if (findProperty("JALVIEW_VERSION")==null || "".equals(JALVIEW_VERSION)) {
139 JALVIEW_VERSION = releaseProps.get("jalview.version")
141 println("JALVIEW_VERSION is set to '${JALVIEW_VERSION}'")
143 // this property set when running Eclipse headlessly
144 j2sHeadlessBuildProperty = string("net.sf.j2s.core.headlessbuild")
145 // this property set by Eclipse
146 eclipseApplicationProperty = string("eclipse.application")
147 // CHECK IF RUNNING FROM WITHIN ECLIPSE
148 def eclipseApplicationPropertyVal = System.properties[eclipseApplicationProperty]
149 IN_ECLIPSE = eclipseApplicationPropertyVal != null && eclipseApplicationPropertyVal.startsWith("org.eclipse.ui.")
150 // BUT WITHOUT THE HEADLESS BUILD PROPERTY SET
151 if (System.properties[j2sHeadlessBuildProperty].equals("true")) {
152 println("Setting IN_ECLIPSE to ${IN_ECLIPSE} as System.properties['${j2sHeadlessBuildProperty}'] == '${System.properties[j2sHeadlessBuildProperty]}'")
156 println("WITHIN ECLIPSE IDE")
158 println("HEADLESS BUILD")
161 J2S_ENABLED = (project.hasProperty('j2s.compiler.status') && project['j2s.compiler.status'] != null && project['j2s.compiler.status'] == "enable")
163 println("J2S ENABLED")
166 System.properties.sort { it.key }.each {
167 key, val -> println("SYSTEM PROPERTY ${key}='${val}'")
170 if (false && IN_ECLIPSE) {
171 jalviewDir = jalviewDirAbsolutePath
176 buildDate = new Date().format("yyyyMMdd")
179 bareSourceDir = string(source_dir)
180 sourceDir = string("${jalviewDir}/${bareSourceDir}")
181 resourceDir = string("${jalviewDir}/${resource_dir}")
182 bareTestSourceDir = string(test_source_dir)
183 testDir = string("${jalviewDir}/${bareTestSourceDir}")
185 classesDir = string("${jalviewDir}/${classes_dir}")
188 useClover = clover.equals("true")
189 cloverBuildDir = "${buildDir}/clover"
190 cloverInstrDir = file("${cloverBuildDir}/clover-instr")
191 cloverClassesDir = file("${cloverBuildDir}/clover-classes")
192 cloverReportDir = file("${buildDir}/reports/clover")
193 cloverTestInstrDir = file("${cloverBuildDir}/clover-test-instr")
194 cloverTestClassesDir = file("${cloverBuildDir}/clover-test-classes")
195 //cloverTestClassesDir = cloverClassesDir
196 cloverDb = string("${cloverBuildDir}/clover.db")
198 testSourceDir = useClover ? cloverTestInstrDir : testDir
199 testClassesDir = useClover ? cloverTestClassesDir : "${jalviewDir}/${test_output_dir}"
201 getdownChannelDir = string("${getdown_website_dir}/${propertiesChannelName}")
202 getdownAppBaseDir = string("${jalviewDir}/${getdownChannelDir}/${JAVA_VERSION}")
203 getdownArchiveDir = string("${jalviewDir}/${getdown_archive_dir}")
204 getdownFullArchiveDir = null
205 getdownTextLines = []
206 getdownLaunchJvl = null
207 getdownVersionLaunchJvl = null
209 buildProperties = null
211 // the following values might be overridden by the CHANNEL switch
212 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
213 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
214 getdownArchiveAppBase = getdown_archive_base
215 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}")
216 getdownAppDistDir = getdown_app_dir_alt
217 getdownImagesDir = string("${jalviewDir}/${getdown_images_dir}")
218 getdownSetAppBaseProperty = false // whether to pass the appbase and appdistdir to the application
219 reportRsyncCommand = false
220 jvlChannelName = CHANNEL.toLowerCase()
221 install4jSuffix = CHANNEL.substring(0, 1).toUpperCase() + CHANNEL.substring(1).toLowerCase(); // BUILD -> Build
222 install4jDMGDSStore = "${install4j_images_dir}/${install4j_dmg_ds_store}"
223 install4jDMGBackgroundImage = "${install4j_images_dir}/${install4j_dmg_background}"
224 install4jInstallerName = "${jalview_name} Non-Release Installer"
225 install4jExecutableName = install4j_executable_name
226 install4jExtraScheme = "jalviewx"
227 install4jMacIconsFile = string("${install4j_images_dir}/${install4j_mac_icons_file}")
228 install4jWindowsIconsFile = string("${install4j_images_dir}/${install4j_windows_icons_file}")
229 install4jPngIconFile = string("${install4j_images_dir}/${install4j_png_icon_file}")
230 install4jBackground = string("${install4j_images_dir}/${install4j_background}")
231 install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
232 install4jCheckSums = true
234 applicationName = "${jalview_name}"
238 // TODO: get bamboo build artifact URL for getdown artifacts
239 getdown_channel_base = bamboo_channelbase
240 getdownChannelName = string("${bamboo_planKey}/${JAVA_VERSION}")
241 getdownAppBase = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
242 jvlChannelName += "_${getdownChannelName}"
243 // automatically add the test group Not-bamboo for exclusion
244 if ("".equals(testng_excluded_groups)) {
245 testng_excluded_groups = "Not-bamboo"
247 install4jExtraScheme = "jalviewb"
250 case [ "RELEASE", "JALVIEWJS-RELEASE" ]:
251 getdownAppDistDir = getdown_app_dir_release
252 getdownSetAppBaseProperty = true
253 reportRsyncCommand = true
255 install4jInstallerName = "${jalview_name} Installer"
259 getdownChannelName = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
260 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
261 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
262 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
263 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
265 package_dir = string("${ARCHIVEDIR}/${package_dir}")
266 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
269 reportRsyncCommand = true
270 install4jExtraScheme = "jalviewa"
274 getdownChannelName = string("archive/${JALVIEW_VERSION}")
275 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
276 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
277 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
278 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
280 package_dir = string("${ARCHIVEDIR}/${package_dir}")
281 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
284 reportRsyncCommand = true
285 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
286 install4jSuffix = "Archive"
287 install4jExtraScheme = "jalviewa"
291 reportRsyncCommand = true
292 getdownSetAppBaseProperty = true
293 // DEVELOP-RELEASE is usually associated with a Jalview release series so set the version
294 JALVIEW_VERSION=JALVIEW_VERSION+"-d${buildDate}"
296 install4jSuffix = "Develop"
297 install4jExtraScheme = "jalviewd"
298 install4jInstallerName = "${jalview_name} Develop Installer"
302 reportRsyncCommand = true
303 getdownSetAppBaseProperty = true
304 // Don't ignore transpile errors for release build
305 if (jalviewjs_ignore_transpile_errors.equals("true")) {
306 jalviewjs_ignore_transpile_errors = "false"
307 println("Setting jalviewjs_ignore_transpile_errors to 'false'")
309 JALVIEW_VERSION = JALVIEW_VERSION+"-test"
310 install4jSuffix = "Test"
311 install4jExtraScheme = "jalviewt"
312 install4jInstallerName = "${jalview_name} Test Installer"
315 case ~/^SCRATCH(|-[-\w]*)$/:
316 getdownChannelName = CHANNEL
317 JALVIEW_VERSION = JALVIEW_VERSION+"-"+CHANNEL
319 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
320 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
321 reportRsyncCommand = true
322 install4jSuffix = "Scratch"
326 if (!file("${LOCALDIR}").exists()) {
327 throw new GradleException("Must provide a LOCALDIR value to produce a local distribution")
329 getdownAppBase = file(file("${LOCALDIR}").getAbsolutePath()).toURI().toString()
330 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
332 JALVIEW_VERSION = "TEST"
333 install4jSuffix = "Test-Local"
334 install4jExtraScheme = "jalviewt"
335 install4jInstallerName = "${jalview_name} Test Installer"
338 case [ "LOCAL", "JALVIEWJS" ]:
339 JALVIEW_VERSION = "TEST"
340 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
341 getdownArchiveAppBase = file("${jalviewDir}/${getdown_archive_dir}").toURI().toString()
342 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
343 install4jExtraScheme = "jalviewl"
344 install4jCheckSums = false
347 default: // something wrong specified
348 throw new GradleException("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
352 JALVIEW_VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
353 hugoDataJsonFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_data_installers_dir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
354 hugoArchiveMdFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_version_archive_dir}/Version-${JALVIEW_VERSION_UNDERSCORES}/_index.md")
355 // override getdownAppBase if requested
356 if (findProperty("getdown_appbase_override") != null) {
357 // revert to LOCAL if empty string
358 if (string(getdown_appbase_override) == "") {
359 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
360 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
361 } else if (string(getdown_appbase_override).startsWith("file://")) {
362 getdownAppBase = string(getdown_appbase_override)
363 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
365 getdownAppBase = string(getdown_appbase_override)
367 println("Overriding getdown appbase with '${getdownAppBase}'")
369 // sanitise file name for jalview launcher file for this channel
370 jvlChannelName = jvlChannelName.replaceAll("[^\\w\\-]+", "_")
371 // install4j application and folder names
372 if (install4jSuffix == "") {
373 install4jBundleId = "${install4j_bundle_id}"
374 install4jWinApplicationId = install4j_release_win_application_id
376 applicationName = "${jalview_name} ${install4jSuffix}"
377 install4jBundleId = "${install4j_bundle_id}-" + install4jSuffix.toLowerCase()
378 // add int hash of install4jSuffix to the last part of the application_id
379 def id = install4j_release_win_application_id
380 def idsplitreverse = id.split("-").reverse()
381 idsplitreverse[0] = idsplitreverse[0].toInteger() + install4jSuffix.hashCode()
382 install4jWinApplicationId = idsplitreverse.reverse().join("-")
384 // sanitise folder and id names
385 // install4jApplicationFolder = e.g. "Jalview Build"
386 install4jApplicationFolder = applicationName
387 .replaceAll("[\"'~:/\\\\\\s]", "_") // replace all awkward filename chars " ' ~ : / \
388 .replaceAll("_+", "_") // collapse __
389 install4jInternalId = applicationName
391 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
392 .replaceAll("_+", "") // collapse __
393 //.replaceAll("_*-_*", "-") // collapse _-_
394 install4jUnixApplicationFolder = applicationName
396 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
397 .replaceAll("_+", "_") // collapse __
398 .replaceAll("_*-_*", "-") // collapse _-_
401 getdownWrapperLink = install4jUnixApplicationFolder // e.g. "jalview_local"
402 getdownAppDir = string("${getdownAppBaseDir}/${getdownAppDistDir}")
403 //getdownJ11libDir = "${getdownAppBaseDir}/${getdown_j11lib_dir}"
404 getdownResourceDir = string("${getdownAppBaseDir}/${getdown_resource_dir}")
405 getdownInstallDir = string("${getdownAppBaseDir}/${getdown_install_dir}")
406 getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
407 getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
408 /* compile without modules -- using classpath libraries
409 modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
410 modules_runtimeClasspath = modules_compileClasspath
415 apply plugin: "com.palantir.git-version"
416 def details = versionDetails()
417 gitHash = details.gitHash
418 gitBranch = details.branchName
419 } catch(org.gradle.api.internal.plugins.PluginApplicationException e) {
420 println("Not in a git repository. Using git values from RELEASE properties file.")
421 gitHash = releaseProps.getProperty("git.hash")
422 gitBranch = releaseProps.getProperty("git.branch")
423 } catch(java.lang.RuntimeException e1) {
424 throw new GradleException("Error with git-version plugin. Directory '.git' exists but versionDetails() cannot be found.")
427 println("Using a ${CHANNEL} profile.")
429 additional_compiler_args = []
430 // configure classpath/args for j8/j11 compilation
431 if (JAVA_VERSION.equals("1.8")) {
432 JAVA_INTEGER_VERSION = string("8")
435 libDistDir = j8libDir
436 compile_source_compatibility = 1.8
437 compile_target_compatibility = 1.8
438 // these are getdown.txt properties defined dependent on the JAVA_VERSION
439 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
440 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
441 // this property is assigned below and expanded to multiple lines in the getdown task
442 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
443 // this property is for the Java library used in eclipse
444 eclipseJavaRuntimeName = string("JavaSE-1.8")
445 } else if (JAVA_VERSION.equals("11")) {
446 JAVA_INTEGER_VERSION = string("11")
448 libDistDir = j11libDir
449 compile_source_compatibility = 11
450 compile_target_compatibility = 11
451 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
452 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
453 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
454 eclipseJavaRuntimeName = string("JavaSE-11")
455 /* compile without modules -- using classpath libraries
456 additional_compiler_args += [
457 '--module-path', modules_compileClasspath.asPath,
458 '--add-modules', j11modules
461 } else if (JAVA_VERSION.equals("17")) {
462 JAVA_INTEGER_VERSION = string("17")
464 libDistDir = j17libDir
465 compile_source_compatibility = 17
466 compile_target_compatibility = 17
467 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
468 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
469 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
470 eclipseJavaRuntimeName = string("JavaSE-17")
471 /* compile without modules -- using classpath libraries
472 additional_compiler_args += [
473 '--module-path', modules_compileClasspath.asPath,
474 '--add-modules', j11modules
478 throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
483 JAVA_MIN_VERSION = JAVA_VERSION
484 JAVA_MAX_VERSION = JAVA_VERSION
485 def jreInstallsDir = string(jre_installs_dir)
486 if (jreInstallsDir.startsWith("~/")) {
487 jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
489 macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
490 windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
491 linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
492 macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_mac_x64.tar.gz")
493 windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_windows_x64.tar.gz")
494 linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_linux_x64.tar.gz")
495 install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
496 install4jConfFileName = string("jalview-install4j-conf.install4j")
497 install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
498 install4jHomeDir = install4j_home_dir
499 if (install4jHomeDir.startsWith("~/")) {
500 install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
503 resourceBuildDir = string("${buildDir}/resources")
504 resourcesBuildDir = string("${resourceBuildDir}/resources_build")
505 helpBuildDir = string("${resourceBuildDir}/help_build")
506 docBuildDir = string("${resourceBuildDir}/doc_build")
508 if (buildProperties == null) {
509 buildProperties = string("${resourcesBuildDir}/${build_properties_file}")
511 buildingHTML = string("${jalviewDir}/${doc_dir}/building.html")
512 helpParentDir = string("${jalviewDir}/${help_parent_dir}")
513 helpSourceDir = string("${helpParentDir}/${help_dir}")
514 helpFile = string("${helpBuildDir}/${help_dir}/help.jhm")
517 relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
518 jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
519 jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
521 jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
523 jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
525 jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
526 jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
527 jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
528 jalviewjsJalviewCoreHtmlFile = string("")
529 jalviewjsJalviewCoreName = string(jalviewjs_core_name)
530 jalviewjsCoreClasslists = []
531 jalviewjsJalviewTemplateName = string(jalviewjs_name)
532 jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
533 jalviewjsJ2sAltSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_alt_settings}")
534 jalviewjsJ2sProps = null
535 jalviewjsJ2sPlugin = jalviewjs_j2s_plugin
537 eclipseWorkspace = null
538 eclipseBinary = string("")
539 eclipseVersion = string("")
549 outputDir = file(classesDir)
553 srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ]
556 compileClasspath = files(sourceSets.main.java.outputDir)
557 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
559 runtimeClasspath = compileClasspath
560 runtimeClasspath += files(sourceSets.main.resources.srcDirs)
565 srcDirs cloverInstrDir
566 outputDir = cloverClassesDir
570 srcDirs = sourceSets.main.resources.srcDirs
573 compileClasspath = files( sourceSets.clover.java.outputDir )
574 //compileClasspath += files( testClassesDir )
575 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
576 compileClasspath += fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
577 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
579 runtimeClasspath = compileClasspath
584 srcDirs testSourceDir
585 outputDir = file(testClassesDir)
589 srcDirs = useClover ? sourceSets.clover.resources.srcDirs : sourceSets.main.resources.srcDirs
592 compileClasspath = files( sourceSets.test.java.outputDir )
593 compileClasspath += useClover ? sourceSets.clover.compileClasspath : sourceSets.main.compileClasspath
594 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
596 runtimeClasspath = compileClasspath
597 runtimeClasspath += files(sourceSets.test.resources.srcDirs)
603 // eclipse project and settings files creation, also used by buildship
606 name = eclipse_project_name
608 natures 'org.eclipse.jdt.core.javanature',
609 'org.eclipse.jdt.groovy.core.groovyNature',
610 'org.eclipse.buildship.core.gradleprojectnature'
612 buildCommand 'org.eclipse.jdt.core.javabuilder'
613 buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
617 //defaultOutputDir = sourceSets.main.java.outputDir
618 configurations.each{ c->
619 if (c.isCanBeResolved()) {
620 minusConfigurations += [c]
624 plusConfigurations = [ ]
628 def removeTheseToo = []
629 HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
630 cp.entries.each { entry ->
631 // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
632 // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
633 // we add the resources and help/help dirs in as libs afterwards (see below)
634 if (entry.kind == 'src') {
635 if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
636 removeTheseToo += entry
638 alreadyAddedSrcPath.putAt(entry.path, true)
643 cp.entries.removeAll(removeTheseToo)
645 //cp.entries += new Output("${eclipse_bin_dir}/main")
646 if (file(helpParentDir).isDirectory()) {
647 cp.entries += new Library(fileReference(helpParentDir))
649 if (file(resourceDir).isDirectory()) {
650 cp.entries += new Library(fileReference(resourceDir))
653 HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
655 sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
656 //don't want to add outputDir as eclipse is using its own output dir in bin/main
657 if (it.isDirectory() || ! it.exists()) {
658 // don't add dirs to classpath, especially if they don't exist
659 return false // groovy "continue" in .any closure
661 def itPath = it.toString()
662 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
663 // make relative path
664 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
666 if (alreadyAddedLibPath.get(itPath)) {
667 //println("Not adding duplicate entry "+itPath)
669 //println("Adding entry "+itPath)
670 cp.entries += new Library(fileReference(itPath))
671 alreadyAddedLibPath.put(itPath, true)
675 sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
676 //no longer want to add outputDir as eclipse is using its own output dir in bin/main
677 if (it.isDirectory() || ! it.exists()) {
678 // don't add dirs to classpath
679 return false // groovy "continue" in .any closure
682 def itPath = it.toString()
683 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
684 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
686 if (alreadyAddedLibPath.get(itPath)) {
689 def lib = new Library(fileReference(itPath))
690 lib.entryAttributes["test"] = "true"
692 alreadyAddedLibPath.put(itPath, true)
700 containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
705 // for the IDE, use java 11 compatibility
706 sourceCompatibility = compile_source_compatibility
707 targetCompatibility = compile_target_compatibility
708 javaRuntimeName = eclipseJavaRuntimeName
710 // add in jalview project specific properties/preferences into eclipse core preferences
712 withProperties { props ->
713 def jalview_prefs = new Properties()
714 def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
715 jalview_prefs.load(ins)
717 jalview_prefs.forEach { t, v ->
718 if (props.getAt(t) == null) {
722 // codestyle file -- overrides previous formatter prefs
723 def csFile = file("${jalviewDirAbsolutePath}/${eclipse_codestyle_file}")
724 if (csFile.exists()) {
725 XmlParser parser = new XmlParser()
726 def profiles = parser.parse(csFile)
727 def profile = profiles.'profile'.find { p -> (p.'@kind' == "CodeFormatterProfile" && p.'@name' == "Jalview") }
728 if (profile != null) {
729 profile.'setting'.each { s ->
731 def value = s.'@value'
732 if (id != null && value != null) {
733 props.putAt(id, value)
744 // Don't want these to be activated if in headless build
745 synchronizationTasks "eclipseSynchronizationTask"
746 //autoBuildTasks "eclipseAutoBuildTask"
752 /* hack to change eclipse prefs in .settings files other than org.eclipse.jdt.core.prefs */
753 // Class to allow updating arbitrary properties files
754 class PropertiesFile extends PropertiesPersistableConfigurationObject {
755 public PropertiesFile(PropertiesTransformer t) { super(t); }
756 @Override protected void load(Properties properties) { }
757 @Override protected void store(Properties properties) { }
758 @Override protected String getDefaultResourceName() { return ""; }
759 // This is necessary, because PropertiesPersistableConfigurationObject fails
760 // if no default properties file exists.
761 @Override public void loadDefaults() { load(new StringBufferInputStream("")); }
764 // Task to update arbitrary properties files (set outputFile)
765 class PropertiesFileTask extends PropertiesGeneratorTask<PropertiesFile> {
766 private final PropertiesFileContentMerger file;
767 public PropertiesFileTask() { file = new PropertiesFileContentMerger(getTransformer()); }
768 protected PropertiesFile create() { return new PropertiesFile(getTransformer()); }
769 protected void configure(PropertiesFile props) {
770 file.getBeforeMerged().execute(props); file.getWhenMerged().execute(props);
772 public void file(Closure closure) { ConfigureUtil.configure(closure, file); }
775 task eclipseUIPreferences(type: PropertiesFileTask) {
776 description = "Generate Eclipse additional settings"
777 def filename = "org.eclipse.jdt.ui.prefs"
778 outputFile = "$projectDir/.settings/${filename}" as File
781 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
786 task eclipseGroovyCorePreferences(type: PropertiesFileTask) {
787 description = "Generate Eclipse additional settings"
788 def filename = "org.eclipse.jdt.groovy.core.prefs"
789 outputFile = "$projectDir/.settings/${filename}" as File
792 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
797 task eclipseAllPreferences {
799 dependsOn eclipseUIPreferences
800 dependsOn eclipseGroovyCorePreferences
803 eclipseUIPreferences.mustRunAfter eclipseJdt
804 eclipseGroovyCorePreferences.mustRunAfter eclipseJdt
806 /* end of eclipse preferences hack */
814 delete cloverBuildDir
815 delete cloverReportDir
820 task cloverInstrJava(type: JavaExec) {
821 group = "Verification"
822 description = "Create clover instrumented source java files"
824 dependsOn cleanClover
826 inputs.files(sourceSets.main.allJava)
827 outputs.dir(cloverInstrDir)
829 //classpath = fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
830 classpath = sourceSets.clover.compileClasspath
831 main = "com.atlassian.clover.CloverInstr"
839 cloverInstrDir.getPath(),
841 def srcFiles = sourceSets.main.allJava.files
844 { file -> file.absolutePath }
847 args argsList.toArray()
850 delete cloverInstrDir
851 println("Clover: About to instrument "+srcFiles.size() +" files")
856 task cloverInstrTests(type: JavaExec) {
857 group = "Verification"
858 description = "Create clover instrumented source test files"
860 dependsOn cleanClover
862 inputs.files(testDir)
863 outputs.dir(cloverTestInstrDir)
865 classpath = sourceSets.clover.compileClasspath
866 main = "com.atlassian.clover.CloverInstr"
876 cloverTestInstrDir.getPath(),
878 args argsList.toArray()
881 delete cloverTestInstrDir
882 println("Clover: About to instrument test files")
888 group = "Verification"
889 description = "Create clover instrumented all source files"
891 dependsOn cloverInstrJava
892 dependsOn cloverInstrTests
896 cloverClasses.dependsOn cloverInstr
899 task cloverConsoleReport(type: JavaExec) {
900 group = "Verification"
901 description = "Creates clover console report"
904 file(cloverDb).exists()
907 inputs.dir cloverClassesDir
909 classpath = sourceSets.clover.runtimeClasspath
910 main = "com.atlassian.clover.reporters.console.ConsoleReporter"
912 if (cloverreport_mem.length() > 0) {
913 maxHeapSize = cloverreport_mem
915 if (cloverreport_jvmargs.length() > 0) {
916 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
926 args argsList.toArray()
930 task cloverHtmlReport(type: JavaExec) {
931 group = "Verification"
932 description = "Creates clover HTML report"
935 file(cloverDb).exists()
938 def cloverHtmlDir = cloverReportDir
939 inputs.dir cloverClassesDir
940 outputs.dir cloverHtmlDir
942 classpath = sourceSets.clover.runtimeClasspath
943 main = "com.atlassian.clover.reporters.html.HtmlReporter"
945 if (cloverreport_mem.length() > 0) {
946 maxHeapSize = cloverreport_mem
948 if (cloverreport_jvmargs.length() > 0) {
949 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
960 if (cloverreport_html_options.length() > 0) {
961 argsList += cloverreport_html_options.split(" ")
964 args argsList.toArray()
968 task cloverXmlReport(type: JavaExec) {
969 group = "Verification"
970 description = "Creates clover XML report"
973 file(cloverDb).exists()
976 def cloverXmlFile = "${cloverReportDir}/clover.xml"
977 inputs.dir cloverClassesDir
978 outputs.file cloverXmlFile
980 classpath = sourceSets.clover.runtimeClasspath
981 main = "com.atlassian.clover.reporters.xml.XMLReporter"
983 if (cloverreport_mem.length() > 0) {
984 maxHeapSize = cloverreport_mem
986 if (cloverreport_jvmargs.length() > 0) {
987 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
998 if (cloverreport_xml_options.length() > 0) {
999 argsList += cloverreport_xml_options.split(" ")
1002 args argsList.toArray()
1007 group = "Verification"
1008 description = "Creates clover reports"
1010 dependsOn cloverXmlReport
1011 dependsOn cloverHtmlReport
1018 sourceCompatibility = compile_source_compatibility
1019 targetCompatibility = compile_target_compatibility
1020 options.compilerArgs += additional_compiler_args
1021 print ("Setting target compatibility to "+targetCompatibility+"\n")
1023 //classpath += configurations.cloverRuntime
1029 // JBP->BS should the print statement in doFirst refer to compile_target_compatibility ?
1030 sourceCompatibility = compile_source_compatibility
1031 targetCompatibility = compile_target_compatibility
1032 options.compilerArgs = additional_compiler_args
1033 options.encoding = "UTF-8"
1035 print ("Setting target compatibility to "+compile_target_compatibility+"\n")
1042 sourceCompatibility = compile_source_compatibility
1043 targetCompatibility = compile_target_compatibility
1044 options.compilerArgs = additional_compiler_args
1046 print ("Setting target compatibility to "+targetCompatibility+"\n")
1053 delete sourceSets.main.java.outputDir
1059 dependsOn cleanClover
1061 delete sourceSets.test.java.outputDir
1066 // format is a string like date.format("dd MMMM yyyy")
1067 def getDate(format) {
1068 return date.format(format)
1072 def convertMdToHtml (FileTree mdFiles, File cssFile) {
1073 MutableDataSet options = new MutableDataSet()
1075 def extensions = new ArrayList<>()
1076 extensions.add(AnchorLinkExtension.create())
1077 extensions.add(AutolinkExtension.create())
1078 extensions.add(StrikethroughExtension.create())
1079 extensions.add(TaskListExtension.create())
1080 extensions.add(TablesExtension.create())
1081 extensions.add(TocExtension.create())
1083 options.set(Parser.EXTENSIONS, extensions)
1085 // set GFM table parsing options
1086 options.set(TablesExtension.WITH_CAPTION, false)
1087 options.set(TablesExtension.COLUMN_SPANS, false)
1088 options.set(TablesExtension.MIN_HEADER_ROWS, 1)
1089 options.set(TablesExtension.MAX_HEADER_ROWS, 1)
1090 options.set(TablesExtension.APPEND_MISSING_COLUMNS, true)
1091 options.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
1092 options.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
1094 options.set(AnchorLinkExtension.ANCHORLINKS_SET_ID, false)
1095 options.set(AnchorLinkExtension.ANCHORLINKS_ANCHOR_CLASS, "anchor")
1096 options.set(AnchorLinkExtension.ANCHORLINKS_SET_NAME, true)
1097 options.set(AnchorLinkExtension.ANCHORLINKS_TEXT_PREFIX, "<span class=\"octicon octicon-link\"></span>")
1099 Parser parser = Parser.builder(options).build()
1100 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1102 mdFiles.each { mdFile ->
1103 // add table of contents
1104 def mdText = "[TOC]\n"+mdFile.text
1106 // grab the first top-level title
1108 def titleRegex = /(?m)^#(\s+|([^#]))(.*)/
1109 def matcher = mdText =~ titleRegex
1110 if (matcher.size() > 0) {
1111 // matcher[0][2] is the first character of the title if there wasn't any whitespace after the #
1112 title = (matcher[0][2] != null ? matcher[0][2] : "")+matcher[0][3]
1114 // or use the filename if none found
1115 if (title == null) {
1116 title = mdFile.getName()
1119 Node document = parser.parse(mdText)
1120 String htmlBody = renderer.render(document)
1121 def htmlText = '''<html>
1122 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1123 <html xmlns="http://www.w3.org/1999/xhtml">
1125 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1126 <meta http-equiv="Content-Style-Type" content="text/css" />
1127 <meta name="generator" content="flexmark" />
1129 htmlText += ((title != null) ? " <title>${title}</title>" : '' )
1131 <style type="text/css">code{white-space: pre;}</style>
1133 htmlText += ((cssFile != null) ? cssFile.text : '')
1134 htmlText += '''</head>
1137 htmlText += htmlBody
1143 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1144 def htmlFile = file(htmlFilePath)
1145 println("Creating ${htmlFilePath}")
1146 htmlFile.text = htmlText
1151 task copyDocs(type: Copy) {
1152 def inputDir = "${jalviewDir}/${doc_dir}"
1153 def outputDir = "${docBuildDir}/${doc_dir}"
1157 include('**/*.html')
1159 filter(ReplaceTokens,
1163 'Version-Rel': JALVIEW_VERSION,
1164 'Year-Rel': getDate("yyyy")
1171 exclude('**/*.html')
1176 inputs.dir(inputDir)
1177 outputs.dir(outputDir)
1181 task convertMdFiles {
1183 def mdFiles = fileTree(dir: docBuildDir, include: "**/*.md")
1184 def cssFile = file("${jalviewDir}/${flexmark_css}")
1187 convertMdToHtml(mdFiles, cssFile)
1190 inputs.files(mdFiles)
1191 inputs.file(cssFile)
1194 mdFiles.each { mdFile ->
1195 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1196 htmlFiles.add(file(htmlFilePath))
1198 outputs.files(htmlFiles)
1202 def hugoTemplateSubstitutions(String input, Map extras=null) {
1203 def replacements = [
1204 DATE: getDate("yyyy-MM-dd"),
1205 CHANNEL: propertiesChannelName,
1206 APPLICATION_NAME: applicationName,
1208 GIT_BRANCH: gitBranch,
1209 VERSION: JALVIEW_VERSION,
1210 JAVA_VERSION: JAVA_VERSION,
1211 VERSION_UNDERSCORES: JALVIEW_VERSION_UNDERSCORES,
1216 if (extras != null) {
1217 extras.each{ k, v ->
1218 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1221 replacements.each{ k, v ->
1222 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1227 def mdFileComponents(File mdFile, def dateOnly=false) {
1230 if (mdFile.exists()) {
1231 def inFrontMatter = false
1232 def firstLine = true
1233 mdFile.eachLine { line ->
1234 if (line.matches("---")) {
1235 def prev = inFrontMatter
1236 inFrontMatter = firstLine
1237 if (inFrontMatter != prev)
1240 if (inFrontMatter) {
1242 if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/) {
1243 map["date"] = new Date().parse("yyyy-MM-dd HH:mm:ss", m[0][1])
1244 } else if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2})/) {
1245 map["date"] = new Date().parse("yyyy-MM-dd", m[0][1])
1246 } else if (m = line =~ /^channel:\s*(\S+)/) {
1247 map["channel"] = m[0][1]
1248 } else if (m = line =~ /^version:\s*(\S+)/) {
1249 map["version"] = m[0][1]
1250 } else if (m = line =~ /^\s*([^:]+)\s*:\s*(\S.*)/) {
1251 map[ m[0][1] ] = m[0][2]
1253 if (dateOnly && map["date"] != null) {
1259 content += line+"\n"
1264 return dateOnly ? map["date"] : [map, content]
1267 task hugoTemplates {
1269 description "Create partially populated md pages for hugo website build"
1271 def hugoTemplatesDir = file("${jalviewDir}/${hugo_templates_dir}")
1272 def hugoBuildDir = "${jalviewDir}/${hugo_build_dir}"
1273 def templateFiles = fileTree(dir: hugoTemplatesDir)
1274 def releaseMdFile = file("${jalviewDir}/${releases_dir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1275 def whatsnewMdFile = file("${jalviewDir}/${whatsnew_dir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1276 def oldJvlFile = file("${jalviewDir}/${hugo_old_jvl}")
1277 def jalviewjsFile = file("${jalviewDir}/${hugo_jalviewjs}")
1280 // specific release template for version archive
1283 def givenDate = null
1284 def givenChannel = null
1285 def givenVersion = null
1286 if (CHANNEL == "RELEASE") {
1287 def (map, content) = mdFileComponents(releaseMdFile)
1288 givenDate = map.date
1289 givenChannel = map.channel
1290 givenVersion = map.version
1292 if (givenVersion != null && givenVersion != JALVIEW_VERSION) {
1293 throw new GradleException("'version' header (${givenVersion}) found in ${releaseMdFile} does not match JALVIEW_VERSION (${JALVIEW_VERSION})")
1296 if (whatsnewMdFile.exists())
1297 whatsnew = whatsnewMdFile.text
1300 def oldJvl = oldJvlFile.exists() ? oldJvlFile.collect{it} : []
1301 def jalviewjsLink = jalviewjsFile.exists() ? jalviewjsFile.collect{it} : []
1303 def changesHugo = null
1304 if (changes != null) {
1305 changesHugo = '<div class="release_notes">\n\n'
1306 def inSection = false
1307 changes.eachLine { line ->
1309 if (m = line =~ /^##([^#].*)$/) {
1311 changesHugo += "</div>\n\n"
1313 def section = m[0][1].trim()
1314 section = section.toLowerCase()
1315 section = section.replaceAll(/ +/, "_")
1316 section = section.replaceAll(/[^a-z0-9_\-]/, "")
1317 changesHugo += "<div class=\"${section}\">\n\n"
1319 } else if (m = line =~ /^(\s*-\s*)<!--([^>]+)-->(.*?)(<br\/?>)?\s*$/) {
1320 def comment = m[0][2].trim()
1321 if (comment != "") {
1322 comment = comment.replaceAll('"', """)
1324 comment.eachMatch(/JAL-\d+/) { jal -> issuekeys += jal }
1325 def newline = m[0][1]
1326 if (comment.trim() != "")
1327 newline += "{{<comment>}}${comment}{{</comment>}} "
1328 newline += m[0][3].trim()
1329 if (issuekeys.size() > 0)
1330 newline += " {{< jal issue=\"${issuekeys.join(",")}\" alt=\"${comment}\" >}}"
1331 if (m[0][4] != null)
1336 changesHugo += line+"\n"
1339 changesHugo += "\n</div>\n\n"
1341 changesHugo += '</div>'
1344 templateFiles.each{ templateFile ->
1345 def newFileName = string(hugoTemplateSubstitutions(templateFile.getName()))
1346 def relPath = hugoTemplatesDir.toPath().relativize(templateFile.toPath()).getParent()
1347 def newRelPathName = hugoTemplateSubstitutions( relPath.toString() )
1349 def outPathName = string("${hugoBuildDir}/$newRelPathName")
1353 rename(templateFile.getName(), newFileName)
1357 def newFile = file("${outPathName}/${newFileName}".toString())
1358 def content = newFile.text
1359 newFile.text = hugoTemplateSubstitutions(content,
1362 CHANGES: changesHugo,
1363 DATE: givenDate == null ? "" : givenDate.format("yyyy-MM-dd"),
1364 DRAFT: givenDate == null ? "true" : "false",
1365 JALVIEWJSLINK: jalviewjsLink.contains(JALVIEW_VERSION) ? "true" : "false",
1366 JVL_HEADER: oldJvl.contains(JALVIEW_VERSION) ? "jvl: true" : ""
1373 inputs.file(oldJvlFile)
1374 inputs.dir(hugoTemplatesDir)
1375 inputs.property("JALVIEW_VERSION", { JALVIEW_VERSION })
1376 inputs.property("CHANNEL", { CHANNEL })
1379 def getMdDate(File mdFile) {
1380 return mdFileComponents(mdFile, true)
1383 def getMdSections(String content) {
1385 def sectionContent = ""
1386 def sectionName = null
1387 content.eachLine { line ->
1389 if (m = line =~ /^##([^#].*)$/) {
1390 if (sectionName != null) {
1391 sections[sectionName] = sectionContent
1395 sectionName = m[0][1].trim()
1396 sectionName = sectionName.toLowerCase()
1397 sectionName = sectionName.replaceAll(/ +/, "_")
1398 sectionName = sectionName.replaceAll(/[^a-z0-9_\-]/, "")
1399 } else if (sectionName != null) {
1400 sectionContent += line+"\n"
1403 if (sectionContent != null) {
1404 sections[sectionName] = sectionContent
1408 task copyHelp(type: Copy) {
1409 def inputDir = helpSourceDir
1410 def outputDir = "${helpBuildDir}/${help_dir}"
1414 include('**/*.html')
1418 filter(ReplaceTokens,
1422 'Version-Rel': JALVIEW_VERSION,
1423 'Year-Rel': getDate("yyyy")
1430 exclude('**/*.html')
1437 inputs.dir(inputDir)
1438 outputs.files(helpFile)
1439 outputs.dir(outputDir)
1443 task releasesTemplates {
1445 description "Recreate whatsNew.html and releases.html from markdown files and templates in help"
1449 def releasesTemplateFile = file("${jalviewDir}/${releases_template}")
1450 def whatsnewTemplateFile = file("${jalviewDir}/${whatsnew_template}")
1451 def releasesHtmlFile = file("${helpBuildDir}/${help_dir}/${releases_html}")
1452 def whatsnewHtmlFile = file("${helpBuildDir}/${help_dir}/${whatsnew_html}")
1453 def releasesMdDir = "${jalviewDir}/${releases_dir}"
1454 def whatsnewMdDir = "${jalviewDir}/${whatsnew_dir}"
1457 def releaseMdFile = file("${releasesMdDir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1458 def whatsnewMdFile = file("${whatsnewMdDir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1460 if (CHANNEL == "RELEASE") {
1461 if (!releaseMdFile.exists()) {
1462 throw new GradleException("File ${releaseMdFile} must be created for RELEASE")
1464 if (!whatsnewMdFile.exists()) {
1465 throw new GradleException("File ${whatsnewMdFile} must be created for RELEASE")
1469 def releaseFiles = fileTree(dir: releasesMdDir, include: "release-*.md")
1470 def releaseFilesDates = releaseFiles.collectEntries {
1471 [(it): getMdDate(it)]
1473 releaseFiles = releaseFiles.sort { a,b -> releaseFilesDates[a].compareTo(releaseFilesDates[b]) }
1475 def releasesTemplate = releasesTemplateFile.text
1476 def m = releasesTemplate =~ /(?s)__VERSION_LOOP_START__(.*)__VERSION_LOOP_END__/
1477 def versionTemplate = m[0][1]
1479 MutableDataSet options = new MutableDataSet()
1481 def extensions = new ArrayList<>()
1482 options.set(Parser.EXTENSIONS, extensions)
1483 options.set(Parser.HTML_BLOCK_COMMENT_ONLY_FULL_LINE, true)
1485 Parser parser = Parser.builder(options).build()
1486 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1488 def actualVersions = releaseFiles.collect { rf ->
1489 def (rfMap, rfContent) = mdFileComponents(rf)
1490 return rfMap.version
1492 def versionsHtml = ""
1493 def linkedVersions = []
1494 releaseFiles.reverse().each { rFile ->
1495 def (rMap, rContent) = mdFileComponents(rFile)
1497 def versionLink = ""
1498 def partialVersion = ""
1499 def firstPart = true
1500 rMap.version.split("\\.").each { part ->
1501 def displayPart = ( firstPart ? "" : "." ) + part
1502 partialVersion += displayPart
1504 linkedVersions.contains(partialVersion)
1505 || ( actualVersions.contains(partialVersion) && partialVersion != rMap.version )
1507 versionLink += displayPart
1509 versionLink += "<a id=\"Jalview.${partialVersion}\">${displayPart}</a>"
1510 linkedVersions += partialVersion
1514 def displayDate = releaseFilesDates[rFile].format("dd/MM/yyyy")
1517 def rContentProcessed = ""
1518 rContent.eachLine { line ->
1519 if (lm = line =~ /^(\s*-)(\s*<!--[^>]*?-->)(.*)$/) {
1520 line = "${lm[0][1]}${lm[0][3]}${lm[0][2]}"
1521 } else if (lm = line =~ /^###([^#]+.*)$/) {
1522 line = "_${lm[0][1].trim()}_"
1524 rContentProcessed += line + "\n"
1527 def rContentSections = getMdSections(rContentProcessed)
1528 def rVersion = versionTemplate
1529 if (rVersion != "") {
1530 def rNewFeatures = rContentSections["new_features"]
1531 def rIssuesResolved = rContentSections["issues_resolved"]
1532 Node newFeaturesNode = parser.parse(rNewFeatures)
1533 String newFeaturesHtml = renderer.render(newFeaturesNode)
1534 Node issuesResolvedNode = parser.parse(rIssuesResolved)
1535 String issuesResolvedHtml = renderer.render(issuesResolvedNode)
1536 rVersion = hugoTemplateSubstitutions(rVersion,
1538 VERSION: rMap.version,
1539 VERSION_LINK: versionLink,
1540 DISPLAY_DATE: displayDate,
1541 NEW_FEATURES: newFeaturesHtml,
1542 ISSUES_RESOLVED: issuesResolvedHtml
1545 versionsHtml += rVersion
1549 releasesTemplate = releasesTemplate.replaceAll("(?s)__VERSION_LOOP_START__.*__VERSION_LOOP_END__", versionsHtml)
1550 releasesTemplate = hugoTemplateSubstitutions(releasesTemplate)
1551 releasesHtmlFile.text = releasesTemplate
1553 if (whatsnewMdFile.exists()) {
1554 def wnDisplayDate = releaseFilesDates[releaseMdFile] != null ? releaseFilesDates[releaseMdFile].format("dd MMMM yyyy") : ""
1555 def whatsnewMd = hugoTemplateSubstitutions(whatsnewMdFile.text)
1556 Node whatsnewNode = parser.parse(whatsnewMd)
1557 String whatsnewHtml = renderer.render(whatsnewNode)
1558 whatsnewHtml = whatsnewTemplateFile.text.replaceAll("__WHATS_NEW__", whatsnewHtml)
1559 whatsnewHtmlFile.text = hugoTemplateSubstitutions(whatsnewHtml,
1561 VERSION: JALVIEW_VERSION,
1562 DISPLAY_DATE: wnDisplayDate
1565 } else if (gradle.taskGraph.hasTask(":linkCheck")) {
1566 whatsnewHtmlFile.text = "Development build " + getDate("yyyy-MM-dd HH:mm:ss")
1571 inputs.file(releasesTemplateFile)
1572 inputs.file(whatsnewTemplateFile)
1573 inputs.dir(releasesMdDir)
1574 inputs.dir(whatsnewMdDir)
1575 outputs.file(releasesHtmlFile)
1576 outputs.file(whatsnewHtmlFile)
1578 task copyResources(type: Copy) {
1580 description = "Copy (and make text substitutions in) the resources dir to the build area"
1582 def inputDir = resourceDir
1583 def outputDir = resourcesBuildDir
1587 include('**/*.html')
1589 filter(ReplaceTokens,
1593 'Version-Rel': JALVIEW_VERSION,
1594 'Year-Rel': getDate("yyyy")
1601 exclude('**/*.html')
1606 inputs.dir(inputDir)
1607 outputs.dir(outputDir)
1610 task copyChannelResources(type: Copy) {
1611 dependsOn copyResources
1613 description = "Copy the channel resources dir to the build resources area"
1615 def inputDir = "${channelDir}/${resource_dir}"
1616 def outputDir = resourcesBuildDir
1620 inputs.dir(inputDir)
1621 outputs.dir(outputDir)
1624 task createBuildProperties(type: WriteProperties) {
1625 dependsOn copyResources
1627 description = "Create the ${buildProperties} file"
1629 inputs.dir(sourceDir)
1630 inputs.dir(resourcesBuildDir)
1631 outputFile (buildProperties)
1632 // taking time specific comment out to allow better incremental builds
1633 comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
1634 //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
1635 property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
1636 property "VERSION", JALVIEW_VERSION
1637 property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
1638 property "JAVA_COMPILE_VERSION", JAVA_INTEGER_VERSION
1639 if (getdownSetAppBaseProperty) {
1640 property "GETDOWNAPPBASE", getdownAppBase
1641 property "GETDOWNAPPDISTDIR", getdownAppDistDir
1643 outputs.file(outputFile)
1647 task buildIndices(type: JavaExec) {
1649 classpath = sourceSets.main.compileClasspath
1650 main = "com.sun.java.help.search.Indexer"
1651 workingDir = "${helpBuildDir}/${help_dir}"
1654 inputs.dir("${workingDir}/${argDir}")
1656 outputs.dir("${classesDir}/doc")
1657 outputs.dir("${classesDir}/help")
1658 outputs.file("${workingDir}/JavaHelpSearch/DOCS")
1659 outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
1660 outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
1661 outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
1662 outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
1663 outputs.file("${workingDir}/JavaHelpSearch/TMAP")
1666 task buildResources {
1667 dependsOn copyResources
1668 dependsOn copyChannelResources
1669 dependsOn createBuildProperties
1673 dependsOn buildResources
1676 dependsOn releasesTemplates
1677 dependsOn convertMdFiles
1678 dependsOn buildIndices
1682 compileJava.dependsOn prepare
1683 run.dependsOn compileJava
1684 //run.dependsOn prepare
1687 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1692 dependsOn cloverClasses
1694 dependsOn compileJava //?
1698 includeGroups testng_groups
1699 excludeGroups testng_excluded_groups
1701 useDefaultListeners=true
1704 maxHeapSize = "1024m"
1706 workingDir = jalviewDir
1707 def testLaf = project.findProperty("test_laf")
1708 if (testLaf != null) {
1709 println("Setting Test LaF to '${testLaf}'")
1710 systemProperty "laf", testLaf
1712 def testHiDPIScale = project.findProperty("test_HiDPIScale")
1713 if (testHiDPIScale != null) {
1714 println("Setting Test HiDPI Scale to '${testHiDPIScale}'")
1715 systemProperty "sun.java2d.uiScale", testHiDPIScale
1717 sourceCompatibility = compile_source_compatibility
1718 targetCompatibility = compile_target_compatibility
1719 jvmArgs += additional_compiler_args
1723 println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1729 task compileLinkCheck(type: JavaCompile) {
1731 classpath = files("${jalviewDir}/${utils_dir}")
1732 destinationDir = file("${jalviewDir}/${utils_dir}")
1733 source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1735 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1736 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1737 outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1738 outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1742 task linkCheck(type: JavaExec) {
1744 dependsOn compileLinkCheck
1746 def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1747 classpath = files("${jalviewDir}/${utils_dir}")
1748 main = "HelpLinksChecker"
1749 workingDir = "${helpBuildDir}"
1750 args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1752 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1753 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1756 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1760 inputs.dir(helpBuildDir)
1761 outputs.file(helpLinksCheckerOutFile)
1765 // import the pubhtmlhelp target
1766 ant.properties.basedir = "${jalviewDir}"
1767 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1768 ant.importBuild "${utils_dir}/publishHelp.xml"
1771 task cleanPackageDir(type: Delete) {
1773 delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1783 attributes "Main-Class": main_class,
1784 "Permissions": "all-permissions",
1785 "Application-Name": applicationName,
1786 "Codebase": application_codebase,
1787 "Implementation-Version": JALVIEW_VERSION
1790 def outputDir = "${jalviewDir}/${package_dir}"
1791 destinationDirectory = file(outputDir)
1792 archiveFileName = rootProject.name+".jar"
1793 duplicatesStrategy "EXCLUDE"
1800 exclude "**/*.jar.*"
1802 inputs.dir(sourceSets.main.java.outputDir)
1803 sourceSets.main.resources.srcDirs.each{ dir ->
1806 outputs.file("${outputDir}/${archiveFileName}")
1810 task copyJars(type: Copy) {
1811 from fileTree(dir: classesDir, include: "**/*.jar").files
1812 into "${jalviewDir}/${package_dir}"
1816 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1817 task syncJars(type: Sync) {
1819 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1820 into "${jalviewDir}/${package_dir}"
1822 include jar.archiveFileName.getOrNull()
1829 description = "Put all required libraries in dist"
1830 // order of "cleanPackageDir", "copyJars", "jar" important!
1831 jar.mustRunAfter cleanPackageDir
1832 syncJars.mustRunAfter cleanPackageDir
1833 dependsOn cleanPackageDir
1836 outputs.dir("${jalviewDir}/${package_dir}")
1841 dependsOn cleanPackageDir
1848 group = "distribution"
1849 description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1853 from ("${jalviewDir}/${libDistDir}") {
1857 attributes "Implementation-Version": JALVIEW_VERSION,
1858 "Application-Name": applicationName
1861 duplicatesStrategy "INCLUDE"
1863 mainClassName = shadow_jar_main_class
1865 classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1870 task getdownWebsite() {
1871 group = "distribution"
1872 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1877 def getdownWebsiteResourceFilenames = []
1878 def getdownResourceDir = getdownResourceDir
1879 def getdownResourceFilenames = []
1882 // clean the getdown website and files dir before creating getdown folders
1883 delete getdownAppBaseDir
1884 delete getdownFilesDir
1887 from buildProperties
1888 rename(file(buildProperties).getName(), getdown_build_properties)
1891 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1894 from channelPropsFile
1895 into getdownAppBaseDir
1897 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
1899 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
1900 def props = project.properties.sort { it.key }
1901 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
1902 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
1904 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
1905 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
1907 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
1908 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
1910 if (getdownImagesDir != null && file(getdownImagesDir).exists()) {
1911 props.put("getdown_txt_ui.background_image", "${getdownImagesDir}/${getdown_background_image}")
1912 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesDir}/${getdown_instant_background_image}")
1913 props.put("getdown_txt_ui.error_background", "${getdownImagesDir}/${getdown_error_background}")
1914 props.put("getdown_txt_ui.progress_image", "${getdownImagesDir}/${getdown_progress_image}")
1915 props.put("getdown_txt_ui.icon", "${getdownImagesDir}/${getdown_icon}")
1916 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesDir}/${getdown_mac_dock_icon}")
1919 props.put("getdown_txt_title", jalview_name)
1920 props.put("getdown_txt_ui.name", applicationName)
1922 // start with appbase
1923 getdownTextLines += "appbase = ${getdownAppBase}"
1924 props.each{ prop, val ->
1925 if (prop.startsWith("getdown_txt_") && val != null) {
1926 if (prop.startsWith("getdown_txt_multi_")) {
1927 def key = prop.substring(18)
1928 val.split(",").each{ v ->
1929 def line = "${key} = ${v}"
1930 getdownTextLines += line
1933 // file values rationalised
1934 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
1936 if (val.indexOf('/') == 0) {
1939 } else if (val.indexOf('/') > 0) {
1940 // relative path (relative to jalviewDir)
1941 r = file( "${jalviewDir}/${val}" )
1944 val = "${getdown_resource_dir}/" + r.getName()
1945 getdownWebsiteResourceFilenames += val
1946 getdownResourceFilenames += r.getPath()
1949 if (! prop.startsWith("getdown_txt_resource")) {
1950 def line = prop.substring(12) + " = ${val}"
1951 getdownTextLines += line
1957 getdownWebsiteResourceFilenames.each{ filename ->
1958 getdownTextLines += "resource = ${filename}"
1960 getdownResourceFilenames.each{ filename ->
1963 into getdownResourceDir
1967 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
1968 getdownWrapperScripts.each{ script ->
1969 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
1973 into "${getdownAppBaseDir}/${getdown_wrapper_script_dir}"
1975 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
1980 fileTree(file(package_dir)).each{ f ->
1981 if (f.isDirectory()) {
1982 def files = fileTree(dir: f, include: ["*"]).getFiles()
1984 } else if (f.exists()) {
1988 def jalviewJar = jar.archiveFileName.getOrNull()
1989 // put jalview.jar first for CLASSPATH and .properties files reasons
1990 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
1991 def name = f.getName()
1992 def line = "code = ${getdownAppDistDir}/${name}"
1993 getdownTextLines += line
2000 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
2002 if (JAVA_VERSION.equals("11")) {
2003 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
2004 j11libFiles.sort().each{f ->
2005 def name = f.getName()
2006 def line = "code = ${getdown_j11lib_dir}/${name}"
2007 getdownTextLines += line
2010 into getdownJ11libDir
2016 // 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.
2017 //getdownTextLines += "class = " + file(getdownLauncher).getName()
2018 getdownTextLines += "resource = ${getdown_launcher_new}"
2019 getdownTextLines += "class = ${main_class}"
2020 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
2021 if (getdownSetAppBaseProperty) {
2022 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
2023 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
2026 def getdownTxt = file("${getdownAppBaseDir}/getdown.txt")
2027 getdownTxt.write(getdownTextLines.join("\n"))
2029 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
2030 def launchJvl = file("${getdownAppBaseDir}/${getdownLaunchJvl}")
2031 launchJvl.write("appbase=${getdownAppBase}")
2033 // files going into the getdown website dir: getdown-launcher.jar
2035 from getdownLauncher
2036 rename(file(getdownLauncher).getName(), getdown_launcher_new)
2037 into getdownAppBaseDir
2040 // files going into the getdown website dir: getdown-launcher(-local).jar
2042 from getdownLauncher
2043 if (file(getdownLauncher).getName() != getdown_launcher) {
2044 rename(file(getdownLauncher).getName(), getdown_launcher)
2046 into getdownAppBaseDir
2049 // files going into the getdown website dir: ./install dir and files
2050 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
2053 from getdownLauncher
2054 from "${getdownAppDir}/${getdown_build_properties}"
2055 if (file(getdownLauncher).getName() != getdown_launcher) {
2056 rename(file(getdownLauncher).getName(), getdown_launcher)
2058 into getdownInstallDir
2061 // and make a copy in the getdown files dir (these are not downloaded by getdown)
2063 from getdownInstallDir
2064 into getdownFilesInstallDir
2068 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2072 from getdownLauncher
2073 from "${getdownAppBaseDir}/${getdown_build_properties}"
2074 from "${getdownAppBaseDir}/${channel_props}"
2075 if (file(getdownLauncher).getName() != getdown_launcher) {
2076 rename(file(getdownLauncher).getName(), getdown_launcher)
2078 into getdownFilesDir
2081 // and ./resource (not all downloaded by getdown)
2083 from getdownResourceDir
2084 into "${getdownFilesDir}/${getdown_resource_dir}"
2089 inputs.dir("${jalviewDir}/${package_dir}")
2091 outputs.dir(getdownAppBaseDir)
2092 outputs.dir(getdownFilesDir)
2096 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
2097 task getdownDigestDir(type: JavaExec) {
2099 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
2101 def digestDirPropertyName = "DIGESTDIR"
2103 classpath = files(getdownLauncher)
2104 def digestDir = findProperty(digestDirPropertyName)
2105 if (digestDir == null) {
2106 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
2110 main = "com.threerings.getdown.tools.Digester"
2114 task getdownDigest(type: JavaExec) {
2115 group = "distribution"
2116 description = "Digest the getdown website folder"
2117 dependsOn getdownWebsite
2119 classpath = files(getdownLauncher)
2121 main = "com.threerings.getdown.tools.Digester"
2122 args getdownAppBaseDir
2123 inputs.dir(getdownAppBaseDir)
2124 outputs.file("${getdownAppBaseDir}/digest2.txt")
2129 group = "distribution"
2130 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
2131 dependsOn getdownDigest
2133 if (reportRsyncCommand) {
2134 def fromDir = getdownAppBaseDir + (getdownAppBaseDir.endsWith('/')?'':'/')
2135 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
2136 println "LIKELY RSYNC COMMAND:"
2137 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
2138 if (RUNRSYNC == "true") {
2140 commandLine "mkdir", "-p", toDir
2143 commandLine "rsync", "-avh", "--delete", fromDir, toDir
2151 task getdownArchiveBuild() {
2152 group = "distribution"
2153 description = "Put files in the archive dir to go on the website"
2155 dependsOn getdownWebsite
2157 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
2158 def vDir = "${getdownArchiveDir}/${v}"
2159 getdownFullArchiveDir = "${vDir}/getdown"
2160 getdownVersionLaunchJvl = "${vDir}/jalview-${v}.jvl"
2162 def vAltDir = "alt_${v}"
2163 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
2166 // cleanup old "old" dir
2167 delete getdownArchiveDir
2169 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
2170 getdownArchiveTxt.getParentFile().mkdirs()
2171 def getdownArchiveTextLines = []
2172 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
2176 from "${getdownAppBaseDir}/${getdownAppDistDir}"
2177 into "${getdownFullArchiveDir}/${vAltDir}"
2180 getdownTextLines.each { line ->
2181 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
2182 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
2183 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
2184 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
2185 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
2186 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
2187 // remove the existing resource = resource/ or bin/ lines
2188 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
2189 getdownArchiveTextLines += line
2193 // the resource dir -- add these files as resource lines in getdown.txt
2195 from "${archiveImagesDir}"
2196 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
2198 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
2202 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
2204 def vLaunchJvl = file(getdownVersionLaunchJvl)
2205 vLaunchJvl.getParentFile().mkdirs()
2206 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
2207 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
2208 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
2209 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
2210 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
2211 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
2213 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2215 from getdownLauncher
2216 from "${getdownAppBaseDir}/${getdownLaunchJvl}"
2217 from "${getdownAppBaseDir}/${getdown_launcher_new}"
2218 from "${getdownAppBaseDir}/${channel_props}"
2219 if (file(getdownLauncher).getName() != getdown_launcher) {
2220 rename(file(getdownLauncher).getName(), getdown_launcher)
2222 into getdownFullArchiveDir
2228 task getdownArchiveDigest(type: JavaExec) {
2229 group = "distribution"
2230 description = "Digest the getdown archive folder"
2232 dependsOn getdownArchiveBuild
2235 classpath = files(getdownLauncher)
2236 args getdownFullArchiveDir
2238 main = "com.threerings.getdown.tools.Digester"
2239 inputs.dir(getdownFullArchiveDir)
2240 outputs.file("${getdownFullArchiveDir}/digest2.txt")
2243 task getdownArchive() {
2244 group = "distribution"
2245 description = "Build the website archive dir with getdown digest"
2247 dependsOn getdownArchiveBuild
2248 dependsOn getdownArchiveDigest
2250 tasks.withType(JavaCompile) {
2251 options.encoding = 'UTF-8'
2257 delete getdownAppBaseDir
2258 delete getdownFilesDir
2259 delete getdownArchiveDir
2265 if (file(install4jHomeDir).exists()) {
2267 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
2268 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
2269 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
2270 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
2272 installDir(file(install4jHomeDir))
2274 mediaTypes = Arrays.asList(install4j_media_types.split(","))
2278 task copyInstall4jTemplate {
2279 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
2280 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
2281 inputs.file(install4jTemplateFile)
2282 inputs.file(install4jFileAssociationsFile)
2283 inputs.property("CHANNEL", { CHANNEL })
2284 outputs.file(install4jConfFile)
2287 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
2289 // turn off code signing if no OSX_KEYPASS
2290 if (OSX_KEYPASS == "") {
2291 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
2292 codeSigning.'@macEnabled' = "false"
2294 install4jConfigXml.'**'.windows.each { windows ->
2295 windows.'@runPostProcessor' = "false"
2299 // disable install screen for OSX dmg (for 2.11.2.0)
2300 install4jConfigXml.'**'.macosArchive.each { macosArchive ->
2301 macosArchive.attributes().remove('executeSetupApp')
2302 macosArchive.attributes().remove('setupAppId')
2304 // turn off checksum creation for LOCAL channel
2305 def e = install4jConfigXml.application[0]
2306 e.'@createChecksums' = string(install4jCheckSums)
2308 // put file association actions where placeholder action is
2309 def install4jFileAssociationsText = install4jFileAssociationsFile.text
2310 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
2311 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
2312 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
2313 def parent = a.parent()
2315 fileAssociationActions.each { faa ->
2318 // don't need to continue in .any loop once replacements have been made
2323 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
2324 // NB we're deleting the /other/ one!
2325 // Also remove the examples subdir from non-release versions
2326 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
2327 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
2328 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
2329 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
2331 // remove the examples subdir from Full File Set
2332 def files = install4jConfigXml.files[0]
2333 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
2334 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
2335 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
2336 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
2337 dirEntry.parent().remove(dirEntry)
2339 install4jConfigXml.'**'.action.any { a ->
2340 if (a.'@customizedId' == customizedIdToDelete) {
2341 def parent = a.parent()
2347 // write install4j file
2348 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
2355 delete install4jConfFile
2359 task cleanInstallersDataFiles {
2360 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2361 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2362 def hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
2364 delete installersOutputTxt
2365 delete installersSha256
2366 delete hugoDataJsonFile
2370 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2371 group = "distribution"
2372 description = "Create the install4j installers"
2374 dependsOn copyInstall4jTemplate
2375 dependsOn cleanInstallersDataFiles
2377 projectFile = install4jConfFile
2379 // create an md5 for the input files to use as version for install4j conf file
2380 def digest = MessageDigest.getInstance("MD5")
2382 (file("${install4jDir}/${install4j_template}").text +
2383 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2384 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2385 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2386 if (filesMd5.length() >= 8) {
2387 filesMd5 = filesMd5.substring(0,8)
2389 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2392 'JALVIEW_NAME': jalview_name,
2393 'JALVIEW_APPLICATION_NAME': applicationName,
2394 'JALVIEW_DIR': "../..",
2395 'OSX_KEYSTORE': OSX_KEYSTORE,
2396 'OSX_APPLEID': OSX_APPLEID,
2397 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2398 'JSIGN_SH': JSIGN_SH,
2399 'JRE_DIR': getdown_app_dir_java,
2400 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2401 'JALVIEW_VERSION': JALVIEW_VERSION,
2402 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2403 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2404 'JAVA_VERSION': JAVA_VERSION,
2405 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2406 'VERSION': JALVIEW_VERSION,
2407 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2408 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2409 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2410 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2411 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2412 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2413 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2414 'BUNDLE_ID': install4jBundleId,
2415 'INTERNAL_ID': install4jInternalId,
2416 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2417 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2418 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
2419 'WRAPPER_LINK': getdownWrapperLink,
2420 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2421 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2422 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2423 'INSTALLER_NAME': install4jInstallerName,
2424 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2425 'GETDOWN_CHANNEL_DIR': getdownChannelDir,
2426 'GETDOWN_FILES_DIR': getdown_files_dir,
2427 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2428 'GETDOWN_DIST_DIR': getdownAppDistDir,
2429 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2430 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2431 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2432 'BUILD_DIR': install4jBuildDir,
2433 'APPLICATION_CATEGORIES': install4j_application_categories,
2434 'APPLICATION_FOLDER': install4jApplicationFolder,
2435 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2436 'EXECUTABLE_NAME': install4jExecutableName,
2437 'EXTRA_SCHEME': install4jExtraScheme,
2438 'MAC_ICONS_FILE': install4jMacIconsFile,
2439 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2440 'PNG_ICON_FILE': install4jPngIconFile,
2441 'BACKGROUND': install4jBackground,
2445 //println("INSTALL4J VARIABLES:")
2446 //variables.each{k,v->println("${k}=${v}")}
2448 destination = "${jalviewDir}/${install4jBuildDir}"
2449 buildSelected = true
2451 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2453 disableSigning = true
2454 disableNotarization = true
2458 macKeystorePassword = OSX_KEYPASS
2461 if (OSX_ALTOOLPASS) {
2462 appleIdPassword = OSX_ALTOOLPASS
2463 disableNotarization = false
2465 disableNotarization = true
2469 println("Using projectFile "+projectFile)
2470 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2474 inputs.dir(getdownAppBaseDir)
2475 inputs.file(install4jConfFile)
2476 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2477 inputs.dir(macosJavaVMDir)
2478 inputs.dir(windowsJavaVMDir)
2479 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2482 def getDataHash(File myFile) {
2483 HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
2484 return myFile.exists()
2486 "file" : myFile.getName(),
2487 "filesize" : myFile.length(),
2488 "sha256" : hash.toString()
2493 def writeDataJsonFile(File installersOutputTxt, File installersSha256, File dataJsonFile) {
2495 "channel" : getdownChannelName,
2496 "date" : getDate("yyyy-MM-dd HH:mm:ss"),
2497 "git-commit" : "${gitHash} [${gitBranch}]",
2498 "version" : JALVIEW_VERSION
2500 // install4j installer files
2501 if (installersOutputTxt.exists()) {
2503 installersOutputTxt.readLines().each { def line ->
2504 if (line.startsWith("#")) {
2507 line.replaceAll("\n","")
2508 def vals = line.split("\t")
2509 def filename = vals[3]
2510 def filesize = file(filename).length()
2511 filename = filename.replaceAll(/^.*\//, "")
2512 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2513 idHash."${filename}" = vals[0]
2515 if (install4jCheckSums && installersSha256.exists()) {
2516 installersSha256.readLines().each { def line ->
2517 if (line.startsWith("#")) {
2520 line.replaceAll("\n","")
2521 def vals = line.split(/\s+\*?/)
2522 def filename = vals[1]
2523 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2529 "JAR": shadowJar.archiveFile, // executable JAR
2530 "JVL": getdownVersionLaunchJvl, // version JVL
2531 "SOURCE": sourceDist.archiveFile // source TGZ
2532 ].each { key, value ->
2533 def file = file(value)
2534 if (file.exists()) {
2535 def fileHash = getDataHash(file)
2536 if (fileHash != null) {
2537 hash."${key}" = fileHash;
2541 return dataJsonFile.write(new JsonBuilder(hash).toPrettyString())
2544 task staticMakeInstallersJsonFile {
2546 def output = findProperty("i4j_output")
2547 def sha256 = findProperty("i4j_sha256")
2548 def json = findProperty("i4j_json")
2549 if (output == null || sha256 == null || json == null) {
2550 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2552 writeDataJsonFile(file(output), file(sha256), file(json))
2557 dependsOn installerFiles
2562 eclipse().configFile(eclipse_codestyle_file)
2566 task createSourceReleaseProperties(type: WriteProperties) {
2567 group = "distribution"
2568 description = "Create the source RELEASE properties file"
2570 def sourceTarBuildDir = "${buildDir}/sourceTar"
2571 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2572 outputFile (sourceReleasePropertiesFile)
2575 releaseProps.each{ key, val -> property key, val }
2576 property "git.branch", gitBranch
2577 property "git.hash", gitHash
2580 outputs.file(outputFile)
2583 task sourceDist(type: Tar) {
2584 group "distribution"
2585 description "Create a source .tar.gz file for distribution"
2587 dependsOn createBuildProperties
2588 dependsOn convertMdFiles
2589 dependsOn eclipseAllPreferences
2590 dependsOn createSourceReleaseProperties
2593 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2594 archiveFileName = outputFileName
2596 compression Compression.GZIP
2611 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2613 "utils/InstallAnywhere",
2628 "gradle.properties",
2640 ".settings/org.eclipse.buildship.core.prefs",
2641 ".settings/org.eclipse.jdt.core.prefs"
2645 exclude (EXCLUDE_FILES)
2646 include (PROCESS_FILES)
2647 filter(ReplaceTokens,
2651 'Version-Rel': JALVIEW_VERSION,
2652 'Year-Rel': getDate("yyyy")
2657 exclude (EXCLUDE_FILES)
2658 exclude (PROCESS_FILES)
2659 exclude ("appletlib")
2660 exclude ("**/*locales")
2661 exclude ("*locales/**")
2662 exclude ("utils/InstallAnywhere")
2664 exclude (getdown_files_dir)
2665 // getdown_website_dir and getdown_archive_dir moved to build/website/docroot/getdown
2666 //exclude (getdown_website_dir)
2667 //exclude (getdown_archive_dir)
2669 // exluding these as not using jars as modules yet
2670 exclude ("${j11modDir}/**/*.jar")
2673 include(INCLUDE_FILES)
2675 // from (jalviewDir) {
2676 // // explicit includes for stuff that seemed to not get included
2677 // include(fileTree("test/**/*."))
2678 // exclude(EXCLUDE_FILES)
2679 // exclude(PROCESS_FILES)
2682 from(file(buildProperties).getParent()) {
2683 include(file(buildProperties).getName())
2684 rename(file(buildProperties).getName(), "build_properties")
2686 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2690 def sourceTarBuildDir = "${buildDir}/sourceTar"
2691 from(sourceTarBuildDir) {
2692 // this includes the appended RELEASE properties file
2696 task dataInstallersJson {
2698 description "Create the installers-VERSION.json data file for installer files created"
2700 mustRunAfter installers
2701 mustRunAfter shadowJar
2702 mustRunAfter sourceDist
2703 mustRunAfter getdownArchive
2705 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2706 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2708 if (installersOutputTxt.exists()) {
2709 inputs.file(installersOutputTxt)
2711 if (install4jCheckSums && installersSha256.exists()) {
2712 inputs.file(installersSha256)
2715 shadowJar.archiveFile, // executable JAR
2716 getdownVersionLaunchJvl, // version JVL
2717 sourceDist.archiveFile // source TGZ
2718 ].each { fileName ->
2719 if (file(fileName).exists()) {
2720 inputs.file(fileName)
2724 outputs.file(hugoDataJsonFile)
2727 writeDataJsonFile(installersOutputTxt, installersSha256, hugoDataJsonFile)
2733 description "Copies all help pages to build dir. Runs ant task 'pubhtmlhelp'."
2735 dependsOn pubhtmlhelp
2737 inputs.dir("${helpBuildDir}/${help_dir}")
2738 outputs.dir("${buildDir}/distributions/${help_dir}")
2742 task j2sSetHeadlessBuild {
2749 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2751 description "Enable the alternative J2S Config file for headless build"
2753 outputFile = jalviewjsJ2sSettingsFileName
2754 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2755 def j2sProps = new Properties()
2756 if (j2sPropsFile.exists()) {
2758 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2759 j2sProps.load(j2sPropsFileFIS)
2760 j2sPropsFileFIS.close()
2762 j2sProps.each { prop, val ->
2765 } catch (Exception e) {
2766 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2770 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2771 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2776 task jalviewjsSetEclipseWorkspace {
2777 def propKey = "jalviewjs_eclipse_workspace"
2779 if (project.hasProperty(propKey)) {
2780 propVal = project.getProperty(propKey)
2781 if (propVal.startsWith("~/")) {
2782 propVal = System.getProperty("user.home") + propVal.substring(1)
2785 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2786 def propsFile = file(propsFileName)
2787 def eclipseWsDir = propVal
2788 def props = new Properties()
2790 def writeProps = true
2791 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2792 def ins = new FileInputStream(propsFileName)
2795 if (props.getProperty(propKey, null) != null) {
2796 eclipseWsDir = props.getProperty(propKey)
2801 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2802 def tempDir = File.createTempDir()
2803 eclipseWsDir = tempDir.getAbsolutePath()
2806 eclipseWorkspace = file(eclipseWsDir)
2809 // do not run a headless transpile when we claim to be in Eclipse
2811 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2812 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2814 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2818 props.setProperty(propKey, eclipseWsDir)
2819 propsFile.parentFile.mkdirs()
2820 def bytes = new ByteArrayOutputStream()
2821 props.store(bytes, null)
2822 def propertiesString = bytes.toString()
2823 propsFile.text = propertiesString
2829 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2832 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2833 outputs.file(propsFileName)
2834 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2838 task jalviewjsEclipsePaths {
2841 def eclipseRoot = jalviewjs_eclipse_root
2842 if (eclipseRoot.startsWith("~/")) {
2843 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
2845 if (OperatingSystem.current().isMacOsX()) {
2846 eclipseRoot += "/Eclipse.app"
2847 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
2848 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
2849 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
2850 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2851 eclipseRoot += "/eclipse"
2853 eclipseBinary = "${eclipseRoot}/eclipse.exe"
2854 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2855 } else { // linux or unix
2856 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2857 eclipseRoot += "/eclipse"
2858 println("eclipseDir exists")
2860 eclipseBinary = "${eclipseRoot}/eclipse"
2861 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2864 eclipseVersion = "4.13" // default
2865 def assumedVersion = true
2866 if (file(eclipseProduct).exists()) {
2867 def fis = new FileInputStream(eclipseProduct)
2868 def props = new Properties()
2870 eclipseVersion = props.getProperty("version")
2872 assumedVersion = false
2875 def propKey = "eclipse_debug"
2876 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
2879 // do not run a headless transpile when we claim to be in Eclipse
2881 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2882 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2884 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2887 if (!assumedVersion) {
2888 println("ECLIPSE VERSION=${eclipseVersion}")
2894 task printProperties {
2896 description "Output to console all System.properties"
2898 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
2904 dependsOn eclipseProject
2905 dependsOn eclipseClasspath
2906 dependsOn eclipseJdt
2910 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
2911 task jalviewjsEclipseCopyDropins(type: Copy) {
2912 dependsOn jalviewjsEclipsePaths
2914 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
2915 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
2916 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
2923 // this eclipse -clean doesn't actually work
2924 task jalviewjsCleanEclipse(type: Exec) {
2925 dependsOn eclipseSetup
2926 dependsOn jalviewjsEclipsePaths
2927 dependsOn jalviewjsEclipseCopyDropins
2929 executable(eclipseBinary)
2930 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
2936 def inputString = """exit
2939 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
2940 standardInput = inputByteStream
2943 /* not really working yet
2944 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
2948 task jalviewjsTransferUnzipSwingJs {
2949 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
2953 from zipTree(file_zip)
2954 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2958 inputs.file file_zip
2959 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2963 task jalviewjsTransferUnzipLib {
2964 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
2967 zipFiles.each { file_zip ->
2969 from zipTree(file_zip)
2970 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2975 inputs.files zipFiles
2976 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2980 task jalviewjsTransferUnzipAllLibs {
2981 dependsOn jalviewjsTransferUnzipSwingJs
2982 dependsOn jalviewjsTransferUnzipLib
2986 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
2988 description "Create the alternative j2s file from the j2s.* properties"
2990 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
2991 def siteDirProperty = "j2s.site.directory"
2992 def setSiteDir = false
2993 jalviewjsJ2sProps.each { prop, val ->
2995 if (prop == siteDirProperty) {
2996 if (!(val.startsWith('/') || val.startsWith("file://") )) {
2997 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
3003 if (!setSiteDir) { // default site location, don't override specifically set property
3004 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
3007 outputFile = jalviewjsJ2sAltSettingsFileName
3010 inputs.properties(jalviewjsJ2sProps)
3011 outputs.file(jalviewjsJ2sAltSettingsFileName)
3016 task jalviewjsEclipseSetup {
3017 dependsOn jalviewjsEclipseCopyDropins
3018 dependsOn jalviewjsSetEclipseWorkspace
3019 dependsOn jalviewjsCreateJ2sSettings
3023 task jalviewjsSyncAllLibs (type: Sync) {
3024 dependsOn jalviewjsTransferUnzipAllLibs
3025 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
3026 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
3027 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3031 def outputFiles = []
3032 rename { filename ->
3033 outputFiles += "${outputDir}/${filename}"
3040 // should this be exclude really ?
3041 duplicatesStrategy "INCLUDE"
3043 outputs.files outputFiles
3044 inputs.files inputFiles
3048 task jalviewjsSyncResources (type: Sync) {
3049 dependsOn buildResources
3051 def inputFiles = fileTree(dir: resourcesBuildDir)
3052 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3056 def outputFiles = []
3057 rename { filename ->
3058 outputFiles += "${outputDir}/${filename}"
3064 outputs.files outputFiles
3065 inputs.files inputFiles
3069 task jalviewjsSyncSiteResources (type: Sync) {
3070 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
3071 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3075 def outputFiles = []
3076 rename { filename ->
3077 outputFiles += "${outputDir}/${filename}"
3083 outputs.files outputFiles
3084 inputs.files inputFiles
3088 task jalviewjsSyncBuildProperties (type: Sync) {
3089 dependsOn createBuildProperties
3090 def inputFiles = [file(buildProperties)]
3091 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3095 def outputFiles = []
3096 rename { filename ->
3097 outputFiles += "${outputDir}/${filename}"
3103 outputs.files outputFiles
3104 inputs.files inputFiles
3108 task jalviewjsProjectImport(type: Exec) {
3109 dependsOn eclipseSetup
3110 dependsOn jalviewjsEclipsePaths
3111 dependsOn jalviewjsEclipseSetup
3114 // do not run a headless import when we claim to be in Eclipse
3116 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3117 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3119 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3123 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
3124 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
3125 executable(eclipseBinary)
3126 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
3130 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3132 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3133 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3136 inputs.file("${jalviewDir}/.project")
3137 outputs.upToDateWhen {
3138 file(projdir).exists()
3143 task jalviewjsTranspile(type: Exec) {
3144 dependsOn jalviewjsEclipseSetup
3145 dependsOn jalviewjsProjectImport
3146 dependsOn jalviewjsEclipsePaths
3148 dependsOn jalviewjsEnableAltFileProperty
3152 // do not run a headless transpile when we claim to be in Eclipse
3154 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3155 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3157 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3161 executable(eclipseBinary)
3162 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
3166 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3168 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3169 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3175 stdout = new ByteArrayOutputStream()
3176 stderr = new ByteArrayOutputStream()
3178 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
3179 def logOutFile = file(logOutFileName)
3180 logOutFile.createNewFile()
3181 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
3182 BINARY: ${eclipseBinary}
3183 VERSION: ${eclipseVersion}
3184 WORKSPACE: ${eclipseWorkspace}
3185 DEBUG: ${eclipseDebug}
3188 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3189 // combine stdout and stderr
3190 def logErrFOS = logOutFOS
3192 if (jalviewjs_j2s_to_console.equals("true")) {
3193 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3194 new org.apache.tools.ant.util.TeeOutputStream(
3198 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3199 new org.apache.tools.ant.util.TeeOutputStream(
3204 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3207 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3214 if (stdout.toString().contains("Error processing ")) {
3215 // j2s did not complete transpile
3216 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3217 if (jalviewjs_ignore_transpile_errors.equals("true")) {
3218 println("IGNORING TRANSPILE ERRORS")
3219 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3221 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3226 inputs.dir("${jalviewDir}/${sourceDir}")
3227 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
3228 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
3232 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
3234 def stdout = new ByteArrayOutputStream()
3235 def stderr = new ByteArrayOutputStream()
3237 def coreFile = file(jsfile)
3239 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
3241 logOutFile.createNewFile()
3242 logOutFile.append(msg+"\n")
3244 def coreTop = file(prefixFile)
3245 def coreBottom = file(suffixFile)
3246 coreFile.getParentFile().mkdirs()
3247 coreFile.createNewFile()
3248 coreFile.write( coreTop.getText("UTF-8") )
3252 def t = f.getText("UTF-8")
3253 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
3254 coreFile.append( t )
3256 msg = "...file '"+f.getPath()+"' does not exist, skipping"
3258 logOutFile.append(msg+"\n")
3261 coreFile.append( coreBottom.getText("UTF-8") )
3263 msg = "Generating ${zjsfile}"
3265 logOutFile.append(msg+"\n")
3266 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3267 def logErrFOS = logOutFOS
3270 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
3271 main = "com.google.javascript.jscomp.CommandLineRunner"
3272 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
3273 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
3276 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
3278 logOutFile.append(msg+"\n")
3280 if (logOutConsole) {
3281 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3282 new org.apache.tools.ant.util.TeeOutputStream(
3286 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3287 new org.apache.tools.ant.util.TeeOutputStream(
3292 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3295 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3302 logOutFile.append(msg+"\n")
3306 task jalviewjsBuildAllCores {
3308 description "Build the core js lib closures listed in the classlists dir"
3309 dependsOn jalviewjsTranspile
3310 dependsOn jalviewjsTransferUnzipSwingJs
3312 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
3313 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
3314 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
3315 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
3316 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
3317 def prefixFile = "${jsDir}/core/coretop2.js"
3318 def suffixFile = "${jsDir}/core/corebottom2.js"
3320 inputs.file prefixFile
3321 inputs.file suffixFile
3323 def classlistFiles = []
3324 // add the classlists found int the jalviewjs_classlists_dir
3325 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
3327 def name = file.getName() - ".txt"
3334 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
3335 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
3336 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
3338 jalviewjsCoreClasslists = []
3340 classlistFiles.each {
3343 def file = hash['file']
3344 if (! file.exists()) {
3345 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
3346 return false // this is a "continue" in groovy .each closure
3348 def name = hash['name']
3350 name = file.getName() - ".txt"
3358 def list = fileTree(dir: j2sDir, includes: filelist)
3360 def jsfile = "${outputDir}/core${name}.js"
3361 def zjsfile = "${outputDir}/core${name}.z.js"
3363 jalviewjsCoreClasslists += [
3372 outputs.file(jsfile)
3373 outputs.file(zjsfile)
3376 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
3377 def stevesoftClasslistName = "_stevesoft"
3378 def stevesoftClasslist = [
3379 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
3380 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
3381 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
3382 'name': stevesoftClasslistName
3384 jalviewjsCoreClasslists += stevesoftClasslist
3385 inputs.files(stevesoftClasslist['list'])
3386 outputs.file(stevesoftClasslist['jsfile'])
3387 outputs.file(stevesoftClasslist['zjsfile'])
3390 def allClasslistName = "_all"
3391 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3392 allJsFiles += fileTree(
3396 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3397 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3398 "**/org/jmol/export/JSExporter.js"
3401 allJsFiles += fileTree(
3405 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3406 "**/sun/misc/Unsafe.js",
3407 "**/swingjs/jquery/jquery-editable-select.js",
3408 "**/swingjs/jquery/j2sComboBox.js",
3409 "**/sun/misc/FloatingDecimal.js"
3412 def allClasslist = [
3413 'jsfile': "${outputDir}/core${allClasslistName}.js",
3414 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
3416 'name': allClasslistName
3418 // not including this version of "all" core at the moment
3419 //jalviewjsCoreClasslists += allClasslist
3420 inputs.files(allClasslist['list'])
3421 outputs.file(allClasslist['jsfile'])
3422 outputs.file(allClasslist['zjsfile'])
3425 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3426 logOutFile.getParentFile().mkdirs()
3427 logOutFile.createNewFile()
3428 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3430 jalviewjsCoreClasslists.each {
3431 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3438 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3441 into file(outputFile).getParentFile()
3442 rename { filename ->
3443 if (filename.equals(inputFile.getName())) {
3444 return file(outputFile).getName()
3448 filter(ReplaceTokens,
3452 'MAIN': '"'+main_class+'"',
3454 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3455 'COREKEY': jalviewjs_core_key,
3456 'CORENAME': coreName
3463 task jalviewjsPublishCoreTemplates {
3464 dependsOn jalviewjsBuildAllCores
3465 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3466 def inputFile = file(inputFileName)
3467 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3469 def outputFiles = []
3470 jalviewjsCoreClasslists.each { cl ->
3471 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3472 cl['outputfile'] = outputFile
3473 outputFiles += outputFile
3477 jalviewjsCoreClasslists.each { cl ->
3478 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3481 inputs.file(inputFile)
3482 outputs.files(outputFiles)
3486 task jalviewjsSyncCore (type: Sync) {
3487 dependsOn jalviewjsBuildAllCores
3488 dependsOn jalviewjsPublishCoreTemplates
3489 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3490 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3494 def outputFiles = []
3495 rename { filename ->
3496 outputFiles += "${outputDir}/${filename}"
3502 outputs.files outputFiles
3503 inputs.files inputFiles
3507 // this Copy version of TransferSiteJs will delete anything else in the target dir
3508 task jalviewjsCopyTransferSiteJs(type: Copy) {
3509 dependsOn jalviewjsTranspile
3510 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3511 into "${jalviewDir}/${jalviewjsSiteDir}"
3515 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3516 task jalviewjsSyncTransferSiteJs(type: Sync) {
3517 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3519 into "${jalviewDir}/${jalviewjsSiteDir}"
3526 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3527 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3528 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3529 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3531 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3532 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3533 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3534 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3537 task jalviewjsPrepareSite {
3539 description "Prepares the website folder including unzipping files and copying resources"
3540 dependsOn jalviewjsSyncAllLibs
3541 dependsOn jalviewjsSyncResources
3542 dependsOn jalviewjsSyncSiteResources
3543 dependsOn jalviewjsSyncBuildProperties
3544 dependsOn jalviewjsSyncCore
3548 task jalviewjsBuildSite {
3550 description "Builds the whole website including transpiled code"
3551 dependsOn jalviewjsCopyTransferSiteJs
3552 dependsOn jalviewjsPrepareSite
3556 task cleanJalviewjsTransferSite {
3558 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3559 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3560 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3561 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3566 task cleanJalviewjsSite {
3567 dependsOn cleanJalviewjsTransferSite
3569 delete "${jalviewDir}/${jalviewjsSiteDir}"
3574 task jalviewjsSiteTar(type: Tar) {
3576 description "Creates a tar.gz file for the website"
3577 dependsOn jalviewjsBuildSite
3578 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3579 archiveFileName = outputFilename
3581 compression Compression.GZIP
3583 from "${jalviewDir}/${jalviewjsSiteDir}"
3584 into jalviewjs_site_dir // this is inside the tar file
3586 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3590 task jalviewjsServer {
3592 def filename = "jalviewjsTest.html"
3593 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3594 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3599 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3600 factory = f.newInstance()
3601 } catch (ClassNotFoundException e) {
3602 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3604 def port = Integer.valueOf(jalviewjs_server_port)
3609 while(port < start+1000 && !running) {
3611 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3612 jalviewjsServer = factory.start(doc_root, port)
3614 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3615 println("SERVER STARTED with document root ${doc_root}.")
3616 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3617 println("For debug: "+url+"?j2sdebug")
3618 println("For verbose: "+url+"?j2sverbose")
3619 } catch (Exception e) {
3624 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3625 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3626 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3628 jalviewjsCoreClasslists.each { cl ->
3629 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3631 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3633 println("For core ${cl.name}: "+urlcore)
3636 file(htmlFile).text = htmlText
3639 outputs.file(htmlFile)
3640 outputs.upToDateWhen({false})
3644 task cleanJalviewjsAll {
3646 description "Delete all configuration and build artifacts to do with JalviewJS build"
3647 dependsOn cleanJalviewjsSite
3648 dependsOn jalviewjsEclipsePaths
3651 delete "${jalviewDir}/${jalviewjsBuildDir}"
3652 delete "${jalviewDir}/${eclipse_bin_dir}"
3653 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3654 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3656 delete jalviewjsJ2sAltSettingsFileName
3659 outputs.upToDateWhen( { false } )
3663 task jalviewjsIDE_checkJ2sPlugin {
3664 group "00 JalviewJS in Eclipse"
3665 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3668 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3669 def j2sPluginFile = file(j2sPlugin)
3670 def eclipseHome = System.properties["eclipse.home.location"]
3671 if (eclipseHome == null || ! IN_ECLIPSE) {
3672 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3674 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3675 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3676 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3677 eclipseJ2sPluginDirs += altPluginsDir
3679 def foundPlugin = false
3680 def j2sPluginFileName = j2sPluginFile.getName()
3681 def eclipseJ2sPlugin
3682 def eclipseJ2sPluginFile
3683 eclipseJ2sPluginDirs.any { dir ->
3684 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3685 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3686 if (eclipseJ2sPluginFile.exists()) {
3692 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3693 System.err.println(msg)
3694 throw new StopExecutionException(msg)
3697 def digest = MessageDigest.getInstance("MD5")
3699 digest.update(j2sPluginFile.text.bytes)
3700 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3702 digest.update(eclipseJ2sPluginFile.text.bytes)
3703 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3705 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3706 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3707 System.err.println(msg)
3708 throw new StopExecutionException(msg)
3710 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3716 task jalviewjsIDE_copyJ2sPlugin {
3717 group "00 JalviewJS in Eclipse"
3718 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3721 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3722 def j2sPluginFile = file(j2sPlugin)
3723 def eclipseHome = System.properties["eclipse.home.location"]
3724 if (eclipseHome == null || ! IN_ECLIPSE) {
3725 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3727 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3728 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3729 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3730 System.err.println(msg)
3733 eclipseJ2sPluginFile.getParentFile().mkdirs()
3734 into eclipseJ2sPluginFile.getParent()
3740 task jalviewjsIDE_j2sFile {
3741 group "00 JalviewJS in Eclipse"
3742 description "Creates the .j2s file"
3743 dependsOn jalviewjsCreateJ2sSettings
3747 task jalviewjsIDE_SyncCore {
3748 group "00 JalviewJS in Eclipse"
3749 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3750 dependsOn jalviewjsSyncCore
3754 task jalviewjsIDE_SyncSiteAll {
3755 dependsOn jalviewjsSyncAllLibs
3756 dependsOn jalviewjsSyncResources
3757 dependsOn jalviewjsSyncSiteResources
3758 dependsOn jalviewjsSyncBuildProperties
3762 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3765 task jalviewjsIDE_PrepareSite {
3766 group "00 JalviewJS in Eclipse"
3767 description "Sync libs and resources to site dir, but not closure cores"
3769 dependsOn jalviewjsIDE_SyncSiteAll
3770 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3774 task jalviewjsIDE_AssembleSite {
3775 group "00 JalviewJS in Eclipse"
3776 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3777 dependsOn jalviewjsPrepareSite
3781 task jalviewjsIDE_SiteClean {
3782 group "00 JalviewJS in Eclipse"
3783 description "Deletes the Eclipse transpiled site"
3784 dependsOn cleanJalviewjsSite
3788 task jalviewjsIDE_Server {
3789 group "00 JalviewJS in Eclipse"
3790 description "Starts a webserver on localhost to test the website"
3791 dependsOn jalviewjsServer
3795 // buildship runs this at import or gradle refresh
3796 task eclipseSynchronizationTask {
3797 //dependsOn eclipseSetup
3798 dependsOn createBuildProperties
3800 dependsOn jalviewjsIDE_j2sFile
3801 dependsOn jalviewjsIDE_checkJ2sPlugin
3802 dependsOn jalviewjsIDE_PrepareSite
3807 // buildship runs this at build time or project refresh
3808 task eclipseAutoBuildTask {
3809 //dependsOn jalviewjsIDE_checkJ2sPlugin
3810 //dependsOn jalviewjsIDE_PrepareSite
3816 description "Build the site"
3817 dependsOn jalviewjsBuildSite