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")
142 // this property set when running Eclipse headlessly
143 j2sHeadlessBuildProperty = string("net.sf.j2s.core.headlessbuild")
144 // this property set by Eclipse
145 eclipseApplicationProperty = string("eclipse.application")
146 // CHECK IF RUNNING FROM WITHIN ECLIPSE
147 def eclipseApplicationPropertyVal = System.properties[eclipseApplicationProperty]
148 IN_ECLIPSE = eclipseApplicationPropertyVal != null && eclipseApplicationPropertyVal.startsWith("org.eclipse.ui.")
149 // BUT WITHOUT THE HEADLESS BUILD PROPERTY SET
150 if (System.properties[j2sHeadlessBuildProperty].equals("true")) {
151 println("Setting IN_ECLIPSE to ${IN_ECLIPSE} as System.properties['${j2sHeadlessBuildProperty}'] == '${System.properties[j2sHeadlessBuildProperty]}'")
155 println("WITHIN ECLIPSE IDE")
157 println("HEADLESS BUILD")
160 J2S_ENABLED = (project.hasProperty('j2s.compiler.status') && project['j2s.compiler.status'] != null && project['j2s.compiler.status'] == "enable")
162 println("J2S ENABLED")
165 System.properties.sort { it.key }.each {
166 key, val -> println("SYSTEM PROPERTY ${key}='${val}'")
169 if (false && IN_ECLIPSE) {
170 jalviewDir = jalviewDirAbsolutePath
175 buildDate = new Date().format("yyyyMMdd")
178 bareSourceDir = string(source_dir)
179 sourceDir = string("${jalviewDir}/${bareSourceDir}")
180 resourceDir = string("${jalviewDir}/${resource_dir}")
181 bareTestSourceDir = string(test_source_dir)
182 testDir = string("${jalviewDir}/${bareTestSourceDir}")
184 classesDir = string("${jalviewDir}/${classes_dir}")
187 useClover = clover.equals("true")
188 cloverBuildDir = "${buildDir}/clover"
189 cloverInstrDir = file("${cloverBuildDir}/clover-instr")
190 cloverClassesDir = file("${cloverBuildDir}/clover-classes")
191 cloverReportDir = file("${buildDir}/reports/clover")
192 cloverTestInstrDir = file("${cloverBuildDir}/clover-test-instr")
193 cloverTestClassesDir = file("${cloverBuildDir}/clover-test-classes")
194 //cloverTestClassesDir = cloverClassesDir
195 cloverDb = string("${cloverBuildDir}/clover.db")
197 testSourceDir = useClover ? cloverTestInstrDir : testDir
198 testClassesDir = useClover ? cloverTestClassesDir : "${jalviewDir}/${test_output_dir}"
200 getdownChannelDir = string("${getdown_website_dir}/${propertiesChannelName}")
201 getdownAppBaseDir = string("${jalviewDir}/${getdownChannelDir}/${JAVA_VERSION}")
202 getdownArchiveDir = string("${jalviewDir}/${getdown_archive_dir}")
203 getdownFullArchiveDir = null
204 getdownTextLines = []
205 getdownLaunchJvl = null
206 getdownVersionLaunchJvl = null
208 buildProperties = null
210 // the following values might be overridden by the CHANNEL switch
211 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
212 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
213 getdownArchiveAppBase = getdown_archive_base
214 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}")
215 getdownAppDistDir = getdown_app_dir_alt
216 getdownImagesDir = string("${jalviewDir}/${getdown_images_dir}")
217 getdownSetAppBaseProperty = false // whether to pass the appbase and appdistdir to the application
218 reportRsyncCommand = false
219 jvlChannelName = CHANNEL.toLowerCase()
220 install4jSuffix = CHANNEL.substring(0, 1).toUpperCase() + CHANNEL.substring(1).toLowerCase(); // BUILD -> Build
221 install4jDMGDSStore = "${install4j_images_dir}/${install4j_dmg_ds_store}"
222 install4jDMGBackgroundImage = "${install4j_images_dir}/${install4j_dmg_background}"
223 install4jInstallerName = "${jalview_name} Non-Release Installer"
224 install4jExecutableName = install4j_executable_name
225 install4jExtraScheme = "jalviewx"
226 install4jMacIconsFile = string("${install4j_images_dir}/${install4j_mac_icons_file}")
227 install4jWindowsIconsFile = string("${install4j_images_dir}/${install4j_windows_icons_file}")
228 install4jPngIconFile = string("${install4j_images_dir}/${install4j_png_icon_file}")
229 install4jBackground = string("${install4j_images_dir}/${install4j_background}")
230 install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
231 install4jCheckSums = true
233 applicationName = "${jalview_name}"
237 // TODO: get bamboo build artifact URL for getdown artifacts
238 getdown_channel_base = bamboo_channelbase
239 getdownChannelName = string("${bamboo_planKey}/${JAVA_VERSION}")
240 getdownAppBase = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
241 jvlChannelName += "_${getdownChannelName}"
242 // automatically add the test group Not-bamboo for exclusion
243 if ("".equals(testng_excluded_groups)) {
244 testng_excluded_groups = "Not-bamboo"
246 install4jExtraScheme = "jalviewb"
249 case [ "RELEASE", "JALVIEWJS-RELEASE" ]:
250 getdownAppDistDir = getdown_app_dir_release
251 getdownSetAppBaseProperty = true
252 reportRsyncCommand = true
254 install4jInstallerName = "${jalview_name} Installer"
258 getdownChannelName = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
259 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
260 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
261 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
262 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
264 package_dir = string("${ARCHIVEDIR}/${package_dir}")
265 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
268 reportRsyncCommand = true
269 install4jExtraScheme = "jalviewa"
273 getdownChannelName = string("archive/${JALVIEW_VERSION}")
274 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
275 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
276 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
277 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
279 package_dir = string("${ARCHIVEDIR}/${package_dir}")
280 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
283 reportRsyncCommand = true
284 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
285 install4jSuffix = "Archive"
286 install4jExtraScheme = "jalviewa"
290 reportRsyncCommand = true
291 getdownSetAppBaseProperty = true
292 // DEVELOP-RELEASE is usually associated with a Jalview release series so set the version
293 JALVIEW_VERSION=JALVIEW_VERSION+"-d${buildDate}"
295 install4jSuffix = "Develop"
296 install4jExtraScheme = "jalviewd"
297 install4jInstallerName = "${jalview_name} Develop Installer"
301 reportRsyncCommand = true
302 getdownSetAppBaseProperty = true
303 // Don't ignore transpile errors for release build
304 if (jalviewjs_ignore_transpile_errors.equals("true")) {
305 jalviewjs_ignore_transpile_errors = "false"
306 println("Setting jalviewjs_ignore_transpile_errors to 'false'")
308 JALVIEW_VERSION = JALVIEW_VERSION+"-test"
309 install4jSuffix = "Test"
310 install4jExtraScheme = "jalviewt"
311 install4jInstallerName = "${jalview_name} Test Installer"
314 case ~/^SCRATCH(|-[-\w]*)$/:
315 getdownChannelName = CHANNEL
316 JALVIEW_VERSION = JALVIEW_VERSION+"-"+CHANNEL
318 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
319 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
320 reportRsyncCommand = true
321 install4jSuffix = "Scratch"
325 if (!file("${LOCALDIR}").exists()) {
326 throw new GradleException("Must provide a LOCALDIR value to produce a local distribution")
328 getdownAppBase = file(file("${LOCALDIR}").getAbsolutePath()).toURI().toString()
329 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
331 JALVIEW_VERSION = "TEST"
332 install4jSuffix = "Test-Local"
333 install4jExtraScheme = "jalviewt"
334 install4jInstallerName = "${jalview_name} Test Installer"
337 case [ "LOCAL", "JALVIEWJS" ]:
338 JALVIEW_VERSION = "TEST"
339 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
340 getdownArchiveAppBase = file("${jalviewDir}/${getdown_archive_dir}").toURI().toString()
341 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
342 install4jExtraScheme = "jalviewl"
343 install4jCheckSums = false
346 default: // something wrong specified
347 throw new GradleException("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
351 JALVIEW_VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
352 hugoDataJsonFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_data_installers_dir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
353 hugoArchiveMdFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_version_archive_dir}/Version-${JALVIEW_VERSION_UNDERSCORES}/_index.md")
354 // override getdownAppBase if requested
355 if (findProperty("getdown_appbase_override") != null) {
356 // revert to LOCAL if empty string
357 if (string(getdown_appbase_override) == "") {
358 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
359 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
360 } else if (string(getdown_appbase_override).startsWith("file://")) {
361 getdownAppBase = string(getdown_appbase_override)
362 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
364 getdownAppBase = string(getdown_appbase_override)
366 println("Overriding getdown appbase with '${getdownAppBase}'")
368 // sanitise file name for jalview launcher file for this channel
369 jvlChannelName = jvlChannelName.replaceAll("[^\\w\\-]+", "_")
370 // install4j application and folder names
371 if (install4jSuffix == "") {
372 install4jBundleId = "${install4j_bundle_id}"
373 install4jWinApplicationId = install4j_release_win_application_id
375 applicationName = "${jalview_name} ${install4jSuffix}"
376 install4jBundleId = "${install4j_bundle_id}-" + install4jSuffix.toLowerCase()
377 // add int hash of install4jSuffix to the last part of the application_id
378 def id = install4j_release_win_application_id
379 def idsplitreverse = id.split("-").reverse()
380 idsplitreverse[0] = idsplitreverse[0].toInteger() + install4jSuffix.hashCode()
381 install4jWinApplicationId = idsplitreverse.reverse().join("-")
383 // sanitise folder and id names
384 // install4jApplicationFolder = e.g. "Jalview Build"
385 install4jApplicationFolder = applicationName
386 .replaceAll("[\"'~:/\\\\\\s]", "_") // replace all awkward filename chars " ' ~ : / \
387 .replaceAll("_+", "_") // collapse __
388 install4jInternalId = applicationName
390 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
391 .replaceAll("_+", "") // collapse __
392 //.replaceAll("_*-_*", "-") // collapse _-_
393 install4jUnixApplicationFolder = applicationName
395 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
396 .replaceAll("_+", "_") // collapse __
397 .replaceAll("_*-_*", "-") // collapse _-_
400 getdownWrapperLink = install4jUnixApplicationFolder // e.g. "jalview_local"
401 getdownAppDir = string("${getdownAppBaseDir}/${getdownAppDistDir}")
402 //getdownJ11libDir = "${getdownAppBaseDir}/${getdown_j11lib_dir}"
403 getdownResourceDir = string("${getdownAppBaseDir}/${getdown_resource_dir}")
404 getdownInstallDir = string("${getdownAppBaseDir}/${getdown_install_dir}")
405 getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
406 getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
407 /* compile without modules -- using classpath libraries
408 modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
409 modules_runtimeClasspath = modules_compileClasspath
415 apply plugin: "com.palantir.git-version"
416 def details = versionDetails()
417 gitHash = details.gitHash
418 gitBranch = details.branchName
419 } catch(org.gradle.api.internal.plugins.PluginApplicationException e) {
420 println("Not in a git repository. Using git values from RELEASE properties file.")
421 gitHash = releaseProps.getProperty("git.hash")
422 gitBranch = releaseProps.getProperty("git.branch")
423 } catch(java.lang.RuntimeException e1) {
424 throw new GradleException("Error with git-version plugin. Directory '.git' exists but versionDetails() cannot be found.")
427 println("Using a ${CHANNEL} profile.")
429 additional_compiler_args = []
430 // configure classpath/args for j8/j11 compilation
431 if (JAVA_VERSION.equals("1.8")) {
432 JAVA_INTEGER_VERSION = string("8")
435 libDistDir = j8libDir
436 compile_source_compatibility = 1.8
437 compile_target_compatibility = 1.8
438 // these are getdown.txt properties defined dependent on the JAVA_VERSION
439 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
440 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
441 // this property is assigned below and expanded to multiple lines in the getdown task
442 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
443 // this property is for the Java library used in eclipse
444 eclipseJavaRuntimeName = string("JavaSE-1.8")
445 } else if (JAVA_VERSION.equals("11")) {
446 JAVA_INTEGER_VERSION = string("11")
448 libDistDir = j11libDir
449 compile_source_compatibility = 11
450 compile_target_compatibility = 11
451 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
452 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
453 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
454 eclipseJavaRuntimeName = string("JavaSE-11")
455 /* compile without modules -- using classpath libraries
456 additional_compiler_args += [
457 '--module-path', modules_compileClasspath.asPath,
458 '--add-modules', j11modules
461 } else if (JAVA_VERSION.equals("17")) {
462 JAVA_INTEGER_VERSION = string("17")
464 libDistDir = j17libDir
465 compile_source_compatibility = 17
466 compile_target_compatibility = 17
467 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
468 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
469 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
470 eclipseJavaRuntimeName = string("JavaSE-17")
471 /* compile without modules -- using classpath libraries
472 additional_compiler_args += [
473 '--module-path', modules_compileClasspath.asPath,
474 '--add-modules', j11modules
478 throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
483 JAVA_MIN_VERSION = JAVA_VERSION
484 JAVA_MAX_VERSION = JAVA_VERSION
485 def jreInstallsDir = string(jre_installs_dir)
486 if (jreInstallsDir.startsWith("~/")) {
487 jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
489 macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
490 windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
491 linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
492 macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_mac_x64.tar.gz")
493 windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_windows_x64.tar.gz")
494 linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_linux_x64.tar.gz")
495 install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
496 install4jConfFileName = string("jalview-install4j-conf.install4j")
497 install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
498 install4jHomeDir = install4j_home_dir
499 if (install4jHomeDir.startsWith("~/")) {
500 install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
503 resourceBuildDir = string("${buildDir}/resources")
504 resourcesBuildDir = string("${resourceBuildDir}/resources_build")
505 helpBuildDir = string("${resourceBuildDir}/help_build")
506 docBuildDir = string("${resourceBuildDir}/doc_build")
508 if (buildProperties == null) {
509 buildProperties = string("${resourcesBuildDir}/${build_properties_file}")
511 buildingHTML = string("${jalviewDir}/${doc_dir}/building.html")
512 helpParentDir = string("${jalviewDir}/${help_parent_dir}")
513 helpSourceDir = string("${helpParentDir}/${help_dir}")
514 helpFile = string("${helpBuildDir}/${help_dir}/help.jhm")
517 relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
518 jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
519 jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
521 jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
523 jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
525 jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
526 jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
527 jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
528 jalviewjsJalviewCoreHtmlFile = string("")
529 jalviewjsJalviewCoreName = string(jalviewjs_core_name)
530 jalviewjsCoreClasslists = []
531 jalviewjsJalviewTemplateName = string(jalviewjs_name)
532 jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
533 jalviewjsJ2sAltSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_alt_settings}")
534 jalviewjsJ2sProps = null
535 jalviewjsJ2sPlugin = jalviewjs_j2s_plugin
537 eclipseWorkspace = null
538 eclipseBinary = string("")
539 eclipseVersion = string("")
549 outputDir = file(classesDir)
553 srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ]
556 compileClasspath = files(sourceSets.main.java.outputDir)
557 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
559 runtimeClasspath = compileClasspath
560 runtimeClasspath += files(sourceSets.main.resources.srcDirs)
565 srcDirs cloverInstrDir
566 outputDir = cloverClassesDir
570 srcDirs = sourceSets.main.resources.srcDirs
573 compileClasspath = files( sourceSets.clover.java.outputDir )
574 //compileClasspath += files( testClassesDir )
575 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
576 compileClasspath += fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
577 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
579 runtimeClasspath = compileClasspath
584 srcDirs testSourceDir
585 outputDir = file(testClassesDir)
589 srcDirs = useClover ? sourceSets.clover.resources.srcDirs : sourceSets.main.resources.srcDirs
592 compileClasspath = files( sourceSets.test.java.outputDir )
593 compileClasspath += useClover ? sourceSets.clover.compileClasspath : sourceSets.main.compileClasspath
594 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
596 runtimeClasspath = compileClasspath
597 runtimeClasspath += files(sourceSets.test.resources.srcDirs)
603 // eclipse project and settings files creation, also used by buildship
606 name = eclipse_project_name
608 natures 'org.eclipse.jdt.core.javanature',
609 'org.eclipse.jdt.groovy.core.groovyNature',
610 'org.eclipse.buildship.core.gradleprojectnature'
612 buildCommand 'org.eclipse.jdt.core.javabuilder'
613 buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
617 //defaultOutputDir = sourceSets.main.java.outputDir
618 configurations.each{ c->
619 if (c.isCanBeResolved()) {
620 minusConfigurations += [c]
624 plusConfigurations = [ ]
628 def removeTheseToo = []
629 HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
630 cp.entries.each { entry ->
631 // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
632 // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
633 // we add the resources and help/help dirs in as libs afterwards (see below)
634 if (entry.kind == 'src') {
635 if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
636 removeTheseToo += entry
638 alreadyAddedSrcPath.putAt(entry.path, true)
643 cp.entries.removeAll(removeTheseToo)
645 //cp.entries += new Output("${eclipse_bin_dir}/main")
646 if (file(helpParentDir).isDirectory()) {
647 cp.entries += new Library(fileReference(helpParentDir))
649 if (file(resourceDir).isDirectory()) {
650 cp.entries += new Library(fileReference(resourceDir))
653 HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
655 sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
656 //don't want to add outputDir as eclipse is using its own output dir in bin/main
657 if (it.isDirectory() || ! it.exists()) {
658 // don't add dirs to classpath, especially if they don't exist
659 return false // groovy "continue" in .any closure
661 def itPath = it.toString()
662 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
663 // make relative path
664 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
666 if (alreadyAddedLibPath.get(itPath)) {
667 //println("Not adding duplicate entry "+itPath)
669 //println("Adding entry "+itPath)
670 cp.entries += new Library(fileReference(itPath))
671 alreadyAddedLibPath.put(itPath, true)
675 sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
676 //no longer want to add outputDir as eclipse is using its own output dir in bin/main
677 if (it.isDirectory() || ! it.exists()) {
678 // don't add dirs to classpath
679 return false // groovy "continue" in .any closure
682 def itPath = it.toString()
683 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
684 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
686 if (alreadyAddedLibPath.get(itPath)) {
689 def lib = new Library(fileReference(itPath))
690 lib.entryAttributes["test"] = "true"
692 alreadyAddedLibPath.put(itPath, true)
700 containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
705 // for the IDE, use java 11 compatibility
706 sourceCompatibility = compile_source_compatibility
707 targetCompatibility = compile_target_compatibility
708 javaRuntimeName = eclipseJavaRuntimeName
710 // add in jalview project specific properties/preferences into eclipse core preferences
712 withProperties { props ->
713 def jalview_prefs = new Properties()
714 def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
715 jalview_prefs.load(ins)
717 jalview_prefs.forEach { t, v ->
718 if (props.getAt(t) == null) {
722 // codestyle file -- overrides previous formatter prefs
723 def csFile = file("${jalviewDirAbsolutePath}/${eclipse_codestyle_file}")
724 if (csFile.exists()) {
725 XmlParser parser = new XmlParser()
726 def profiles = parser.parse(csFile)
727 def profile = profiles.'profile'.find { p -> (p.'@kind' == "CodeFormatterProfile" && p.'@name' == "Jalview") }
728 if (profile != null) {
729 profile.'setting'.each { s ->
731 def value = s.'@value'
732 if (id != null && value != null) {
733 props.putAt(id, value)
744 // Don't want these to be activated if in headless build
745 synchronizationTasks "eclipseSynchronizationTask"
746 //autoBuildTasks "eclipseAutoBuildTask"
752 /* hack to change eclipse prefs in .settings files other than org.eclipse.jdt.core.prefs */
753 // Class to allow updating arbitrary properties files
754 class PropertiesFile extends PropertiesPersistableConfigurationObject {
755 public PropertiesFile(PropertiesTransformer t) { super(t); }
756 @Override protected void load(Properties properties) { }
757 @Override protected void store(Properties properties) { }
758 @Override protected String getDefaultResourceName() { return ""; }
759 // This is necessary, because PropertiesPersistableConfigurationObject fails
760 // if no default properties file exists.
761 @Override public void loadDefaults() { load(new StringBufferInputStream("")); }
764 // Task to update arbitrary properties files (set outputFile)
765 class PropertiesFileTask extends PropertiesGeneratorTask<PropertiesFile> {
766 private final PropertiesFileContentMerger file;
767 public PropertiesFileTask() { file = new PropertiesFileContentMerger(getTransformer()); }
768 protected PropertiesFile create() { return new PropertiesFile(getTransformer()); }
769 protected void configure(PropertiesFile props) {
770 file.getBeforeMerged().execute(props); file.getWhenMerged().execute(props);
772 public void file(Closure closure) { ConfigureUtil.configure(closure, file); }
775 task eclipseUIPreferences(type: PropertiesFileTask) {
776 description = "Generate Eclipse additional settings"
777 def filename = "org.eclipse.jdt.ui.prefs"
778 outputFile = "$projectDir/.settings/${filename}" as File
781 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
786 task eclipseGroovyCorePreferences(type: PropertiesFileTask) {
787 description = "Generate Eclipse additional settings"
788 def filename = "org.eclipse.jdt.groovy.core.prefs"
789 outputFile = "$projectDir/.settings/${filename}" as File
792 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
797 task eclipseAllPreferences {
799 dependsOn eclipseUIPreferences
800 dependsOn eclipseGroovyCorePreferences
803 eclipseUIPreferences.mustRunAfter eclipseJdt
804 eclipseGroovyCorePreferences.mustRunAfter eclipseJdt
806 /* end of eclipse preferences hack */
814 delete cloverBuildDir
815 delete cloverReportDir
820 task cloverInstrJava(type: JavaExec) {
821 group = "Verification"
822 description = "Create clover instrumented source java files"
824 dependsOn cleanClover
826 inputs.files(sourceSets.main.allJava)
827 outputs.dir(cloverInstrDir)
829 //classpath = fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
830 classpath = sourceSets.clover.compileClasspath
831 main = "com.atlassian.clover.CloverInstr"
839 cloverInstrDir.getPath(),
841 def srcFiles = sourceSets.main.allJava.files
844 { file -> file.absolutePath }
847 args argsList.toArray()
850 delete cloverInstrDir
851 println("Clover: About to instrument "+srcFiles.size() +" files")
856 task cloverInstrTests(type: JavaExec) {
857 group = "Verification"
858 description = "Create clover instrumented source test files"
860 dependsOn cleanClover
862 inputs.files(testDir)
863 outputs.dir(cloverTestInstrDir)
865 classpath = sourceSets.clover.compileClasspath
866 main = "com.atlassian.clover.CloverInstr"
876 cloverTestInstrDir.getPath(),
878 args argsList.toArray()
881 delete cloverTestInstrDir
882 println("Clover: About to instrument test files")
888 group = "Verification"
889 description = "Create clover instrumented all source files"
891 dependsOn cloverInstrJava
892 dependsOn cloverInstrTests
896 cloverClasses.dependsOn cloverInstr
899 task cloverConsoleReport(type: JavaExec) {
900 group = "Verification"
901 description = "Creates clover console report"
904 file(cloverDb).exists()
907 inputs.dir cloverClassesDir
909 classpath = sourceSets.clover.runtimeClasspath
910 main = "com.atlassian.clover.reporters.console.ConsoleReporter"
912 if (cloverreport_mem.length() > 0) {
913 maxHeapSize = cloverreport_mem
915 if (cloverreport_jvmargs.length() > 0) {
916 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
926 args argsList.toArray()
930 task cloverHtmlReport(type: JavaExec) {
931 group = "Verification"
932 description = "Creates clover HTML report"
935 file(cloverDb).exists()
938 def cloverHtmlDir = cloverReportDir
939 inputs.dir cloverClassesDir
940 outputs.dir cloverHtmlDir
942 classpath = sourceSets.clover.runtimeClasspath
943 main = "com.atlassian.clover.reporters.html.HtmlReporter"
945 if (cloverreport_mem.length() > 0) {
946 maxHeapSize = cloverreport_mem
948 if (cloverreport_jvmargs.length() > 0) {
949 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
960 if (cloverreport_html_options.length() > 0) {
961 argsList += cloverreport_html_options.split(" ")
964 args argsList.toArray()
968 task cloverXmlReport(type: JavaExec) {
969 group = "Verification"
970 description = "Creates clover XML report"
973 file(cloverDb).exists()
976 def cloverXmlFile = "${cloverReportDir}/clover.xml"
977 inputs.dir cloverClassesDir
978 outputs.file cloverXmlFile
980 classpath = sourceSets.clover.runtimeClasspath
981 main = "com.atlassian.clover.reporters.xml.XMLReporter"
983 if (cloverreport_mem.length() > 0) {
984 maxHeapSize = cloverreport_mem
986 if (cloverreport_jvmargs.length() > 0) {
987 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
998 if (cloverreport_xml_options.length() > 0) {
999 argsList += cloverreport_xml_options.split(" ")
1002 args argsList.toArray()
1007 group = "Verification"
1008 description = "Creates clover reports"
1010 dependsOn cloverXmlReport
1011 dependsOn cloverHtmlReport
1018 sourceCompatibility = compile_source_compatibility
1019 targetCompatibility = compile_target_compatibility
1020 options.compilerArgs += additional_compiler_args
1021 print ("Setting target compatibility to "+targetCompatibility+"\n")
1023 //classpath += configurations.cloverRuntime
1029 // JBP->BS should the print statement in doFirst refer to compile_target_compatibility ?
1030 sourceCompatibility = compile_source_compatibility
1031 targetCompatibility = compile_target_compatibility
1032 options.compilerArgs = additional_compiler_args
1033 options.encoding = "UTF-8"
1035 print ("Setting target compatibility to "+compile_target_compatibility+"\n")
1042 sourceCompatibility = compile_source_compatibility
1043 targetCompatibility = compile_target_compatibility
1044 options.compilerArgs = additional_compiler_args
1046 print ("Setting target compatibility to "+targetCompatibility+"\n")
1053 delete sourceSets.main.java.outputDir
1059 dependsOn cleanClover
1061 delete sourceSets.test.java.outputDir
1066 // format is a string like date.format("dd MMMM yyyy")
1067 def getDate(format) {
1068 return date.format(format)
1072 def convertMdToHtml (FileTree mdFiles, File cssFile) {
1073 MutableDataSet options = new MutableDataSet()
1075 def extensions = new ArrayList<>()
1076 extensions.add(AnchorLinkExtension.create())
1077 extensions.add(AutolinkExtension.create())
1078 extensions.add(StrikethroughExtension.create())
1079 extensions.add(TaskListExtension.create())
1080 extensions.add(TablesExtension.create())
1081 extensions.add(TocExtension.create())
1083 options.set(Parser.EXTENSIONS, extensions)
1085 // set GFM table parsing options
1086 options.set(TablesExtension.WITH_CAPTION, false)
1087 options.set(TablesExtension.COLUMN_SPANS, false)
1088 options.set(TablesExtension.MIN_HEADER_ROWS, 1)
1089 options.set(TablesExtension.MAX_HEADER_ROWS, 1)
1090 options.set(TablesExtension.APPEND_MISSING_COLUMNS, true)
1091 options.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
1092 options.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
1094 options.set(AnchorLinkExtension.ANCHORLINKS_SET_ID, false)
1095 options.set(AnchorLinkExtension.ANCHORLINKS_ANCHOR_CLASS, "anchor")
1096 options.set(AnchorLinkExtension.ANCHORLINKS_SET_NAME, true)
1097 options.set(AnchorLinkExtension.ANCHORLINKS_TEXT_PREFIX, "<span class=\"octicon octicon-link\"></span>")
1099 Parser parser = Parser.builder(options).build()
1100 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1102 mdFiles.each { mdFile ->
1103 // add table of contents
1104 def mdText = "[TOC]\n"+mdFile.text
1106 // grab the first top-level title
1108 def titleRegex = /(?m)^#(\s+|([^#]))(.*)/
1109 def matcher = mdText =~ titleRegex
1110 if (matcher.size() > 0) {
1111 // matcher[0][2] is the first character of the title if there wasn't any whitespace after the #
1112 title = (matcher[0][2] != null ? matcher[0][2] : "")+matcher[0][3]
1114 // or use the filename if none found
1115 if (title == null) {
1116 title = mdFile.getName()
1119 Node document = parser.parse(mdText)
1120 String htmlBody = renderer.render(document)
1121 def htmlText = '''<html>
1122 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1123 <html xmlns="http://www.w3.org/1999/xhtml">
1125 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1126 <meta http-equiv="Content-Style-Type" content="text/css" />
1127 <meta name="generator" content="flexmark" />
1129 htmlText += ((title != null) ? " <title>${title}</title>" : '' )
1131 <style type="text/css">code{white-space: pre;}</style>
1133 htmlText += ((cssFile != null) ? cssFile.text : '')
1134 htmlText += '''</head>
1137 htmlText += htmlBody
1143 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1144 def htmlFile = file(htmlFilePath)
1145 println("Creating ${htmlFilePath}")
1146 htmlFile.text = htmlText
1151 task copyDocs(type: Copy) {
1152 def inputDir = "${jalviewDir}/${doc_dir}"
1153 def outputDir = "${docBuildDir}/${doc_dir}"
1157 include('**/*.html')
1159 filter(ReplaceTokens,
1163 'Version-Rel': JALVIEW_VERSION,
1164 'Year-Rel': getDate("yyyy")
1171 exclude('**/*.html')
1176 inputs.dir(inputDir)
1177 outputs.dir(outputDir)
1181 task convertMdFiles {
1183 def mdFiles = fileTree(dir: docBuildDir, include: "**/*.md")
1184 def cssFile = file("${jalviewDir}/${flexmark_css}")
1187 convertMdToHtml(mdFiles, cssFile)
1190 inputs.files(mdFiles)
1191 inputs.file(cssFile)
1194 mdFiles.each { mdFile ->
1195 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1196 htmlFiles.add(file(htmlFilePath))
1198 outputs.files(htmlFiles)
1202 def hugoTemplateSubstitutions(String input, Map extras=null) {
1203 def replacements = [
1204 DATE: getDate("yyyy-MM-dd"),
1205 CHANNEL: propertiesChannelName,
1206 APPLICATION_NAME: applicationName,
1208 GIT_BRANCH: gitBranch,
1209 VERSION: JALVIEW_VERSION,
1210 JAVA_VERSION: JAVA_VERSION,
1211 VERSION_UNDERSCORES: JALVIEW_VERSION_UNDERSCORES,
1216 if (extras != null) {
1217 extras.each{ k, v ->
1218 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1221 replacements.each{ k, v ->
1222 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1227 def mdFileComponents(File mdFile, def dateOnly=false) {
1230 if (mdFile.exists()) {
1231 def inFrontMatter = false
1232 def firstLine = true
1233 mdFile.eachLine { line ->
1234 if (line.matches("---")) {
1235 def prev = inFrontMatter
1236 inFrontMatter = firstLine
1237 if (inFrontMatter != prev)
1240 if (inFrontMatter) {
1242 if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/) {
1243 map["date"] = new Date().parse("yyyy-MM-dd HH:mm:ss", m[0][1])
1244 } else if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2})/) {
1245 map["date"] = new Date().parse("yyyy-MM-dd", m[0][1])
1246 } else if (m = line =~ /^channel:\s*(\S+)/) {
1247 map["channel"] = m[0][1]
1248 } else if (m = line =~ /^version:\s*(\S+)/) {
1249 map["version"] = m[0][1]
1250 } else if (m = line =~ /^\s*([^:]+)\s*:\s*(\S.*)/) {
1251 map[ m[0][1] ] = m[0][2]
1253 if (dateOnly && map["date"] != null) {
1259 content += line+"\n"
1264 return dateOnly ? map["date"] : [map, content]
1267 task hugoTemplates {
1269 description "Create partially populated md pages for hugo website build"
1271 def hugoTemplatesDir = file("${jalviewDir}/${hugo_templates_dir}")
1272 def hugoBuildDir = "${jalviewDir}/${hugo_build_dir}"
1273 def templateFiles = fileTree(dir: hugoTemplatesDir)
1274 def releaseMdFile = file("${jalviewDir}/${releases_dir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1275 def whatsnewMdFile = file("${jalviewDir}/${whatsnew_dir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1276 def oldJvlFile = file("${jalviewDir}/${hugo_old_jvl}")
1277 def jalviewjsFile = file("${jalviewDir}/${hugo_jalviewjs}")
1280 // specific release template for version archive
1283 def givenDate = null
1284 def givenChannel = null
1285 def givenVersion = null
1286 if (CHANNEL == "RELEASE") {
1287 def (map, content) = mdFileComponents(releaseMdFile)
1288 givenDate = map.date
1289 givenChannel = map.channel
1290 givenVersion = map.version
1292 if (givenVersion != null && givenVersion != JALVIEW_VERSION) {
1293 throw new GradleException("'version' header (${givenVersion}) found in ${releaseMdFile} does not match JALVIEW_VERSION (${JALVIEW_VERSION})")
1296 if (whatsnewMdFile.exists())
1297 whatsnew = whatsnewMdFile.text
1300 def oldJvl = oldJvlFile.exists() ? oldJvlFile.collect{it} : []
1301 def jalviewjsLink = jalviewjsFile.exists() ? jalviewjsFile.collect{it} : []
1303 def changesHugo = null
1304 if (changes != null) {
1305 changesHugo = '<div class="release_notes">\n\n'
1306 def inSection = false
1307 changes.eachLine { line ->
1309 if (m = line =~ /^##([^#].*)$/) {
1311 changesHugo += "</div>\n\n"
1313 def section = m[0][1].trim()
1314 section = section.toLowerCase()
1315 section = section.replaceAll(/ +/, "_")
1316 section = section.replaceAll(/[^a-z0-9_\-]/, "")
1317 changesHugo += "<div class=\"${section}\">\n\n"
1319 } else if (m = line =~ /^(\s*-\s*)<!--([^>]+)-->(.*?)(<br\/?>)?\s*$/) {
1320 def comment = m[0][2].trim()
1321 if (comment != "") {
1322 comment = comment.replaceAll('"', """)
1324 comment.eachMatch(/JAL-\d+/) { jal -> issuekeys += jal }
1325 def newline = m[0][1]
1326 if (comment.trim() != "")
1327 newline += "{{<comment>}}${comment}{{</comment>}} "
1328 newline += m[0][3].trim()
1329 if (issuekeys.size() > 0)
1330 newline += " {{< jal issue=\"${issuekeys.join(",")}\" alt=\"${comment}\" >}}"
1331 if (m[0][4] != null)
1336 changesHugo += line+"\n"
1339 changesHugo += "\n</div>\n\n"
1341 changesHugo += '</div>'
1344 templateFiles.each{ templateFile ->
1345 def newFileName = string(hugoTemplateSubstitutions(templateFile.getName()))
1346 def relPath = hugoTemplatesDir.toPath().relativize(templateFile.toPath()).getParent()
1347 def newRelPathName = hugoTemplateSubstitutions( relPath.toString() )
1349 def outPathName = string("${hugoBuildDir}/$newRelPathName")
1353 rename(templateFile.getName(), newFileName)
1357 def newFile = file("${outPathName}/${newFileName}".toString())
1358 def content = newFile.text
1359 newFile.text = hugoTemplateSubstitutions(content,
1362 CHANGES: changesHugo,
1363 DATE: givenDate == null ? "" : givenDate.format("yyyy-MM-dd"),
1364 DRAFT: givenDate == null ? "true" : "false",
1365 JALVIEWJSLINK: jalviewjsLink.contains(JALVIEW_VERSION) ? "true" : "false",
1366 JVL_HEADER: oldJvl.contains(JALVIEW_VERSION) ? "jvl: true" : ""
1373 inputs.file(oldJvlFile)
1374 inputs.dir(hugoTemplatesDir)
1375 inputs.property("JALVIEW_VERSION", { JALVIEW_VERSION })
1376 inputs.property("CHANNEL", { CHANNEL })
1379 def getMdDate(File mdFile) {
1380 return mdFileComponents(mdFile, true)
1383 def getMdSections(String content) {
1385 def sectionContent = ""
1386 def sectionName = null
1387 content.eachLine { line ->
1389 if (m = line =~ /^##([^#].*)$/) {
1390 if (sectionName != null) {
1391 sections[sectionName] = sectionContent
1395 sectionName = m[0][1].trim()
1396 sectionName = sectionName.toLowerCase()
1397 sectionName = sectionName.replaceAll(/ +/, "_")
1398 sectionName = sectionName.replaceAll(/[^a-z0-9_\-]/, "")
1399 } else if (sectionName != null) {
1400 sectionContent += line+"\n"
1403 if (sectionContent != null) {
1404 sections[sectionName] = sectionContent
1409 task releasesTemplates {
1411 description "Recreate whatsNew.html and releases.html from markdown files and templates in help"
1413 def releasesTemplateFile = file("${jalviewDir}/${releases_template}")
1414 def whatsnewTemplateFile = file("${jalviewDir}/${whatsnew_template}")
1415 def releasesHtmlFile = file("${helpSourceDir}/${releases_html}")
1416 def whatsnewHtmlFile = file("${helpSourceDir}/${whatsnew_html}")
1417 def releasesMdDir = "${jalviewDir}/${releases_dir}"
1418 def whatsnewMdDir = "${jalviewDir}/${whatsnew_dir}"
1421 def releaseMdFile = file("${releasesMdDir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1422 def whatsnewMdFile = file("${whatsnewMdDir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1424 if (CHANNEL == "RELEASE") {
1425 if (!releaseMdFile.exists()) {
1426 throw new GradleException("File ${releaseMdFile} must be created for RELEASE")
1428 if (!whatsnewMdFile.exists()) {
1429 throw new GradleException("File ${whatsnewMdFile} must be created for RELEASE")
1433 def releaseFiles = fileTree(dir: releasesMdDir, include: "release-*.md")
1434 def releaseFilesDates = releaseFiles.collectEntries {
1435 [(it): getMdDate(it)]
1437 releaseFiles = releaseFiles.sort { a,b -> releaseFilesDates[a].compareTo(releaseFilesDates[b]) }
1439 def releasesTemplate = releasesTemplateFile.text
1440 def m = releasesTemplate =~ /(?s)__VERSION_LOOP_START__(.*)__VERSION_LOOP_END__/
1441 def versionTemplate = m[0][1]
1443 MutableDataSet options = new MutableDataSet()
1445 def extensions = new ArrayList<>()
1446 options.set(Parser.EXTENSIONS, extensions)
1447 options.set(Parser.HTML_BLOCK_COMMENT_ONLY_FULL_LINE, true)
1449 Parser parser = Parser.builder(options).build()
1450 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1452 def actualVersions = releaseFiles.collect { rf ->
1453 def (rfMap, rfContent) = mdFileComponents(rf)
1454 return rfMap.version
1456 def versionsHtml = ""
1457 def linkedVersions = []
1458 releaseFiles.reverse().each { rFile ->
1459 def (rMap, rContent) = mdFileComponents(rFile)
1461 def versionLink = ""
1462 def partialVersion = ""
1463 def firstPart = true
1464 rMap.version.split("\\.").each { part ->
1465 def displayPart = ( firstPart ? "" : "." ) + part
1466 partialVersion += displayPart
1468 linkedVersions.contains(partialVersion)
1469 || ( actualVersions.contains(partialVersion) && partialVersion != rMap.version )
1471 versionLink += displayPart
1473 versionLink += "<a id=\"Jalview.${partialVersion}\">${displayPart}</a>"
1474 linkedVersions += partialVersion
1478 def displayDate = releaseFilesDates[rFile].format("d MMMMM yyyy")
1481 def rContentProcessed = ""
1482 rContent.eachLine { line ->
1483 if (lm = line =~ /^(\s*-)(\s*<!--[^>]*?-->)(.*)$/) {
1484 line = "${lm[0][1]}${lm[0][3]}${lm[0][2]}"
1485 } else if (lm = line =~ /^###([^#]+.*)$/) {
1486 line = "_${lm[0][1].trim()}_"
1488 rContentProcessed += line + "\n"
1491 def rContentSections = getMdSections(rContentProcessed)
1492 def rVersion = versionTemplate
1493 if (rVersion != "") {
1494 def rNewFeatures = rContentSections["new_features"]
1495 def rIssuesResolved = rContentSections["issues_resolved"]
1496 Node newFeaturesNode = parser.parse(rNewFeatures)
1497 String newFeaturesHtml = renderer.render(newFeaturesNode)
1498 Node issuesResolvedNode = parser.parse(rIssuesResolved)
1499 String issuesResolvedHtml = renderer.render(issuesResolvedNode)
1500 rVersion = hugoTemplateSubstitutions(rVersion,
1502 VERSION: rMap.version,
1503 VERSION_LINK: versionLink,
1504 DISPLAY_DATE: displayDate,
1505 NEW_FEATURES: newFeaturesHtml,
1506 ISSUES_RESOLVED: issuesResolvedHtml
1509 versionsHtml += rVersion
1513 releasesTemplate = releasesTemplate.replaceAll("(?s)__VERSION_LOOP_START__.*__VERSION_LOOP_END__", versionsHtml)
1514 releasesTemplate = hugoTemplateSubstitutions(releasesTemplate)
1515 releasesHtmlFile.text = releasesTemplate
1517 if (whatsnewMdFile.exists()) {
1518 def whatsnewMd = hugoTemplateSubstitutions(whatsnewMdFile.text)
1519 Node whatsnewNode = parser.parse(whatsnewMd)
1520 String whatsnewHtml = renderer.render(whatsnewNode)
1521 whatsnewHtml = whatsnewTemplateFile.text.replaceAll("__WHATS_NEW__", whatsnewHtml)
1522 whatsnewHtmlFile.text = hugoTemplateSubstitutions(whatsnewHtml,
1529 inputs.file(releasesTemplateFile)
1530 inputs.file(whatsnewTemplateFile)
1531 inputs.dir(releasesMdDir)
1532 inputs.dir(whatsnewMdDir)
1533 outputs.file(releasesHtmlFile)
1534 outputs.file(whatsnewHtmlFile)
1538 task copyHelp(type: Copy) {
1539 dependsOn releasesTemplates
1541 def inputDir = helpSourceDir
1542 def outputDir = "${helpBuildDir}/${help_dir}"
1546 include('**/*.html')
1550 filter(ReplaceTokens,
1554 'Version-Rel': JALVIEW_VERSION,
1555 'Year-Rel': getDate("yyyy")
1562 exclude('**/*.html')
1569 inputs.dir(inputDir)
1570 outputs.files(helpFile)
1571 outputs.dir(outputDir)
1575 task copyResources(type: Copy) {
1577 description = "Copy (and make text substitutions in) the resources dir to the build area"
1579 def inputDir = resourceDir
1580 def outputDir = resourcesBuildDir
1584 include('**/*.html')
1586 filter(ReplaceTokens,
1590 'Version-Rel': JALVIEW_VERSION,
1591 'Year-Rel': getDate("yyyy")
1598 exclude('**/*.html')
1603 inputs.dir(inputDir)
1604 outputs.dir(outputDir)
1607 task copyChannelResources(type: Copy) {
1608 dependsOn copyResources
1610 description = "Copy the channel resources dir to the build resources area"
1612 def inputDir = "${channelDir}/${resource_dir}"
1613 def outputDir = resourcesBuildDir
1617 inputs.dir(inputDir)
1618 outputs.dir(outputDir)
1621 task createBuildProperties(type: WriteProperties) {
1622 dependsOn copyResources
1624 description = "Create the ${buildProperties} file"
1626 inputs.dir(sourceDir)
1627 inputs.dir(resourcesBuildDir)
1628 outputFile (buildProperties)
1629 // taking time specific comment out to allow better incremental builds
1630 comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
1631 //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
1632 property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
1633 property "VERSION", JALVIEW_VERSION
1634 property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
1635 if (getdownSetAppBaseProperty) {
1636 property "GETDOWNAPPBASE", getdownAppBase
1637 property "GETDOWNAPPDISTDIR", getdownAppDistDir
1639 outputs.file(outputFile)
1643 task buildIndices(type: JavaExec) {
1645 classpath = sourceSets.main.compileClasspath
1646 main = "com.sun.java.help.search.Indexer"
1647 workingDir = "${helpBuildDir}/${help_dir}"
1650 inputs.dir("${workingDir}/${argDir}")
1652 outputs.dir("${classesDir}/doc")
1653 outputs.dir("${classesDir}/help")
1654 outputs.file("${workingDir}/JavaHelpSearch/DOCS")
1655 outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
1656 outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
1657 outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
1658 outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
1659 outputs.file("${workingDir}/JavaHelpSearch/TMAP")
1662 task buildResources {
1663 dependsOn copyResources
1664 dependsOn copyChannelResources
1665 dependsOn createBuildProperties
1669 dependsOn buildResources
1672 dependsOn convertMdFiles
1673 dependsOn buildIndices
1677 compileJava.dependsOn prepare
1678 run.dependsOn compileJava
1679 //run.dependsOn prepare
1682 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1687 dependsOn cloverClasses
1689 dependsOn compileJava //?
1693 includeGroups testng_groups
1694 excludeGroups testng_excluded_groups
1696 useDefaultListeners=true
1699 maxHeapSize = "1024m"
1701 workingDir = jalviewDir
1702 def testLaf = project.findProperty("test_laf")
1703 if (testLaf != null) {
1704 println("Setting Test LaF to '${testLaf}'")
1705 systemProperty "laf", testLaf
1707 def testHiDPIScale = project.findProperty("test_HiDPIScale")
1708 if (testHiDPIScale != null) {
1709 println("Setting Test HiDPI Scale to '${testHiDPIScale}'")
1710 systemProperty "sun.java2d.uiScale", testHiDPIScale
1712 sourceCompatibility = compile_source_compatibility
1713 targetCompatibility = compile_target_compatibility
1714 jvmArgs += additional_compiler_args
1718 println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1724 task compileLinkCheck(type: JavaCompile) {
1726 classpath = files("${jalviewDir}/${utils_dir}")
1727 destinationDir = file("${jalviewDir}/${utils_dir}")
1728 source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1730 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1731 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1732 outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1733 outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1737 task linkCheck(type: JavaExec) {
1739 dependsOn compileLinkCheck
1741 def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1742 classpath = files("${jalviewDir}/${utils_dir}")
1743 main = "HelpLinksChecker"
1744 workingDir = jalviewDir
1745 args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1747 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1748 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1751 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1755 inputs.dir(helpBuildDir)
1756 outputs.file(helpLinksCheckerOutFile)
1760 // import the pubhtmlhelp target
1761 ant.properties.basedir = "${jalviewDir}"
1762 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1763 ant.importBuild "${utils_dir}/publishHelp.xml"
1766 task cleanPackageDir(type: Delete) {
1768 delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1778 attributes "Main-Class": main_class,
1779 "Permissions": "all-permissions",
1780 "Application-Name": applicationName,
1781 "Codebase": application_codebase,
1782 "Implementation-Version": JALVIEW_VERSION
1785 def outputDir = "${jalviewDir}/${package_dir}"
1786 destinationDirectory = file(outputDir)
1787 archiveFileName = rootProject.name+".jar"
1788 duplicatesStrategy "EXCLUDE"
1795 exclude "**/*.jar.*"
1797 inputs.dir(sourceSets.main.java.outputDir)
1798 sourceSets.main.resources.srcDirs.each{ dir ->
1801 outputs.file("${outputDir}/${archiveFileName}")
1805 task copyJars(type: Copy) {
1806 from fileTree(dir: classesDir, include: "**/*.jar").files
1807 into "${jalviewDir}/${package_dir}"
1811 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1812 task syncJars(type: Sync) {
1814 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1815 into "${jalviewDir}/${package_dir}"
1817 include jar.archiveFileName.getOrNull()
1824 description = "Put all required libraries in dist"
1825 // order of "cleanPackageDir", "copyJars", "jar" important!
1826 jar.mustRunAfter cleanPackageDir
1827 syncJars.mustRunAfter cleanPackageDir
1828 dependsOn cleanPackageDir
1831 outputs.dir("${jalviewDir}/${package_dir}")
1836 dependsOn cleanPackageDir
1843 group = "distribution"
1844 description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1848 from ("${jalviewDir}/${libDistDir}") {
1852 attributes "Implementation-Version": JALVIEW_VERSION,
1853 "Application-Name": applicationName
1856 duplicatesStrategy "INCLUDE"
1858 mainClassName = shadow_jar_main_class
1860 classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1865 task getdownWebsite() {
1866 group = "distribution"
1867 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1872 def getdownWebsiteResourceFilenames = []
1873 def getdownResourceDir = getdownResourceDir
1874 def getdownResourceFilenames = []
1877 // clean the getdown website and files dir before creating getdown folders
1878 delete getdownAppBaseDir
1879 delete getdownFilesDir
1882 from buildProperties
1883 rename(file(buildProperties).getName(), getdown_build_properties)
1886 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1889 from channelPropsFile
1890 into getdownAppBaseDir
1892 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
1894 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
1895 def props = project.properties.sort { it.key }
1896 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
1897 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
1899 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
1900 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
1902 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
1903 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
1905 if (getdownImagesDir != null && file(getdownImagesDir).exists()) {
1906 props.put("getdown_txt_ui.background_image", "${getdownImagesDir}/${getdown_background_image}")
1907 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesDir}/${getdown_instant_background_image}")
1908 props.put("getdown_txt_ui.error_background", "${getdownImagesDir}/${getdown_error_background}")
1909 props.put("getdown_txt_ui.progress_image", "${getdownImagesDir}/${getdown_progress_image}")
1910 props.put("getdown_txt_ui.icon", "${getdownImagesDir}/${getdown_icon}")
1911 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesDir}/${getdown_mac_dock_icon}")
1914 props.put("getdown_txt_title", jalview_name)
1915 props.put("getdown_txt_ui.name", applicationName)
1917 // start with appbase
1918 getdownTextLines += "appbase = ${getdownAppBase}"
1919 props.each{ prop, val ->
1920 if (prop.startsWith("getdown_txt_") && val != null) {
1921 if (prop.startsWith("getdown_txt_multi_")) {
1922 def key = prop.substring(18)
1923 val.split(",").each{ v ->
1924 def line = "${key} = ${v}"
1925 getdownTextLines += line
1928 // file values rationalised
1929 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
1931 if (val.indexOf('/') == 0) {
1934 } else if (val.indexOf('/') > 0) {
1935 // relative path (relative to jalviewDir)
1936 r = file( "${jalviewDir}/${val}" )
1939 val = "${getdown_resource_dir}/" + r.getName()
1940 getdownWebsiteResourceFilenames += val
1941 getdownResourceFilenames += r.getPath()
1944 if (! prop.startsWith("getdown_txt_resource")) {
1945 def line = prop.substring(12) + " = ${val}"
1946 getdownTextLines += line
1952 getdownWebsiteResourceFilenames.each{ filename ->
1953 getdownTextLines += "resource = ${filename}"
1955 getdownResourceFilenames.each{ filename ->
1958 into getdownResourceDir
1962 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
1963 getdownWrapperScripts.each{ script ->
1964 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
1968 into "${getdownAppBaseDir}/${getdown_wrapper_script_dir}"
1970 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
1975 fileTree(file(package_dir)).each{ f ->
1976 if (f.isDirectory()) {
1977 def files = fileTree(dir: f, include: ["*"]).getFiles()
1979 } else if (f.exists()) {
1983 def jalviewJar = jar.archiveFileName.getOrNull()
1984 // put jalview.jar first for CLASSPATH and .properties files reasons
1985 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
1986 def name = f.getName()
1987 def line = "code = ${getdownAppDistDir}/${name}"
1988 getdownTextLines += line
1995 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
1997 if (JAVA_VERSION.equals("11")) {
1998 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
1999 j11libFiles.sort().each{f ->
2000 def name = f.getName()
2001 def line = "code = ${getdown_j11lib_dir}/${name}"
2002 getdownTextLines += line
2005 into getdownJ11libDir
2011 // 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.
2012 //getdownTextLines += "class = " + file(getdownLauncher).getName()
2013 getdownTextLines += "resource = ${getdown_launcher_new}"
2014 getdownTextLines += "class = ${main_class}"
2015 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
2016 if (getdownSetAppBaseProperty) {
2017 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
2018 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
2021 def getdownTxt = file("${getdownAppBaseDir}/getdown.txt")
2022 getdownTxt.write(getdownTextLines.join("\n"))
2024 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
2025 def launchJvl = file("${getdownAppBaseDir}/${getdownLaunchJvl}")
2026 launchJvl.write("appbase=${getdownAppBase}")
2028 // files going into the getdown website dir: getdown-launcher.jar
2030 from getdownLauncher
2031 rename(file(getdownLauncher).getName(), getdown_launcher_new)
2032 into getdownAppBaseDir
2035 // files going into the getdown website dir: getdown-launcher(-local).jar
2037 from getdownLauncher
2038 if (file(getdownLauncher).getName() != getdown_launcher) {
2039 rename(file(getdownLauncher).getName(), getdown_launcher)
2041 into getdownAppBaseDir
2044 // files going into the getdown website dir: ./install dir and files
2045 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
2048 from getdownLauncher
2049 from "${getdownAppDir}/${getdown_build_properties}"
2050 if (file(getdownLauncher).getName() != getdown_launcher) {
2051 rename(file(getdownLauncher).getName(), getdown_launcher)
2053 into getdownInstallDir
2056 // and make a copy in the getdown files dir (these are not downloaded by getdown)
2058 from getdownInstallDir
2059 into getdownFilesInstallDir
2063 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2067 from getdownLauncher
2068 from "${getdownAppBaseDir}/${getdown_build_properties}"
2069 from "${getdownAppBaseDir}/${channel_props}"
2070 if (file(getdownLauncher).getName() != getdown_launcher) {
2071 rename(file(getdownLauncher).getName(), getdown_launcher)
2073 into getdownFilesDir
2076 // and ./resource (not all downloaded by getdown)
2078 from getdownResourceDir
2079 into "${getdownFilesDir}/${getdown_resource_dir}"
2084 inputs.dir("${jalviewDir}/${package_dir}")
2086 outputs.dir(getdownAppBaseDir)
2087 outputs.dir(getdownFilesDir)
2091 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
2092 task getdownDigestDir(type: JavaExec) {
2094 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
2096 def digestDirPropertyName = "DIGESTDIR"
2098 classpath = files(getdownLauncher)
2099 def digestDir = findProperty(digestDirPropertyName)
2100 if (digestDir == null) {
2101 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
2105 main = "com.threerings.getdown.tools.Digester"
2109 task getdownDigest(type: JavaExec) {
2110 group = "distribution"
2111 description = "Digest the getdown website folder"
2112 dependsOn getdownWebsite
2114 classpath = files(getdownLauncher)
2116 main = "com.threerings.getdown.tools.Digester"
2117 args getdownAppBaseDir
2118 inputs.dir(getdownAppBaseDir)
2119 outputs.file("${getdownAppBaseDir}/digest2.txt")
2124 group = "distribution"
2125 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
2126 dependsOn getdownDigest
2128 if (reportRsyncCommand) {
2129 def fromDir = getdownAppBaseDir + (getdownAppBaseDir.endsWith('/')?'':'/')
2130 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
2131 println "LIKELY RSYNC COMMAND:"
2132 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
2133 if (RUNRSYNC == "true") {
2135 commandLine "mkdir", "-p", toDir
2138 commandLine "rsync", "-avh", "--delete", fromDir, toDir
2146 task getdownArchiveBuild() {
2147 group = "distribution"
2148 description = "Put files in the archive dir to go on the website"
2150 dependsOn getdownWebsite
2152 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
2153 def vDir = "${getdownArchiveDir}/${v}"
2154 getdownFullArchiveDir = "${vDir}/getdown"
2155 getdownVersionLaunchJvl = "${vDir}/jalview-${v}.jvl"
2157 def vAltDir = "alt_${v}"
2158 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
2161 // cleanup old "old" dir
2162 delete getdownArchiveDir
2164 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
2165 getdownArchiveTxt.getParentFile().mkdirs()
2166 def getdownArchiveTextLines = []
2167 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
2171 from "${getdownAppBaseDir}/${getdownAppDistDir}"
2172 into "${getdownFullArchiveDir}/${vAltDir}"
2175 getdownTextLines.each { line ->
2176 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
2177 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
2178 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
2179 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
2180 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
2181 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
2182 // remove the existing resource = resource/ or bin/ lines
2183 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
2184 getdownArchiveTextLines += line
2188 // the resource dir -- add these files as resource lines in getdown.txt
2190 from "${archiveImagesDir}"
2191 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
2193 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
2197 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
2199 def vLaunchJvl = file(getdownVersionLaunchJvl)
2200 vLaunchJvl.getParentFile().mkdirs()
2201 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
2202 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
2203 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
2204 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
2205 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
2206 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
2208 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2210 from getdownLauncher
2211 from "${getdownAppBaseDir}/${getdownLaunchJvl}"
2212 from "${getdownAppBaseDir}/${getdown_launcher_new}"
2213 from "${getdownAppBaseDir}/${channel_props}"
2214 if (file(getdownLauncher).getName() != getdown_launcher) {
2215 rename(file(getdownLauncher).getName(), getdown_launcher)
2217 into getdownFullArchiveDir
2223 task getdownArchiveDigest(type: JavaExec) {
2224 group = "distribution"
2225 description = "Digest the getdown archive folder"
2227 dependsOn getdownArchiveBuild
2230 classpath = files(getdownLauncher)
2231 args getdownFullArchiveDir
2233 main = "com.threerings.getdown.tools.Digester"
2234 inputs.dir(getdownFullArchiveDir)
2235 outputs.file("${getdownFullArchiveDir}/digest2.txt")
2238 task getdownArchive() {
2239 group = "distribution"
2240 description = "Build the website archive dir with getdown digest"
2242 dependsOn getdownArchiveBuild
2243 dependsOn getdownArchiveDigest
2246 tasks.withType(JavaCompile) {
2247 options.encoding = 'UTF-8'
2253 delete getdownAppBaseDir
2254 delete getdownFilesDir
2255 delete getdownArchiveDir
2261 if (file(install4jHomeDir).exists()) {
2263 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
2264 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
2265 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
2266 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
2268 installDir(file(install4jHomeDir))
2270 mediaTypes = Arrays.asList(install4j_media_types.split(","))
2274 task copyInstall4jTemplate {
2275 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
2276 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
2277 inputs.file(install4jTemplateFile)
2278 inputs.file(install4jFileAssociationsFile)
2279 inputs.property("CHANNEL", { CHANNEL })
2280 outputs.file(install4jConfFile)
2283 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
2285 // turn off code signing if no OSX_KEYPASS
2286 if (OSX_KEYPASS == "") {
2287 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
2288 codeSigning.'@macEnabled' = "false"
2290 install4jConfigXml.'**'.windows.each { windows ->
2291 windows.'@runPostProcessor' = "false"
2295 // disable install screen for OSX dmg (for 2.11.2.0)
2296 install4jConfigXml.'**'.macosArchive.each { macosArchive ->
2297 macosArchive.attributes().remove('executeSetupApp')
2298 macosArchive.attributes().remove('setupAppId')
2301 // turn off checksum creation for LOCAL channel
2302 def e = install4jConfigXml.application[0]
2303 e.'@createChecksums' = string(install4jCheckSums)
2305 // put file association actions where placeholder action is
2306 def install4jFileAssociationsText = install4jFileAssociationsFile.text
2307 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
2308 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
2309 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
2310 def parent = a.parent()
2312 fileAssociationActions.each { faa ->
2315 // don't need to continue in .any loop once replacements have been made
2320 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
2321 // NB we're deleting the /other/ one!
2322 // Also remove the examples subdir from non-release versions
2323 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
2324 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
2325 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
2326 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
2328 // remove the examples subdir from Full File Set
2329 def files = install4jConfigXml.files[0]
2330 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
2331 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
2332 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
2333 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
2334 dirEntry.parent().remove(dirEntry)
2336 install4jConfigXml.'**'.action.any { a ->
2337 if (a.'@customizedId' == customizedIdToDelete) {
2338 def parent = a.parent()
2344 // write install4j file
2345 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
2352 delete install4jConfFile
2356 task cleanInstallersDataFiles {
2357 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2358 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2359 def hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
2361 delete installersOutputTxt
2362 delete installersSha256
2363 delete hugoDataJsonFile
2367 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2368 group = "distribution"
2369 description = "Create the install4j installers"
2371 dependsOn copyInstall4jTemplate
2372 dependsOn cleanInstallersDataFiles
2374 projectFile = install4jConfFile
2376 // create an md5 for the input files to use as version for install4j conf file
2377 def digest = MessageDigest.getInstance("MD5")
2379 (file("${install4jDir}/${install4j_template}").text +
2380 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2381 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2382 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2383 if (filesMd5.length() >= 8) {
2384 filesMd5 = filesMd5.substring(0,8)
2386 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2389 'JALVIEW_NAME': jalview_name,
2390 'JALVIEW_APPLICATION_NAME': applicationName,
2391 'JALVIEW_DIR': "../..",
2392 'OSX_KEYSTORE': OSX_KEYSTORE,
2393 'OSX_APPLEID': OSX_APPLEID,
2394 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2395 'JSIGN_SH': JSIGN_SH,
2396 'JRE_DIR': getdown_app_dir_java,
2397 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2398 'JALVIEW_VERSION': JALVIEW_VERSION,
2399 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2400 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2401 'JAVA_VERSION': JAVA_VERSION,
2402 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2403 'VERSION': JALVIEW_VERSION,
2404 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2405 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2406 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2407 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2408 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2409 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2410 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2411 'BUNDLE_ID': install4jBundleId,
2412 'INTERNAL_ID': install4jInternalId,
2413 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2414 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2415 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
2416 'WRAPPER_LINK': getdownWrapperLink,
2417 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2418 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2419 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2420 'INSTALLER_NAME': install4jInstallerName,
2421 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2422 'GETDOWN_CHANNEL_DIR': getdownChannelDir,
2423 'GETDOWN_FILES_DIR': getdown_files_dir,
2424 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2425 'GETDOWN_DIST_DIR': getdownAppDistDir,
2426 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2427 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2428 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2429 'BUILD_DIR': install4jBuildDir,
2430 'APPLICATION_CATEGORIES': install4j_application_categories,
2431 'APPLICATION_FOLDER': install4jApplicationFolder,
2432 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2433 'EXECUTABLE_NAME': install4jExecutableName,
2434 'EXTRA_SCHEME': install4jExtraScheme,
2435 'MAC_ICONS_FILE': install4jMacIconsFile,
2436 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2437 'PNG_ICON_FILE': install4jPngIconFile,
2438 'BACKGROUND': install4jBackground,
2442 //println("INSTALL4J VARIABLES:")
2443 //variables.each{k,v->println("${k}=${v}")}
2445 destination = "${jalviewDir}/${install4jBuildDir}"
2446 buildSelected = true
2448 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2450 disableSigning = true
2451 disableNotarization = true
2455 macKeystorePassword = OSX_KEYPASS
2458 if (OSX_ALTOOLPASS) {
2459 appleIdPassword = OSX_ALTOOLPASS
2460 disableNotarization = false
2462 disableNotarization = true
2466 println("Using projectFile "+projectFile)
2467 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2471 inputs.dir(getdownAppBaseDir)
2472 inputs.file(install4jConfFile)
2473 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2474 inputs.dir(macosJavaVMDir)
2475 inputs.dir(windowsJavaVMDir)
2476 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2479 def getDataHash(File myFile) {
2480 HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
2481 return myFile.exists()
2483 "file" : myFile.getName(),
2484 "filesize" : myFile.length(),
2485 "sha256" : hash.toString()
2490 def writeDataJsonFile(File installersOutputTxt, File installersSha256, File dataJsonFile) {
2492 "channel" : getdownChannelName,
2493 "date" : getDate("yyyy-MM-dd HH:mm:ss"),
2494 "git-commit" : "${gitHash} [${gitBranch}]",
2495 "version" : JALVIEW_VERSION
2497 // install4j installer files
2498 if (installersOutputTxt.exists()) {
2500 installersOutputTxt.readLines().each { def line ->
2501 if (line.startsWith("#")) {
2504 line.replaceAll("\n","")
2505 def vals = line.split("\t")
2506 def filename = vals[3]
2507 def filesize = file(filename).length()
2508 filename = filename.replaceAll(/^.*\//, "")
2509 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2510 idHash."${filename}" = vals[0]
2512 if (install4jCheckSums && installersSha256.exists()) {
2513 installersSha256.readLines().each { def line ->
2514 if (line.startsWith("#")) {
2517 line.replaceAll("\n","")
2518 def vals = line.split(/\s+\*?/)
2519 def filename = vals[1]
2520 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2526 "JAR": shadowJar.archiveFile, // executable JAR
2527 "JVL": getdownVersionLaunchJvl, // version JVL
2528 "SOURCE": sourceDist.archiveFile // source TGZ
2529 ].each { key, value ->
2530 def file = file(value)
2531 if (file.exists()) {
2532 def fileHash = getDataHash(file)
2533 if (fileHash != null) {
2534 hash."${key}" = fileHash;
2538 return dataJsonFile.write(new JsonBuilder(hash).toPrettyString())
2541 task staticMakeInstallersJsonFile {
2543 def output = findProperty("i4j_output")
2544 def sha256 = findProperty("i4j_sha256")
2545 def json = findProperty("i4j_json")
2546 if (output == null || sha256 == null || json == null) {
2547 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2549 writeDataJsonFile(file(output), file(sha256), file(json))
2554 dependsOn installerFiles
2560 eclipse().configFile(eclipse_codestyle_file)
2564 task createSourceReleaseProperties(type: WriteProperties) {
2565 group = "distribution"
2566 description = "Create the source RELEASE properties file"
2568 def sourceTarBuildDir = "${buildDir}/sourceTar"
2569 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2570 outputFile (sourceReleasePropertiesFile)
2573 releaseProps.each{ key, val -> property key, val }
2574 property "git.branch", gitBranch
2575 property "git.hash", gitHash
2578 outputs.file(outputFile)
2581 task sourceDist(type: Tar) {
2582 group "distribution"
2583 description "Create a source .tar.gz file for distribution"
2585 dependsOn createBuildProperties
2586 dependsOn convertMdFiles
2587 dependsOn eclipseAllPreferences
2588 dependsOn createSourceReleaseProperties
2591 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2592 archiveFileName = outputFileName
2594 compression Compression.GZIP
2609 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2611 "utils/InstallAnywhere",
2626 "gradle.properties",
2638 ".settings/org.eclipse.buildship.core.prefs",
2639 ".settings/org.eclipse.jdt.core.prefs"
2643 exclude (EXCLUDE_FILES)
2644 include (PROCESS_FILES)
2645 filter(ReplaceTokens,
2649 'Version-Rel': JALVIEW_VERSION,
2650 'Year-Rel': getDate("yyyy")
2655 exclude (EXCLUDE_FILES)
2656 exclude (PROCESS_FILES)
2657 exclude ("appletlib")
2658 exclude ("**/*locales")
2659 exclude ("*locales/**")
2660 exclude ("utils/InstallAnywhere")
2662 exclude (getdown_files_dir)
2663 // getdown_website_dir and getdown_archive_dir moved to build/website/docroot/getdown
2664 //exclude (getdown_website_dir)
2665 //exclude (getdown_archive_dir)
2667 // exluding these as not using jars as modules yet
2668 exclude ("${j11modDir}/**/*.jar")
2671 include(INCLUDE_FILES)
2673 // from (jalviewDir) {
2674 // // explicit includes for stuff that seemed to not get included
2675 // include(fileTree("test/**/*."))
2676 // exclude(EXCLUDE_FILES)
2677 // exclude(PROCESS_FILES)
2680 from(file(buildProperties).getParent()) {
2681 include(file(buildProperties).getName())
2682 rename(file(buildProperties).getName(), "build_properties")
2684 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2688 def sourceTarBuildDir = "${buildDir}/sourceTar"
2689 from(sourceTarBuildDir) {
2690 // this includes the appended RELEASE properties file
2694 task dataInstallersJson {
2696 description "Create the installers-VERSION.json data file for installer files created"
2698 mustRunAfter installers
2699 mustRunAfter shadowJar
2700 mustRunAfter sourceDist
2701 mustRunAfter getdownArchive
2703 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2704 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2706 if (installersOutputTxt.exists()) {
2707 inputs.file(installersOutputTxt)
2709 if (install4jCheckSums && installersSha256.exists()) {
2710 inputs.file(installersSha256)
2713 shadowJar.archiveFile, // executable JAR
2714 getdownVersionLaunchJvl, // version JVL
2715 sourceDist.archiveFile // source TGZ
2716 ].each { fileName ->
2717 if (file(fileName).exists()) {
2718 inputs.file(fileName)
2722 outputs.file(hugoDataJsonFile)
2725 writeDataJsonFile(installersOutputTxt, installersSha256, hugoDataJsonFile)
2731 description "Copies all help pages to build dir. Runs ant task 'pubhtmlhelp'."
2734 dependsOn pubhtmlhelp
2736 inputs.dir("${helpBuildDir}/${help_dir}")
2737 outputs.dir("${buildDir}/distributions/${help_dir}")
2741 task j2sSetHeadlessBuild {
2748 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2750 description "Enable the alternative J2S Config file for headless build"
2752 outputFile = jalviewjsJ2sSettingsFileName
2753 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2754 def j2sProps = new Properties()
2755 if (j2sPropsFile.exists()) {
2757 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2758 j2sProps.load(j2sPropsFileFIS)
2759 j2sPropsFileFIS.close()
2761 j2sProps.each { prop, val ->
2764 } catch (Exception e) {
2765 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2769 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2770 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2775 task jalviewjsSetEclipseWorkspace {
2776 def propKey = "jalviewjs_eclipse_workspace"
2778 if (project.hasProperty(propKey)) {
2779 propVal = project.getProperty(propKey)
2780 if (propVal.startsWith("~/")) {
2781 propVal = System.getProperty("user.home") + propVal.substring(1)
2784 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2785 def propsFile = file(propsFileName)
2786 def eclipseWsDir = propVal
2787 def props = new Properties()
2789 def writeProps = true
2790 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2791 def ins = new FileInputStream(propsFileName)
2794 if (props.getProperty(propKey, null) != null) {
2795 eclipseWsDir = props.getProperty(propKey)
2800 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2801 def tempDir = File.createTempDir()
2802 eclipseWsDir = tempDir.getAbsolutePath()
2805 eclipseWorkspace = file(eclipseWsDir)
2808 // do not run a headless transpile when we claim to be in Eclipse
2810 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2811 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2813 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2817 props.setProperty(propKey, eclipseWsDir)
2818 propsFile.parentFile.mkdirs()
2819 def bytes = new ByteArrayOutputStream()
2820 props.store(bytes, null)
2821 def propertiesString = bytes.toString()
2822 propsFile.text = propertiesString
2828 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2831 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2832 outputs.file(propsFileName)
2833 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2837 task jalviewjsEclipsePaths {
2840 def eclipseRoot = jalviewjs_eclipse_root
2841 if (eclipseRoot.startsWith("~/")) {
2842 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
2844 if (OperatingSystem.current().isMacOsX()) {
2845 eclipseRoot += "/Eclipse.app"
2846 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
2847 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
2848 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
2849 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2850 eclipseRoot += "/eclipse"
2852 eclipseBinary = "${eclipseRoot}/eclipse.exe"
2853 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2854 } else { // linux or unix
2855 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2856 eclipseRoot += "/eclipse"
2857 println("eclipseDir exists")
2859 eclipseBinary = "${eclipseRoot}/eclipse"
2860 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2863 eclipseVersion = "4.13" // default
2864 def assumedVersion = true
2865 if (file(eclipseProduct).exists()) {
2866 def fis = new FileInputStream(eclipseProduct)
2867 def props = new Properties()
2869 eclipseVersion = props.getProperty("version")
2871 assumedVersion = false
2874 def propKey = "eclipse_debug"
2875 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
2878 // do not run a headless transpile when we claim to be in Eclipse
2880 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2881 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2883 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2886 if (!assumedVersion) {
2887 println("ECLIPSE VERSION=${eclipseVersion}")
2893 task printProperties {
2895 description "Output to console all System.properties"
2897 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
2903 dependsOn eclipseProject
2904 dependsOn eclipseClasspath
2905 dependsOn eclipseJdt
2909 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
2910 task jalviewjsEclipseCopyDropins(type: Copy) {
2911 dependsOn jalviewjsEclipsePaths
2913 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
2914 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
2915 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
2922 // this eclipse -clean doesn't actually work
2923 task jalviewjsCleanEclipse(type: Exec) {
2924 dependsOn eclipseSetup
2925 dependsOn jalviewjsEclipsePaths
2926 dependsOn jalviewjsEclipseCopyDropins
2928 executable(eclipseBinary)
2929 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
2935 def inputString = """exit
2938 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
2939 standardInput = inputByteStream
2942 /* not really working yet
2943 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
2947 task jalviewjsTransferUnzipSwingJs {
2948 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
2952 from zipTree(file_zip)
2953 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2957 inputs.file file_zip
2958 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2962 task jalviewjsTransferUnzipLib {
2963 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
2966 zipFiles.each { file_zip ->
2968 from zipTree(file_zip)
2969 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2974 inputs.files zipFiles
2975 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2979 task jalviewjsTransferUnzipAllLibs {
2980 dependsOn jalviewjsTransferUnzipSwingJs
2981 dependsOn jalviewjsTransferUnzipLib
2985 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
2987 description "Create the alternative j2s file from the j2s.* properties"
2989 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
2990 def siteDirProperty = "j2s.site.directory"
2991 def setSiteDir = false
2992 jalviewjsJ2sProps.each { prop, val ->
2994 if (prop == siteDirProperty) {
2995 if (!(val.startsWith('/') || val.startsWith("file://") )) {
2996 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
3002 if (!setSiteDir) { // default site location, don't override specifically set property
3003 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
3006 outputFile = jalviewjsJ2sAltSettingsFileName
3009 inputs.properties(jalviewjsJ2sProps)
3010 outputs.file(jalviewjsJ2sAltSettingsFileName)
3015 task jalviewjsEclipseSetup {
3016 dependsOn jalviewjsEclipseCopyDropins
3017 dependsOn jalviewjsSetEclipseWorkspace
3018 dependsOn jalviewjsCreateJ2sSettings
3022 task jalviewjsSyncAllLibs (type: Sync) {
3023 dependsOn jalviewjsTransferUnzipAllLibs
3024 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
3025 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
3026 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3030 def outputFiles = []
3031 rename { filename ->
3032 outputFiles += "${outputDir}/${filename}"
3039 // should this be exclude really ?
3040 duplicatesStrategy "INCLUDE"
3042 outputs.files outputFiles
3043 inputs.files inputFiles
3047 task jalviewjsSyncResources (type: Sync) {
3048 dependsOn buildResources
3050 def inputFiles = fileTree(dir: resourcesBuildDir)
3051 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3055 def outputFiles = []
3056 rename { filename ->
3057 outputFiles += "${outputDir}/${filename}"
3063 outputs.files outputFiles
3064 inputs.files inputFiles
3068 task jalviewjsSyncSiteResources (type: Sync) {
3069 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
3070 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3074 def outputFiles = []
3075 rename { filename ->
3076 outputFiles += "${outputDir}/${filename}"
3082 outputs.files outputFiles
3083 inputs.files inputFiles
3087 task jalviewjsSyncBuildProperties (type: Sync) {
3088 dependsOn createBuildProperties
3089 def inputFiles = [file(buildProperties)]
3090 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3094 def outputFiles = []
3095 rename { filename ->
3096 outputFiles += "${outputDir}/${filename}"
3102 outputs.files outputFiles
3103 inputs.files inputFiles
3107 task jalviewjsProjectImport(type: Exec) {
3108 dependsOn eclipseSetup
3109 dependsOn jalviewjsEclipsePaths
3110 dependsOn jalviewjsEclipseSetup
3113 // do not run a headless import when we claim to be in Eclipse
3115 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3116 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3118 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3122 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
3123 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
3124 executable(eclipseBinary)
3125 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
3129 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3131 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3132 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3135 inputs.file("${jalviewDir}/.project")
3136 outputs.upToDateWhen {
3137 file(projdir).exists()
3142 task jalviewjsTranspile(type: Exec) {
3143 dependsOn jalviewjsEclipseSetup
3144 dependsOn jalviewjsProjectImport
3145 dependsOn jalviewjsEclipsePaths
3147 dependsOn jalviewjsEnableAltFileProperty
3151 // do not run a headless transpile when we claim to be in Eclipse
3153 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3154 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3156 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3160 executable(eclipseBinary)
3161 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
3165 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3167 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3168 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3174 stdout = new ByteArrayOutputStream()
3175 stderr = new ByteArrayOutputStream()
3177 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
3178 def logOutFile = file(logOutFileName)
3179 logOutFile.createNewFile()
3180 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
3181 BINARY: ${eclipseBinary}
3182 VERSION: ${eclipseVersion}
3183 WORKSPACE: ${eclipseWorkspace}
3184 DEBUG: ${eclipseDebug}
3187 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3188 // combine stdout and stderr
3189 def logErrFOS = logOutFOS
3191 if (jalviewjs_j2s_to_console.equals("true")) {
3192 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3193 new org.apache.tools.ant.util.TeeOutputStream(
3197 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3198 new org.apache.tools.ant.util.TeeOutputStream(
3203 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3206 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3213 if (stdout.toString().contains("Error processing ")) {
3214 // j2s did not complete transpile
3215 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3216 if (jalviewjs_ignore_transpile_errors.equals("true")) {
3217 println("IGNORING TRANSPILE ERRORS")
3218 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3220 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3225 inputs.dir("${jalviewDir}/${sourceDir}")
3226 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
3227 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
3231 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
3233 def stdout = new ByteArrayOutputStream()
3234 def stderr = new ByteArrayOutputStream()
3236 def coreFile = file(jsfile)
3238 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
3240 logOutFile.createNewFile()
3241 logOutFile.append(msg+"\n")
3243 def coreTop = file(prefixFile)
3244 def coreBottom = file(suffixFile)
3245 coreFile.getParentFile().mkdirs()
3246 coreFile.createNewFile()
3247 coreFile.write( coreTop.getText("UTF-8") )
3251 def t = f.getText("UTF-8")
3252 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
3253 coreFile.append( t )
3255 msg = "...file '"+f.getPath()+"' does not exist, skipping"
3257 logOutFile.append(msg+"\n")
3260 coreFile.append( coreBottom.getText("UTF-8") )
3262 msg = "Generating ${zjsfile}"
3264 logOutFile.append(msg+"\n")
3265 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3266 def logErrFOS = logOutFOS
3269 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
3270 main = "com.google.javascript.jscomp.CommandLineRunner"
3271 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
3272 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
3275 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
3277 logOutFile.append(msg+"\n")
3279 if (logOutConsole) {
3280 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3281 new org.apache.tools.ant.util.TeeOutputStream(
3285 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3286 new org.apache.tools.ant.util.TeeOutputStream(
3291 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3294 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3301 logOutFile.append(msg+"\n")
3305 task jalviewjsBuildAllCores {
3307 description "Build the core js lib closures listed in the classlists dir"
3308 dependsOn jalviewjsTranspile
3309 dependsOn jalviewjsTransferUnzipSwingJs
3311 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
3312 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
3313 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
3314 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
3315 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
3316 def prefixFile = "${jsDir}/core/coretop2.js"
3317 def suffixFile = "${jsDir}/core/corebottom2.js"
3319 inputs.file prefixFile
3320 inputs.file suffixFile
3322 def classlistFiles = []
3323 // add the classlists found int the jalviewjs_classlists_dir
3324 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
3326 def name = file.getName() - ".txt"
3333 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
3334 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
3335 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
3337 jalviewjsCoreClasslists = []
3339 classlistFiles.each {
3342 def file = hash['file']
3343 if (! file.exists()) {
3344 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
3345 return false // this is a "continue" in groovy .each closure
3347 def name = hash['name']
3349 name = file.getName() - ".txt"
3357 def list = fileTree(dir: j2sDir, includes: filelist)
3359 def jsfile = "${outputDir}/core${name}.js"
3360 def zjsfile = "${outputDir}/core${name}.z.js"
3362 jalviewjsCoreClasslists += [
3371 outputs.file(jsfile)
3372 outputs.file(zjsfile)
3375 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
3376 def stevesoftClasslistName = "_stevesoft"
3377 def stevesoftClasslist = [
3378 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
3379 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
3380 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
3381 'name': stevesoftClasslistName
3383 jalviewjsCoreClasslists += stevesoftClasslist
3384 inputs.files(stevesoftClasslist['list'])
3385 outputs.file(stevesoftClasslist['jsfile'])
3386 outputs.file(stevesoftClasslist['zjsfile'])
3389 def allClasslistName = "_all"
3390 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3391 allJsFiles += fileTree(
3395 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3396 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3397 "**/org/jmol/export/JSExporter.js"
3400 allJsFiles += fileTree(
3404 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3405 "**/sun/misc/Unsafe.js",
3406 "**/swingjs/jquery/jquery-editable-select.js",
3407 "**/swingjs/jquery/j2sComboBox.js",
3408 "**/sun/misc/FloatingDecimal.js"
3411 def allClasslist = [
3412 'jsfile': "${outputDir}/core${allClasslistName}.js",
3413 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
3415 'name': allClasslistName
3417 // not including this version of "all" core at the moment
3418 //jalviewjsCoreClasslists += allClasslist
3419 inputs.files(allClasslist['list'])
3420 outputs.file(allClasslist['jsfile'])
3421 outputs.file(allClasslist['zjsfile'])
3424 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3425 logOutFile.getParentFile().mkdirs()
3426 logOutFile.createNewFile()
3427 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3429 jalviewjsCoreClasslists.each {
3430 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3437 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3440 into file(outputFile).getParentFile()
3441 rename { filename ->
3442 if (filename.equals(inputFile.getName())) {
3443 return file(outputFile).getName()
3447 filter(ReplaceTokens,
3451 'MAIN': '"'+main_class+'"',
3453 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3454 'COREKEY': jalviewjs_core_key,
3455 'CORENAME': coreName
3462 task jalviewjsPublishCoreTemplates {
3463 dependsOn jalviewjsBuildAllCores
3464 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3465 def inputFile = file(inputFileName)
3466 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3468 def outputFiles = []
3469 jalviewjsCoreClasslists.each { cl ->
3470 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3471 cl['outputfile'] = outputFile
3472 outputFiles += outputFile
3476 jalviewjsCoreClasslists.each { cl ->
3477 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3480 inputs.file(inputFile)
3481 outputs.files(outputFiles)
3485 task jalviewjsSyncCore (type: Sync) {
3486 dependsOn jalviewjsBuildAllCores
3487 dependsOn jalviewjsPublishCoreTemplates
3488 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3489 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3493 def outputFiles = []
3494 rename { filename ->
3495 outputFiles += "${outputDir}/${filename}"
3501 outputs.files outputFiles
3502 inputs.files inputFiles
3506 // this Copy version of TransferSiteJs will delete anything else in the target dir
3507 task jalviewjsCopyTransferSiteJs(type: Copy) {
3508 dependsOn jalviewjsTranspile
3509 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3510 into "${jalviewDir}/${jalviewjsSiteDir}"
3514 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3515 task jalviewjsSyncTransferSiteJs(type: Sync) {
3516 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3518 into "${jalviewDir}/${jalviewjsSiteDir}"
3525 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3526 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3527 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3528 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3530 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3531 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3532 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3533 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3536 task jalviewjsPrepareSite {
3538 description "Prepares the website folder including unzipping files and copying resources"
3539 dependsOn jalviewjsSyncAllLibs
3540 dependsOn jalviewjsSyncResources
3541 dependsOn jalviewjsSyncSiteResources
3542 dependsOn jalviewjsSyncBuildProperties
3543 dependsOn jalviewjsSyncCore
3547 task jalviewjsBuildSite {
3549 description "Builds the whole website including transpiled code"
3550 dependsOn jalviewjsCopyTransferSiteJs
3551 dependsOn jalviewjsPrepareSite
3555 task cleanJalviewjsTransferSite {
3557 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3558 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3559 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3560 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3565 task cleanJalviewjsSite {
3566 dependsOn cleanJalviewjsTransferSite
3568 delete "${jalviewDir}/${jalviewjsSiteDir}"
3573 task jalviewjsSiteTar(type: Tar) {
3575 description "Creates a tar.gz file for the website"
3576 dependsOn jalviewjsBuildSite
3577 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3578 archiveFileName = outputFilename
3580 compression Compression.GZIP
3582 from "${jalviewDir}/${jalviewjsSiteDir}"
3583 into jalviewjs_site_dir // this is inside the tar file
3585 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3589 task jalviewjsServer {
3591 def filename = "jalviewjsTest.html"
3592 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3593 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3598 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3599 factory = f.newInstance()
3600 } catch (ClassNotFoundException e) {
3601 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3603 def port = Integer.valueOf(jalviewjs_server_port)
3608 while(port < start+1000 && !running) {
3610 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3611 jalviewjsServer = factory.start(doc_root, port)
3613 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3614 println("SERVER STARTED with document root ${doc_root}.")
3615 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3616 println("For debug: "+url+"?j2sdebug")
3617 println("For verbose: "+url+"?j2sverbose")
3618 } catch (Exception e) {
3623 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3624 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3625 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3627 jalviewjsCoreClasslists.each { cl ->
3628 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3630 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3632 println("For core ${cl.name}: "+urlcore)
3635 file(htmlFile).text = htmlText
3638 outputs.file(htmlFile)
3639 outputs.upToDateWhen({false})
3643 task cleanJalviewjsAll {
3645 description "Delete all configuration and build artifacts to do with JalviewJS build"
3646 dependsOn cleanJalviewjsSite
3647 dependsOn jalviewjsEclipsePaths
3650 delete "${jalviewDir}/${jalviewjsBuildDir}"
3651 delete "${jalviewDir}/${eclipse_bin_dir}"
3652 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3653 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3655 delete jalviewjsJ2sAltSettingsFileName
3658 outputs.upToDateWhen( { false } )
3662 task jalviewjsIDE_checkJ2sPlugin {
3663 group "00 JalviewJS in Eclipse"
3664 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3667 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3668 def j2sPluginFile = file(j2sPlugin)
3669 def eclipseHome = System.properties["eclipse.home.location"]
3670 if (eclipseHome == null || ! IN_ECLIPSE) {
3671 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3673 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3674 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3675 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3676 eclipseJ2sPluginDirs += altPluginsDir
3678 def foundPlugin = false
3679 def j2sPluginFileName = j2sPluginFile.getName()
3680 def eclipseJ2sPlugin
3681 def eclipseJ2sPluginFile
3682 eclipseJ2sPluginDirs.any { dir ->
3683 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3684 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3685 if (eclipseJ2sPluginFile.exists()) {
3691 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3692 System.err.println(msg)
3693 throw new StopExecutionException(msg)
3696 def digest = MessageDigest.getInstance("MD5")
3698 digest.update(j2sPluginFile.text.bytes)
3699 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3701 digest.update(eclipseJ2sPluginFile.text.bytes)
3702 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3704 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3705 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3706 System.err.println(msg)
3707 throw new StopExecutionException(msg)
3709 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3715 task jalviewjsIDE_copyJ2sPlugin {
3716 group "00 JalviewJS in Eclipse"
3717 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3720 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3721 def j2sPluginFile = file(j2sPlugin)
3722 def eclipseHome = System.properties["eclipse.home.location"]
3723 if (eclipseHome == null || ! IN_ECLIPSE) {
3724 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3726 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3727 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3728 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3729 System.err.println(msg)
3732 eclipseJ2sPluginFile.getParentFile().mkdirs()
3733 into eclipseJ2sPluginFile.getParent()
3739 task jalviewjsIDE_j2sFile {
3740 group "00 JalviewJS in Eclipse"
3741 description "Creates the .j2s file"
3742 dependsOn jalviewjsCreateJ2sSettings
3746 task jalviewjsIDE_SyncCore {
3747 group "00 JalviewJS in Eclipse"
3748 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3749 dependsOn jalviewjsSyncCore
3753 task jalviewjsIDE_SyncSiteAll {
3754 dependsOn jalviewjsSyncAllLibs
3755 dependsOn jalviewjsSyncResources
3756 dependsOn jalviewjsSyncSiteResources
3757 dependsOn jalviewjsSyncBuildProperties
3761 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3764 task jalviewjsIDE_PrepareSite {
3765 group "00 JalviewJS in Eclipse"
3766 description "Sync libs and resources to site dir, but not closure cores"
3768 dependsOn jalviewjsIDE_SyncSiteAll
3769 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3773 task jalviewjsIDE_AssembleSite {
3774 group "00 JalviewJS in Eclipse"
3775 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3776 dependsOn jalviewjsPrepareSite
3780 task jalviewjsIDE_SiteClean {
3781 group "00 JalviewJS in Eclipse"
3782 description "Deletes the Eclipse transpiled site"
3783 dependsOn cleanJalviewjsSite
3787 task jalviewjsIDE_Server {
3788 group "00 JalviewJS in Eclipse"
3789 description "Starts a webserver on localhost to test the website"
3790 dependsOn jalviewjsServer
3794 // buildship runs this at import or gradle refresh
3795 task eclipseSynchronizationTask {
3796 //dependsOn eclipseSetup
3797 dependsOn createBuildProperties
3799 dependsOn jalviewjsIDE_j2sFile
3800 dependsOn jalviewjsIDE_checkJ2sPlugin
3801 dependsOn jalviewjsIDE_PrepareSite
3806 // buildship runs this at build time or project refresh
3807 task eclipseAutoBuildTask {
3808 //dependsOn jalviewjsIDE_checkJ2sPlugin
3809 //dependsOn jalviewjsIDE_PrepareSite
3815 description "Build the site"
3816 dependsOn jalviewjsBuildSite