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
1702 // Uncomment to show stdout and stderr for tests in gradle build output
1703 // testLogging.showStandardStreams = true
1706 maxHeapSize = "1024m"
1708 workingDir = jalviewDir
1709 def testLaf = project.findProperty("test_laf")
1710 if (testLaf != null) {
1711 println("Setting Test LaF to '${testLaf}'")
1712 systemProperty "laf", testLaf
1714 def testHiDPIScale = project.findProperty("test_HiDPIScale")
1715 if (testHiDPIScale != null) {
1716 println("Setting Test HiDPI Scale to '${testHiDPIScale}'")
1717 systemProperty "sun.java2d.uiScale", testHiDPIScale
1719 sourceCompatibility = compile_source_compatibility
1720 targetCompatibility = compile_target_compatibility
1721 jvmArgs += additional_compiler_args
1725 println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1731 task compileLinkCheck(type: JavaCompile) {
1733 classpath = files("${jalviewDir}/${utils_dir}")
1734 destinationDir = file("${jalviewDir}/${utils_dir}")
1735 source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1737 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1738 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1739 outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1740 outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1744 task linkCheck(type: JavaExec) {
1746 dependsOn compileLinkCheck
1748 def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1749 classpath = files("${jalviewDir}/${utils_dir}")
1750 main = "HelpLinksChecker"
1751 workingDir = "${helpBuildDir}"
1752 args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1754 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1755 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1758 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1762 inputs.dir(helpBuildDir)
1763 outputs.file(helpLinksCheckerOutFile)
1767 // import the pubhtmlhelp target
1768 ant.properties.basedir = "${jalviewDir}"
1769 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1770 ant.importBuild "${utils_dir}/publishHelp.xml"
1773 task cleanPackageDir(type: Delete) {
1775 delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1785 attributes "Main-Class": main_class,
1786 "Permissions": "all-permissions",
1787 "Application-Name": applicationName,
1788 "Codebase": application_codebase,
1789 "Implementation-Version": JALVIEW_VERSION
1792 def outputDir = "${jalviewDir}/${package_dir}"
1793 destinationDirectory = file(outputDir)
1794 archiveFileName = rootProject.name+".jar"
1795 duplicatesStrategy "EXCLUDE"
1802 exclude "**/*.jar.*"
1804 inputs.dir(sourceSets.main.java.outputDir)
1805 sourceSets.main.resources.srcDirs.each{ dir ->
1808 outputs.file("${outputDir}/${archiveFileName}")
1812 task copyJars(type: Copy) {
1813 from fileTree(dir: classesDir, include: "**/*.jar").files
1814 into "${jalviewDir}/${package_dir}"
1818 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1819 task syncJars(type: Sync) {
1821 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1822 into "${jalviewDir}/${package_dir}"
1824 include jar.archiveFileName.getOrNull()
1831 description = "Put all required libraries in dist"
1832 // order of "cleanPackageDir", "copyJars", "jar" important!
1833 jar.mustRunAfter cleanPackageDir
1834 syncJars.mustRunAfter cleanPackageDir
1835 dependsOn cleanPackageDir
1838 outputs.dir("${jalviewDir}/${package_dir}")
1843 dependsOn cleanPackageDir
1850 group = "distribution"
1851 description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1855 from ("${jalviewDir}/${libDistDir}") {
1859 attributes "Implementation-Version": JALVIEW_VERSION,
1860 "Application-Name": applicationName
1863 duplicatesStrategy "INCLUDE"
1865 mainClassName = shadow_jar_main_class
1867 classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1872 task getdownWebsite() {
1873 group = "distribution"
1874 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1879 def getdownWebsiteResourceFilenames = []
1880 def getdownResourceDir = getdownResourceDir
1881 def getdownResourceFilenames = []
1884 // clean the getdown website and files dir before creating getdown folders
1885 delete getdownAppBaseDir
1886 delete getdownFilesDir
1889 from buildProperties
1890 rename(file(buildProperties).getName(), getdown_build_properties)
1893 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1896 from channelPropsFile
1897 into getdownAppBaseDir
1899 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
1901 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
1902 def props = project.properties.sort { it.key }
1903 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
1904 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
1906 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
1907 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
1909 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
1910 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
1912 if (getdownImagesDir != null && file(getdownImagesDir).exists()) {
1913 props.put("getdown_txt_ui.background_image", "${getdownImagesDir}/${getdown_background_image}")
1914 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesDir}/${getdown_instant_background_image}")
1915 props.put("getdown_txt_ui.error_background", "${getdownImagesDir}/${getdown_error_background}")
1916 props.put("getdown_txt_ui.progress_image", "${getdownImagesDir}/${getdown_progress_image}")
1917 props.put("getdown_txt_ui.icon", "${getdownImagesDir}/${getdown_icon}")
1918 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesDir}/${getdown_mac_dock_icon}")
1921 props.put("getdown_txt_title", jalview_name)
1922 props.put("getdown_txt_ui.name", applicationName)
1924 // start with appbase
1925 getdownTextLines += "appbase = ${getdownAppBase}"
1926 props.each{ prop, val ->
1927 if (prop.startsWith("getdown_txt_") && val != null) {
1928 if (prop.startsWith("getdown_txt_multi_")) {
1929 def key = prop.substring(18)
1930 val.split(",").each{ v ->
1931 def line = "${key} = ${v}"
1932 getdownTextLines += line
1935 // file values rationalised
1936 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
1938 if (val.indexOf('/') == 0) {
1941 } else if (val.indexOf('/') > 0) {
1942 // relative path (relative to jalviewDir)
1943 r = file( "${jalviewDir}/${val}" )
1946 val = "${getdown_resource_dir}/" + r.getName()
1947 getdownWebsiteResourceFilenames += val
1948 getdownResourceFilenames += r.getPath()
1951 if (! prop.startsWith("getdown_txt_resource")) {
1952 def line = prop.substring(12) + " = ${val}"
1953 getdownTextLines += line
1959 getdownWebsiteResourceFilenames.each{ filename ->
1960 getdownTextLines += "resource = ${filename}"
1962 getdownResourceFilenames.each{ filename ->
1965 into getdownResourceDir
1969 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
1970 getdownWrapperScripts.each{ script ->
1971 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
1975 into "${getdownAppBaseDir}/${getdown_wrapper_script_dir}"
1977 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
1982 fileTree(file(package_dir)).each{ f ->
1983 if (f.isDirectory()) {
1984 def files = fileTree(dir: f, include: ["*"]).getFiles()
1986 } else if (f.exists()) {
1990 def jalviewJar = jar.archiveFileName.getOrNull()
1991 // put jalview.jar first for CLASSPATH and .properties files reasons
1992 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
1993 def name = f.getName()
1994 def line = "code = ${getdownAppDistDir}/${name}"
1995 getdownTextLines += line
2002 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
2004 if (JAVA_VERSION.equals("11")) {
2005 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
2006 j11libFiles.sort().each{f ->
2007 def name = f.getName()
2008 def line = "code = ${getdown_j11lib_dir}/${name}"
2009 getdownTextLines += line
2012 into getdownJ11libDir
2018 // 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.
2019 //getdownTextLines += "class = " + file(getdownLauncher).getName()
2020 getdownTextLines += "resource = ${getdown_launcher_new}"
2021 getdownTextLines += "class = ${main_class}"
2022 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
2023 if (getdownSetAppBaseProperty) {
2024 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
2025 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
2028 def getdownTxt = file("${getdownAppBaseDir}/getdown.txt")
2029 getdownTxt.write(getdownTextLines.join("\n"))
2031 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
2032 def launchJvl = file("${getdownAppBaseDir}/${getdownLaunchJvl}")
2033 launchJvl.write("appbase=${getdownAppBase}")
2035 // files going into the getdown website dir: getdown-launcher.jar
2037 from getdownLauncher
2038 rename(file(getdownLauncher).getName(), getdown_launcher_new)
2039 into getdownAppBaseDir
2042 // files going into the getdown website dir: getdown-launcher(-local).jar
2044 from getdownLauncher
2045 if (file(getdownLauncher).getName() != getdown_launcher) {
2046 rename(file(getdownLauncher).getName(), getdown_launcher)
2048 into getdownAppBaseDir
2051 // files going into the getdown website dir: ./install dir and files
2052 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
2055 from getdownLauncher
2056 from "${getdownAppDir}/${getdown_build_properties}"
2057 if (file(getdownLauncher).getName() != getdown_launcher) {
2058 rename(file(getdownLauncher).getName(), getdown_launcher)
2060 into getdownInstallDir
2063 // and make a copy in the getdown files dir (these are not downloaded by getdown)
2065 from getdownInstallDir
2066 into getdownFilesInstallDir
2070 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2074 from getdownLauncher
2075 from "${getdownAppBaseDir}/${getdown_build_properties}"
2076 from "${getdownAppBaseDir}/${channel_props}"
2077 if (file(getdownLauncher).getName() != getdown_launcher) {
2078 rename(file(getdownLauncher).getName(), getdown_launcher)
2080 into getdownFilesDir
2083 // and ./resource (not all downloaded by getdown)
2085 from getdownResourceDir
2086 into "${getdownFilesDir}/${getdown_resource_dir}"
2091 inputs.dir("${jalviewDir}/${package_dir}")
2093 outputs.dir(getdownAppBaseDir)
2094 outputs.dir(getdownFilesDir)
2098 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
2099 task getdownDigestDir(type: JavaExec) {
2101 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
2103 def digestDirPropertyName = "DIGESTDIR"
2105 classpath = files(getdownLauncher)
2106 def digestDir = findProperty(digestDirPropertyName)
2107 if (digestDir == null) {
2108 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
2112 main = "com.threerings.getdown.tools.Digester"
2116 task getdownDigest(type: JavaExec) {
2117 group = "distribution"
2118 description = "Digest the getdown website folder"
2119 dependsOn getdownWebsite
2121 classpath = files(getdownLauncher)
2123 main = "com.threerings.getdown.tools.Digester"
2124 args getdownAppBaseDir
2125 inputs.dir(getdownAppBaseDir)
2126 outputs.file("${getdownAppBaseDir}/digest2.txt")
2131 group = "distribution"
2132 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
2133 dependsOn getdownDigest
2135 if (reportRsyncCommand) {
2136 def fromDir = getdownAppBaseDir + (getdownAppBaseDir.endsWith('/')?'':'/')
2137 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
2138 println "LIKELY RSYNC COMMAND:"
2139 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
2140 if (RUNRSYNC == "true") {
2142 commandLine "mkdir", "-p", toDir
2145 commandLine "rsync", "-avh", "--delete", fromDir, toDir
2153 task getdownArchiveBuild() {
2154 group = "distribution"
2155 description = "Put files in the archive dir to go on the website"
2157 dependsOn getdownWebsite
2159 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
2160 def vDir = "${getdownArchiveDir}/${v}"
2161 getdownFullArchiveDir = "${vDir}/getdown"
2162 getdownVersionLaunchJvl = "${vDir}/jalview-${v}.jvl"
2164 def vAltDir = "alt_${v}"
2165 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
2168 // cleanup old "old" dir
2169 delete getdownArchiveDir
2171 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
2172 getdownArchiveTxt.getParentFile().mkdirs()
2173 def getdownArchiveTextLines = []
2174 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
2178 from "${getdownAppBaseDir}/${getdownAppDistDir}"
2179 into "${getdownFullArchiveDir}/${vAltDir}"
2182 getdownTextLines.each { line ->
2183 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
2184 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
2185 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
2186 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
2187 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
2188 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
2189 // remove the existing resource = resource/ or bin/ lines
2190 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
2191 getdownArchiveTextLines += line
2195 // the resource dir -- add these files as resource lines in getdown.txt
2197 from "${archiveImagesDir}"
2198 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
2200 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
2204 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
2206 def vLaunchJvl = file(getdownVersionLaunchJvl)
2207 vLaunchJvl.getParentFile().mkdirs()
2208 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
2209 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
2210 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
2211 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
2212 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
2213 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
2215 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2217 from getdownLauncher
2218 from "${getdownAppBaseDir}/${getdownLaunchJvl}"
2219 from "${getdownAppBaseDir}/${getdown_launcher_new}"
2220 from "${getdownAppBaseDir}/${channel_props}"
2221 if (file(getdownLauncher).getName() != getdown_launcher) {
2222 rename(file(getdownLauncher).getName(), getdown_launcher)
2224 into getdownFullArchiveDir
2230 task getdownArchiveDigest(type: JavaExec) {
2231 group = "distribution"
2232 description = "Digest the getdown archive folder"
2234 dependsOn getdownArchiveBuild
2237 classpath = files(getdownLauncher)
2238 args getdownFullArchiveDir
2240 main = "com.threerings.getdown.tools.Digester"
2241 inputs.dir(getdownFullArchiveDir)
2242 outputs.file("${getdownFullArchiveDir}/digest2.txt")
2245 task getdownArchive() {
2246 group = "distribution"
2247 description = "Build the website archive dir with getdown digest"
2249 dependsOn getdownArchiveBuild
2250 dependsOn getdownArchiveDigest
2252 tasks.withType(JavaCompile) {
2253 options.encoding = 'UTF-8'
2259 delete getdownAppBaseDir
2260 delete getdownFilesDir
2261 delete getdownArchiveDir
2267 if (file(install4jHomeDir).exists()) {
2269 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
2270 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
2271 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
2272 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
2274 installDir(file(install4jHomeDir))
2276 mediaTypes = Arrays.asList(install4j_media_types.split(","))
2280 task copyInstall4jTemplate {
2281 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
2282 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
2283 inputs.file(install4jTemplateFile)
2284 inputs.file(install4jFileAssociationsFile)
2285 inputs.property("CHANNEL", { CHANNEL })
2286 outputs.file(install4jConfFile)
2289 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
2291 // turn off code signing if no OSX_KEYPASS
2292 if (OSX_KEYPASS == "") {
2293 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
2294 codeSigning.'@macEnabled' = "false"
2296 install4jConfigXml.'**'.windows.each { windows ->
2297 windows.'@runPostProcessor' = "false"
2301 // disable install screen for OSX dmg (for 2.11.2.0)
2302 install4jConfigXml.'**'.macosArchive.each { macosArchive ->
2303 macosArchive.attributes().remove('executeSetupApp')
2304 macosArchive.attributes().remove('setupAppId')
2306 // turn off checksum creation for LOCAL channel
2307 def e = install4jConfigXml.application[0]
2308 e.'@createChecksums' = string(install4jCheckSums)
2310 // put file association actions where placeholder action is
2311 def install4jFileAssociationsText = install4jFileAssociationsFile.text
2312 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
2313 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
2314 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
2315 def parent = a.parent()
2317 fileAssociationActions.each { faa ->
2320 // don't need to continue in .any loop once replacements have been made
2325 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
2326 // NB we're deleting the /other/ one!
2327 // Also remove the examples subdir from non-release versions
2328 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
2329 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
2330 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
2331 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
2333 // remove the examples subdir from Full File Set
2334 def files = install4jConfigXml.files[0]
2335 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
2336 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
2337 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
2338 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
2339 dirEntry.parent().remove(dirEntry)
2341 install4jConfigXml.'**'.action.any { a ->
2342 if (a.'@customizedId' == customizedIdToDelete) {
2343 def parent = a.parent()
2349 // write install4j file
2350 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
2357 delete install4jConfFile
2361 task cleanInstallersDataFiles {
2362 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2363 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2364 def hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
2366 delete installersOutputTxt
2367 delete installersSha256
2368 delete hugoDataJsonFile
2372 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2373 group = "distribution"
2374 description = "Create the install4j installers"
2376 dependsOn copyInstall4jTemplate
2377 dependsOn cleanInstallersDataFiles
2379 projectFile = install4jConfFile
2381 // create an md5 for the input files to use as version for install4j conf file
2382 def digest = MessageDigest.getInstance("MD5")
2384 (file("${install4jDir}/${install4j_template}").text +
2385 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2386 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2387 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2388 if (filesMd5.length() >= 8) {
2389 filesMd5 = filesMd5.substring(0,8)
2391 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2394 'JALVIEW_NAME': jalview_name,
2395 'JALVIEW_APPLICATION_NAME': applicationName,
2396 'JALVIEW_DIR': "../..",
2397 'OSX_KEYSTORE': OSX_KEYSTORE,
2398 'OSX_APPLEID': OSX_APPLEID,
2399 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2400 'JSIGN_SH': JSIGN_SH,
2401 'JRE_DIR': getdown_app_dir_java,
2402 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2403 'JALVIEW_VERSION': JALVIEW_VERSION,
2404 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2405 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2406 'JAVA_VERSION': JAVA_VERSION,
2407 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2408 'VERSION': JALVIEW_VERSION,
2409 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2410 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2411 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2412 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2413 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2414 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2415 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2416 'BUNDLE_ID': install4jBundleId,
2417 'INTERNAL_ID': install4jInternalId,
2418 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2419 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2420 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
2421 'WRAPPER_LINK': getdownWrapperLink,
2422 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2423 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2424 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2425 'INSTALLER_NAME': install4jInstallerName,
2426 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2427 'GETDOWN_CHANNEL_DIR': getdownChannelDir,
2428 'GETDOWN_FILES_DIR': getdown_files_dir,
2429 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2430 'GETDOWN_DIST_DIR': getdownAppDistDir,
2431 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2432 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2433 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2434 'BUILD_DIR': install4jBuildDir,
2435 'APPLICATION_CATEGORIES': install4j_application_categories,
2436 'APPLICATION_FOLDER': install4jApplicationFolder,
2437 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2438 'EXECUTABLE_NAME': install4jExecutableName,
2439 'EXTRA_SCHEME': install4jExtraScheme,
2440 'MAC_ICONS_FILE': install4jMacIconsFile,
2441 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2442 'PNG_ICON_FILE': install4jPngIconFile,
2443 'BACKGROUND': install4jBackground,
2447 //println("INSTALL4J VARIABLES:")
2448 //variables.each{k,v->println("${k}=${v}")}
2450 destination = "${jalviewDir}/${install4jBuildDir}"
2451 buildSelected = true
2453 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2455 disableSigning = true
2456 disableNotarization = true
2460 macKeystorePassword = OSX_KEYPASS
2463 if (OSX_ALTOOLPASS) {
2464 appleIdPassword = OSX_ALTOOLPASS
2465 disableNotarization = false
2467 disableNotarization = true
2471 println("Using projectFile "+projectFile)
2472 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2476 inputs.dir(getdownAppBaseDir)
2477 inputs.file(install4jConfFile)
2478 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2479 inputs.dir(macosJavaVMDir)
2480 inputs.dir(windowsJavaVMDir)
2481 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2484 def getDataHash(File myFile) {
2485 HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
2486 return myFile.exists()
2488 "file" : myFile.getName(),
2489 "filesize" : myFile.length(),
2490 "sha256" : hash.toString()
2495 def writeDataJsonFile(File installersOutputTxt, File installersSha256, File dataJsonFile) {
2497 "channel" : getdownChannelName,
2498 "date" : getDate("yyyy-MM-dd HH:mm:ss"),
2499 "git-commit" : "${gitHash} [${gitBranch}]",
2500 "version" : JALVIEW_VERSION
2502 // install4j installer files
2503 if (installersOutputTxt.exists()) {
2505 installersOutputTxt.readLines().each { def line ->
2506 if (line.startsWith("#")) {
2509 line.replaceAll("\n","")
2510 def vals = line.split("\t")
2511 def filename = vals[3]
2512 def filesize = file(filename).length()
2513 filename = filename.replaceAll(/^.*\//, "")
2514 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2515 idHash."${filename}" = vals[0]
2517 if (install4jCheckSums && installersSha256.exists()) {
2518 installersSha256.readLines().each { def line ->
2519 if (line.startsWith("#")) {
2522 line.replaceAll("\n","")
2523 def vals = line.split(/\s+\*?/)
2524 def filename = vals[1]
2525 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2531 "JAR": shadowJar.archiveFile, // executable JAR
2532 "JVL": getdownVersionLaunchJvl, // version JVL
2533 "SOURCE": sourceDist.archiveFile // source TGZ
2534 ].each { key, value ->
2535 def file = file(value)
2536 if (file.exists()) {
2537 def fileHash = getDataHash(file)
2538 if (fileHash != null) {
2539 hash."${key}" = fileHash;
2543 return dataJsonFile.write(new JsonBuilder(hash).toPrettyString())
2546 task staticMakeInstallersJsonFile {
2548 def output = findProperty("i4j_output")
2549 def sha256 = findProperty("i4j_sha256")
2550 def json = findProperty("i4j_json")
2551 if (output == null || sha256 == null || json == null) {
2552 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2554 writeDataJsonFile(file(output), file(sha256), file(json))
2559 dependsOn installerFiles
2564 eclipse().configFile(eclipse_codestyle_file)
2568 task createSourceReleaseProperties(type: WriteProperties) {
2569 group = "distribution"
2570 description = "Create the source RELEASE properties file"
2572 def sourceTarBuildDir = "${buildDir}/sourceTar"
2573 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2574 outputFile (sourceReleasePropertiesFile)
2577 releaseProps.each{ key, val -> property key, val }
2578 property "git.branch", gitBranch
2579 property "git.hash", gitHash
2582 outputs.file(outputFile)
2585 task sourceDist(type: Tar) {
2586 group "distribution"
2587 description "Create a source .tar.gz file for distribution"
2589 dependsOn createBuildProperties
2590 dependsOn convertMdFiles
2591 dependsOn eclipseAllPreferences
2592 dependsOn createSourceReleaseProperties
2595 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2596 archiveFileName = outputFileName
2598 compression Compression.GZIP
2613 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2615 "utils/InstallAnywhere",
2630 "gradle.properties",
2642 ".settings/org.eclipse.buildship.core.prefs",
2643 ".settings/org.eclipse.jdt.core.prefs"
2647 exclude (EXCLUDE_FILES)
2648 include (PROCESS_FILES)
2649 filter(ReplaceTokens,
2653 'Version-Rel': JALVIEW_VERSION,
2654 'Year-Rel': getDate("yyyy")
2659 exclude (EXCLUDE_FILES)
2660 exclude (PROCESS_FILES)
2661 exclude ("appletlib")
2662 exclude ("**/*locales")
2663 exclude ("*locales/**")
2664 exclude ("utils/InstallAnywhere")
2666 exclude (getdown_files_dir)
2667 // getdown_website_dir and getdown_archive_dir moved to build/website/docroot/getdown
2668 //exclude (getdown_website_dir)
2669 //exclude (getdown_archive_dir)
2671 // exluding these as not using jars as modules yet
2672 exclude ("${j11modDir}/**/*.jar")
2675 include(INCLUDE_FILES)
2677 // from (jalviewDir) {
2678 // // explicit includes for stuff that seemed to not get included
2679 // include(fileTree("test/**/*."))
2680 // exclude(EXCLUDE_FILES)
2681 // exclude(PROCESS_FILES)
2684 from(file(buildProperties).getParent()) {
2685 include(file(buildProperties).getName())
2686 rename(file(buildProperties).getName(), "build_properties")
2688 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2692 def sourceTarBuildDir = "${buildDir}/sourceTar"
2693 from(sourceTarBuildDir) {
2694 // this includes the appended RELEASE properties file
2698 task dataInstallersJson {
2700 description "Create the installers-VERSION.json data file for installer files created"
2702 mustRunAfter installers
2703 mustRunAfter shadowJar
2704 mustRunAfter sourceDist
2705 mustRunAfter getdownArchive
2707 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2708 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2710 if (installersOutputTxt.exists()) {
2711 inputs.file(installersOutputTxt)
2713 if (install4jCheckSums && installersSha256.exists()) {
2714 inputs.file(installersSha256)
2717 shadowJar.archiveFile, // executable JAR
2718 getdownVersionLaunchJvl, // version JVL
2719 sourceDist.archiveFile // source TGZ
2720 ].each { fileName ->
2721 if (file(fileName).exists()) {
2722 inputs.file(fileName)
2726 outputs.file(hugoDataJsonFile)
2729 writeDataJsonFile(installersOutputTxt, installersSha256, hugoDataJsonFile)
2735 description "Copies all help pages to build dir. Runs ant task 'pubhtmlhelp'."
2737 dependsOn pubhtmlhelp
2739 inputs.dir("${helpBuildDir}/${help_dir}")
2740 outputs.dir("${buildDir}/distributions/${help_dir}")
2744 task j2sSetHeadlessBuild {
2751 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2753 description "Enable the alternative J2S Config file for headless build"
2755 outputFile = jalviewjsJ2sSettingsFileName
2756 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2757 def j2sProps = new Properties()
2758 if (j2sPropsFile.exists()) {
2760 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2761 j2sProps.load(j2sPropsFileFIS)
2762 j2sPropsFileFIS.close()
2764 j2sProps.each { prop, val ->
2767 } catch (Exception e) {
2768 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2772 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2773 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2778 task jalviewjsSetEclipseWorkspace {
2779 def propKey = "jalviewjs_eclipse_workspace"
2781 if (project.hasProperty(propKey)) {
2782 propVal = project.getProperty(propKey)
2783 if (propVal.startsWith("~/")) {
2784 propVal = System.getProperty("user.home") + propVal.substring(1)
2787 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2788 def propsFile = file(propsFileName)
2789 def eclipseWsDir = propVal
2790 def props = new Properties()
2792 def writeProps = true
2793 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2794 def ins = new FileInputStream(propsFileName)
2797 if (props.getProperty(propKey, null) != null) {
2798 eclipseWsDir = props.getProperty(propKey)
2803 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2804 def tempDir = File.createTempDir()
2805 eclipseWsDir = tempDir.getAbsolutePath()
2808 eclipseWorkspace = file(eclipseWsDir)
2811 // do not run a headless transpile when we claim to be in Eclipse
2813 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2814 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2816 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2820 props.setProperty(propKey, eclipseWsDir)
2821 propsFile.parentFile.mkdirs()
2822 def bytes = new ByteArrayOutputStream()
2823 props.store(bytes, null)
2824 def propertiesString = bytes.toString()
2825 propsFile.text = propertiesString
2831 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2834 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2835 outputs.file(propsFileName)
2836 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2840 task jalviewjsEclipsePaths {
2843 def eclipseRoot = jalviewjs_eclipse_root
2844 if (eclipseRoot.startsWith("~/")) {
2845 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
2847 if (OperatingSystem.current().isMacOsX()) {
2848 eclipseRoot += "/Eclipse.app"
2849 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
2850 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
2851 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
2852 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2853 eclipseRoot += "/eclipse"
2855 eclipseBinary = "${eclipseRoot}/eclipse.exe"
2856 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2857 } else { // linux or unix
2858 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2859 eclipseRoot += "/eclipse"
2860 println("eclipseDir exists")
2862 eclipseBinary = "${eclipseRoot}/eclipse"
2863 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2866 eclipseVersion = "4.13" // default
2867 def assumedVersion = true
2868 if (file(eclipseProduct).exists()) {
2869 def fis = new FileInputStream(eclipseProduct)
2870 def props = new Properties()
2872 eclipseVersion = props.getProperty("version")
2874 assumedVersion = false
2877 def propKey = "eclipse_debug"
2878 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
2881 // do not run a headless transpile when we claim to be in Eclipse
2883 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2884 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2886 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2889 if (!assumedVersion) {
2890 println("ECLIPSE VERSION=${eclipseVersion}")
2896 task printProperties {
2898 description "Output to console all System.properties"
2900 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
2906 dependsOn eclipseProject
2907 dependsOn eclipseClasspath
2908 dependsOn eclipseJdt
2912 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
2913 task jalviewjsEclipseCopyDropins(type: Copy) {
2914 dependsOn jalviewjsEclipsePaths
2916 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
2917 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
2918 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
2925 // this eclipse -clean doesn't actually work
2926 task jalviewjsCleanEclipse(type: Exec) {
2927 dependsOn eclipseSetup
2928 dependsOn jalviewjsEclipsePaths
2929 dependsOn jalviewjsEclipseCopyDropins
2931 executable(eclipseBinary)
2932 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
2938 def inputString = """exit
2941 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
2942 standardInput = inputByteStream
2945 /* not really working yet
2946 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
2950 task jalviewjsTransferUnzipSwingJs {
2951 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
2955 from zipTree(file_zip)
2956 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2960 inputs.file file_zip
2961 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2965 task jalviewjsTransferUnzipLib {
2966 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
2969 zipFiles.each { file_zip ->
2971 from zipTree(file_zip)
2972 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2977 inputs.files zipFiles
2978 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2982 task jalviewjsTransferUnzipAllLibs {
2983 dependsOn jalviewjsTransferUnzipSwingJs
2984 dependsOn jalviewjsTransferUnzipLib
2988 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
2990 description "Create the alternative j2s file from the j2s.* properties"
2992 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
2993 def siteDirProperty = "j2s.site.directory"
2994 def setSiteDir = false
2995 jalviewjsJ2sProps.each { prop, val ->
2997 if (prop == siteDirProperty) {
2998 if (!(val.startsWith('/') || val.startsWith("file://") )) {
2999 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
3005 if (!setSiteDir) { // default site location, don't override specifically set property
3006 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
3009 outputFile = jalviewjsJ2sAltSettingsFileName
3012 inputs.properties(jalviewjsJ2sProps)
3013 outputs.file(jalviewjsJ2sAltSettingsFileName)
3018 task jalviewjsEclipseSetup {
3019 dependsOn jalviewjsEclipseCopyDropins
3020 dependsOn jalviewjsSetEclipseWorkspace
3021 dependsOn jalviewjsCreateJ2sSettings
3025 task jalviewjsSyncAllLibs (type: Sync) {
3026 dependsOn jalviewjsTransferUnzipAllLibs
3027 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
3028 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
3029 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3033 def outputFiles = []
3034 rename { filename ->
3035 outputFiles += "${outputDir}/${filename}"
3042 // should this be exclude really ?
3043 duplicatesStrategy "INCLUDE"
3045 outputs.files outputFiles
3046 inputs.files inputFiles
3050 task jalviewjsSyncResources (type: Sync) {
3051 dependsOn buildResources
3053 def inputFiles = fileTree(dir: resourcesBuildDir)
3054 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3058 def outputFiles = []
3059 rename { filename ->
3060 outputFiles += "${outputDir}/${filename}"
3066 outputs.files outputFiles
3067 inputs.files inputFiles
3071 task jalviewjsSyncSiteResources (type: Sync) {
3072 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
3073 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3077 def outputFiles = []
3078 rename { filename ->
3079 outputFiles += "${outputDir}/${filename}"
3085 outputs.files outputFiles
3086 inputs.files inputFiles
3090 task jalviewjsSyncBuildProperties (type: Sync) {
3091 dependsOn createBuildProperties
3092 def inputFiles = [file(buildProperties)]
3093 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3097 def outputFiles = []
3098 rename { filename ->
3099 outputFiles += "${outputDir}/${filename}"
3105 outputs.files outputFiles
3106 inputs.files inputFiles
3110 task jalviewjsProjectImport(type: Exec) {
3111 dependsOn eclipseSetup
3112 dependsOn jalviewjsEclipsePaths
3113 dependsOn jalviewjsEclipseSetup
3116 // do not run a headless import when we claim to be in Eclipse
3118 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3119 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3121 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3125 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
3126 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
3127 executable(eclipseBinary)
3128 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
3132 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3134 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3135 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3138 inputs.file("${jalviewDir}/.project")
3139 outputs.upToDateWhen {
3140 file(projdir).exists()
3145 task jalviewjsTranspile(type: Exec) {
3146 dependsOn jalviewjsEclipseSetup
3147 dependsOn jalviewjsProjectImport
3148 dependsOn jalviewjsEclipsePaths
3150 dependsOn jalviewjsEnableAltFileProperty
3154 // do not run a headless transpile when we claim to be in Eclipse
3156 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3157 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3159 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3163 executable(eclipseBinary)
3164 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
3168 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3170 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3171 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3177 stdout = new ByteArrayOutputStream()
3178 stderr = new ByteArrayOutputStream()
3180 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
3181 def logOutFile = file(logOutFileName)
3182 logOutFile.createNewFile()
3183 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
3184 BINARY: ${eclipseBinary}
3185 VERSION: ${eclipseVersion}
3186 WORKSPACE: ${eclipseWorkspace}
3187 DEBUG: ${eclipseDebug}
3190 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3191 // combine stdout and stderr
3192 def logErrFOS = logOutFOS
3194 if (jalviewjs_j2s_to_console.equals("true")) {
3195 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3196 new org.apache.tools.ant.util.TeeOutputStream(
3200 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3201 new org.apache.tools.ant.util.TeeOutputStream(
3206 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3209 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3216 if (stdout.toString().contains("Error processing ")) {
3217 // j2s did not complete transpile
3218 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3219 if (jalviewjs_ignore_transpile_errors.equals("true")) {
3220 println("IGNORING TRANSPILE ERRORS")
3221 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3223 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3228 inputs.dir("${jalviewDir}/${sourceDir}")
3229 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
3230 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
3234 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
3236 def stdout = new ByteArrayOutputStream()
3237 def stderr = new ByteArrayOutputStream()
3239 def coreFile = file(jsfile)
3241 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
3243 logOutFile.createNewFile()
3244 logOutFile.append(msg+"\n")
3246 def coreTop = file(prefixFile)
3247 def coreBottom = file(suffixFile)
3248 coreFile.getParentFile().mkdirs()
3249 coreFile.createNewFile()
3250 coreFile.write( coreTop.getText("UTF-8") )
3254 def t = f.getText("UTF-8")
3255 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
3256 coreFile.append( t )
3258 msg = "...file '"+f.getPath()+"' does not exist, skipping"
3260 logOutFile.append(msg+"\n")
3263 coreFile.append( coreBottom.getText("UTF-8") )
3265 msg = "Generating ${zjsfile}"
3267 logOutFile.append(msg+"\n")
3268 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3269 def logErrFOS = logOutFOS
3272 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
3273 main = "com.google.javascript.jscomp.CommandLineRunner"
3274 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
3275 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
3278 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
3280 logOutFile.append(msg+"\n")
3282 if (logOutConsole) {
3283 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3284 new org.apache.tools.ant.util.TeeOutputStream(
3288 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3289 new org.apache.tools.ant.util.TeeOutputStream(
3294 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3297 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3304 logOutFile.append(msg+"\n")
3308 task jalviewjsBuildAllCores {
3310 description "Build the core js lib closures listed in the classlists dir"
3311 dependsOn jalviewjsTranspile
3312 dependsOn jalviewjsTransferUnzipSwingJs
3314 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
3315 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
3316 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
3317 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
3318 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
3319 def prefixFile = "${jsDir}/core/coretop2.js"
3320 def suffixFile = "${jsDir}/core/corebottom2.js"
3322 inputs.file prefixFile
3323 inputs.file suffixFile
3325 def classlistFiles = []
3326 // add the classlists found int the jalviewjs_classlists_dir
3327 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
3329 def name = file.getName() - ".txt"
3336 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
3337 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
3338 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
3340 jalviewjsCoreClasslists = []
3342 classlistFiles.each {
3345 def file = hash['file']
3346 if (! file.exists()) {
3347 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
3348 return false // this is a "continue" in groovy .each closure
3350 def name = hash['name']
3352 name = file.getName() - ".txt"
3360 def list = fileTree(dir: j2sDir, includes: filelist)
3362 def jsfile = "${outputDir}/core${name}.js"
3363 def zjsfile = "${outputDir}/core${name}.z.js"
3365 jalviewjsCoreClasslists += [
3374 outputs.file(jsfile)
3375 outputs.file(zjsfile)
3378 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
3379 def stevesoftClasslistName = "_stevesoft"
3380 def stevesoftClasslist = [
3381 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
3382 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
3383 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
3384 'name': stevesoftClasslistName
3386 jalviewjsCoreClasslists += stevesoftClasslist
3387 inputs.files(stevesoftClasslist['list'])
3388 outputs.file(stevesoftClasslist['jsfile'])
3389 outputs.file(stevesoftClasslist['zjsfile'])
3392 def allClasslistName = "_all"
3393 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3394 allJsFiles += fileTree(
3398 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3399 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3400 "**/org/jmol/export/JSExporter.js"
3403 allJsFiles += fileTree(
3407 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3408 "**/sun/misc/Unsafe.js",
3409 "**/swingjs/jquery/jquery-editable-select.js",
3410 "**/swingjs/jquery/j2sComboBox.js",
3411 "**/sun/misc/FloatingDecimal.js"
3414 def allClasslist = [
3415 'jsfile': "${outputDir}/core${allClasslistName}.js",
3416 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
3418 'name': allClasslistName
3420 // not including this version of "all" core at the moment
3421 //jalviewjsCoreClasslists += allClasslist
3422 inputs.files(allClasslist['list'])
3423 outputs.file(allClasslist['jsfile'])
3424 outputs.file(allClasslist['zjsfile'])
3427 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3428 logOutFile.getParentFile().mkdirs()
3429 logOutFile.createNewFile()
3430 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3432 jalviewjsCoreClasslists.each {
3433 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3440 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3443 into file(outputFile).getParentFile()
3444 rename { filename ->
3445 if (filename.equals(inputFile.getName())) {
3446 return file(outputFile).getName()
3450 filter(ReplaceTokens,
3454 'MAIN': '"'+main_class+'"',
3456 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3457 'COREKEY': jalviewjs_core_key,
3458 'CORENAME': coreName
3465 task jalviewjsPublishCoreTemplates {
3466 dependsOn jalviewjsBuildAllCores
3467 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3468 def inputFile = file(inputFileName)
3469 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3471 def outputFiles = []
3472 jalviewjsCoreClasslists.each { cl ->
3473 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3474 cl['outputfile'] = outputFile
3475 outputFiles += outputFile
3479 jalviewjsCoreClasslists.each { cl ->
3480 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3483 inputs.file(inputFile)
3484 outputs.files(outputFiles)
3488 task jalviewjsSyncCore (type: Sync) {
3489 dependsOn jalviewjsBuildAllCores
3490 dependsOn jalviewjsPublishCoreTemplates
3491 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3492 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3496 def outputFiles = []
3497 rename { filename ->
3498 outputFiles += "${outputDir}/${filename}"
3504 outputs.files outputFiles
3505 inputs.files inputFiles
3509 // this Copy version of TransferSiteJs will delete anything else in the target dir
3510 task jalviewjsCopyTransferSiteJs(type: Copy) {
3511 dependsOn jalviewjsTranspile
3512 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3513 into "${jalviewDir}/${jalviewjsSiteDir}"
3517 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3518 task jalviewjsSyncTransferSiteJs(type: Sync) {
3519 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3521 into "${jalviewDir}/${jalviewjsSiteDir}"
3528 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3529 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3530 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3531 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3533 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3534 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3535 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3536 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3539 task jalviewjsPrepareSite {
3541 description "Prepares the website folder including unzipping files and copying resources"
3542 dependsOn jalviewjsSyncAllLibs
3543 dependsOn jalviewjsSyncResources
3544 dependsOn jalviewjsSyncSiteResources
3545 dependsOn jalviewjsSyncBuildProperties
3546 dependsOn jalviewjsSyncCore
3550 task jalviewjsBuildSite {
3552 description "Builds the whole website including transpiled code"
3553 dependsOn jalviewjsCopyTransferSiteJs
3554 dependsOn jalviewjsPrepareSite
3558 task cleanJalviewjsTransferSite {
3560 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3561 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3562 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3563 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3568 task cleanJalviewjsSite {
3569 dependsOn cleanJalviewjsTransferSite
3571 delete "${jalviewDir}/${jalviewjsSiteDir}"
3576 task jalviewjsSiteTar(type: Tar) {
3578 description "Creates a tar.gz file for the website"
3579 dependsOn jalviewjsBuildSite
3580 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3581 archiveFileName = outputFilename
3583 compression Compression.GZIP
3585 from "${jalviewDir}/${jalviewjsSiteDir}"
3586 into jalviewjs_site_dir // this is inside the tar file
3588 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3592 task jalviewjsServer {
3594 def filename = "jalviewjsTest.html"
3595 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3596 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3601 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3602 factory = f.newInstance()
3603 } catch (ClassNotFoundException e) {
3604 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3606 def port = Integer.valueOf(jalviewjs_server_port)
3611 while(port < start+1000 && !running) {
3613 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3614 jalviewjsServer = factory.start(doc_root, port)
3616 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3617 println("SERVER STARTED with document root ${doc_root}.")
3618 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3619 println("For debug: "+url+"?j2sdebug")
3620 println("For verbose: "+url+"?j2sverbose")
3621 } catch (Exception e) {
3626 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3627 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3628 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3630 jalviewjsCoreClasslists.each { cl ->
3631 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3633 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3635 println("For core ${cl.name}: "+urlcore)
3638 file(htmlFile).text = htmlText
3641 outputs.file(htmlFile)
3642 outputs.upToDateWhen({false})
3646 task cleanJalviewjsAll {
3648 description "Delete all configuration and build artifacts to do with JalviewJS build"
3649 dependsOn cleanJalviewjsSite
3650 dependsOn jalviewjsEclipsePaths
3653 delete "${jalviewDir}/${jalviewjsBuildDir}"
3654 delete "${jalviewDir}/${eclipse_bin_dir}"
3655 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3656 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3658 delete jalviewjsJ2sAltSettingsFileName
3661 outputs.upToDateWhen( { false } )
3665 task jalviewjsIDE_checkJ2sPlugin {
3666 group "00 JalviewJS in Eclipse"
3667 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3670 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3671 def j2sPluginFile = file(j2sPlugin)
3672 def eclipseHome = System.properties["eclipse.home.location"]
3673 if (eclipseHome == null || ! IN_ECLIPSE) {
3674 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3676 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3677 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3678 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3679 eclipseJ2sPluginDirs += altPluginsDir
3681 def foundPlugin = false
3682 def j2sPluginFileName = j2sPluginFile.getName()
3683 def eclipseJ2sPlugin
3684 def eclipseJ2sPluginFile
3685 eclipseJ2sPluginDirs.any { dir ->
3686 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3687 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3688 if (eclipseJ2sPluginFile.exists()) {
3694 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3695 System.err.println(msg)
3696 throw new StopExecutionException(msg)
3699 def digest = MessageDigest.getInstance("MD5")
3701 digest.update(j2sPluginFile.text.bytes)
3702 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3704 digest.update(eclipseJ2sPluginFile.text.bytes)
3705 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3707 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3708 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3709 System.err.println(msg)
3710 throw new StopExecutionException(msg)
3712 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3718 task jalviewjsIDE_copyJ2sPlugin {
3719 group "00 JalviewJS in Eclipse"
3720 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3723 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3724 def j2sPluginFile = file(j2sPlugin)
3725 def eclipseHome = System.properties["eclipse.home.location"]
3726 if (eclipseHome == null || ! IN_ECLIPSE) {
3727 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3729 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3730 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3731 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3732 System.err.println(msg)
3735 eclipseJ2sPluginFile.getParentFile().mkdirs()
3736 into eclipseJ2sPluginFile.getParent()
3742 task jalviewjsIDE_j2sFile {
3743 group "00 JalviewJS in Eclipse"
3744 description "Creates the .j2s file"
3745 dependsOn jalviewjsCreateJ2sSettings
3749 task jalviewjsIDE_SyncCore {
3750 group "00 JalviewJS in Eclipse"
3751 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3752 dependsOn jalviewjsSyncCore
3756 task jalviewjsIDE_SyncSiteAll {
3757 dependsOn jalviewjsSyncAllLibs
3758 dependsOn jalviewjsSyncResources
3759 dependsOn jalviewjsSyncSiteResources
3760 dependsOn jalviewjsSyncBuildProperties
3764 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3767 task jalviewjsIDE_PrepareSite {
3768 group "00 JalviewJS in Eclipse"
3769 description "Sync libs and resources to site dir, but not closure cores"
3771 dependsOn jalviewjsIDE_SyncSiteAll
3772 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3776 task jalviewjsIDE_AssembleSite {
3777 group "00 JalviewJS in Eclipse"
3778 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3779 dependsOn jalviewjsPrepareSite
3783 task jalviewjsIDE_SiteClean {
3784 group "00 JalviewJS in Eclipse"
3785 description "Deletes the Eclipse transpiled site"
3786 dependsOn cleanJalviewjsSite
3790 task jalviewjsIDE_Server {
3791 group "00 JalviewJS in Eclipse"
3792 description "Starts a webserver on localhost to test the website"
3793 dependsOn jalviewjsServer
3797 // buildship runs this at import or gradle refresh
3798 task eclipseSynchronizationTask {
3799 //dependsOn eclipseSetup
3800 dependsOn createBuildProperties
3802 dependsOn jalviewjsIDE_j2sFile
3803 dependsOn jalviewjsIDE_checkJ2sPlugin
3804 dependsOn jalviewjsIDE_PrepareSite
3809 // buildship runs this at build time or project refresh
3810 task eclipseAutoBuildTask {
3811 //dependsOn jalviewjsIDE_checkJ2sPlugin
3812 //dependsOn jalviewjsIDE_PrepareSite
3818 description "Build the site"
3819 dependsOn jalviewjsBuildSite