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 '1.5' // 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
416 apply plugin: "com.palantir.git-version"
417 def details = versionDetails()
418 gitHash = details.gitHash
419 gitBranch = details.branchName
420 } catch(org.gradle.api.internal.plugins.PluginApplicationException e) {
421 println("Not in a git repository. Using git values from RELEASE properties file.")
422 gitHash = releaseProps.getProperty("git.hash")
423 gitBranch = releaseProps.getProperty("git.branch")
424 } catch(java.lang.RuntimeException e1) {
425 throw new GradleException("Error with git-version plugin. Directory '.git' exists but versionDetails() cannot be found.")
428 println("Using a ${CHANNEL} profile.")
430 additional_compiler_args = []
431 // configure classpath/args for j8/j11 compilation
432 if (JAVA_VERSION.equals("1.8")) {
433 JAVA_INTEGER_VERSION = string("8")
436 libDistDir = j8libDir
437 compile_source_compatibility = 1.8
438 compile_target_compatibility = 1.8
439 // these are getdown.txt properties defined dependent on the JAVA_VERSION
440 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
441 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
442 // this property is assigned below and expanded to multiple lines in the getdown task
443 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
444 // this property is for the Java library used in eclipse
445 eclipseJavaRuntimeName = string("JavaSE-1.8")
446 } else if (JAVA_VERSION.equals("11")) {
447 JAVA_INTEGER_VERSION = string("11")
449 libDistDir = j11libDir
450 compile_source_compatibility = 11
451 compile_target_compatibility = 11
452 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
453 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
454 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
455 eclipseJavaRuntimeName = string("JavaSE-11")
456 /* compile without modules -- using classpath libraries
457 additional_compiler_args += [
458 '--module-path', modules_compileClasspath.asPath,
459 '--add-modules', j11modules
462 } else if (JAVA_VERSION.equals("17")) {
463 JAVA_INTEGER_VERSION = string("17")
465 libDistDir = j17libDir
466 compile_source_compatibility = 17
467 compile_target_compatibility = 17
468 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
469 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
470 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
471 eclipseJavaRuntimeName = string("JavaSE-17")
472 /* compile without modules -- using classpath libraries
473 additional_compiler_args += [
474 '--module-path', modules_compileClasspath.asPath,
475 '--add-modules', j11modules
479 throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
484 JAVA_MIN_VERSION = JAVA_VERSION
485 JAVA_MAX_VERSION = JAVA_VERSION
486 def jreInstallsDir = string(jre_installs_dir)
487 if (jreInstallsDir.startsWith("~/")) {
488 jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
490 macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
491 windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
492 linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
493 macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_mac_x64.tar.gz")
494 windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_windows_x64.tar.gz")
495 linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_linux_x64.tar.gz")
496 install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
497 install4jConfFileName = string("jalview-install4j-conf.install4j")
498 install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
499 install4jHomeDir = install4j_home_dir
500 if (install4jHomeDir.startsWith("~/")) {
501 install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
504 resourceBuildDir = string("${buildDir}/resources")
505 resourcesBuildDir = string("${resourceBuildDir}/resources_build")
506 helpBuildDir = string("${resourceBuildDir}/help_build")
507 docBuildDir = string("${resourceBuildDir}/doc_build")
509 if (buildProperties == null) {
510 buildProperties = string("${resourcesBuildDir}/${build_properties_file}")
512 buildingHTML = string("${jalviewDir}/${doc_dir}/building.html")
513 helpParentDir = string("${jalviewDir}/${help_parent_dir}")
514 helpSourceDir = string("${helpParentDir}/${help_dir}")
515 helpFile = string("${helpBuildDir}/${help_dir}/help.jhm")
518 relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
519 jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
520 jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
522 jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
524 jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
526 jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
527 jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
528 jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
529 jalviewjsJalviewCoreHtmlFile = string("")
530 jalviewjsJalviewCoreName = string(jalviewjs_core_name)
531 jalviewjsCoreClasslists = []
532 jalviewjsJalviewTemplateName = string(jalviewjs_name)
533 jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
534 jalviewjsJ2sAltSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_alt_settings}")
535 jalviewjsJ2sProps = null
536 jalviewjsJ2sPlugin = jalviewjs_j2s_plugin
538 eclipseWorkspace = null
539 eclipseBinary = string("")
540 eclipseVersion = string("")
550 outputDir = file(classesDir)
554 srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ]
557 compileClasspath = files(sourceSets.main.java.outputDir)
558 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
560 runtimeClasspath = compileClasspath
561 runtimeClasspath += files(sourceSets.main.resources.srcDirs)
566 srcDirs cloverInstrDir
567 outputDir = cloverClassesDir
571 srcDirs = sourceSets.main.resources.srcDirs
574 compileClasspath = files( sourceSets.clover.java.outputDir )
575 //compileClasspath += files( testClassesDir )
576 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
577 compileClasspath += fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
578 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
580 runtimeClasspath = compileClasspath
585 srcDirs testSourceDir
586 outputDir = file(testClassesDir)
590 srcDirs = useClover ? sourceSets.clover.resources.srcDirs : sourceSets.main.resources.srcDirs
593 compileClasspath = files( sourceSets.test.java.outputDir )
594 compileClasspath += useClover ? sourceSets.clover.compileClasspath : sourceSets.main.compileClasspath
595 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
597 runtimeClasspath = compileClasspath
598 runtimeClasspath += files(sourceSets.test.resources.srcDirs)
604 // eclipse project and settings files creation, also used by buildship
607 name = eclipse_project_name
609 natures 'org.eclipse.jdt.core.javanature',
610 'org.eclipse.jdt.groovy.core.groovyNature',
611 'org.eclipse.buildship.core.gradleprojectnature'
613 buildCommand 'org.eclipse.jdt.core.javabuilder'
614 buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
618 //defaultOutputDir = sourceSets.main.java.outputDir
619 configurations.each{ c->
620 if (c.isCanBeResolved()) {
621 minusConfigurations += [c]
625 plusConfigurations = [ ]
629 def removeTheseToo = []
630 HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
631 cp.entries.each { entry ->
632 // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
633 // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
634 // we add the resources and help/help dirs in as libs afterwards (see below)
635 if (entry.kind == 'src') {
636 if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
637 removeTheseToo += entry
639 alreadyAddedSrcPath.putAt(entry.path, true)
644 cp.entries.removeAll(removeTheseToo)
646 //cp.entries += new Output("${eclipse_bin_dir}/main")
647 if (file(helpParentDir).isDirectory()) {
648 cp.entries += new Library(fileReference(helpParentDir))
650 if (file(resourceDir).isDirectory()) {
651 cp.entries += new Library(fileReference(resourceDir))
654 HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
656 sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
657 //don't want to add outputDir as eclipse is using its own output dir in bin/main
658 if (it.isDirectory() || ! it.exists()) {
659 // don't add dirs to classpath, especially if they don't exist
660 return false // groovy "continue" in .any closure
662 def itPath = it.toString()
663 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
664 // make relative path
665 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
667 if (alreadyAddedLibPath.get(itPath)) {
668 //println("Not adding duplicate entry "+itPath)
670 //println("Adding entry "+itPath)
671 cp.entries += new Library(fileReference(itPath))
672 alreadyAddedLibPath.put(itPath, true)
676 sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
677 //no longer want to add outputDir as eclipse is using its own output dir in bin/main
678 if (it.isDirectory() || ! it.exists()) {
679 // don't add dirs to classpath
680 return false // groovy "continue" in .any closure
683 def itPath = it.toString()
684 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
685 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
687 if (alreadyAddedLibPath.get(itPath)) {
690 def lib = new Library(fileReference(itPath))
691 lib.entryAttributes["test"] = "true"
693 alreadyAddedLibPath.put(itPath, true)
701 containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
706 // for the IDE, use java 11 compatibility
707 sourceCompatibility = compile_source_compatibility
708 targetCompatibility = compile_target_compatibility
709 javaRuntimeName = eclipseJavaRuntimeName
711 // add in jalview project specific properties/preferences into eclipse core preferences
713 withProperties { props ->
714 def jalview_prefs = new Properties()
715 def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
716 jalview_prefs.load(ins)
718 jalview_prefs.forEach { t, v ->
719 if (props.getAt(t) == null) {
723 // codestyle file -- overrides previous formatter prefs
724 def csFile = file("${jalviewDirAbsolutePath}/${eclipse_codestyle_file}")
725 if (csFile.exists()) {
726 XmlParser parser = new XmlParser()
727 def profiles = parser.parse(csFile)
728 def profile = profiles.'profile'.find { p -> (p.'@kind' == "CodeFormatterProfile" && p.'@name' == "Jalview") }
729 if (profile != null) {
730 profile.'setting'.each { s ->
732 def value = s.'@value'
733 if (id != null && value != null) {
734 props.putAt(id, value)
745 // Don't want these to be activated if in headless build
746 synchronizationTasks "eclipseSynchronizationTask"
747 //autoBuildTasks "eclipseAutoBuildTask"
753 /* hack to change eclipse prefs in .settings files other than org.eclipse.jdt.core.prefs */
754 // Class to allow updating arbitrary properties files
755 class PropertiesFile extends PropertiesPersistableConfigurationObject {
756 public PropertiesFile(PropertiesTransformer t) { super(t); }
757 @Override protected void load(Properties properties) { }
758 @Override protected void store(Properties properties) { }
759 @Override protected String getDefaultResourceName() { return ""; }
760 // This is necessary, because PropertiesPersistableConfigurationObject fails
761 // if no default properties file exists.
762 @Override public void loadDefaults() { load(new StringBufferInputStream("")); }
765 // Task to update arbitrary properties files (set outputFile)
766 class PropertiesFileTask extends PropertiesGeneratorTask<PropertiesFile> {
767 private final PropertiesFileContentMerger file;
768 public PropertiesFileTask() { file = new PropertiesFileContentMerger(getTransformer()); }
769 protected PropertiesFile create() { return new PropertiesFile(getTransformer()); }
770 protected void configure(PropertiesFile props) {
771 file.getBeforeMerged().execute(props); file.getWhenMerged().execute(props);
773 public void file(Closure closure) { ConfigureUtil.configure(closure, file); }
776 task eclipseUIPreferences(type: PropertiesFileTask) {
777 description = "Generate Eclipse additional settings"
778 def filename = "org.eclipse.jdt.ui.prefs"
779 outputFile = "$projectDir/.settings/${filename}" as File
782 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
787 task eclipseGroovyCorePreferences(type: PropertiesFileTask) {
788 description = "Generate Eclipse additional settings"
789 def filename = "org.eclipse.jdt.groovy.core.prefs"
790 outputFile = "$projectDir/.settings/${filename}" as File
793 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
798 task eclipseAllPreferences {
800 dependsOn eclipseUIPreferences
801 dependsOn eclipseGroovyCorePreferences
804 eclipseUIPreferences.mustRunAfter eclipseJdt
805 eclipseGroovyCorePreferences.mustRunAfter eclipseJdt
807 /* end of eclipse preferences hack */
815 delete cloverBuildDir
816 delete cloverReportDir
821 task cloverInstrJava(type: JavaExec) {
822 group = "Verification"
823 description = "Create clover instrumented source java files"
825 dependsOn cleanClover
827 inputs.files(sourceSets.main.allJava)
828 outputs.dir(cloverInstrDir)
830 //classpath = fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
831 classpath = sourceSets.clover.compileClasspath
832 main = "com.atlassian.clover.CloverInstr"
840 cloverInstrDir.getPath(),
842 def srcFiles = sourceSets.main.allJava.files
845 { file -> file.absolutePath }
848 args argsList.toArray()
851 delete cloverInstrDir
852 println("Clover: About to instrument "+srcFiles.size() +" files")
857 task cloverInstrTests(type: JavaExec) {
858 group = "Verification"
859 description = "Create clover instrumented source test files"
861 dependsOn cleanClover
863 inputs.files(testDir)
864 outputs.dir(cloverTestInstrDir)
866 classpath = sourceSets.clover.compileClasspath
867 main = "com.atlassian.clover.CloverInstr"
877 cloverTestInstrDir.getPath(),
879 args argsList.toArray()
882 delete cloverTestInstrDir
883 println("Clover: About to instrument test files")
889 group = "Verification"
890 description = "Create clover instrumented all source files"
892 dependsOn cloverInstrJava
893 dependsOn cloverInstrTests
897 cloverClasses.dependsOn cloverInstr
900 task cloverConsoleReport(type: JavaExec) {
901 group = "Verification"
902 description = "Creates clover console report"
905 file(cloverDb).exists()
908 inputs.dir cloverClassesDir
910 classpath = sourceSets.clover.runtimeClasspath
911 main = "com.atlassian.clover.reporters.console.ConsoleReporter"
913 if (cloverreport_mem.length() > 0) {
914 maxHeapSize = cloverreport_mem
916 if (cloverreport_jvmargs.length() > 0) {
917 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
927 args argsList.toArray()
931 task cloverHtmlReport(type: JavaExec) {
932 group = "Verification"
933 description = "Creates clover HTML report"
936 file(cloverDb).exists()
939 def cloverHtmlDir = cloverReportDir
940 inputs.dir cloverClassesDir
941 outputs.dir cloverHtmlDir
943 classpath = sourceSets.clover.runtimeClasspath
944 main = "com.atlassian.clover.reporters.html.HtmlReporter"
946 if (cloverreport_mem.length() > 0) {
947 maxHeapSize = cloverreport_mem
949 if (cloverreport_jvmargs.length() > 0) {
950 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
961 if (cloverreport_html_options.length() > 0) {
962 argsList += cloverreport_html_options.split(" ")
965 args argsList.toArray()
969 task cloverXmlReport(type: JavaExec) {
970 group = "Verification"
971 description = "Creates clover XML report"
974 file(cloverDb).exists()
977 def cloverXmlFile = "${cloverReportDir}/clover.xml"
978 inputs.dir cloverClassesDir
979 outputs.file cloverXmlFile
981 classpath = sourceSets.clover.runtimeClasspath
982 main = "com.atlassian.clover.reporters.xml.XMLReporter"
984 if (cloverreport_mem.length() > 0) {
985 maxHeapSize = cloverreport_mem
987 if (cloverreport_jvmargs.length() > 0) {
988 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
999 if (cloverreport_xml_options.length() > 0) {
1000 argsList += cloverreport_xml_options.split(" ")
1003 args argsList.toArray()
1008 group = "Verification"
1009 description = "Creates clover reports"
1011 dependsOn cloverXmlReport
1012 dependsOn cloverHtmlReport
1019 sourceCompatibility = compile_source_compatibility
1020 targetCompatibility = compile_target_compatibility
1021 options.compilerArgs += additional_compiler_args
1022 print ("Setting target compatibility to "+targetCompatibility+"\n")
1024 //classpath += configurations.cloverRuntime
1030 // JBP->BS should the print statement in doFirst refer to compile_target_compatibility ?
1031 sourceCompatibility = compile_source_compatibility
1032 targetCompatibility = compile_target_compatibility
1033 options.compilerArgs = additional_compiler_args
1034 options.encoding = "UTF-8"
1036 print ("Setting target compatibility to "+compile_target_compatibility+"\n")
1043 sourceCompatibility = compile_source_compatibility
1044 targetCompatibility = compile_target_compatibility
1045 options.compilerArgs = additional_compiler_args
1047 print ("Setting target compatibility to "+targetCompatibility+"\n")
1054 delete sourceSets.main.java.outputDir
1060 dependsOn cleanClover
1062 delete sourceSets.test.java.outputDir
1067 // format is a string like date.format("dd MMMM yyyy")
1068 def getDate(format) {
1069 return date.format(format)
1073 def convertMdToHtml (FileTree mdFiles, File cssFile) {
1074 MutableDataSet options = new MutableDataSet()
1076 def extensions = new ArrayList<>()
1077 extensions.add(AnchorLinkExtension.create())
1078 extensions.add(AutolinkExtension.create())
1079 extensions.add(StrikethroughExtension.create())
1080 extensions.add(TaskListExtension.create())
1081 extensions.add(TablesExtension.create())
1082 extensions.add(TocExtension.create())
1084 options.set(Parser.EXTENSIONS, extensions)
1086 // set GFM table parsing options
1087 options.set(TablesExtension.WITH_CAPTION, false)
1088 options.set(TablesExtension.COLUMN_SPANS, false)
1089 options.set(TablesExtension.MIN_HEADER_ROWS, 1)
1090 options.set(TablesExtension.MAX_HEADER_ROWS, 1)
1091 options.set(TablesExtension.APPEND_MISSING_COLUMNS, true)
1092 options.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
1093 options.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
1095 options.set(AnchorLinkExtension.ANCHORLINKS_SET_ID, false)
1096 options.set(AnchorLinkExtension.ANCHORLINKS_ANCHOR_CLASS, "anchor")
1097 options.set(AnchorLinkExtension.ANCHORLINKS_SET_NAME, true)
1098 options.set(AnchorLinkExtension.ANCHORLINKS_TEXT_PREFIX, "<span class=\"octicon octicon-link\"></span>")
1100 Parser parser = Parser.builder(options).build()
1101 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1103 mdFiles.each { mdFile ->
1104 // add table of contents
1105 def mdText = "[TOC]\n"+mdFile.text
1107 // grab the first top-level title
1109 def titleRegex = /(?m)^#(\s+|([^#]))(.*)/
1110 def matcher = mdText =~ titleRegex
1111 if (matcher.size() > 0) {
1112 // matcher[0][2] is the first character of the title if there wasn't any whitespace after the #
1113 title = (matcher[0][2] != null ? matcher[0][2] : "")+matcher[0][3]
1115 // or use the filename if none found
1116 if (title == null) {
1117 title = mdFile.getName()
1120 Node document = parser.parse(mdText)
1121 String htmlBody = renderer.render(document)
1122 def htmlText = '''<html>
1123 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1124 <html xmlns="http://www.w3.org/1999/xhtml">
1126 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1127 <meta http-equiv="Content-Style-Type" content="text/css" />
1128 <meta name="generator" content="flexmark" />
1130 htmlText += ((title != null) ? " <title>${title}</title>" : '' )
1132 <style type="text/css">code{white-space: pre;}</style>
1134 htmlText += ((cssFile != null) ? cssFile.text : '')
1135 htmlText += '''</head>
1138 htmlText += htmlBody
1144 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1145 def htmlFile = file(htmlFilePath)
1146 println("Creating ${htmlFilePath}")
1147 htmlFile.text = htmlText
1152 task copyDocs(type: Copy) {
1153 def inputDir = "${jalviewDir}/${doc_dir}"
1154 def outputDir = "${docBuildDir}/${doc_dir}"
1158 include('**/*.html')
1160 filter(ReplaceTokens,
1164 'Version-Rel': JALVIEW_VERSION,
1165 'Year-Rel': getDate("yyyy")
1172 exclude('**/*.html')
1177 inputs.dir(inputDir)
1178 outputs.dir(outputDir)
1182 task convertMdFiles {
1184 def mdFiles = fileTree(dir: docBuildDir, include: "**/*.md")
1185 def cssFile = file("${jalviewDir}/${flexmark_css}")
1188 convertMdToHtml(mdFiles, cssFile)
1191 inputs.files(mdFiles)
1192 inputs.file(cssFile)
1195 mdFiles.each { mdFile ->
1196 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1197 htmlFiles.add(file(htmlFilePath))
1199 outputs.files(htmlFiles)
1203 def hugoTemplateSubstitutions(String input, Map extras=null) {
1204 def replacements = [
1205 DATE: getDate("yyyy-MM-dd"),
1206 CHANNEL: propertiesChannelName,
1207 APPLICATION_NAME: applicationName,
1209 GIT_BRANCH: gitBranch,
1210 VERSION: JALVIEW_VERSION,
1211 JAVA_VERSION: JAVA_VERSION,
1212 VERSION_UNDERSCORES: JALVIEW_VERSION_UNDERSCORES,
1217 if (extras != null) {
1218 extras.each{ k, v ->
1219 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1222 replacements.each{ k, v ->
1223 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1228 def mdFileComponents(File mdFile, def dateOnly=false) {
1231 if (mdFile.exists()) {
1232 def inFrontMatter = false
1233 def firstLine = true
1234 mdFile.eachLine { line ->
1235 if (line.matches("---")) {
1236 def prev = inFrontMatter
1237 inFrontMatter = firstLine
1238 if (inFrontMatter != prev)
1241 if (inFrontMatter) {
1243 if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/) {
1244 map["date"] = new Date().parse("yyyy-MM-dd HH:mm:ss", m[0][1])
1245 } else if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2})/) {
1246 map["date"] = new Date().parse("yyyy-MM-dd", m[0][1])
1247 } else if (m = line =~ /^channel:\s*(\S+)/) {
1248 map["channel"] = m[0][1]
1249 } else if (m = line =~ /^version:\s*(\S+)/) {
1250 map["version"] = m[0][1]
1251 } else if (m = line =~ /^\s*([^:]+)\s*:\s*(\S.*)/) {
1252 map[ m[0][1] ] = m[0][2]
1254 if (dateOnly && map["date"] != null) {
1260 content += line+"\n"
1265 return dateOnly ? map["date"] : [map, content]
1268 task hugoTemplates {
1270 description "Create partially populated md pages for hugo website build"
1272 def hugoTemplatesDir = file("${jalviewDir}/${hugo_templates_dir}")
1273 def hugoBuildDir = "${jalviewDir}/${hugo_build_dir}"
1274 def templateFiles = fileTree(dir: hugoTemplatesDir)
1275 def releaseMdFile = file("${jalviewDir}/${releases_dir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1276 def whatsnewMdFile = file("${jalviewDir}/${whatsnew_dir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1277 def oldJvlFile = file("${jalviewDir}/${hugo_old_jvl}")
1278 def jalviewjsFile = file("${jalviewDir}/${hugo_jalviewjs}")
1281 // specific release template for version archive
1284 def givenDate = null
1285 def givenChannel = null
1286 def givenVersion = null
1287 if (CHANNEL == "RELEASE") {
1288 def (map, content) = mdFileComponents(releaseMdFile)
1289 givenDate = map.date
1290 givenChannel = map.channel
1291 givenVersion = map.version
1293 if (givenVersion != null && givenVersion != JALVIEW_VERSION) {
1294 throw new GradleException("'version' header (${givenVersion}) found in ${releaseMdFile} does not match JALVIEW_VERSION (${JALVIEW_VERSION})")
1297 if (whatsnewMdFile.exists())
1298 whatsnew = whatsnewMdFile.text
1301 def oldJvl = oldJvlFile.exists() ? oldJvlFile.collect{it} : []
1302 def jalviewjsLink = jalviewjsFile.exists() ? jalviewjsFile.collect{it} : []
1304 def changesHugo = null
1305 if (changes != null) {
1306 changesHugo = '<div class="release_notes">\n\n'
1307 def inSection = false
1308 changes.eachLine { line ->
1310 if (m = line =~ /^##([^#].*)$/) {
1312 changesHugo += "</div>\n\n"
1314 def section = m[0][1].trim()
1315 section = section.toLowerCase()
1316 section = section.replaceAll(/ +/, "_")
1317 section = section.replaceAll(/[^a-z0-9_\-]/, "")
1318 changesHugo += "<div class=\"${section}\">\n\n"
1320 } else if (m = line =~ /^(\s*-\s*)<!--([^>]+)-->(.*?)(<br\/?>)?\s*$/) {
1321 def comment = m[0][2].trim()
1322 if (comment != "") {
1323 comment = comment.replaceAll('"', """)
1325 comment.eachMatch(/JAL-\d+/) { jal -> issuekeys += jal }
1326 def newline = m[0][1]
1327 if (comment.trim() != "")
1328 newline += "{{<comment>}}${comment}{{</comment>}} "
1329 newline += m[0][3].trim()
1330 if (issuekeys.size() > 0)
1331 newline += " {{< jal issue=\"${issuekeys.join(",")}\" alt=\"${comment}\" >}}"
1332 if (m[0][4] != null)
1337 changesHugo += line+"\n"
1340 changesHugo += "\n</div>\n\n"
1342 changesHugo += '</div>'
1345 templateFiles.each{ templateFile ->
1346 def newFileName = string(hugoTemplateSubstitutions(templateFile.getName()))
1347 def relPath = hugoTemplatesDir.toPath().relativize(templateFile.toPath()).getParent()
1348 def newRelPathName = hugoTemplateSubstitutions( relPath.toString() )
1350 def outPathName = string("${hugoBuildDir}/$newRelPathName")
1354 rename(templateFile.getName(), newFileName)
1358 def newFile = file("${outPathName}/${newFileName}".toString())
1359 def content = newFile.text
1360 newFile.text = hugoTemplateSubstitutions(content,
1363 CHANGES: changesHugo,
1364 DATE: givenDate == null ? "" : givenDate.format("yyyy-MM-dd"),
1365 DRAFT: givenDate == null ? "true" : "false",
1366 JALVIEWJSLINK: jalviewjsLink.contains(JALVIEW_VERSION) ? "true" : "false",
1367 JVL_HEADER: oldJvl.contains(JALVIEW_VERSION) ? "jvl: true" : ""
1374 inputs.file(oldJvlFile)
1375 inputs.dir(hugoTemplatesDir)
1376 inputs.property("JALVIEW_VERSION", { JALVIEW_VERSION })
1377 inputs.property("CHANNEL", { CHANNEL })
1380 def getMdDate(File mdFile) {
1381 return mdFileComponents(mdFile, true)
1384 def getMdSections(String content) {
1386 def sectionContent = ""
1387 def sectionName = null
1388 content.eachLine { line ->
1390 if (m = line =~ /^##([^#].*)$/) {
1391 if (sectionName != null) {
1392 sections[sectionName] = sectionContent
1396 sectionName = m[0][1].trim()
1397 sectionName = sectionName.toLowerCase()
1398 sectionName = sectionName.replaceAll(/ +/, "_")
1399 sectionName = sectionName.replaceAll(/[^a-z0-9_\-]/, "")
1400 } else if (sectionName != null) {
1401 sectionContent += line+"\n"
1404 if (sectionContent != null) {
1405 sections[sectionName] = sectionContent
1410 task releasesTemplates {
1412 description "Recreate whatsNew.html and releases.html from markdown files and templates in help"
1414 def releasesTemplateFile = file("${jalviewDir}/${releases_template}")
1415 def whatsnewTemplateFile = file("${jalviewDir}/${whatsnew_template}")
1416 def releasesHtmlFile = file("${helpSourceDir}/${releases_html}")
1417 def whatsnewHtmlFile = file("${helpSourceDir}/${whatsnew_html}")
1418 def releasesMdDir = "${jalviewDir}/${releases_dir}"
1419 def whatsnewMdDir = "${jalviewDir}/${whatsnew_dir}"
1422 def releaseMdFile = file("${releasesMdDir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1423 def whatsnewMdFile = file("${whatsnewMdDir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1425 if (CHANNEL == "RELEASE") {
1426 if (!releaseMdFile.exists()) {
1427 throw new GradleException("File ${releaseMdFile} must be created for RELEASE")
1429 if (!whatsnewMdFile.exists()) {
1430 throw new GradleException("File ${whatsnewMdFile} must be created for RELEASE")
1434 def releaseFiles = fileTree(dir: releasesMdDir, include: "release-*.md")
1435 def releaseFilesDates = releaseFiles.collectEntries {
1436 [(it): getMdDate(it)]
1438 releaseFiles = releaseFiles.sort { a,b -> releaseFilesDates[a].compareTo(releaseFilesDates[b]) }
1440 def releasesTemplate = releasesTemplateFile.text
1441 def m = releasesTemplate =~ /(?s)__VERSION_LOOP_START__(.*)__VERSION_LOOP_END__/
1442 def versionTemplate = m[0][1]
1444 MutableDataSet options = new MutableDataSet()
1446 def extensions = new ArrayList<>()
1447 options.set(Parser.EXTENSIONS, extensions)
1448 options.set(Parser.HTML_BLOCK_COMMENT_ONLY_FULL_LINE, true)
1450 Parser parser = Parser.builder(options).build()
1451 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1453 def actualVersions = releaseFiles.collect { rf ->
1454 def (rfMap, rfContent) = mdFileComponents(rf)
1455 return rfMap.version
1457 def versionsHtml = ""
1458 def linkedVersions = []
1459 releaseFiles.reverse().each { rFile ->
1460 def (rMap, rContent) = mdFileComponents(rFile)
1462 def versionLink = ""
1463 def partialVersion = ""
1464 def firstPart = true
1465 rMap.version.split("\\.").each { part ->
1466 def displayPart = ( firstPart ? "" : "." ) + part
1467 partialVersion += displayPart
1469 linkedVersions.contains(partialVersion)
1470 || ( actualVersions.contains(partialVersion) && partialVersion != rMap.version )
1472 versionLink += displayPart
1474 versionLink += "<a id=\"Jalview.${partialVersion}\">${displayPart}</a>"
1475 linkedVersions += partialVersion
1479 def displayDate = releaseFilesDates[rFile].format("dd/MM/yyyy")
1482 def rContentProcessed = ""
1483 rContent.eachLine { line ->
1484 if (lm = line =~ /^(\s*-)(\s*<!--[^>]*?-->)(.*)$/) {
1485 line = "${lm[0][1]}${lm[0][3]}${lm[0][2]}"
1486 } else if (lm = line =~ /^###([^#]+.*)$/) {
1487 line = "_${lm[0][1].trim()}_"
1489 rContentProcessed += line + "\n"
1492 def rContentSections = getMdSections(rContentProcessed)
1493 def rVersion = versionTemplate
1494 if (rVersion != "") {
1495 def rNewFeatures = rContentSections["new_features"]
1496 def rIssuesResolved = rContentSections["issues_resolved"]
1497 Node newFeaturesNode = parser.parse(rNewFeatures)
1498 String newFeaturesHtml = renderer.render(newFeaturesNode)
1499 Node issuesResolvedNode = parser.parse(rIssuesResolved)
1500 String issuesResolvedHtml = renderer.render(issuesResolvedNode)
1501 rVersion = hugoTemplateSubstitutions(rVersion,
1503 VERSION: rMap.version,
1504 VERSION_LINK: versionLink,
1505 DISPLAY_DATE: displayDate,
1506 NEW_FEATURES: newFeaturesHtml,
1507 ISSUES_RESOLVED: issuesResolvedHtml
1510 versionsHtml += rVersion
1514 releasesTemplate = releasesTemplate.replaceAll("(?s)__VERSION_LOOP_START__.*__VERSION_LOOP_END__", versionsHtml)
1515 releasesTemplate = hugoTemplateSubstitutions(releasesTemplate)
1516 releasesHtmlFile.text = releasesTemplate
1518 if (whatsnewMdFile.exists()) {
1519 def wnDisplayDate = releaseFilesDates[releaseMdFile] != null ? releaseFilesDates[releaseMdFile].format("dd MMMM yyyy") : ""
1520 def whatsnewMd = hugoTemplateSubstitutions(whatsnewMdFile.text)
1521 Node whatsnewNode = parser.parse(whatsnewMd)
1522 String whatsnewHtml = renderer.render(whatsnewNode)
1523 whatsnewHtml = whatsnewTemplateFile.text.replaceAll("__WHATS_NEW__", whatsnewHtml)
1524 whatsnewHtmlFile.text = hugoTemplateSubstitutions(whatsnewHtml,
1526 DISPLAY_DATE: wnDisplayDate
1533 inputs.file(releasesTemplateFile)
1534 inputs.file(whatsnewTemplateFile)
1535 inputs.dir(releasesMdDir)
1536 inputs.dir(whatsnewMdDir)
1537 outputs.file(releasesHtmlFile)
1538 outputs.file(whatsnewHtmlFile)
1542 task copyHelp(type: Copy) {
1543 dependsOn releasesTemplates
1545 def inputDir = helpSourceDir
1546 def outputDir = "${helpBuildDir}/${help_dir}"
1550 include('**/*.html')
1554 filter(ReplaceTokens,
1558 'Version-Rel': JALVIEW_VERSION,
1559 'Year-Rel': getDate("yyyy")
1566 exclude('**/*.html')
1573 inputs.dir(inputDir)
1574 outputs.files(helpFile)
1575 outputs.dir(outputDir)
1579 task copyResources(type: Copy) {
1581 description = "Copy (and make text substitutions in) the resources dir to the build area"
1583 def inputDir = resourceDir
1584 def outputDir = resourcesBuildDir
1588 include('**/*.html')
1590 filter(ReplaceTokens,
1594 'Version-Rel': JALVIEW_VERSION,
1595 'Year-Rel': getDate("yyyy")
1602 exclude('**/*.html')
1607 inputs.dir(inputDir)
1608 outputs.dir(outputDir)
1611 task copyChannelResources(type: Copy) {
1612 dependsOn copyResources
1614 description = "Copy the channel resources dir to the build resources area"
1616 def inputDir = "${channelDir}/${resource_dir}"
1617 def outputDir = resourcesBuildDir
1621 inputs.dir(inputDir)
1622 outputs.dir(outputDir)
1625 task createBuildProperties(type: WriteProperties) {
1626 dependsOn copyResources
1628 description = "Create the ${buildProperties} file"
1630 inputs.dir(sourceDir)
1631 inputs.dir(resourcesBuildDir)
1632 outputFile (buildProperties)
1633 // taking time specific comment out to allow better incremental builds
1634 comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
1635 //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
1636 property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
1637 property "VERSION", JALVIEW_VERSION
1638 property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
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 convertMdFiles
1677 dependsOn buildIndices
1681 compileJava.dependsOn prepare
1682 run.dependsOn compileJava
1683 //run.dependsOn prepare
1686 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1691 dependsOn cloverClasses
1693 dependsOn compileJava //?
1697 includeGroups testng_groups
1698 excludeGroups testng_excluded_groups
1700 useDefaultListeners=true
1703 maxHeapSize = "1024m"
1705 workingDir = jalviewDir
1706 def testLaf = project.findProperty("test_laf")
1707 if (testLaf != null) {
1708 println("Setting Test LaF to '${testLaf}'")
1709 systemProperty "laf", testLaf
1711 def testHiDPIScale = project.findProperty("test_HiDPIScale")
1712 if (testHiDPIScale != null) {
1713 println("Setting Test HiDPI Scale to '${testHiDPIScale}'")
1714 systemProperty "sun.java2d.uiScale", testHiDPIScale
1716 sourceCompatibility = compile_source_compatibility
1717 targetCompatibility = compile_target_compatibility
1718 jvmArgs += additional_compiler_args
1722 println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1728 task compileLinkCheck(type: JavaCompile) {
1730 classpath = files("${jalviewDir}/${utils_dir}")
1731 destinationDir = file("${jalviewDir}/${utils_dir}")
1732 source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1734 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1735 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1736 outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1737 outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1741 task linkCheck(type: JavaExec) {
1743 dependsOn compileLinkCheck
1745 def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1746 classpath = files("${jalviewDir}/${utils_dir}")
1747 main = "HelpLinksChecker"
1748 workingDir = jalviewDir
1749 args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1751 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1752 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1755 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1759 inputs.dir(helpBuildDir)
1760 outputs.file(helpLinksCheckerOutFile)
1764 // import the pubhtmlhelp target
1765 ant.properties.basedir = "${jalviewDir}"
1766 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1767 ant.importBuild "${utils_dir}/publishHelp.xml"
1770 task cleanPackageDir(type: Delete) {
1772 delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1782 attributes "Main-Class": main_class,
1783 "Permissions": "all-permissions",
1784 "Application-Name": applicationName,
1785 "Codebase": application_codebase,
1786 "Implementation-Version": JALVIEW_VERSION
1789 def outputDir = "${jalviewDir}/${package_dir}"
1790 destinationDirectory = file(outputDir)
1791 archiveFileName = rootProject.name+".jar"
1792 duplicatesStrategy "EXCLUDE"
1799 exclude "**/*.jar.*"
1801 inputs.dir(sourceSets.main.java.outputDir)
1802 sourceSets.main.resources.srcDirs.each{ dir ->
1805 outputs.file("${outputDir}/${archiveFileName}")
1809 task copyJars(type: Copy) {
1810 from fileTree(dir: classesDir, include: "**/*.jar").files
1811 into "${jalviewDir}/${package_dir}"
1815 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1816 task syncJars(type: Sync) {
1818 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1819 into "${jalviewDir}/${package_dir}"
1821 include jar.archiveFileName.getOrNull()
1828 description = "Put all required libraries in dist"
1829 // order of "cleanPackageDir", "copyJars", "jar" important!
1830 jar.mustRunAfter cleanPackageDir
1831 syncJars.mustRunAfter cleanPackageDir
1832 dependsOn cleanPackageDir
1835 outputs.dir("${jalviewDir}/${package_dir}")
1840 dependsOn cleanPackageDir
1847 group = "distribution"
1848 description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1852 from ("${jalviewDir}/${libDistDir}") {
1856 attributes "Implementation-Version": JALVIEW_VERSION,
1857 "Application-Name": applicationName
1860 duplicatesStrategy "INCLUDE"
1862 mainClassName = shadow_jar_main_class
1864 classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1869 task getdownWebsite() {
1870 group = "distribution"
1871 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1876 def getdownWebsiteResourceFilenames = []
1877 def getdownResourceDir = getdownResourceDir
1878 def getdownResourceFilenames = []
1881 // clean the getdown website and files dir before creating getdown folders
1882 delete getdownAppBaseDir
1883 delete getdownFilesDir
1886 from buildProperties
1887 rename(file(buildProperties).getName(), getdown_build_properties)
1890 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1893 from channelPropsFile
1894 into getdownAppBaseDir
1896 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
1898 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
1899 def props = project.properties.sort { it.key }
1900 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
1901 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
1903 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
1904 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
1906 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
1907 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
1909 if (getdownImagesDir != null && file(getdownImagesDir).exists()) {
1910 props.put("getdown_txt_ui.background_image", "${getdownImagesDir}/${getdown_background_image}")
1911 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesDir}/${getdown_instant_background_image}")
1912 props.put("getdown_txt_ui.error_background", "${getdownImagesDir}/${getdown_error_background}")
1913 props.put("getdown_txt_ui.progress_image", "${getdownImagesDir}/${getdown_progress_image}")
1914 props.put("getdown_txt_ui.icon", "${getdownImagesDir}/${getdown_icon}")
1915 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesDir}/${getdown_mac_dock_icon}")
1918 props.put("getdown_txt_title", jalview_name)
1919 props.put("getdown_txt_ui.name", applicationName)
1921 // start with appbase
1922 getdownTextLines += "appbase = ${getdownAppBase}"
1923 props.each{ prop, val ->
1924 if (prop.startsWith("getdown_txt_") && val != null) {
1925 if (prop.startsWith("getdown_txt_multi_")) {
1926 def key = prop.substring(18)
1927 val.split(",").each{ v ->
1928 def line = "${key} = ${v}"
1929 getdownTextLines += line
1932 // file values rationalised
1933 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
1935 if (val.indexOf('/') == 0) {
1938 } else if (val.indexOf('/') > 0) {
1939 // relative path (relative to jalviewDir)
1940 r = file( "${jalviewDir}/${val}" )
1943 val = "${getdown_resource_dir}/" + r.getName()
1944 getdownWebsiteResourceFilenames += val
1945 getdownResourceFilenames += r.getPath()
1948 if (! prop.startsWith("getdown_txt_resource")) {
1949 def line = prop.substring(12) + " = ${val}"
1950 getdownTextLines += line
1956 getdownWebsiteResourceFilenames.each{ filename ->
1957 getdownTextLines += "resource = ${filename}"
1959 getdownResourceFilenames.each{ filename ->
1962 into getdownResourceDir
1966 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
1967 getdownWrapperScripts.each{ script ->
1968 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
1972 into "${getdownAppBaseDir}/${getdown_wrapper_script_dir}"
1974 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
1979 fileTree(file(package_dir)).each{ f ->
1980 if (f.isDirectory()) {
1981 def files = fileTree(dir: f, include: ["*"]).getFiles()
1983 } else if (f.exists()) {
1987 def jalviewJar = jar.archiveFileName.getOrNull()
1988 // put jalview.jar first for CLASSPATH and .properties files reasons
1989 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
1990 def name = f.getName()
1991 def line = "code = ${getdownAppDistDir}/${name}"
1992 getdownTextLines += line
1999 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
2001 if (JAVA_VERSION.equals("11")) {
2002 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
2003 j11libFiles.sort().each{f ->
2004 def name = f.getName()
2005 def line = "code = ${getdown_j11lib_dir}/${name}"
2006 getdownTextLines += line
2009 into getdownJ11libDir
2015 // 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.
2016 //getdownTextLines += "class = " + file(getdownLauncher).getName()
2017 getdownTextLines += "resource = ${getdown_launcher_new}"
2018 getdownTextLines += "class = ${main_class}"
2019 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
2020 if (getdownSetAppBaseProperty) {
2021 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
2022 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
2025 def getdownTxt = file("${getdownAppBaseDir}/getdown.txt")
2026 getdownTxt.write(getdownTextLines.join("\n"))
2028 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
2029 def launchJvl = file("${getdownAppBaseDir}/${getdownLaunchJvl}")
2030 launchJvl.write("appbase=${getdownAppBase}")
2032 // files going into the getdown website dir: getdown-launcher.jar
2034 from getdownLauncher
2035 rename(file(getdownLauncher).getName(), getdown_launcher_new)
2036 into getdownAppBaseDir
2039 // files going into the getdown website dir: getdown-launcher(-local).jar
2041 from getdownLauncher
2042 if (file(getdownLauncher).getName() != getdown_launcher) {
2043 rename(file(getdownLauncher).getName(), getdown_launcher)
2045 into getdownAppBaseDir
2048 // files going into the getdown website dir: ./install dir and files
2049 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
2052 from getdownLauncher
2053 from "${getdownAppDir}/${getdown_build_properties}"
2054 if (file(getdownLauncher).getName() != getdown_launcher) {
2055 rename(file(getdownLauncher).getName(), getdown_launcher)
2057 into getdownInstallDir
2060 // and make a copy in the getdown files dir (these are not downloaded by getdown)
2062 from getdownInstallDir
2063 into getdownFilesInstallDir
2067 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2071 from getdownLauncher
2072 from "${getdownAppBaseDir}/${getdown_build_properties}"
2073 from "${getdownAppBaseDir}/${channel_props}"
2074 if (file(getdownLauncher).getName() != getdown_launcher) {
2075 rename(file(getdownLauncher).getName(), getdown_launcher)
2077 into getdownFilesDir
2080 // and ./resource (not all downloaded by getdown)
2082 from getdownResourceDir
2083 into "${getdownFilesDir}/${getdown_resource_dir}"
2088 inputs.dir("${jalviewDir}/${package_dir}")
2090 outputs.dir(getdownAppBaseDir)
2091 outputs.dir(getdownFilesDir)
2095 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
2096 task getdownDigestDir(type: JavaExec) {
2098 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
2100 def digestDirPropertyName = "DIGESTDIR"
2102 classpath = files(getdownLauncher)
2103 def digestDir = findProperty(digestDirPropertyName)
2104 if (digestDir == null) {
2105 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
2109 main = "com.threerings.getdown.tools.Digester"
2113 task getdownDigest(type: JavaExec) {
2114 group = "distribution"
2115 description = "Digest the getdown website folder"
2116 dependsOn getdownWebsite
2118 classpath = files(getdownLauncher)
2120 main = "com.threerings.getdown.tools.Digester"
2121 args getdownAppBaseDir
2122 inputs.dir(getdownAppBaseDir)
2123 outputs.file("${getdownAppBaseDir}/digest2.txt")
2128 group = "distribution"
2129 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
2130 dependsOn getdownDigest
2132 if (reportRsyncCommand) {
2133 def fromDir = getdownAppBaseDir + (getdownAppBaseDir.endsWith('/')?'':'/')
2134 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
2135 println "LIKELY RSYNC COMMAND:"
2136 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
2137 if (RUNRSYNC == "true") {
2139 commandLine "mkdir", "-p", toDir
2142 commandLine "rsync", "-avh", "--delete", fromDir, toDir
2150 task getdownArchiveBuild() {
2151 group = "distribution"
2152 description = "Put files in the archive dir to go on the website"
2154 dependsOn getdownWebsite
2156 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
2157 def vDir = "${getdownArchiveDir}/${v}"
2158 getdownFullArchiveDir = "${vDir}/getdown"
2159 getdownVersionLaunchJvl = "${vDir}/jalview-${v}.jvl"
2161 def vAltDir = "alt_${v}"
2162 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
2165 // cleanup old "old" dir
2166 delete getdownArchiveDir
2168 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
2169 getdownArchiveTxt.getParentFile().mkdirs()
2170 def getdownArchiveTextLines = []
2171 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
2175 from "${getdownAppBaseDir}/${getdownAppDistDir}"
2176 into "${getdownFullArchiveDir}/${vAltDir}"
2179 getdownTextLines.each { line ->
2180 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
2181 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
2182 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
2183 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
2184 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
2185 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
2186 // remove the existing resource = resource/ or bin/ lines
2187 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
2188 getdownArchiveTextLines += line
2192 // the resource dir -- add these files as resource lines in getdown.txt
2194 from "${archiveImagesDir}"
2195 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
2197 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
2201 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
2203 def vLaunchJvl = file(getdownVersionLaunchJvl)
2204 vLaunchJvl.getParentFile().mkdirs()
2205 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
2206 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
2207 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
2208 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
2209 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
2210 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
2212 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2214 from getdownLauncher
2215 from "${getdownAppBaseDir}/${getdownLaunchJvl}"
2216 from "${getdownAppBaseDir}/${getdown_launcher_new}"
2217 from "${getdownAppBaseDir}/${channel_props}"
2218 if (file(getdownLauncher).getName() != getdown_launcher) {
2219 rename(file(getdownLauncher).getName(), getdown_launcher)
2221 into getdownFullArchiveDir
2227 task getdownArchiveDigest(type: JavaExec) {
2228 group = "distribution"
2229 description = "Digest the getdown archive folder"
2231 dependsOn getdownArchiveBuild
2234 classpath = files(getdownLauncher)
2235 args getdownFullArchiveDir
2237 main = "com.threerings.getdown.tools.Digester"
2238 inputs.dir(getdownFullArchiveDir)
2239 outputs.file("${getdownFullArchiveDir}/digest2.txt")
2242 task getdownArchive() {
2243 group = "distribution"
2244 description = "Build the website archive dir with getdown digest"
2246 dependsOn getdownArchiveBuild
2247 dependsOn getdownArchiveDigest
2250 tasks.withType(JavaCompile) {
2251 options.encoding = 'UTF-8'
2257 delete getdownAppBaseDir
2258 delete getdownFilesDir
2259 delete getdownArchiveDir
2265 if (file(install4jHomeDir).exists()) {
2267 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
2268 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
2269 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
2270 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
2272 installDir(file(install4jHomeDir))
2274 mediaTypes = Arrays.asList(install4j_media_types.split(","))
2278 task copyInstall4jTemplate {
2279 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
2280 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
2281 inputs.file(install4jTemplateFile)
2282 inputs.file(install4jFileAssociationsFile)
2283 inputs.property("CHANNEL", { CHANNEL })
2284 outputs.file(install4jConfFile)
2287 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
2289 // turn off code signing if no OSX_KEYPASS
2290 if (OSX_KEYPASS == "") {
2291 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
2292 codeSigning.'@macEnabled' = "false"
2294 install4jConfigXml.'**'.windows.each { windows ->
2295 windows.'@runPostProcessor' = "false"
2299 // disable install screen for OSX dmg (for 2.11.2.0)
2300 install4jConfigXml.'**'.macosArchive.each { macosArchive ->
2301 macosArchive.attributes().remove('executeSetupApp')
2302 macosArchive.attributes().remove('setupAppId')
2305 // turn off checksum creation for LOCAL channel
2306 def e = install4jConfigXml.application[0]
2307 e.'@createChecksums' = string(install4jCheckSums)
2309 // put file association actions where placeholder action is
2310 def install4jFileAssociationsText = install4jFileAssociationsFile.text
2311 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
2312 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
2313 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
2314 def parent = a.parent()
2316 fileAssociationActions.each { faa ->
2319 // don't need to continue in .any loop once replacements have been made
2324 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
2325 // NB we're deleting the /other/ one!
2326 // Also remove the examples subdir from non-release versions
2327 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
2328 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
2329 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
2330 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
2332 // remove the examples subdir from Full File Set
2333 def files = install4jConfigXml.files[0]
2334 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
2335 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
2336 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
2337 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
2338 dirEntry.parent().remove(dirEntry)
2340 install4jConfigXml.'**'.action.any { a ->
2341 if (a.'@customizedId' == customizedIdToDelete) {
2342 def parent = a.parent()
2348 // write install4j file
2349 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
2356 delete install4jConfFile
2360 task cleanInstallersDataFiles {
2361 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2362 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2363 def hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
2365 delete installersOutputTxt
2366 delete installersSha256
2367 delete hugoDataJsonFile
2371 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2372 group = "distribution"
2373 description = "Create the install4j installers"
2375 dependsOn copyInstall4jTemplate
2376 dependsOn cleanInstallersDataFiles
2378 projectFile = install4jConfFile
2380 // create an md5 for the input files to use as version for install4j conf file
2381 def digest = MessageDigest.getInstance("MD5")
2383 (file("${install4jDir}/${install4j_template}").text +
2384 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2385 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2386 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2387 if (filesMd5.length() >= 8) {
2388 filesMd5 = filesMd5.substring(0,8)
2390 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2393 'JALVIEW_NAME': jalview_name,
2394 'JALVIEW_APPLICATION_NAME': applicationName,
2395 'JALVIEW_DIR': "../..",
2396 'OSX_KEYSTORE': OSX_KEYSTORE,
2397 'OSX_APPLEID': OSX_APPLEID,
2398 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2399 'JSIGN_SH': JSIGN_SH,
2400 'JRE_DIR': getdown_app_dir_java,
2401 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2402 'JALVIEW_VERSION': JALVIEW_VERSION,
2403 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2404 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2405 'JAVA_VERSION': JAVA_VERSION,
2406 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2407 'VERSION': JALVIEW_VERSION,
2408 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2409 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2410 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2411 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2412 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2413 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2414 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2415 'BUNDLE_ID': install4jBundleId,
2416 'INTERNAL_ID': install4jInternalId,
2417 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2418 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2419 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
2420 'WRAPPER_LINK': getdownWrapperLink,
2421 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2422 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2423 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2424 'INSTALLER_NAME': install4jInstallerName,
2425 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2426 'GETDOWN_CHANNEL_DIR': getdownChannelDir,
2427 'GETDOWN_FILES_DIR': getdown_files_dir,
2428 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2429 'GETDOWN_DIST_DIR': getdownAppDistDir,
2430 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2431 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2432 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2433 'BUILD_DIR': install4jBuildDir,
2434 'APPLICATION_CATEGORIES': install4j_application_categories,
2435 'APPLICATION_FOLDER': install4jApplicationFolder,
2436 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2437 'EXECUTABLE_NAME': install4jExecutableName,
2438 'EXTRA_SCHEME': install4jExtraScheme,
2439 'MAC_ICONS_FILE': install4jMacIconsFile,
2440 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2441 'PNG_ICON_FILE': install4jPngIconFile,
2442 'BACKGROUND': install4jBackground,
2446 //println("INSTALL4J VARIABLES:")
2447 //variables.each{k,v->println("${k}=${v}")}
2449 destination = "${jalviewDir}/${install4jBuildDir}"
2450 buildSelected = true
2452 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2454 disableSigning = true
2455 disableNotarization = true
2459 macKeystorePassword = OSX_KEYPASS
2462 if (OSX_ALTOOLPASS) {
2463 appleIdPassword = OSX_ALTOOLPASS
2464 disableNotarization = false
2466 disableNotarization = true
2470 println("Using projectFile "+projectFile)
2471 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2475 inputs.dir(getdownAppBaseDir)
2476 inputs.file(install4jConfFile)
2477 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2478 inputs.dir(macosJavaVMDir)
2479 inputs.dir(windowsJavaVMDir)
2480 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2483 def getDataHash(File myFile) {
2484 HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
2485 return myFile.exists()
2487 "file" : myFile.getName(),
2488 "filesize" : myFile.length(),
2489 "sha256" : hash.toString()
2494 def writeDataJsonFile(File installersOutputTxt, File installersSha256, File dataJsonFile) {
2496 "channel" : getdownChannelName,
2497 "date" : getDate("yyyy-MM-dd HH:mm:ss"),
2498 "git-commit" : "${gitHash} [${gitBranch}]",
2499 "version" : JALVIEW_VERSION
2501 // install4j installer files
2502 if (installersOutputTxt.exists()) {
2504 installersOutputTxt.readLines().each { def line ->
2505 if (line.startsWith("#")) {
2508 line.replaceAll("\n","")
2509 def vals = line.split("\t")
2510 def filename = vals[3]
2511 def filesize = file(filename).length()
2512 filename = filename.replaceAll(/^.*\//, "")
2513 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2514 idHash."${filename}" = vals[0]
2516 if (install4jCheckSums && installersSha256.exists()) {
2517 installersSha256.readLines().each { def line ->
2518 if (line.startsWith("#")) {
2521 line.replaceAll("\n","")
2522 def vals = line.split(/\s+\*?/)
2523 def filename = vals[1]
2524 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2530 "JAR": shadowJar.archiveFile, // executable JAR
2531 "JVL": getdownVersionLaunchJvl, // version JVL
2532 "SOURCE": sourceDist.archiveFile // source TGZ
2533 ].each { key, value ->
2534 def file = file(value)
2535 if (file.exists()) {
2536 def fileHash = getDataHash(file)
2537 if (fileHash != null) {
2538 hash."${key}" = fileHash;
2542 return dataJsonFile.write(new JsonBuilder(hash).toPrettyString())
2545 task staticMakeInstallersJsonFile {
2547 def output = findProperty("i4j_output")
2548 def sha256 = findProperty("i4j_sha256")
2549 def json = findProperty("i4j_json")
2550 if (output == null || sha256 == null || json == null) {
2551 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2553 writeDataJsonFile(file(output), file(sha256), file(json))
2558 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'."
2738 dependsOn pubhtmlhelp
2740 inputs.dir("${helpBuildDir}/${help_dir}")
2741 outputs.dir("${buildDir}/distributions/${help_dir}")
2745 task j2sSetHeadlessBuild {
2752 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2754 description "Enable the alternative J2S Config file for headless build"
2756 outputFile = jalviewjsJ2sSettingsFileName
2757 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2758 def j2sProps = new Properties()
2759 if (j2sPropsFile.exists()) {
2761 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2762 j2sProps.load(j2sPropsFileFIS)
2763 j2sPropsFileFIS.close()
2765 j2sProps.each { prop, val ->
2768 } catch (Exception e) {
2769 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2773 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2774 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2779 task jalviewjsSetEclipseWorkspace {
2780 def propKey = "jalviewjs_eclipse_workspace"
2782 if (project.hasProperty(propKey)) {
2783 propVal = project.getProperty(propKey)
2784 if (propVal.startsWith("~/")) {
2785 propVal = System.getProperty("user.home") + propVal.substring(1)
2788 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2789 def propsFile = file(propsFileName)
2790 def eclipseWsDir = propVal
2791 def props = new Properties()
2793 def writeProps = true
2794 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2795 def ins = new FileInputStream(propsFileName)
2798 if (props.getProperty(propKey, null) != null) {
2799 eclipseWsDir = props.getProperty(propKey)
2804 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2805 def tempDir = File.createTempDir()
2806 eclipseWsDir = tempDir.getAbsolutePath()
2809 eclipseWorkspace = file(eclipseWsDir)
2812 // do not run a headless transpile when we claim to be in Eclipse
2814 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2815 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2817 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2821 props.setProperty(propKey, eclipseWsDir)
2822 propsFile.parentFile.mkdirs()
2823 def bytes = new ByteArrayOutputStream()
2824 props.store(bytes, null)
2825 def propertiesString = bytes.toString()
2826 propsFile.text = propertiesString
2832 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2835 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2836 outputs.file(propsFileName)
2837 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2841 task jalviewjsEclipsePaths {
2844 def eclipseRoot = jalviewjs_eclipse_root
2845 if (eclipseRoot.startsWith("~/")) {
2846 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
2848 if (OperatingSystem.current().isMacOsX()) {
2849 eclipseRoot += "/Eclipse.app"
2850 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
2851 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
2852 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
2853 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2854 eclipseRoot += "/eclipse"
2856 eclipseBinary = "${eclipseRoot}/eclipse.exe"
2857 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2858 } else { // linux or unix
2859 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2860 eclipseRoot += "/eclipse"
2861 println("eclipseDir exists")
2863 eclipseBinary = "${eclipseRoot}/eclipse"
2864 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2867 eclipseVersion = "4.13" // default
2868 def assumedVersion = true
2869 if (file(eclipseProduct).exists()) {
2870 def fis = new FileInputStream(eclipseProduct)
2871 def props = new Properties()
2873 eclipseVersion = props.getProperty("version")
2875 assumedVersion = false
2878 def propKey = "eclipse_debug"
2879 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
2882 // do not run a headless transpile when we claim to be in Eclipse
2884 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2885 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2887 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2890 if (!assumedVersion) {
2891 println("ECLIPSE VERSION=${eclipseVersion}")
2897 task printProperties {
2899 description "Output to console all System.properties"
2901 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
2907 dependsOn eclipseProject
2908 dependsOn eclipseClasspath
2909 dependsOn eclipseJdt
2913 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
2914 task jalviewjsEclipseCopyDropins(type: Copy) {
2915 dependsOn jalviewjsEclipsePaths
2917 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
2918 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
2919 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
2926 // this eclipse -clean doesn't actually work
2927 task jalviewjsCleanEclipse(type: Exec) {
2928 dependsOn eclipseSetup
2929 dependsOn jalviewjsEclipsePaths
2930 dependsOn jalviewjsEclipseCopyDropins
2932 executable(eclipseBinary)
2933 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
2939 def inputString = """exit
2942 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
2943 standardInput = inputByteStream
2946 /* not really working yet
2947 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
2951 task jalviewjsTransferUnzipSwingJs {
2952 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
2956 from zipTree(file_zip)
2957 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2961 inputs.file file_zip
2962 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2966 task jalviewjsTransferUnzipLib {
2967 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
2970 zipFiles.each { file_zip ->
2972 from zipTree(file_zip)
2973 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2978 inputs.files zipFiles
2979 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2983 task jalviewjsTransferUnzipAllLibs {
2984 dependsOn jalviewjsTransferUnzipSwingJs
2985 dependsOn jalviewjsTransferUnzipLib
2989 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
2991 description "Create the alternative j2s file from the j2s.* properties"
2993 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
2994 def siteDirProperty = "j2s.site.directory"
2995 def setSiteDir = false
2996 jalviewjsJ2sProps.each { prop, val ->
2998 if (prop == siteDirProperty) {
2999 if (!(val.startsWith('/') || val.startsWith("file://") )) {
3000 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
3006 if (!setSiteDir) { // default site location, don't override specifically set property
3007 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
3010 outputFile = jalviewjsJ2sAltSettingsFileName
3013 inputs.properties(jalviewjsJ2sProps)
3014 outputs.file(jalviewjsJ2sAltSettingsFileName)
3019 task jalviewjsEclipseSetup {
3020 dependsOn jalviewjsEclipseCopyDropins
3021 dependsOn jalviewjsSetEclipseWorkspace
3022 dependsOn jalviewjsCreateJ2sSettings
3026 task jalviewjsSyncAllLibs (type: Sync) {
3027 dependsOn jalviewjsTransferUnzipAllLibs
3028 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
3029 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
3030 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3034 def outputFiles = []
3035 rename { filename ->
3036 outputFiles += "${outputDir}/${filename}"
3043 // should this be exclude really ?
3044 duplicatesStrategy "INCLUDE"
3046 outputs.files outputFiles
3047 inputs.files inputFiles
3051 task jalviewjsSyncResources (type: Sync) {
3052 dependsOn buildResources
3054 def inputFiles = fileTree(dir: resourcesBuildDir)
3055 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3059 def outputFiles = []
3060 rename { filename ->
3061 outputFiles += "${outputDir}/${filename}"
3067 outputs.files outputFiles
3068 inputs.files inputFiles
3072 task jalviewjsSyncSiteResources (type: Sync) {
3073 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
3074 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3078 def outputFiles = []
3079 rename { filename ->
3080 outputFiles += "${outputDir}/${filename}"
3086 outputs.files outputFiles
3087 inputs.files inputFiles
3091 task jalviewjsSyncBuildProperties (type: Sync) {
3092 dependsOn createBuildProperties
3093 def inputFiles = [file(buildProperties)]
3094 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3098 def outputFiles = []
3099 rename { filename ->
3100 outputFiles += "${outputDir}/${filename}"
3106 outputs.files outputFiles
3107 inputs.files inputFiles
3111 task jalviewjsProjectImport(type: Exec) {
3112 dependsOn eclipseSetup
3113 dependsOn jalviewjsEclipsePaths
3114 dependsOn jalviewjsEclipseSetup
3117 // do not run a headless import when we claim to be in Eclipse
3119 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3120 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3122 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3126 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
3127 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
3128 executable(eclipseBinary)
3129 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
3133 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3135 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3136 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3139 inputs.file("${jalviewDir}/.project")
3140 outputs.upToDateWhen {
3141 file(projdir).exists()
3146 task jalviewjsTranspile(type: Exec) {
3147 dependsOn jalviewjsEclipseSetup
3148 dependsOn jalviewjsProjectImport
3149 dependsOn jalviewjsEclipsePaths
3151 dependsOn jalviewjsEnableAltFileProperty
3155 // do not run a headless transpile when we claim to be in Eclipse
3157 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3158 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3160 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3164 executable(eclipseBinary)
3165 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
3169 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3171 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3172 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3178 stdout = new ByteArrayOutputStream()
3179 stderr = new ByteArrayOutputStream()
3181 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
3182 def logOutFile = file(logOutFileName)
3183 logOutFile.createNewFile()
3184 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
3185 BINARY: ${eclipseBinary}
3186 VERSION: ${eclipseVersion}
3187 WORKSPACE: ${eclipseWorkspace}
3188 DEBUG: ${eclipseDebug}
3191 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3192 // combine stdout and stderr
3193 def logErrFOS = logOutFOS
3195 if (jalviewjs_j2s_to_console.equals("true")) {
3196 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3197 new org.apache.tools.ant.util.TeeOutputStream(
3201 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3202 new org.apache.tools.ant.util.TeeOutputStream(
3207 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3210 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3217 if (stdout.toString().contains("Error processing ")) {
3218 // j2s did not complete transpile
3219 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3220 if (jalviewjs_ignore_transpile_errors.equals("true")) {
3221 println("IGNORING TRANSPILE ERRORS")
3222 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3224 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3229 inputs.dir("${jalviewDir}/${sourceDir}")
3230 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
3231 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
3235 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
3237 def stdout = new ByteArrayOutputStream()
3238 def stderr = new ByteArrayOutputStream()
3240 def coreFile = file(jsfile)
3242 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
3244 logOutFile.createNewFile()
3245 logOutFile.append(msg+"\n")
3247 def coreTop = file(prefixFile)
3248 def coreBottom = file(suffixFile)
3249 coreFile.getParentFile().mkdirs()
3250 coreFile.createNewFile()
3251 coreFile.write( coreTop.getText("UTF-8") )
3255 def t = f.getText("UTF-8")
3256 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
3257 coreFile.append( t )
3259 msg = "...file '"+f.getPath()+"' does not exist, skipping"
3261 logOutFile.append(msg+"\n")
3264 coreFile.append( coreBottom.getText("UTF-8") )
3266 msg = "Generating ${zjsfile}"
3268 logOutFile.append(msg+"\n")
3269 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3270 def logErrFOS = logOutFOS
3273 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
3274 main = "com.google.javascript.jscomp.CommandLineRunner"
3275 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
3276 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
3279 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
3281 logOutFile.append(msg+"\n")
3283 if (logOutConsole) {
3284 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3285 new org.apache.tools.ant.util.TeeOutputStream(
3289 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3290 new org.apache.tools.ant.util.TeeOutputStream(
3295 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3298 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3305 logOutFile.append(msg+"\n")
3309 task jalviewjsBuildAllCores {
3311 description "Build the core js lib closures listed in the classlists dir"
3312 dependsOn jalviewjsTranspile
3313 dependsOn jalviewjsTransferUnzipSwingJs
3315 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
3316 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
3317 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
3318 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
3319 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
3320 def prefixFile = "${jsDir}/core/coretop2.js"
3321 def suffixFile = "${jsDir}/core/corebottom2.js"
3323 inputs.file prefixFile
3324 inputs.file suffixFile
3326 def classlistFiles = []
3327 // add the classlists found int the jalviewjs_classlists_dir
3328 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
3330 def name = file.getName() - ".txt"
3337 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
3338 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
3339 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
3341 jalviewjsCoreClasslists = []
3343 classlistFiles.each {
3346 def file = hash['file']
3347 if (! file.exists()) {
3348 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
3349 return false // this is a "continue" in groovy .each closure
3351 def name = hash['name']
3353 name = file.getName() - ".txt"
3361 def list = fileTree(dir: j2sDir, includes: filelist)
3363 def jsfile = "${outputDir}/core${name}.js"
3364 def zjsfile = "${outputDir}/core${name}.z.js"
3366 jalviewjsCoreClasslists += [
3375 outputs.file(jsfile)
3376 outputs.file(zjsfile)
3379 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
3380 def stevesoftClasslistName = "_stevesoft"
3381 def stevesoftClasslist = [
3382 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
3383 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
3384 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
3385 'name': stevesoftClasslistName
3387 jalviewjsCoreClasslists += stevesoftClasslist
3388 inputs.files(stevesoftClasslist['list'])
3389 outputs.file(stevesoftClasslist['jsfile'])
3390 outputs.file(stevesoftClasslist['zjsfile'])
3393 def allClasslistName = "_all"
3394 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3395 allJsFiles += fileTree(
3399 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3400 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3401 "**/org/jmol/export/JSExporter.js"
3404 allJsFiles += fileTree(
3408 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3409 "**/sun/misc/Unsafe.js",
3410 "**/swingjs/jquery/jquery-editable-select.js",
3411 "**/swingjs/jquery/j2sComboBox.js",
3412 "**/sun/misc/FloatingDecimal.js"
3415 def allClasslist = [
3416 'jsfile': "${outputDir}/core${allClasslistName}.js",
3417 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
3419 'name': allClasslistName
3421 // not including this version of "all" core at the moment
3422 //jalviewjsCoreClasslists += allClasslist
3423 inputs.files(allClasslist['list'])
3424 outputs.file(allClasslist['jsfile'])
3425 outputs.file(allClasslist['zjsfile'])
3428 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3429 logOutFile.getParentFile().mkdirs()
3430 logOutFile.createNewFile()
3431 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3433 jalviewjsCoreClasslists.each {
3434 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3441 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3444 into file(outputFile).getParentFile()
3445 rename { filename ->
3446 if (filename.equals(inputFile.getName())) {
3447 return file(outputFile).getName()
3451 filter(ReplaceTokens,
3455 'MAIN': '"'+main_class+'"',
3457 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3458 'COREKEY': jalviewjs_core_key,
3459 'CORENAME': coreName
3466 task jalviewjsPublishCoreTemplates {
3467 dependsOn jalviewjsBuildAllCores
3468 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3469 def inputFile = file(inputFileName)
3470 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3472 def outputFiles = []
3473 jalviewjsCoreClasslists.each { cl ->
3474 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3475 cl['outputfile'] = outputFile
3476 outputFiles += outputFile
3480 jalviewjsCoreClasslists.each { cl ->
3481 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3484 inputs.file(inputFile)
3485 outputs.files(outputFiles)
3489 task jalviewjsSyncCore (type: Sync) {
3490 dependsOn jalviewjsBuildAllCores
3491 dependsOn jalviewjsPublishCoreTemplates
3492 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3493 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3497 def outputFiles = []
3498 rename { filename ->
3499 outputFiles += "${outputDir}/${filename}"
3505 outputs.files outputFiles
3506 inputs.files inputFiles
3510 // this Copy version of TransferSiteJs will delete anything else in the target dir
3511 task jalviewjsCopyTransferSiteJs(type: Copy) {
3512 dependsOn jalviewjsTranspile
3513 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3514 into "${jalviewDir}/${jalviewjsSiteDir}"
3518 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3519 task jalviewjsSyncTransferSiteJs(type: Sync) {
3520 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3522 into "${jalviewDir}/${jalviewjsSiteDir}"
3529 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3530 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3531 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3532 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3534 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3535 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3536 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3537 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3540 task jalviewjsPrepareSite {
3542 description "Prepares the website folder including unzipping files and copying resources"
3543 dependsOn jalviewjsSyncAllLibs
3544 dependsOn jalviewjsSyncResources
3545 dependsOn jalviewjsSyncSiteResources
3546 dependsOn jalviewjsSyncBuildProperties
3547 dependsOn jalviewjsSyncCore
3551 task jalviewjsBuildSite {
3553 description "Builds the whole website including transpiled code"
3554 dependsOn jalviewjsCopyTransferSiteJs
3555 dependsOn jalviewjsPrepareSite
3559 task cleanJalviewjsTransferSite {
3561 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3562 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3563 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3564 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3569 task cleanJalviewjsSite {
3570 dependsOn cleanJalviewjsTransferSite
3572 delete "${jalviewDir}/${jalviewjsSiteDir}"
3577 task jalviewjsSiteTar(type: Tar) {
3579 description "Creates a tar.gz file for the website"
3580 dependsOn jalviewjsBuildSite
3581 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3582 archiveFileName = outputFilename
3584 compression Compression.GZIP
3586 from "${jalviewDir}/${jalviewjsSiteDir}"
3587 into jalviewjs_site_dir // this is inside the tar file
3589 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3593 task jalviewjsServer {
3595 def filename = "jalviewjsTest.html"
3596 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3597 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3602 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3603 factory = f.newInstance()
3604 } catch (ClassNotFoundException e) {
3605 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3607 def port = Integer.valueOf(jalviewjs_server_port)
3612 while(port < start+1000 && !running) {
3614 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3615 jalviewjsServer = factory.start(doc_root, port)
3617 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3618 println("SERVER STARTED with document root ${doc_root}.")
3619 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3620 println("For debug: "+url+"?j2sdebug")
3621 println("For verbose: "+url+"?j2sverbose")
3622 } catch (Exception e) {
3627 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3628 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3629 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3631 jalviewjsCoreClasslists.each { cl ->
3632 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3634 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3636 println("For core ${cl.name}: "+urlcore)
3639 file(htmlFile).text = htmlText
3642 outputs.file(htmlFile)
3643 outputs.upToDateWhen({false})
3647 task cleanJalviewjsAll {
3649 description "Delete all configuration and build artifacts to do with JalviewJS build"
3650 dependsOn cleanJalviewjsSite
3651 dependsOn jalviewjsEclipsePaths
3654 delete "${jalviewDir}/${jalviewjsBuildDir}"
3655 delete "${jalviewDir}/${eclipse_bin_dir}"
3656 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3657 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3659 delete jalviewjsJ2sAltSettingsFileName
3662 outputs.upToDateWhen( { false } )
3666 task jalviewjsIDE_checkJ2sPlugin {
3667 group "00 JalviewJS in Eclipse"
3668 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3671 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3672 def j2sPluginFile = file(j2sPlugin)
3673 def eclipseHome = System.properties["eclipse.home.location"]
3674 if (eclipseHome == null || ! IN_ECLIPSE) {
3675 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3677 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3678 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3679 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3680 eclipseJ2sPluginDirs += altPluginsDir
3682 def foundPlugin = false
3683 def j2sPluginFileName = j2sPluginFile.getName()
3684 def eclipseJ2sPlugin
3685 def eclipseJ2sPluginFile
3686 eclipseJ2sPluginDirs.any { dir ->
3687 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3688 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3689 if (eclipseJ2sPluginFile.exists()) {
3695 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3696 System.err.println(msg)
3697 throw new StopExecutionException(msg)
3700 def digest = MessageDigest.getInstance("MD5")
3702 digest.update(j2sPluginFile.text.bytes)
3703 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3705 digest.update(eclipseJ2sPluginFile.text.bytes)
3706 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3708 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3709 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3710 System.err.println(msg)
3711 throw new StopExecutionException(msg)
3713 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3719 task jalviewjsIDE_copyJ2sPlugin {
3720 group "00 JalviewJS in Eclipse"
3721 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3724 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3725 def j2sPluginFile = file(j2sPlugin)
3726 def eclipseHome = System.properties["eclipse.home.location"]
3727 if (eclipseHome == null || ! IN_ECLIPSE) {
3728 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3730 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3731 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3732 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3733 System.err.println(msg)
3736 eclipseJ2sPluginFile.getParentFile().mkdirs()
3737 into eclipseJ2sPluginFile.getParent()
3743 task jalviewjsIDE_j2sFile {
3744 group "00 JalviewJS in Eclipse"
3745 description "Creates the .j2s file"
3746 dependsOn jalviewjsCreateJ2sSettings
3750 task jalviewjsIDE_SyncCore {
3751 group "00 JalviewJS in Eclipse"
3752 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3753 dependsOn jalviewjsSyncCore
3757 task jalviewjsIDE_SyncSiteAll {
3758 dependsOn jalviewjsSyncAllLibs
3759 dependsOn jalviewjsSyncResources
3760 dependsOn jalviewjsSyncSiteResources
3761 dependsOn jalviewjsSyncBuildProperties
3765 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3768 task jalviewjsIDE_PrepareSite {
3769 group "00 JalviewJS in Eclipse"
3770 description "Sync libs and resources to site dir, but not closure cores"
3772 dependsOn jalviewjsIDE_SyncSiteAll
3773 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3777 task jalviewjsIDE_AssembleSite {
3778 group "00 JalviewJS in Eclipse"
3779 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3780 dependsOn jalviewjsPrepareSite
3784 task jalviewjsIDE_SiteClean {
3785 group "00 JalviewJS in Eclipse"
3786 description "Deletes the Eclipse transpiled site"
3787 dependsOn cleanJalviewjsSite
3791 task jalviewjsIDE_Server {
3792 group "00 JalviewJS in Eclipse"
3793 description "Starts a webserver on localhost to test the website"
3794 dependsOn jalviewjsServer
3798 // buildship runs this at import or gradle refresh
3799 task eclipseSynchronizationTask {
3800 //dependsOn eclipseSetup
3801 dependsOn createBuildProperties
3803 dependsOn jalviewjsIDE_j2sFile
3804 dependsOn jalviewjsIDE_checkJ2sPlugin
3805 dependsOn jalviewjsIDE_PrepareSite
3810 // buildship runs this at build time or project refresh
3811 task eclipseAutoBuildTask {
3812 //dependsOn jalviewjsIDE_checkJ2sPlugin
3813 //dependsOn jalviewjsIDE_PrepareSite
3819 description "Build the site"
3820 dependsOn jalviewjsBuildSite