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.spotless" version "6.18.0" //.gradle.spotless" "3.28.0"
49 id 'com.github.johnrengelman.shadow' version '8.1.1' // was 4.0.3
50 id 'com.install4j.gradle' version '9.0.6'
51 id 'com.dorongold.task-tree' version '2.1.0' // only needed to display task dependency tree with gradle task1 [task2 ...] taskTree
52 id 'com.palantir.git-version' version '0.13.0' apply false
63 // in ext the values are cast to Object. Ensure string values are cast as String (and not GStringImpl) for later use
64 def string(Object o) {
65 return o == null ? "" : o.toString()
68 def overrideProperties(String propsFileName, boolean output = false) {
69 if (propsFileName == null) {
72 def propsFile = file(propsFileName)
73 if (propsFile != null && propsFile.exists()) {
74 println("Using properties from file '${propsFileName}'")
76 def p = new Properties()
77 def localPropsFIS = new FileInputStream(propsFile)
83 if (project.hasProperty(key)) {
84 oldval = project.findProperty(key)
85 project.setProperty(key, val)
87 println("Overriding property '${key}' ('${oldval}') with ${file(propsFile).getName()} value '${val}'")
90 ext.setProperty(key, val)
92 println("Setting ext property '${key}' with ${file(propsFile).getName()}s value '${val}'")
96 } catch (Exception e) {
97 println("Exception reading local.properties")
104 jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath()
105 jalviewDirRelativePath = jalviewDir
108 getdownChannelName = CHANNEL.toLowerCase()
109 // default to "default". Currently only has different cosmetics for "develop", "release", "default"
110 propertiesChannelName = ["develop", "release", "test-release", "jalviewjs", "jalviewjs-release" ].contains(getdownChannelName) ? getdownChannelName : "default"
111 // Import channel_properties
112 channelDir = string("${jalviewDir}/${channel_properties_dir}/${propertiesChannelName}")
113 channelGradleProperties = string("${channelDir}/channel_gradle.properties")
114 channelPropsFile = string("${channelDir}/${resource_dir}/${channel_props}")
115 overrideProperties(channelGradleProperties, false)
116 // local build environment properties
117 // can be "projectDir/local.properties"
118 overrideProperties("${projectDir}/local.properties", true)
119 // or "../projectDir_local.properties"
120 overrideProperties(projectDir.getParent() + "/" + projectDir.getName() + "_local.properties", true)
123 // Import releaseProps from the RELEASE file
124 // or a file specified via JALVIEW_RELEASE_FILE if defined
125 // Expect jalview.version and target release branch in jalview.release
126 releaseProps = new Properties();
127 def releasePropFile = findProperty("JALVIEW_RELEASE_FILE");
128 def defaultReleasePropFile = "${jalviewDirAbsolutePath}/RELEASE";
130 (new File(releasePropFile!=null ? releasePropFile : defaultReleasePropFile)).withInputStream {
131 releaseProps.load(it)
133 } catch (Exception fileLoadError) {
134 throw new Error("Couldn't load release properties file "+(releasePropFile==null ? defaultReleasePropFile : "from custom location: releasePropFile"),fileLoadError);
137 // Set JALVIEW_VERSION if it is not already set
138 if (findProperty("JALVIEW_VERSION")==null || "".equals(JALVIEW_VERSION)) {
139 JALVIEW_VERSION = releaseProps.get("jalview.version")
141 println("JALVIEW_VERSION is set to '${JALVIEW_VERSION}'")
143 // this property set when running Eclipse headlessly
144 j2sHeadlessBuildProperty = string("net.sf.j2s.core.headlessbuild")
145 // this property set by Eclipse
146 eclipseApplicationProperty = string("eclipse.application")
147 // CHECK IF RUNNING FROM WITHIN ECLIPSE
148 def eclipseApplicationPropertyVal = System.properties[eclipseApplicationProperty]
149 IN_ECLIPSE = eclipseApplicationPropertyVal != null && eclipseApplicationPropertyVal.startsWith("org.eclipse.ui.")
150 // BUT WITHOUT THE HEADLESS BUILD PROPERTY SET
151 if (System.properties[j2sHeadlessBuildProperty].equals("true")) {
152 println("Setting IN_ECLIPSE to ${IN_ECLIPSE} as System.properties['${j2sHeadlessBuildProperty}'] == '${System.properties[j2sHeadlessBuildProperty]}'")
156 println("WITHIN ECLIPSE IDE")
158 println("HEADLESS BUILD")
161 J2S_ENABLED = (project.hasProperty('j2s.compiler.status') && project['j2s.compiler.status'] != null && project['j2s.compiler.status'] == "enable")
163 println("J2S ENABLED")
166 System.properties.sort { it.key }.each {
167 key, val -> println("SYSTEM PROPERTY ${key}='${val}'")
170 if (false && IN_ECLIPSE) {
171 jalviewDir = jalviewDirAbsolutePath
176 buildDate = new Date().format("yyyyMMdd")
179 bareSourceDir = string(source_dir)
180 sourceDir = string("${jalviewDir}/${bareSourceDir}")
181 resourceDir = string("${jalviewDir}/${resource_dir}")
182 bareTestSourceDir = string(test_source_dir)
183 testDir = string("${jalviewDir}/${bareTestSourceDir}")
185 classesDir = string("${jalviewDir}/${classes_dir}")
186 destinationDirectory = file(classesDir)
189 useClover = clover.equals("true")
190 cloverBuildDir = "${buildDir}/clover"
191 cloverInstrDir = file("${cloverBuildDir}/clover-instr")
192 cloverClassesDir = file("${cloverBuildDir}/clover-classes")
193 cloverReportDir = file("${buildDir}/reports/clover")
194 cloverTestInstrDir = file("${cloverBuildDir}/clover-test-instr")
195 cloverTestClassesDir = file("${cloverBuildDir}/clover-test-classes")
196 //cloverTestClassesDir = cloverClassesDir
197 cloverDb = string("${cloverBuildDir}/clover.db")
199 testSourceDir = useClover ? cloverTestInstrDir : testDir
200 testClassesDir = useClover ? cloverTestClassesDir : "${jalviewDir}/${test_output_dir}"
202 getdownChannelDir = string("${getdown_website_dir}/${propertiesChannelName}")
203 getdownAppBaseDir = string("${jalviewDir}/${getdownChannelDir}/${JAVA_VERSION}")
204 getdownArchiveDir = string("${jalviewDir}/${getdown_archive_dir}")
205 getdownFullArchiveDir = null
206 getdownTextLines = []
207 getdownLaunchJvl = null
208 getdownVersionLaunchJvl = null
210 buildProperties = null
212 // the following values might be overridden by the CHANNEL switch
213 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
214 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
215 getdownArchiveAppBase = getdown_archive_base
216 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}")
217 getdownAppDistDir = getdown_app_dir_alt
218 getdownImagesDir = string("${jalviewDir}/${getdown_images_dir}")
219 getdownSetAppBaseProperty = false // whether to pass the appbase and appdistdir to the application
220 reportRsyncCommand = false
221 jvlChannelName = CHANNEL.toLowerCase()
222 install4jSuffix = CHANNEL.substring(0, 1).toUpperCase() + CHANNEL.substring(1).toLowerCase(); // BUILD -> Build
223 install4jDMGDSStore = "${install4j_images_dir}/${install4j_dmg_ds_store}"
224 install4jDMGBackgroundImage = "${install4j_images_dir}/${install4j_dmg_background}"
225 install4jInstallerName = "${jalview_name} Non-Release Installer"
226 install4jExecutableName = install4j_executable_name
227 install4jExtraScheme = "jalviewx"
228 install4jMacIconsFile = string("${install4j_images_dir}/${install4j_mac_icons_file}")
229 install4jWindowsIconsFile = string("${install4j_images_dir}/${install4j_windows_icons_file}")
230 install4jPngIconFile = string("${install4j_images_dir}/${install4j_png_icon_file}")
231 install4jBackground = string("${install4j_images_dir}/${install4j_background}")
232 install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
233 install4jCheckSums = true
235 applicationName = "${jalview_name}"
239 // TODO: get bamboo build artifact URL for getdown artifacts
240 getdown_channel_base = bamboo_channelbase
241 getdownChannelName = string("${bamboo_planKey}/${JAVA_VERSION}")
242 getdownAppBase = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
243 jvlChannelName += "_${getdownChannelName}"
244 // automatically add the test group Not-bamboo for exclusion
245 if ("".equals(testng_excluded_groups)) {
246 testng_excluded_groups = "Not-bamboo"
248 install4jExtraScheme = "jalviewb"
251 case [ "RELEASE", "JALVIEWJS-RELEASE" ]:
252 getdownAppDistDir = getdown_app_dir_release
253 getdownSetAppBaseProperty = true
254 reportRsyncCommand = true
256 install4jInstallerName = "${jalview_name} Installer"
260 getdownChannelName = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
261 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
262 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
263 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
264 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
266 package_dir = string("${ARCHIVEDIR}/${package_dir}")
267 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
270 reportRsyncCommand = true
271 install4jExtraScheme = "jalviewa"
275 getdownChannelName = string("archive/${JALVIEW_VERSION}")
276 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
277 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
278 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
279 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
281 package_dir = string("${ARCHIVEDIR}/${package_dir}")
282 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
285 reportRsyncCommand = true
286 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
287 install4jSuffix = "Archive"
288 install4jExtraScheme = "jalviewa"
292 reportRsyncCommand = true
293 getdownSetAppBaseProperty = true
294 // DEVELOP-RELEASE is usually associated with a Jalview release series so set the version
295 JALVIEW_VERSION=JALVIEW_VERSION+"-d${buildDate}"
297 install4jSuffix = "Develop"
298 install4jExtraScheme = "jalviewd"
299 install4jInstallerName = "${jalview_name} Develop Installer"
303 reportRsyncCommand = true
304 getdownSetAppBaseProperty = true
305 // Don't ignore transpile errors for release build
306 if (jalviewjs_ignore_transpile_errors.equals("true")) {
307 jalviewjs_ignore_transpile_errors = "false"
308 println("Setting jalviewjs_ignore_transpile_errors to 'false'")
310 JALVIEW_VERSION = JALVIEW_VERSION+"-test"
311 install4jSuffix = "Test"
312 install4jExtraScheme = "jalviewt"
313 install4jInstallerName = "${jalview_name} Test Installer"
316 case ~/^SCRATCH(|-[-\w]*)$/:
317 getdownChannelName = CHANNEL
318 JALVIEW_VERSION = JALVIEW_VERSION+"-"+CHANNEL
320 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
321 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
322 reportRsyncCommand = true
323 install4jSuffix = "Scratch"
327 if (!file("${LOCALDIR}").exists()) {
328 throw new GradleException("Must provide a LOCALDIR value to produce a local distribution")
330 getdownAppBase = file(file("${LOCALDIR}").getAbsolutePath()).toURI().toString()
331 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
333 JALVIEW_VERSION = "TEST"
334 install4jSuffix = "Test-Local"
335 install4jExtraScheme = "jalviewt"
336 install4jInstallerName = "${jalview_name} Test Installer"
339 case [ "LOCAL", "JALVIEWJS" ]:
340 JALVIEW_VERSION = "TEST"
341 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
342 getdownArchiveAppBase = file("${jalviewDir}/${getdown_archive_dir}").toURI().toString()
343 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
344 install4jExtraScheme = "jalviewl"
345 install4jCheckSums = false
348 default: // something wrong specified
349 throw new GradleException("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
353 JALVIEW_VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
354 hugoDataJsonFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_data_installers_dir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
355 hugoArchiveMdFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_version_archive_dir}/Version-${JALVIEW_VERSION_UNDERSCORES}/_index.md")
356 // override getdownAppBase if requested
357 if (findProperty("getdown_appbase_override") != null) {
358 // revert to LOCAL if empty string
359 if (string(getdown_appbase_override) == "") {
360 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
361 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
362 } else if (string(getdown_appbase_override).startsWith("file://")) {
363 getdownAppBase = string(getdown_appbase_override)
364 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
366 getdownAppBase = string(getdown_appbase_override)
368 println("Overriding getdown appbase with '${getdownAppBase}'")
370 // sanitise file name for jalview launcher file for this channel
371 jvlChannelName = jvlChannelName.replaceAll("[^\\w\\-]+", "_")
372 // install4j application and folder names
373 if (install4jSuffix == "") {
374 install4jBundleId = "${install4j_bundle_id}"
375 install4jWinApplicationId = install4j_release_win_application_id
377 applicationName = "${jalview_name} ${install4jSuffix}"
378 install4jBundleId = "${install4j_bundle_id}-" + install4jSuffix.toLowerCase()
379 // add int hash of install4jSuffix to the last part of the application_id
380 def id = install4j_release_win_application_id
381 def idsplitreverse = id.split("-").reverse()
382 idsplitreverse[0] = idsplitreverse[0].toInteger() + install4jSuffix.hashCode()
383 install4jWinApplicationId = idsplitreverse.reverse().join("-")
385 // sanitise folder and id names
386 // install4jApplicationFolder = e.g. "Jalview Build"
387 install4jApplicationFolder = applicationName
388 .replaceAll("[\"'~:/\\\\\\s]", "_") // replace all awkward filename chars " ' ~ : / \
389 .replaceAll("_+", "_") // collapse __
390 install4jInternalId = applicationName
392 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
393 .replaceAll("_+", "") // collapse __
394 //.replaceAll("_*-_*", "-") // collapse _-_
395 install4jUnixApplicationFolder = applicationName
397 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
398 .replaceAll("_+", "_") // collapse __
399 .replaceAll("_*-_*", "-") // collapse _-_
402 getdownWrapperLink = install4jUnixApplicationFolder // e.g. "jalview_local"
403 getdownAppDir = string("${getdownAppBaseDir}/${getdownAppDistDir}")
404 //getdownJ11libDir = "${getdownAppBaseDir}/${getdown_j11lib_dir}"
405 getdownResourceDir = string("${getdownAppBaseDir}/${getdown_resource_dir}")
406 getdownInstallDir = string("${getdownAppBaseDir}/${getdown_install_dir}")
407 getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
408 getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
409 /* compile without modules -- using classpath libraries
410 modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
411 modules_runtimeClasspath = modules_compileClasspath
417 apply plugin: "com.palantir.git-version"
418 def details = versionDetails()
419 gitHash = details.gitHash
420 gitBranch = details.branchName
421 } catch(org.gradle.api.internal.plugins.PluginApplicationException e) {
422 println("Not in a git repository. Using git values from RELEASE properties file.")
423 gitHash = releaseProps.getProperty("git.hash")
424 gitBranch = releaseProps.getProperty("git.branch")
425 } catch(java.lang.RuntimeException e1) {
426 throw new GradleException("Error with git-version plugin. Directory '.git' exists but versionDetails() cannot be found.")
429 println("Using a ${CHANNEL} profile.")
431 additional_compiler_args = []
432 // configure classpath/args for j8/j11 compilation
433 if (JAVA_VERSION.equals("1.8")) {
434 JAVA_INTEGER_VERSION = string("8")
437 libDistDir = j8libDir
438 compile_source_compatibility = 1.8
439 compile_target_compatibility = 1.8
440 // these are getdown.txt properties defined dependent on the JAVA_VERSION
441 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
442 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
443 // this property is assigned below and expanded to multiple lines in the getdown task
444 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
445 // this property is for the Java library used in eclipse
446 eclipseJavaRuntimeName = string("JavaSE-1.8")
447 } else if (JAVA_VERSION.equals("11")) {
448 JAVA_INTEGER_VERSION = string("11")
450 libDistDir = j11libDir
451 compile_source_compatibility = 11
452 compile_target_compatibility = 11
453 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
454 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
455 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
456 eclipseJavaRuntimeName = string("JavaSE-11")
457 /* compile without modules -- using classpath libraries
458 additional_compiler_args += [
459 '--module-path', modules_compileClasspath.asPath,
460 '--add-modules', j11modules
463 } else if (JAVA_VERSION.equals("17")) {
464 JAVA_INTEGER_VERSION = string("17")
466 libDistDir = j17libDir
467 compile_source_compatibility = 17
468 compile_target_compatibility = 17
469 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
470 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
471 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
472 eclipseJavaRuntimeName = string("JavaSE-17")
473 /* compile without modules -- using classpath libraries
474 additional_compiler_args += [
475 '--module-path', modules_compileClasspath.asPath,
476 '--add-modules', j11modules
480 throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
485 JAVA_MIN_VERSION = JAVA_VERSION
486 JAVA_MAX_VERSION = JAVA_VERSION
487 def jreInstallsDir = string(jre_installs_dir)
488 if (jreInstallsDir.startsWith("~/")) {
489 jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
491 macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
492 windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
493 linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
494 macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_mac_x64.tar.gz")
495 windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_windows_x64.tar.gz")
496 linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_linux_x64.tar.gz")
497 install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
498 install4jConfFileName = string("jalview-install4j-conf.install4j")
499 install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
500 install4jHomeDir = install4j_home_dir
501 if (install4jHomeDir.startsWith("~/")) {
502 install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
505 resourceBuildDir = string("${buildDir}/resources")
506 resourcesBuildDir = string("${resourceBuildDir}/resources_build")
507 helpBuildDir = string("${resourceBuildDir}/help_build")
508 docBuildDir = string("${resourceBuildDir}/doc_build")
510 if (buildProperties == null) {
511 buildProperties = string("${resourcesBuildDir}/${build_properties_file}")
513 buildingHTML = string("${jalviewDir}/${doc_dir}/building.html")
514 helpParentDir = string("${jalviewDir}/${help_parent_dir}")
515 helpSourceDir = string("${helpParentDir}/${help_dir}")
516 helpFile = string("${helpBuildDir}/${help_dir}/help.jhm")
519 relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
520 jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
521 jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
523 jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
525 jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
527 jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
528 jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
529 jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
530 jalviewjsJalviewCoreHtmlFile = string("")
531 jalviewjsJalviewCoreName = string(jalviewjs_core_name)
532 jalviewjsCoreClasslists = []
533 jalviewjsJalviewTemplateName = string(jalviewjs_name)
534 jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
535 jalviewjsJ2sAltSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_alt_settings}")
536 jalviewjsJ2sProps = null
537 jalviewjsJ2sPlugin = jalviewjs_j2s_plugin
539 eclipseWorkspace = null
540 eclipseBinary = string("")
541 eclipseVersion = string("")
551 destinationDirectory = file(classesDir)
555 srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ]
558 compileClasspath = files(sourceSets.main.java.destinationDirectory)
559 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
561 runtimeClasspath = compileClasspath
562 runtimeClasspath += files(sourceSets.main.resources.srcDirs)
567 srcDirs cloverInstrDir
568 destinationDirectory = cloverClassesDir
572 srcDirs = sourceSets.main.resources.srcDirs
575 compileClasspath = files( sourceSets.clover.java.destinationDirectory )
576 //compileClasspath += files( testClassesDir )
577 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
578 compileClasspath += fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
579 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
581 runtimeClasspath = compileClasspath
586 srcDirs testSourceDir
587 destinationDirectory = file(testClassesDir)
591 srcDirs = useClover ? sourceSets.clover.resources.srcDirs : sourceSets.main.resources.srcDirs
594 compileClasspath = files( sourceSets.test.java.destinationDirectory )
595 compileClasspath += useClover ? sourceSets.clover.compileClasspath : sourceSets.main.compileClasspath
596 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
598 runtimeClasspath = compileClasspath
599 runtimeClasspath += files(sourceSets.test.resources.srcDirs)
605 // eclipse project and settings files creation, also used by buildship
608 name = eclipse_project_name
610 natures 'org.eclipse.jdt.core.javanature',
611 'org.eclipse.jdt.groovy.core.groovyNature',
612 'org.eclipse.buildship.core.gradleprojectnature'
614 buildCommand 'org.eclipse.jdt.core.javabuilder'
615 buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
619 //defaultOutputDir = sourceSets.main.java.destinationDirectory
620 configurations.each{ c->
621 if (c.isCanBeResolved()) {
622 minusConfigurations += [c]
626 plusConfigurations = [ ]
630 def removeTheseToo = []
631 HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
632 cp.entries.each { entry ->
633 // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
634 // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
635 // we add the resources and help/help dirs in as libs afterwards (see below)
636 if (entry.kind == 'src') {
637 if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
638 removeTheseToo += entry
640 alreadyAddedSrcPath.putAt(entry.path, true)
645 cp.entries.removeAll(removeTheseToo)
647 //cp.entries += new Output("${eclipse_bin_dir}/main")
648 if (file(helpParentDir).isDirectory()) {
649 cp.entries += new Library(fileReference(helpParentDir))
651 if (file(resourceDir).isDirectory()) {
652 cp.entries += new Library(fileReference(resourceDir))
655 HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
657 sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
658 //don't want to add destinationDirectory as eclipse is using its own output dir in bin/main
659 if (it.isDirectory() || ! it.exists()) {
660 // don't add dirs to classpath, especially if they don't exist
661 return false // groovy "continue" in .any closure
663 def itPath = it.toString()
664 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
665 // make relative path
666 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
668 if (alreadyAddedLibPath.get(itPath)) {
669 //println("Not adding duplicate entry "+itPath)
671 //println("Adding entry "+itPath)
672 cp.entries += new Library(fileReference(itPath))
673 alreadyAddedLibPath.put(itPath, true)
677 sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
678 //no longer want to add destinationDirectory as eclipse is using its own output dir in bin/main
679 if (it.isDirectory() || ! it.exists()) {
680 // don't add dirs to classpath
681 return false // groovy "continue" in .any closure
684 def itPath = it.toString()
685 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
686 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
688 if (alreadyAddedLibPath.get(itPath)) {
691 def lib = new Library(fileReference(itPath))
692 lib.entryAttributes["test"] = "true"
694 alreadyAddedLibPath.put(itPath, true)
702 containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
707 // for the IDE, use java 11 compatibility
708 sourceCompatibility = compile_source_compatibility
709 targetCompatibility = compile_target_compatibility
710 javaRuntimeName = eclipseJavaRuntimeName
712 // add in jalview project specific properties/preferences into eclipse core preferences
714 withProperties { props ->
715 def jalview_prefs = new Properties()
716 def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
717 jalview_prefs.load(ins)
719 jalview_prefs.forEach { t, v ->
720 if (props.getAt(t) == null) {
724 // codestyle file -- overrides previous formatter prefs
725 def csFile = file("${jalviewDirAbsolutePath}/${eclipse_codestyle_file}")
726 if (csFile.exists()) {
727 XmlParser parser = new XmlParser()
728 def profiles = parser.parse(csFile)
729 def profile = profiles.'profile'.find { p -> (p.'@kind' == "CodeFormatterProfile" && p.'@name' == "Jalview") }
730 if (profile != null) {
731 profile.'setting'.each { s ->
733 def value = s.'@value'
734 if (id != null && value != null) {
735 props.putAt(id, value)
746 // Don't want these to be activated if in headless build
747 synchronizationTasks "eclipseSynchronizationTask"
748 //autoBuildTasks "eclipseAutoBuildTask"
754 /* hack to change eclipse prefs in .settings files other than org.eclipse.jdt.core.prefs */
755 // Class to allow updating arbitrary properties files
756 class PropertiesFile extends PropertiesPersistableConfigurationObject {
757 public PropertiesFile(PropertiesTransformer t) { super(t); }
758 @Override protected void load(Properties properties) { }
759 @Override protected void store(Properties properties) { }
760 @Override protected String getDefaultResourceName() { return ""; }
761 // This is necessary, because PropertiesPersistableConfigurationObject fails
762 // if no default properties file exists.
763 @Override public void loadDefaults() { load(new StringBufferInputStream("")); }
766 // Task to update arbitrary properties files (set outputFile)
767 class PropertiesFileTask extends PropertiesGeneratorTask<PropertiesFile> {
768 private final PropertiesFileContentMerger file;
769 public PropertiesFileTask() { file = new PropertiesFileContentMerger(getTransformer()); }
770 protected PropertiesFile create() { return new PropertiesFile(getTransformer()); }
771 protected void configure(PropertiesFile props) {
772 file.getBeforeMerged().execute(props); file.getWhenMerged().execute(props);
774 public void file(Closure closure) { ConfigureUtil.configure(closure, file); }
777 task eclipseUIPreferences(type: PropertiesFileTask) {
778 description = "Generate Eclipse additional settings"
779 def filename = "org.eclipse.jdt.ui.prefs"
780 outputFile = "$projectDir/.settings/${filename}" as File
783 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
788 task eclipseGroovyCorePreferences(type: PropertiesFileTask) {
789 description = "Generate Eclipse additional settings"
790 def filename = "org.eclipse.jdt.groovy.core.prefs"
791 outputFile = "$projectDir/.settings/${filename}" as File
794 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
799 task eclipseAllPreferences {
801 dependsOn eclipseUIPreferences
802 dependsOn eclipseGroovyCorePreferences
805 eclipseUIPreferences.mustRunAfter eclipseJdt
806 eclipseGroovyCorePreferences.mustRunAfter eclipseJdt
808 /* end of eclipse preferences hack */
816 delete cloverBuildDir
817 delete cloverReportDir
822 task cloverInstrJava(type: JavaExec) {
823 group = "Verification"
824 description = "Create clover instrumented source java files"
826 dependsOn cleanClover
828 inputs.files(sourceSets.main.allJava)
829 outputs.dir(cloverInstrDir)
831 //classpath = fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
832 classpath = sourceSets.clover.compileClasspath
833 main = "com.atlassian.clover.CloverInstr"
841 cloverInstrDir.getPath(),
843 def srcFiles = sourceSets.main.allJava.files
846 { file -> file.absolutePath }
849 args argsList.toArray()
852 delete cloverInstrDir
853 println("Clover: About to instrument "+srcFiles.size() +" files")
858 task cloverInstrTests(type: JavaExec) {
859 group = "Verification"
860 description = "Create clover instrumented source test files"
862 dependsOn cleanClover
864 inputs.files(testDir)
865 outputs.dir(cloverTestInstrDir)
867 classpath = sourceSets.clover.compileClasspath
868 main = "com.atlassian.clover.CloverInstr"
878 cloverTestInstrDir.getPath(),
880 args argsList.toArray()
883 delete cloverTestInstrDir
884 println("Clover: About to instrument test files")
890 group = "Verification"
891 description = "Create clover instrumented all source files"
893 dependsOn cloverInstrJava
894 dependsOn cloverInstrTests
898 cloverClasses.dependsOn cloverInstr
901 task cloverConsoleReport(type: JavaExec) {
902 group = "Verification"
903 description = "Creates clover console report"
906 file(cloverDb).exists()
909 inputs.dir cloverClassesDir
911 classpath = sourceSets.clover.runtimeClasspath
912 main = "com.atlassian.clover.reporters.console.ConsoleReporter"
914 if (cloverreport_mem.length() > 0) {
915 maxHeapSize = cloverreport_mem
917 if (cloverreport_jvmargs.length() > 0) {
918 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
928 args argsList.toArray()
932 task cloverHtmlReport(type: JavaExec) {
933 group = "Verification"
934 description = "Creates clover HTML report"
937 file(cloverDb).exists()
940 def cloverHtmlDir = cloverReportDir
941 inputs.dir cloverClassesDir
942 outputs.dir cloverHtmlDir
944 classpath = sourceSets.clover.runtimeClasspath
945 main = "com.atlassian.clover.reporters.html.HtmlReporter"
947 if (cloverreport_mem.length() > 0) {
948 maxHeapSize = cloverreport_mem
950 if (cloverreport_jvmargs.length() > 0) {
951 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
962 if (cloverreport_html_options.length() > 0) {
963 argsList += cloverreport_html_options.split(" ")
966 args argsList.toArray()
970 task cloverXmlReport(type: JavaExec) {
971 group = "Verification"
972 description = "Creates clover XML report"
975 file(cloverDb).exists()
978 def cloverXmlFile = "${cloverReportDir}/clover.xml"
979 inputs.dir cloverClassesDir
980 outputs.file cloverXmlFile
982 classpath = sourceSets.clover.runtimeClasspath
983 main = "com.atlassian.clover.reporters.xml.XMLReporter"
985 if (cloverreport_mem.length() > 0) {
986 maxHeapSize = cloverreport_mem
988 if (cloverreport_jvmargs.length() > 0) {
989 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
1000 if (cloverreport_xml_options.length() > 0) {
1001 argsList += cloverreport_xml_options.split(" ")
1004 args argsList.toArray()
1009 group = "Verification"
1010 description = "Creates clover reports"
1012 dependsOn cloverXmlReport
1013 dependsOn cloverHtmlReport
1020 sourceCompatibility = compile_source_compatibility
1021 targetCompatibility = compile_target_compatibility
1022 options.compilerArgs += additional_compiler_args
1023 print ("Setting target compatibility to "+targetCompatibility+"\n")
1025 //classpath += configurations.cloverRuntime
1031 // JBP->BS should the print statement in doFirst refer to compile_target_compatibility ?
1032 sourceCompatibility = compile_source_compatibility
1033 targetCompatibility = compile_target_compatibility
1034 options.compilerArgs = additional_compiler_args
1035 options.encoding = "UTF-8"
1037 print ("Setting target compatibility to "+compile_target_compatibility+"\n")
1044 sourceCompatibility = compile_source_compatibility
1045 targetCompatibility = compile_target_compatibility
1046 options.compilerArgs = additional_compiler_args
1048 print ("Setting target compatibility to "+targetCompatibility+"\n")
1055 delete sourceSets.main.java.destinationDirectory
1061 dependsOn cleanClover
1063 delete sourceSets.test.java.destinationDirectory
1068 // format is a string like date.format("dd MMMM yyyy")
1069 def getDate(format) {
1070 return date.format(format)
1074 def convertMdToHtml (FileTree mdFiles, File cssFile) {
1075 MutableDataSet options = new MutableDataSet()
1077 def extensions = new ArrayList<>()
1078 extensions.add(AnchorLinkExtension.create())
1079 extensions.add(AutolinkExtension.create())
1080 extensions.add(StrikethroughExtension.create())
1081 extensions.add(TaskListExtension.create())
1082 extensions.add(TablesExtension.create())
1083 extensions.add(TocExtension.create())
1085 options.set(Parser.EXTENSIONS, extensions)
1087 // set GFM table parsing options
1088 options.set(TablesExtension.WITH_CAPTION, false)
1089 options.set(TablesExtension.COLUMN_SPANS, false)
1090 options.set(TablesExtension.MIN_HEADER_ROWS, 1)
1091 options.set(TablesExtension.MAX_HEADER_ROWS, 1)
1092 options.set(TablesExtension.APPEND_MISSING_COLUMNS, true)
1093 options.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
1094 options.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
1096 options.set(AnchorLinkExtension.ANCHORLINKS_SET_ID, false)
1097 options.set(AnchorLinkExtension.ANCHORLINKS_ANCHOR_CLASS, "anchor")
1098 options.set(AnchorLinkExtension.ANCHORLINKS_SET_NAME, true)
1099 options.set(AnchorLinkExtension.ANCHORLINKS_TEXT_PREFIX, "<span class=\"octicon octicon-link\"></span>")
1101 Parser parser = Parser.builder(options).build()
1102 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1104 mdFiles.each { mdFile ->
1105 // add table of contents
1106 def mdText = "[TOC]\n"+mdFile.text
1108 // grab the first top-level title
1110 def titleRegex = /(?m)^#(\s+|([^#]))(.*)/
1111 def matcher = mdText =~ titleRegex
1112 if (matcher.size() > 0) {
1113 // matcher[0][2] is the first character of the title if there wasn't any whitespace after the #
1114 title = (matcher[0][2] != null ? matcher[0][2] : "")+matcher[0][3]
1116 // or use the filename if none found
1117 if (title == null) {
1118 title = mdFile.getName()
1121 Node document = parser.parse(mdText)
1122 String htmlBody = renderer.render(document)
1123 def htmlText = '''<html>
1124 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1125 <html xmlns="http://www.w3.org/1999/xhtml">
1127 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1128 <meta http-equiv="Content-Style-Type" content="text/css" />
1129 <meta name="generator" content="flexmark" />
1131 htmlText += ((title != null) ? " <title>${title}</title>" : '' )
1133 <style type="text/css">code{white-space: pre;}</style>
1135 htmlText += ((cssFile != null) ? cssFile.text : '')
1136 htmlText += '''</head>
1139 htmlText += htmlBody
1145 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1146 def htmlFile = file(htmlFilePath)
1147 println("Creating ${htmlFilePath}")
1148 htmlFile.text = htmlText
1153 task copyDocs(type: Copy) {
1154 def inputDir = "${jalviewDir}/${doc_dir}"
1155 def destinationDirectory = "${docBuildDir}/${doc_dir}"
1159 include('**/*.html')
1161 filter(ReplaceTokens,
1165 'Version-Rel': JALVIEW_VERSION,
1166 'Year-Rel': getDate("yyyy")
1173 exclude('**/*.html')
1176 into destinationDirectory
1178 inputs.dir(inputDir)
1179 outputs.dir(destinationDirectory)
1183 task convertMdFiles {
1185 def mdFiles = fileTree(dir: docBuildDir, include: "**/*.md")
1186 def cssFile = file("${jalviewDir}/${flexmark_css}")
1189 convertMdToHtml(mdFiles, cssFile)
1192 inputs.files(mdFiles)
1193 inputs.file(cssFile)
1196 mdFiles.each { mdFile ->
1197 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1198 htmlFiles.add(file(htmlFilePath))
1200 outputs.files(htmlFiles)
1204 def hugoTemplateSubstitutions(String input, Map extras=null) {
1205 def replacements = [
1206 DATE: getDate("yyyy-MM-dd"),
1207 CHANNEL: propertiesChannelName,
1208 APPLICATION_NAME: applicationName,
1210 GIT_BRANCH: gitBranch,
1211 VERSION: JALVIEW_VERSION,
1212 JAVA_VERSION: JAVA_VERSION,
1213 VERSION_UNDERSCORES: JALVIEW_VERSION_UNDERSCORES,
1218 if (extras != null) {
1219 extras.each{ k, v ->
1220 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1223 replacements.each{ k, v ->
1224 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1229 def mdFileComponents(File mdFile, def dateOnly=false) {
1232 if (mdFile.exists()) {
1233 def inFrontMatter = false
1234 def firstLine = true
1235 mdFile.eachLine { line ->
1236 if (line.matches("---")) {
1237 def prev = inFrontMatter
1238 inFrontMatter = firstLine
1239 if (inFrontMatter != prev)
1242 if (inFrontMatter) {
1244 if (m == line =~ /^date:\s*(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/) {
1245 map["date"] = new Date().parse("yyyy-MM-dd HH:mm:ss", m[0][1])
1246 } else if (m == line =~ /^date:\s*(\d{4}-\d{2}-\d{2})/) {
1247 map["date"] = new Date().parse("yyyy-MM-dd", m[0][1])
1248 } else if (m == line =~ /^channel:\s*(\S+)/) {
1249 map["channel"] = m[0][1]
1250 } else if (m == line =~ /^version:\s*(\S+)/) {
1251 map["version"] = m[0][1]
1252 } else if (m == line =~ /^\s*([^:]+)\s*:\s*(\S.*)/) {
1253 map[ m[0][1] ] = m[0][2]
1255 if (dateOnly && map["date"] != null) {
1261 content += line+"\n"
1266 return dateOnly ? map["date"] : [map, content]
1269 task hugoTemplates {
1271 description "Create partially populated md pages for hugo website build"
1273 def hugoTemplatesDir = file("${jalviewDir}/${hugo_templates_dir}")
1274 def hugoBuildDir = "${jalviewDir}/${hugo_build_dir}"
1275 def templateFiles = fileTree(dir: hugoTemplatesDir)
1276 def releaseMdFile = file("${jalviewDir}/${releases_dir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1277 def whatsnewMdFile = file("${jalviewDir}/${whatsnew_dir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1278 def oldJvlFile = file("${jalviewDir}/${hugo_old_jvl}")
1279 def jalviewjsFile = file("${jalviewDir}/${hugo_jalviewjs}")
1282 // specific release template for version archive
1285 def givenDate = null
1286 def givenChannel = null
1287 def givenVersion = null
1288 if (CHANNEL == "RELEASE") {
1289 def (map, content) = mdFileComponents(releaseMdFile)
1290 givenDate = map.date
1291 givenChannel = map.channel
1292 givenVersion = map.version
1294 if (givenVersion != null && givenVersion != JALVIEW_VERSION) {
1295 throw new GradleException("'version' header (${givenVersion}) found in ${releaseMdFile} does not match JALVIEW_VERSION (${JALVIEW_VERSION})")
1298 if (whatsnewMdFile.exists())
1299 whatsnew = whatsnewMdFile.text
1302 def oldJvl = oldJvlFile.exists() ? oldJvlFile.collect{it} : []
1303 def jalviewjsLink = jalviewjsFile.exists() ? jalviewjsFile.collect{it} : []
1305 def changesHugo = null
1306 if (changes != null) {
1307 changesHugo = '<div class="release_notes">\n\n'
1308 def inSection = false
1309 changes.eachLine { line ->
1311 if (m == line =~ /^##([^#].*)$/) {
1313 changesHugo += "</div>\n\n"
1315 def section = m[0][1].trim()
1316 section = section.toLowerCase()
1317 section = section.replaceAll(/ +/, "_")
1318 section = section.replaceAll(/[^a-z0-9_\-]/, "")
1319 changesHugo += "<div class=\"${section}\">\n\n"
1321 } else if (m == line =~ /^(\s*-\s*)<!--([^>]+)-->(.*?)(<br\/?>)?\s*$/) {
1322 def comment = m[0][2].trim()
1323 if (comment != "") {
1324 comment = comment.replaceAll('"', """)
1326 comment.eachMatch(/JAL-\d+/) { jal -> issuekeys += jal }
1327 def newline = m[0][1]
1328 if (comment.trim() != "")
1329 newline += "{{<comment>}}${comment}{{</comment>}} "
1330 newline += m[0][3].trim()
1331 if (issuekeys.size() > 0)
1332 newline += " {{< jal issue=\"${issuekeys.join(",")}\" alt=\"${comment}\" >}}"
1333 if (m[0][4] != null)
1338 changesHugo += line+"\n"
1341 changesHugo += "\n</div>\n\n"
1343 changesHugo += '</div>'
1346 templateFiles.each{ templateFile ->
1347 def newFileName = string(hugoTemplateSubstitutions(templateFile.getName()))
1348 def relPath = hugoTemplatesDir.toPath().relativize(templateFile.toPath()).getParent()
1349 def newRelPathName = hugoTemplateSubstitutions( relPath.toString() )
1351 def outPathName = string("${hugoBuildDir}/$newRelPathName")
1355 rename(templateFile.getName(), newFileName)
1359 def newFile = file("${outPathName}/${newFileName}".toString())
1360 def content = newFile.text
1361 newFile.text = hugoTemplateSubstitutions(content,
1364 CHANGES: changesHugo,
1365 DATE: givenDate == null ? "" : givenDate.format("yyyy-MM-dd"),
1366 DRAFT: givenDate == null ? "true" : "false",
1367 JALVIEWJSLINK: jalviewjsLink.contains(JALVIEW_VERSION) ? "true" : "false",
1368 JVL_HEADER: oldJvl.contains(JALVIEW_VERSION) ? "jvl: true" : ""
1375 inputs.file(oldJvlFile)
1376 inputs.dir(hugoTemplatesDir)
1377 inputs.property("JALVIEW_VERSION", { JALVIEW_VERSION })
1378 inputs.property("CHANNEL", { CHANNEL })
1381 def getMdDate(File mdFile) {
1382 return mdFileComponents(mdFile, true)
1385 def getMdSections(String content) {
1387 def sectionContent = ""
1388 def sectionName = null
1389 content.eachLine { line ->
1391 if (m == line =~ /^##([^#].*)$/) {
1392 if (sectionName != null) {
1393 sections[sectionName] = sectionContent
1397 sectionName = m[0][1].trim()
1398 sectionName = sectionName.toLowerCase()
1399 sectionName = sectionName.replaceAll(/ +/, "_")
1400 sectionName = sectionName.replaceAll(/[^a-z0-9_\-]/, "")
1401 } else if (sectionName != null) {
1402 sectionContent += line+"\n"
1405 if (sectionContent != null) {
1406 sections[sectionName] = sectionContent
1412 task copyHelp(type: Copy) {
1413 def inputDir = helpSourceDir
1414 def destinationDirectory = "${helpBuildDir}/${help_dir}"
1418 include('**/*.html')
1422 filter(ReplaceTokens,
1426 'Version-Rel': JALVIEW_VERSION,
1427 'Year-Rel': getDate("yyyy")
1434 exclude('**/*.html')
1439 into destinationDirectory
1441 inputs.dir(inputDir)
1442 outputs.files(helpFile)
1443 outputs.dir(destinationDirectory)
1448 task releasesTemplates {
1450 description "Recreate whatsNew.html and releases.html from markdown files and templates in help"
1454 def releasesTemplateFile = file("${jalviewDir}/${releases_template}")
1455 def whatsnewTemplateFile = file("${jalviewDir}/${whatsnew_template}")
1456 def releasesHtmlFile = file("${helpBuildDir}/${help_dir}/${releases_html}")
1457 def whatsnewHtmlFile = file("${helpBuildDir}/${help_dir}/${whatsnew_html}")
1458 def releasesMdDir = "${jalviewDir}/${releases_dir}"
1459 def whatsnewMdDir = "${jalviewDir}/${whatsnew_dir}"
1462 def releaseMdFile = file("${releasesMdDir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1463 def whatsnewMdFile = file("${whatsnewMdDir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1465 if (CHANNEL == "RELEASE") {
1466 if (!releaseMdFile.exists()) {
1467 throw new GradleException("File ${releaseMdFile} must be created for RELEASE")
1469 if (!whatsnewMdFile.exists()) {
1470 throw new GradleException("File ${whatsnewMdFile} must be created for RELEASE")
1474 def releaseFiles = fileTree(dir: releasesMdDir, include: "release-*.md")
1475 def releaseFilesDates = releaseFiles.collectEntries {
1476 [(it): getMdDate(it)]
1478 releaseFiles = releaseFiles.sort { a,b -> releaseFilesDates[a].compareTo(releaseFilesDates[b]) }
1480 def releasesTemplate = releasesTemplateFile.text
1481 def m = releasesTemplate =~ /(?s)__VERSION_LOOP_START__(.*)__VERSION_LOOP_END__/
1482 def versionTemplate = m[0][1]
1484 MutableDataSet options = new MutableDataSet()
1486 def extensions = new ArrayList<>()
1487 options.set(Parser.EXTENSIONS, extensions)
1488 options.set(Parser.HTML_BLOCK_COMMENT_ONLY_FULL_LINE, true)
1490 Parser parser = Parser.builder(options).build()
1491 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1493 def actualVersions = releaseFiles.collect { rf ->
1494 def (rfMap, rfContent) = mdFileComponents(rf)
1495 return rfMap.version
1497 def versionsHtml = ""
1498 def linkedVersions = []
1499 releaseFiles.reverse().each { rFile ->
1500 def (rMap, rContent) = mdFileComponents(rFile)
1502 def versionLink = ""
1503 def partialVersion = ""
1504 def firstPart = true
1505 rMap.version.split("\\.").each { part ->
1506 def displayPart = ( firstPart ? "" : "." ) + part
1507 partialVersion += displayPart
1509 linkedVersions.contains(partialVersion)
1510 || ( actualVersions.contains(partialVersion) && partialVersion != rMap.version )
1512 versionLink += displayPart
1514 versionLink += "<a id=\"Jalview.${partialVersion}\">${displayPart}</a>"
1515 linkedVersions += partialVersion
1519 def displayDate = releaseFilesDates[rFile].format("dd/MM/yyyy")
1522 def rContentProcessed = ""
1523 rContent.eachLine { line ->
1524 if (lm == line =~ /^(\s*-)(\s*<!--[^>]*?-->)(.*)$/) {
1525 line = "${lm[0][1]}${lm[0][3]}${lm[0][2]}"
1526 } else if (lm == line =~ /^###([^#]+.*)$/) {
1527 line = "_${lm[0][1].trim()}_"
1529 rContentProcessed += line + "\n"
1532 def rContentSections = getMdSections(rContentProcessed)
1533 def rVersion = versionTemplate
1534 if (rVersion != "") {
1535 def rNewFeatures = rContentSections["new_features"]
1536 def rIssuesResolved = rContentSections["issues_resolved"]
1537 Node newFeaturesNode = parser.parse(rNewFeatures)
1538 String newFeaturesHtml = renderer.render(newFeaturesNode)
1539 Node issuesResolvedNode = parser.parse(rIssuesResolved)
1540 String issuesResolvedHtml = renderer.render(issuesResolvedNode)
1541 rVersion = hugoTemplateSubstitutions(rVersion,
1543 VERSION: rMap.version,
1544 VERSION_LINK: versionLink,
1545 DISPLAY_DATE: displayDate,
1546 NEW_FEATURES: newFeaturesHtml,
1547 ISSUES_RESOLVED: issuesResolvedHtml
1550 versionsHtml += rVersion
1554 releasesTemplate = releasesTemplate.replaceAll("(?s)__VERSION_LOOP_START__.*__VERSION_LOOP_END__", versionsHtml)
1555 releasesTemplate = hugoTemplateSubstitutions(releasesTemplate)
1556 releasesHtmlFile.text = releasesTemplate
1558 if (whatsnewMdFile.exists()) {
1559 def wnDisplayDate = releaseFilesDates[releaseMdFile] != null ? releaseFilesDates[releaseMdFile].format("dd MMMM yyyy") : ""
1560 def whatsnewMd = hugoTemplateSubstitutions(whatsnewMdFile.text)
1561 Node whatsnewNode = parser.parse(whatsnewMd)
1562 String whatsnewHtml = renderer.render(whatsnewNode)
1563 whatsnewHtml = whatsnewTemplateFile.text.replaceAll("__WHATS_NEW__", whatsnewHtml)
1564 whatsnewHtmlFile.text = hugoTemplateSubstitutions(whatsnewHtml,
1566 VERSION: JALVIEW_VERSION,
1567 DISPLAY_DATE: wnDisplayDate
1570 } else if (gradle.taskGraph.hasTask(":linkCheck")) {
1571 whatsnewHtmlFile.text = "Development build " + getDate("yyyy-MM-dd HH:mm:ss")
1576 inputs.file(releasesTemplateFile)
1577 inputs.file(whatsnewTemplateFile)
1578 inputs.dir(releasesMdDir)
1579 inputs.dir(whatsnewMdDir)
1580 outputs.file(releasesHtmlFile)
1581 outputs.file(whatsnewHtmlFile)
1586 task copyResources(type: Copy) {
1588 description = "Copy (and make text substitutions in) the resources dir to the build area"
1590 def inputDir = resourceDir
1591 def destinationDirectory = resourcesBuildDir
1595 include('**/*.html')
1597 filter(ReplaceTokens,
1601 'Version-Rel': JALVIEW_VERSION,
1602 'Year-Rel': getDate("yyyy")
1609 exclude('**/*.html')
1612 into destinationDirectory
1614 inputs.dir(inputDir)
1615 outputs.dir(destinationDirectory)
1618 task copyChannelResources(type: Copy) {
1619 dependsOn copyResources
1621 description = "Copy the channel resources dir to the build resources area"
1623 def inputDir = "${channelDir}/${resource_dir}"
1624 def destinationDirectory = resourcesBuildDir
1626 into destinationDirectory
1628 inputs.dir(inputDir)
1629 outputs.dir(destinationDirectory)
1632 task createBuildProperties(type: WriteProperties) {
1633 dependsOn copyResources
1634 dependsOn copyChannelResources
1636 description = "Create the ${buildProperties} file"
1638 inputs.dir(sourceDir)
1639 inputs.dir(resourcesBuildDir)
1640 outputFile (buildProperties)
1641 // taking time specific comment out to allow better incremental builds
1642 comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
1643 //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
1644 property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
1645 property "VERSION", JALVIEW_VERSION
1646 property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
1647 property "JAVA_COMPILE_VERSION", JAVA_INTEGER_VERSION
1648 if (getdownSetAppBaseProperty) {
1649 property "GETDOWNAPPBASE", getdownAppBase
1650 property "GETDOWNAPPDISTDIR", getdownAppDistDir
1652 outputs.file(outputFile)
1656 task buildIndices(type: JavaExec) {
1658 //dependsOn releasesTemplates
1659 classpath = sourceSets.main.compileClasspath
1660 main = "com.sun.java.help.search.Indexer"
1661 workingDir = "${helpBuildDir}/${help_dir}"
1664 inputs.dir("${workingDir}/${argDir}")
1666 outputs.dir("${classesDir}/doc")
1667 outputs.dir("${classesDir}/help")
1668 outputs.file("${workingDir}/JavaHelpSearch/DOCS")
1669 outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
1670 outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
1671 outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
1672 outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
1673 outputs.file("${workingDir}/JavaHelpSearch/TMAP")
1676 task buildResources {
1677 dependsOn copyResources
1678 dependsOn copyChannelResources
1679 dependsOn createBuildProperties
1683 dependsOn buildResources
1686 //dependsOn releasesTemplates
1687 dependsOn convertMdFiles
1688 dependsOn buildIndices
1692 // random block of dependencies
1693 compileJava.dependsOn prepare
1694 run.dependsOn compileJava
1695 //run.dependsOn prepare
1696 compileTestJava.dependsOn compileJava //
1697 compileTestJava.dependsOn buildIndices //
1698 processResources.dependsOn copyChannelResources //
1699 processResources.dependsOn copyResources //
1700 processResources.dependsOn createBuildProperties //
1701 processResources.dependsOn copyDocs //
1702 processResources.dependsOn convertMdFiles //
1703 processResources.dependsOn copyHelp //
1704 processResources.dependsOn buildIndices //
1707 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1712 dependsOn cloverClasses
1714 dependsOn compileJava //?
1718 includeGroups testng_groups
1719 excludeGroups testng_excluded_groups
1721 useDefaultListeners=true
1724 maxHeapSize = "1024m"
1726 workingDir = jalviewDir
1727 def testLaf = project.findProperty("test_laf")
1728 if (testLaf != null) {
1729 println("Setting Test LaF to '${testLaf}'")
1730 systemProperty "laf", testLaf
1732 def testHiDPIScale = project.findProperty("test_HiDPIScale")
1733 if (testHiDPIScale != null) {
1734 println("Setting Test HiDPI Scale to '${testHiDPIScale}'")
1735 systemProperty "sun.java2d.uiScale", testHiDPIScale
1737 sourceCompatibility = compile_source_compatibility
1738 targetCompatibility = compile_target_compatibility
1739 jvmArgs += additional_compiler_args
1743 println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1750 task compileLinkCheck(type: JavaCompile) {
1752 classpath = files("${jalviewDir}/${utils_dir}")
1753 destinationDir = file("${jalviewDir}/${utils_dir}")
1754 source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1756 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1757 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1758 outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1759 outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1763 task linkCheck(type: JavaExec) {
1765 dependsOn compileLinkCheck
1767 def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1768 classpath = files("${jalviewDir}/${utils_dir}")
1769 main = "HelpLinksChecker"
1770 workingDir = "${helpBuildDir}"
1771 args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1773 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1774 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1777 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1781 inputs.dir(helpBuildDir)
1782 outputs.file(helpLinksCheckerOutFile)
1787 // import the pubhtmlhelp target
1788 ant.properties.basedir = "${jalviewDir}"
1789 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1790 ant.importBuild "${utils_dir}/publishHelp.xml"
1793 task cleanPackageDir(type: Delete) {
1795 delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1799 // block of dependencies
1800 //compileTestJava.dependsOn compileLinkCheck //
1801 //copyChannelResources.dependsOn compileLinkCheck //
1802 //convertMdFiles.dependsOn compileLinkCheck //
1806 dependsOn //linkCheck
1809 attributes "Main-Class": main_class,
1810 "Permissions": "all-permissions",
1811 "Application-Name": applicationName,
1812 "Codebase": application_codebase,
1813 "Implementation-Version": JALVIEW_VERSION
1816 def destinationDirectory = "${jalviewDir}/${package_dir}"
1817 destinationDirectory = file(destinationDirectory)
1818 archiveFileName = rootProject.name+".jar"
1819 duplicatesStrategy "EXCLUDE"
1826 exclude "**/*.jar.*"
1828 inputs.dir(sourceSets.main.java.destinationDirectory)
1829 sourceSets.main.resources.srcDirs.each{ dir ->
1832 outputs.file("${destinationDirectory}/${archiveFileName}")
1836 task copyJars(type: Copy) {
1837 from fileTree(dir: classesDir, include: "**/*.jar").files
1838 into "${jalviewDir}/${package_dir}"
1842 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1843 task syncJars(type: Sync) {
1845 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1846 into "${jalviewDir}/${package_dir}"
1848 include jar.archiveFileName.getOrNull()
1855 description = "Put all required libraries in dist"
1856 // order of "cleanPackageDir", "copyJars", "jar" important!
1857 jar.mustRunAfter cleanPackageDir
1858 syncJars.mustRunAfter cleanPackageDir
1859 dependsOn cleanPackageDir
1862 outputs.dir("${jalviewDir}/${package_dir}")
1867 dependsOn cleanPackageDir
1874 group = "distribution"
1875 description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1879 from ("${jalviewDir}/${libDistDir}") {
1883 attributes "Implementation-Version": JALVIEW_VERSION,
1884 "Application-Name": applicationName
1887 duplicatesStrategy "INCLUDE"
1889 mainClassName = shadow_jar_main_class
1891 archiveClassifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1896 task getdownWebsite() {
1897 group = "distribution"
1898 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1903 def getdownWebsiteResourceFilenames = []
1904 def getdownResourceDir = getdownResourceDir
1905 def getdownResourceFilenames = []
1908 // clean the getdown website and files dir before creating getdown folders
1909 delete getdownAppBaseDir
1910 delete getdownFilesDir
1913 from buildProperties
1914 rename(file(buildProperties).getName(), getdown_build_properties)
1917 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1920 from channelPropsFile
1921 into getdownAppBaseDir
1923 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
1925 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
1926 def props = project.properties.sort { it.key }
1927 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
1928 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
1930 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
1931 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
1933 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
1934 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
1936 if (getdownImagesDir != null && file(getdownImagesDir).exists()) {
1937 props.put("getdown_txt_ui.background_image", "${getdownImagesDir}/${getdown_background_image}")
1938 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesDir}/${getdown_instant_background_image}")
1939 props.put("getdown_txt_ui.error_background", "${getdownImagesDir}/${getdown_error_background}")
1940 props.put("getdown_txt_ui.progress_image", "${getdownImagesDir}/${getdown_progress_image}")
1941 props.put("getdown_txt_ui.icon", "${getdownImagesDir}/${getdown_icon}")
1942 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesDir}/${getdown_mac_dock_icon}")
1945 props.put("getdown_txt_title", jalview_name)
1946 props.put("getdown_txt_ui.name", applicationName)
1948 // start with appbase
1949 getdownTextLines += "appbase = ${getdownAppBase}"
1950 props.each{ prop, val ->
1951 if (prop.startsWith("getdown_txt_") && val != null) {
1952 if (prop.startsWith("getdown_txt_multi_")) {
1953 def key = prop.substring(18)
1954 val.split(",").each{ v ->
1955 def line = "${key} = ${v}"
1956 getdownTextLines += line
1959 // file values rationalised
1960 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
1962 if (val.indexOf('/') == 0) {
1965 } else if (val.indexOf('/') > 0) {
1966 // relative path (relative to jalviewDir)
1967 r = file( "${jalviewDir}/${val}" )
1970 val = "${getdown_resource_dir}/" + r.getName()
1971 getdownWebsiteResourceFilenames += val
1972 getdownResourceFilenames += r.getPath()
1975 if (! prop.startsWith("getdown_txt_resource")) {
1976 def line = prop.substring(12) + " = ${val}"
1977 getdownTextLines += line
1983 getdownWebsiteResourceFilenames.each{ filename ->
1984 getdownTextLines += "resource = ${filename}"
1986 getdownResourceFilenames.each{ filename ->
1989 into getdownResourceDir
1993 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
1994 getdownWrapperScripts.each{ script ->
1995 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
1999 into "${getdownAppBaseDir}/${getdown_wrapper_script_dir}"
2001 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
2006 fileTree(file(package_dir)).each{ f ->
2007 if (f.isDirectory()) {
2008 def files = fileTree(dir: f, include: ["*"]).getFiles()
2010 } else if (f.exists()) {
2014 def jalviewJar = jar.archiveFileName.getOrNull()
2015 // put jalview.jar first for CLASSPATH and .properties files reasons
2016 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
2017 def name = f.getName()
2018 def line = "code = ${getdownAppDistDir}/${name}"
2019 getdownTextLines += line
2026 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
2028 if (JAVA_VERSION.equals("11")) {
2029 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
2030 j11libFiles.sort().each{f ->
2031 def name = f.getName()
2032 def line = "code = ${getdown_j11lib_dir}/${name}"
2033 getdownTextLines += line
2036 into getdownJ11libDir
2042 // 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.
2043 //getdownTextLines += "class = " + file(getdownLauncher).getName()
2044 getdownTextLines += "resource = ${getdown_launcher_new}"
2045 getdownTextLines += "class = ${main_class}"
2046 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
2047 if (getdownSetAppBaseProperty) {
2048 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
2049 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
2052 def getdownTxt = file("${getdownAppBaseDir}/getdown.txt")
2053 getdownTxt.write(getdownTextLines.join("\n"))
2055 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
2056 def launchJvl = file("${getdownAppBaseDir}/${getdownLaunchJvl}")
2057 launchJvl.write("appbase=${getdownAppBase}")
2059 // files going into the getdown website dir: getdown-launcher.jar
2061 from getdownLauncher
2062 rename(file(getdownLauncher).getName(), getdown_launcher_new)
2063 into getdownAppBaseDir
2066 // files going into the getdown website dir: getdown-launcher(-local).jar
2068 from getdownLauncher
2069 if (file(getdownLauncher).getName() != getdown_launcher) {
2070 rename(file(getdownLauncher).getName(), getdown_launcher)
2072 into getdownAppBaseDir
2075 // files going into the getdown website dir: ./install dir and files
2076 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
2079 from getdownLauncher
2080 from "${getdownAppDir}/${getdown_build_properties}"
2081 if (file(getdownLauncher).getName() != getdown_launcher) {
2082 rename(file(getdownLauncher).getName(), getdown_launcher)
2084 into getdownInstallDir
2087 // and make a copy in the getdown files dir (these are not downloaded by getdown)
2089 from getdownInstallDir
2090 into getdownFilesInstallDir
2094 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2098 from getdownLauncher
2099 from "${getdownAppBaseDir}/${getdown_build_properties}"
2100 from "${getdownAppBaseDir}/${channel_props}"
2101 if (file(getdownLauncher).getName() != getdown_launcher) {
2102 rename(file(getdownLauncher).getName(), getdown_launcher)
2104 into getdownFilesDir
2107 // and ./resource (not all downloaded by getdown)
2109 from getdownResourceDir
2110 into "${getdownFilesDir}/${getdown_resource_dir}"
2115 inputs.dir("${jalviewDir}/${package_dir}")
2117 outputs.dir(getdownAppBaseDir)
2118 outputs.dir(getdownFilesDir)
2122 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
2123 task getdownDigestDir(type: JavaExec) {
2125 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
2127 def digestDirPropertyName = "DIGESTDIR"
2129 classpath = files(getdownLauncher)
2130 def digestDir = findProperty(digestDirPropertyName)
2131 if (digestDir == null) {
2132 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
2136 main = "com.threerings.getdown.tools.Digester"
2140 task getdownDigest(type: JavaExec) {
2141 group = "distribution"
2142 description = "Digest the getdown website folder"
2143 dependsOn getdownWebsite
2145 classpath = files(getdownLauncher)
2147 main = "com.threerings.getdown.tools.Digester"
2148 args getdownAppBaseDir
2149 inputs.dir(getdownAppBaseDir)
2150 outputs.file("${getdownAppBaseDir}/digest2.txt")
2155 group = "distribution"
2156 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
2157 dependsOn getdownDigest
2159 if (reportRsyncCommand) {
2160 def fromDir = getdownAppBaseDir + (getdownAppBaseDir.endsWith('/')?'':'/')
2161 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
2162 println "LIKELY RSYNC COMMAND:"
2163 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
2164 if (RUNRSYNC == "true") {
2166 commandLine "mkdir", "-p", toDir
2169 commandLine "rsync", "-avh", "--delete", fromDir, toDir
2177 task getdownArchiveBuild() {
2178 group = "distribution"
2179 description = "Put files in the archive dir to go on the website"
2181 dependsOn getdownWebsite
2183 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
2184 def vDir = "${getdownArchiveDir}/${v}"
2185 getdownFullArchiveDir = "${vDir}/getdown"
2186 getdownVersionLaunchJvl = "${vDir}/jalview-${v}.jvl"
2188 def vAltDir = "alt_${v}"
2189 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
2192 // cleanup old "old" dir
2193 delete getdownArchiveDir
2195 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
2196 getdownArchiveTxt.getParentFile().mkdirs()
2197 def getdownArchiveTextLines = []
2198 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
2202 from "${getdownAppBaseDir}/${getdownAppDistDir}"
2203 into "${getdownFullArchiveDir}/${vAltDir}"
2206 getdownTextLines.each { line ->
2207 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
2208 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
2209 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
2210 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
2211 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
2212 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
2213 // remove the existing resource = resource/ or bin/ lines
2214 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
2215 getdownArchiveTextLines += line
2219 // the resource dir -- add these files as resource lines in getdown.txt
2221 from "${archiveImagesDir}"
2222 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
2224 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
2228 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
2230 def vLaunchJvl = file(getdownVersionLaunchJvl)
2231 vLaunchJvl.getParentFile().mkdirs()
2232 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
2233 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
2234 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
2235 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
2236 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
2237 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
2239 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2241 from getdownLauncher
2242 from "${getdownAppBaseDir}/${getdownLaunchJvl}"
2243 from "${getdownAppBaseDir}/${getdown_launcher_new}"
2244 from "${getdownAppBaseDir}/${channel_props}"
2245 if (file(getdownLauncher).getName() != getdown_launcher) {
2246 rename(file(getdownLauncher).getName(), getdown_launcher)
2248 into getdownFullArchiveDir
2254 task getdownArchiveDigest(type: JavaExec) {
2255 group = "distribution"
2256 description = "Digest the getdown archive folder"
2258 dependsOn getdownArchiveBuild
2261 classpath = files(getdownLauncher)
2262 args getdownFullArchiveDir
2264 main = "com.threerings.getdown.tools.Digester"
2265 inputs.dir(getdownFullArchiveDir)
2266 outputs.file("${getdownFullArchiveDir}/digest2.txt")
2269 task getdownArchive() {
2270 group = "distribution"
2271 description = "Build the website archive dir with getdown digest"
2273 dependsOn getdownArchiveBuild
2274 dependsOn getdownArchiveDigest
2277 tasks.withType(JavaCompile) {
2278 options.encoding = 'UTF-8'
2284 delete getdownAppBaseDir
2285 delete getdownFilesDir
2286 delete getdownArchiveDir
2292 if (file(install4jHomeDir).exists()) {
2294 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
2295 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
2296 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
2297 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
2299 installDir(file(install4jHomeDir))
2301 mediaTypes = Arrays.asList(install4j_media_types.split(","))
2305 task copyInstall4jTemplate {
2306 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
2307 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
2308 inputs.file(install4jTemplateFile)
2309 inputs.file(install4jFileAssociationsFile)
2310 inputs.property("CHANNEL", { CHANNEL })
2311 outputs.file(install4jConfFile)
2314 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
2316 // turn off code signing if no OSX_KEYPASS
2317 if (OSX_KEYPASS == "") {
2318 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
2319 codeSigning.'@macEnabled' = "false"
2321 install4jConfigXml.'**'.windows.each { windows ->
2322 windows.'@runPostProcessor' = "false"
2326 // disable install screen for OSX dmg (for 2.11.2.0)
2327 install4jConfigXml.'**'.macosArchive.each { macosArchive ->
2328 macosArchive.attributes().remove('executeSetupApp')
2329 macosArchive.attributes().remove('setupAppId')
2332 // turn off checksum creation for LOCAL channel
2333 def e = install4jConfigXml.application[0]
2334 e.'@createChecksums' = string(install4jCheckSums)
2336 // put file association actions where placeholder action is
2337 def install4jFileAssociationsText = install4jFileAssociationsFile.text
2338 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
2339 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
2340 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
2341 def parent = a.parent()
2343 fileAssociationActions.each { faa ->
2346 // don't need to continue in .any loop once replacements have been made
2351 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
2352 // NB we're deleting the /other/ one!
2353 // Also remove the examples subdir from non-release versions
2354 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
2355 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
2356 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
2357 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
2359 // remove the examples subdir from Full File Set
2360 def files = install4jConfigXml.files[0]
2361 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
2362 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
2363 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
2364 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
2365 dirEntry.parent().remove(dirEntry)
2367 install4jConfigXml.'**'.action.any { a ->
2368 if (a.'@customizedId' == customizedIdToDelete) {
2369 def parent = a.parent()
2375 // write install4j file
2376 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
2383 delete install4jConfFile
2387 task cleanInstallersDataFiles {
2388 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2389 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2390 def hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
2392 delete installersOutputTxt
2393 delete installersSha256
2394 delete hugoDataJsonFile
2398 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2399 group = "distribution"
2400 description = "Create the install4j installers"
2402 dependsOn copyInstall4jTemplate
2403 dependsOn cleanInstallersDataFiles
2405 projectFile = install4jConfFile
2407 // create an md5 for the input files to use as version for install4j conf file
2408 def digest = MessageDigest.getInstance("MD5")
2410 (file("${install4jDir}/${install4j_template}").text +
2411 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2412 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2413 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2414 if (filesMd5.length() >= 8) {
2415 filesMd5 = filesMd5.substring(0,8)
2417 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2420 'JALVIEW_NAME': jalview_name,
2421 'JALVIEW_APPLICATION_NAME': applicationName,
2422 'JALVIEW_DIR': "../..",
2423 'OSX_KEYSTORE': OSX_KEYSTORE,
2424 'OSX_APPLEID': OSX_APPLEID,
2425 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2426 'JSIGN_SH': JSIGN_SH,
2427 'JRE_DIR': getdown_app_dir_java,
2428 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2429 'JALVIEW_VERSION': JALVIEW_VERSION,
2430 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2431 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2432 'JAVA_VERSION': JAVA_VERSION,
2433 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2434 'VERSION': JALVIEW_VERSION,
2435 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2436 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2437 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2438 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2439 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2440 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2441 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2442 'BUNDLE_ID': install4jBundleId,
2443 'INTERNAL_ID': install4jInternalId,
2444 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2445 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2446 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
2447 'WRAPPER_LINK': getdownWrapperLink,
2448 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2449 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2450 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2451 'INSTALLER_NAME': install4jInstallerName,
2452 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2453 'GETDOWN_CHANNEL_DIR': getdownChannelDir,
2454 'GETDOWN_FILES_DIR': getdown_files_dir,
2455 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2456 'GETDOWN_DIST_DIR': getdownAppDistDir,
2457 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2458 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2459 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2460 'BUILD_DIR': install4jBuildDir,
2461 'APPLICATION_CATEGORIES': install4j_application_categories,
2462 'APPLICATION_FOLDER': install4jApplicationFolder,
2463 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2464 'EXECUTABLE_NAME': install4jExecutableName,
2465 'EXTRA_SCHEME': install4jExtraScheme,
2466 'MAC_ICONS_FILE': install4jMacIconsFile,
2467 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2468 'PNG_ICON_FILE': install4jPngIconFile,
2469 'BACKGROUND': install4jBackground,
2473 //println("INSTALL4J VARIABLES:")
2474 //variables.each{k,v->println("${k}=${v}")}
2476 destination = "${jalviewDir}/${install4jBuildDir}"
2477 buildSelected = true
2479 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2481 disableSigning = true
2482 disableNotarization = true
2486 macKeystorePassword = OSX_KEYPASS
2489 if (OSX_ALTOOLPASS) {
2490 appleIdPassword = OSX_ALTOOLPASS
2491 disableNotarization = false
2493 disableNotarization = true
2497 println("Using projectFile "+projectFile)
2498 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2502 inputs.dir(getdownAppBaseDir)
2503 inputs.file(install4jConfFile)
2504 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2505 inputs.dir(macosJavaVMDir)
2506 inputs.dir(windowsJavaVMDir)
2507 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2510 def getDataHash(File myFile) {
2511 HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
2512 return myFile.exists()
2514 "file" : myFile.getName(),
2515 "filesize" : myFile.length(),
2516 "sha256" : hash.toString()
2521 def writeDataJsonFile(File installersOutputTxt, File installersSha256, File dataJsonFile) {
2523 "channel" : getdownChannelName,
2524 "date" : getDate("yyyy-MM-dd HH:mm:ss"),
2525 "git-commit" : "${gitHash} [${gitBranch}]",
2526 "version" : JALVIEW_VERSION
2528 // install4j installer files
2529 if (installersOutputTxt.exists()) {
2531 installersOutputTxt.readLines().each { def line ->
2532 if (line.startsWith("#")) {
2535 line.replaceAll("\n","")
2536 def vals = line.split("\t")
2537 def filename = vals[3]
2538 def filesize = file(filename).length()
2539 filename = filename.replaceAll(/^.*\//, "")
2540 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2541 idHash."${filename}" = vals[0]
2543 if (install4jCheckSums && installersSha256.exists()) {
2544 installersSha256.readLines().each { def line ->
2545 if (line.startsWith("#")) {
2548 line.replaceAll("\n","")
2549 def vals = line.split(/\s+\*?/)
2550 def filename = vals[1]
2551 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2557 "JAR": shadowJar.archiveFile, // executable JAR
2558 "JVL": getdownVersionLaunchJvl, // version JVL
2559 "SOURCE": sourceDist.archiveFile // source TGZ
2560 ].each { key, value ->
2561 def file = file(value)
2562 if (file.exists()) {
2563 def fileHash = getDataHash(file)
2564 if (fileHash != null) {
2565 hash."${key}" = fileHash;
2569 return dataJsonFile.write(new JsonBuilder(hash).toPrettyString())
2572 task staticMakeInstallersJsonFile {
2574 def output = findProperty("i4j_output")
2575 def sha256 = findProperty("i4j_sha256")
2576 def json = findProperty("i4j_json")
2577 if (output == null || sha256 == null || json == null) {
2578 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2580 writeDataJsonFile(file(output), file(sha256), file(json))
2585 dependsOn installerFiles
2591 eclipse().configFile(eclipse_codestyle_file)
2595 task createSourceReleaseProperties(type: WriteProperties) {
2596 group = "distribution"
2597 description = "Create the source RELEASE properties file"
2599 def sourceTarBuildDir = "${buildDir}/sourceTar"
2600 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2601 outputFile (sourceReleasePropertiesFile)
2604 releaseProps.each{ key, val -> property key, val }
2605 property "git.branch", gitBranch
2606 property "git.hash", gitHash
2609 outputs.file(outputFile)
2612 task sourceDist(type: Tar) {
2613 group "distribution"
2614 description "Create a source .tar.gz file for distribution"
2616 dependsOn createBuildProperties
2617 dependsOn convertMdFiles
2618 dependsOn eclipseAllPreferences
2619 dependsOn createSourceReleaseProperties
2622 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2623 archiveFileName = outputFileName
2625 compression Compression.GZIP
2640 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2642 "utils/InstallAnywhere",
2657 "gradle.properties",
2669 ".settings/org.eclipse.buildship.core.prefs",
2670 ".settings/org.eclipse.jdt.core.prefs"
2674 exclude (EXCLUDE_FILES)
2675 include (PROCESS_FILES)
2676 filter(ReplaceTokens,
2680 'Version-Rel': JALVIEW_VERSION,
2681 'Year-Rel': getDate("yyyy")
2686 exclude (EXCLUDE_FILES)
2687 exclude (PROCESS_FILES)
2688 exclude ("appletlib")
2689 exclude ("**/*locales")
2690 exclude ("*locales/**")
2691 exclude ("utils/InstallAnywhere")
2693 exclude (getdown_files_dir)
2694 // getdown_website_dir and getdown_archive_dir moved to build/website/docroot/getdown
2695 //exclude (getdown_website_dir)
2696 //exclude (getdown_archive_dir)
2698 // exluding these as not using jars as modules yet
2699 exclude ("${j11modDir}/**/*.jar")
2702 include(INCLUDE_FILES)
2704 // from (jalviewDir) {
2705 // // explicit includes for stuff that seemed to not get included
2706 // include(fileTree("test/**/*."))
2707 // exclude(EXCLUDE_FILES)
2708 // exclude(PROCESS_FILES)
2711 from(file(buildProperties).getParent()) {
2712 include(file(buildProperties).getName())
2713 rename(file(buildProperties).getName(), "build_properties")
2715 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2719 def sourceTarBuildDir = "${buildDir}/sourceTar"
2720 from(sourceTarBuildDir) {
2721 // this includes the appended RELEASE properties file
2725 task dataInstallersJson {
2727 description "Create the installers-VERSION.json data file for installer files created"
2729 mustRunAfter installers
2730 mustRunAfter shadowJar
2731 mustRunAfter sourceDist
2732 mustRunAfter getdownArchive
2734 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2735 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2737 if (installersOutputTxt.exists()) {
2738 inputs.file(installersOutputTxt)
2740 if (install4jCheckSums && installersSha256.exists()) {
2741 inputs.file(installersSha256)
2744 shadowJar.archiveFile, // executable JAR
2745 getdownVersionLaunchJvl, // version JVL
2746 sourceDist.archiveFile // source TGZ
2747 ].each { fileName ->
2748 if (file(fileName).exists()) {
2749 inputs.file(fileName)
2753 outputs.file(hugoDataJsonFile)
2756 writeDataJsonFile(installersOutputTxt, installersSha256, hugoDataJsonFile)
2762 description "Copies all help pages to build dir. Runs ant task 'pubhtmlhelp'."
2765 dependsOn pubhtmlhelp
2767 inputs.dir("${helpBuildDir}/${help_dir}")
2768 outputs.dir("${buildDir}/distributions/${help_dir}")
2772 task j2sSetHeadlessBuild {
2779 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2781 description "Enable the alternative J2S Config file for headless build"
2783 outputFile = jalviewjsJ2sSettingsFileName
2784 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2785 def j2sProps = new Properties()
2786 if (j2sPropsFile.exists()) {
2788 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2789 j2sProps.load(j2sPropsFileFIS)
2790 j2sPropsFileFIS.close()
2792 j2sProps.each { prop, val ->
2795 } catch (Exception e) {
2796 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2800 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2801 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2806 task jalviewjsSetEclipseWorkspace {
2807 def propKey = "jalviewjs_eclipse_workspace"
2809 if (project.hasProperty(propKey)) {
2810 propVal = project.getProperty(propKey)
2811 if (propVal.startsWith("~/")) {
2812 propVal = System.getProperty("user.home") + propVal.substring(1)
2815 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2816 def propsFile = file(propsFileName)
2817 def eclipseWsDir = propVal
2818 def props = new Properties()
2820 def writeProps = true
2821 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2822 def ins = new FileInputStream(propsFileName)
2825 if (props.getProperty(propKey, null) != null) {
2826 eclipseWsDir = props.getProperty(propKey)
2831 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2832 def tempDir = File.createTempDir()
2833 eclipseWsDir = tempDir.getAbsolutePath()
2836 eclipseWorkspace = file(eclipseWsDir)
2839 // do not run a headless transpile when we claim to be in Eclipse
2841 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2842 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2844 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2848 props.setProperty(propKey, eclipseWsDir)
2849 propsFile.parentFile.mkdirs()
2850 def bytes = new ByteArrayOutputStream()
2851 props.store(bytes, null)
2852 def propertiesString = bytes.toString()
2853 propsFile.text = propertiesString
2859 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2862 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2863 outputs.file(propsFileName)
2864 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2868 task jalviewjsEclipsePaths {
2871 def eclipseRoot = jalviewjs_eclipse_root
2872 if (eclipseRoot.startsWith("~/")) {
2873 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
2875 if (OperatingSystem.current().isMacOsX()) {
2876 eclipseRoot += "/Eclipse.app"
2877 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
2878 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
2879 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
2880 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2881 eclipseRoot += "/eclipse"
2883 eclipseBinary = "${eclipseRoot}/eclipse.exe"
2884 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2885 } else { // linux or unix
2886 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2887 eclipseRoot += "/eclipse"
2888 println("eclipseDir exists")
2890 eclipseBinary = "${eclipseRoot}/eclipse"
2891 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2894 eclipseVersion = "4.13" // default
2895 def assumedVersion = true
2896 if (file(eclipseProduct).exists()) {
2897 def fis = new FileInputStream(eclipseProduct)
2898 def props = new Properties()
2900 eclipseVersion = props.getProperty("version")
2902 assumedVersion = false
2905 def propKey = "eclipse_debug"
2906 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
2909 // do not run a headless transpile when we claim to be in Eclipse
2911 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2912 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2914 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2917 if (!assumedVersion) {
2918 println("ECLIPSE VERSION=${eclipseVersion}")
2924 task printProperties {
2926 description "Output to console all System.properties"
2928 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
2934 dependsOn eclipseProject
2935 dependsOn eclipseClasspath
2936 dependsOn eclipseJdt
2940 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
2941 task jalviewjsEclipseCopyDropins(type: Copy) {
2942 dependsOn jalviewjsEclipsePaths
2944 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
2945 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
2946 def destinationDirectory = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
2949 into destinationDirectory
2953 // this eclipse -clean doesn't actually work
2954 task jalviewjsCleanEclipse(type: Exec) {
2955 dependsOn eclipseSetup
2956 dependsOn jalviewjsEclipsePaths
2957 dependsOn jalviewjsEclipseCopyDropins
2959 executable(eclipseBinary)
2960 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
2966 def inputString = """exit
2969 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
2970 standardInput = inputByteStream
2973 /* not really working yet
2974 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
2978 task jalviewjsTransferUnzipSwingJs {
2979 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
2983 from zipTree(file_zip)
2984 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2988 inputs.file file_zip
2989 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2993 task jalviewjsTransferUnzipLib {
2994 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
2997 zipFiles.each { file_zip ->
2999 from zipTree(file_zip)
3000 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3005 inputs.files zipFiles
3006 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3010 task jalviewjsTransferUnzipAllLibs {
3011 dependsOn jalviewjsTransferUnzipSwingJs
3012 dependsOn jalviewjsTransferUnzipLib
3016 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
3018 description "Create the alternative j2s file from the j2s.* properties"
3020 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
3021 def siteDirProperty = "j2s.site.directory"
3022 def setSiteDir = false
3023 jalviewjsJ2sProps.each { prop, val ->
3025 if (prop == siteDirProperty) {
3026 if (!(val.startsWith('/') || val.startsWith("file://") )) {
3027 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
3033 if (!setSiteDir) { // default site location, don't override specifically set property
3034 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
3037 outputFile = jalviewjsJ2sAltSettingsFileName
3040 inputs.properties(jalviewjsJ2sProps)
3041 outputs.file(jalviewjsJ2sAltSettingsFileName)
3046 task jalviewjsEclipseSetup {
3047 dependsOn jalviewjsEclipseCopyDropins
3048 dependsOn jalviewjsSetEclipseWorkspace
3049 dependsOn jalviewjsCreateJ2sSettings
3053 task jalviewjsSyncAllLibs (type: Sync) {
3054 dependsOn jalviewjsTransferUnzipAllLibs
3055 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
3056 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
3057 def destinationDirectory = "${jalviewDir}/${jalviewjsSiteDir}"
3060 into destinationDirectory
3061 def outputFiles = []
3062 rename { filename ->
3063 outputFiles += "${destinationDirectory}/${filename}"
3070 // should this be exclude really ?
3071 duplicatesStrategy "INCLUDE"
3073 outputs.files outputFiles
3074 inputs.files inputFiles
3078 task jalviewjsSyncResources (type: Sync) {
3079 dependsOn buildResources
3081 def inputFiles = fileTree(dir: resourcesBuildDir)
3082 def destinationDirectory = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3085 into destinationDirectory
3086 def outputFiles = []
3087 rename { filename ->
3088 outputFiles += "${destinationDirectory}/${filename}"
3094 outputs.files outputFiles
3095 inputs.files inputFiles
3099 task jalviewjsSyncSiteResources (type: Sync) {
3100 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
3101 def destinationDirectory = "${jalviewDir}/${jalviewjsSiteDir}"
3104 into destinationDirectory
3105 def outputFiles = []
3106 rename { filename ->
3107 outputFiles += "${destinationDirectory}/${filename}"
3113 outputs.files outputFiles
3114 inputs.files inputFiles
3118 task jalviewjsSyncBuildProperties (type: Sync) {
3119 dependsOn createBuildProperties
3120 def inputFiles = [file(buildProperties)]
3121 def destinationDirectory = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3124 into destinationDirectory
3125 def outputFiles = []
3126 rename { filename ->
3127 outputFiles += "${destinationDirectory}/${filename}"
3133 outputs.files outputFiles
3134 inputs.files inputFiles
3138 task jalviewjsProjectImport(type: Exec) {
3139 dependsOn eclipseSetup
3140 dependsOn jalviewjsEclipsePaths
3141 dependsOn jalviewjsEclipseSetup
3144 // do not run a headless import when we claim to be in Eclipse
3146 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3147 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3149 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3153 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
3154 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
3155 executable(eclipseBinary)
3156 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
3160 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3162 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3163 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3166 inputs.file("${jalviewDir}/.project")
3167 outputs.upToDateWhen {
3168 file(projdir).exists()
3173 task jalviewjsTranspile(type: Exec) {
3174 dependsOn jalviewjsEclipseSetup
3175 dependsOn jalviewjsProjectImport
3176 dependsOn jalviewjsEclipsePaths
3178 dependsOn jalviewjsEnableAltFileProperty
3182 // do not run a headless transpile when we claim to be in Eclipse
3184 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3185 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3187 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3191 executable(eclipseBinary)
3192 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
3196 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3198 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3199 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3205 stdout = new ByteArrayOutputStream()
3206 stderr = new ByteArrayOutputStream()
3208 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
3209 def logOutFile = file(logOutFileName)
3210 logOutFile.createNewFile()
3211 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
3212 BINARY: ${eclipseBinary}
3213 VERSION: ${eclipseVersion}
3214 WORKSPACE: ${eclipseWorkspace}
3215 DEBUG: ${eclipseDebug}
3218 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3219 // combine stdout and stderr
3220 def logErrFOS = logOutFOS
3222 if (jalviewjs_j2s_to_console.equals("true")) {
3223 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3224 new org.apache.tools.ant.util.TeeOutputStream(
3228 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3229 new org.apache.tools.ant.util.TeeOutputStream(
3234 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3237 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3244 if (stdout.toString().contains("Error processing ")) {
3245 // j2s did not complete transpile
3246 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3247 if (jalviewjs_ignore_transpile_errors.equals("true")) {
3248 println("IGNORING TRANSPILE ERRORS")
3249 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3251 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3256 inputs.dir("${jalviewDir}/${sourceDir}")
3257 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
3258 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
3262 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
3264 def stdout = new ByteArrayOutputStream()
3265 def stderr = new ByteArrayOutputStream()
3267 def coreFile = file(jsfile)
3269 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
3271 logOutFile.createNewFile()
3272 logOutFile.append(msg+"\n")
3274 def coreTop = file(prefixFile)
3275 def coreBottom = file(suffixFile)
3276 coreFile.getParentFile().mkdirs()
3277 coreFile.createNewFile()
3278 coreFile.write( coreTop.getText("UTF-8") )
3282 def t = f.getText("UTF-8")
3283 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
3284 coreFile.append( t )
3286 msg = "...file '"+f.getPath()+"' does not exist, skipping"
3288 logOutFile.append(msg+"\n")
3291 coreFile.append( coreBottom.getText("UTF-8") )
3293 msg = "Generating ${zjsfile}"
3295 logOutFile.append(msg+"\n")
3296 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3297 def logErrFOS = logOutFOS
3300 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
3301 main = "com.google.javascript.jscomp.CommandLineRunner"
3302 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
3303 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
3306 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
3308 logOutFile.append(msg+"\n")
3310 if (logOutConsole) {
3311 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3312 new org.apache.tools.ant.util.TeeOutputStream(
3316 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3317 new org.apache.tools.ant.util.TeeOutputStream(
3322 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3325 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3332 logOutFile.append(msg+"\n")
3336 task jalviewjsBuildAllCores {
3338 description "Build the core js lib closures listed in the classlists dir"
3339 dependsOn jalviewjsTranspile
3340 dependsOn jalviewjsTransferUnzipSwingJs
3342 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
3343 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
3344 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
3345 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
3346 def destinationDirectory = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
3347 def prefixFile = "${jsDir}/core/coretop2.js"
3348 def suffixFile = "${jsDir}/core/corebottom2.js"
3350 inputs.file prefixFile
3351 inputs.file suffixFile
3353 def classlistFiles = []
3354 // add the classlists found int the jalviewjs_classlists_dir
3355 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
3357 def name = file.getName() - ".txt"
3364 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
3365 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
3366 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
3368 jalviewjsCoreClasslists = []
3370 classlistFiles.each {
3373 def file = hash['file']
3374 if (! file.exists()) {
3375 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
3376 return false // this is a "continue" in groovy .each closure
3378 def name = hash['name']
3380 name = file.getName() - ".txt"
3388 def list = fileTree(dir: j2sDir, includes: filelist)
3390 def jsfile = "${destinationDirectory}/core${name}.js"
3391 def zjsfile = "${destinationDirectory}/core${name}.z.js"
3393 jalviewjsCoreClasslists += [
3402 outputs.file(jsfile)
3403 outputs.file(zjsfile)
3406 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
3407 def stevesoftClasslistName = "_stevesoft"
3408 def stevesoftClasslist = [
3409 'jsfile': "${destinationDirectory}/core${stevesoftClasslistName}.js",
3410 'zjsfile': "${destinationDirectory}/core${stevesoftClasslistName}.z.js",
3411 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
3412 'name': stevesoftClasslistName
3414 jalviewjsCoreClasslists += stevesoftClasslist
3415 inputs.files(stevesoftClasslist['list'])
3416 outputs.file(stevesoftClasslist['jsfile'])
3417 outputs.file(stevesoftClasslist['zjsfile'])
3420 def allClasslistName = "_all"
3421 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3422 allJsFiles += fileTree(
3426 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3427 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3428 "**/org/jmol/export/JSExporter.js"
3431 allJsFiles += fileTree(
3435 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3436 "**/sun/misc/Unsafe.js",
3437 "**/swingjs/jquery/jquery-editable-select.js",
3438 "**/swingjs/jquery/j2sComboBox.js",
3439 "**/sun/misc/FloatingDecimal.js"
3442 def allClasslist = [
3443 'jsfile': "${destinationDirectory}/core${allClasslistName}.js",
3444 'zjsfile': "${destinationDirectory}/core${allClasslistName}.z.js",
3446 'name': allClasslistName
3448 // not including this version of "all" core at the moment
3449 //jalviewjsCoreClasslists += allClasslist
3450 inputs.files(allClasslist['list'])
3451 outputs.file(allClasslist['jsfile'])
3452 outputs.file(allClasslist['zjsfile'])
3455 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3456 logOutFile.getParentFile().mkdirs()
3457 logOutFile.createNewFile()
3458 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3460 jalviewjsCoreClasslists.each {
3461 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3468 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3471 into file(outputFile).getParentFile()
3472 rename { filename ->
3473 if (filename.equals(inputFile.getName())) {
3474 return file(outputFile).getName()
3478 filter(ReplaceTokens,
3482 'MAIN': '"'+main_class+'"',
3484 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3485 'COREKEY': jalviewjs_core_key,
3486 'CORENAME': coreName
3493 task jalviewjsPublishCoreTemplates {
3494 dependsOn jalviewjsBuildAllCores
3495 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3496 def inputFile = file(inputFileName)
3497 def destinationDirectory = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3499 def outputFiles = []
3500 jalviewjsCoreClasslists.each { cl ->
3501 def outputFile = "${destinationDirectory}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3502 cl['outputfile'] = outputFile
3503 outputFiles += outputFile
3507 jalviewjsCoreClasslists.each { cl ->
3508 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3511 inputs.file(inputFile)
3512 outputs.files(outputFiles)
3516 task jalviewjsSyncCore (type: Sync) {
3517 dependsOn jalviewjsBuildAllCores
3518 dependsOn jalviewjsPublishCoreTemplates
3519 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3520 def destinationDirectory = "${jalviewDir}/${jalviewjsSiteDir}"
3523 into destinationDirectory
3524 def outputFiles = []
3525 rename { filename ->
3526 outputFiles += "${destinationDirectory}/${filename}"
3532 outputs.files outputFiles
3533 inputs.files inputFiles
3537 // this Copy version of TransferSiteJs will delete anything else in the target dir
3538 task jalviewjsCopyTransferSiteJs(type: Copy) {
3539 dependsOn jalviewjsTranspile
3540 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3541 into "${jalviewDir}/${jalviewjsSiteDir}"
3545 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3546 task jalviewjsSyncTransferSiteJs(type: Sync) {
3547 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3549 into "${jalviewDir}/${jalviewjsSiteDir}"
3556 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3557 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3558 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3559 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3561 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3562 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3563 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3564 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3567 task jalviewjsPrepareSite {
3569 description "Prepares the website folder including unzipping files and copying resources"
3570 dependsOn jalviewjsSyncAllLibs
3571 dependsOn jalviewjsSyncResources
3572 dependsOn jalviewjsSyncSiteResources
3573 dependsOn jalviewjsSyncBuildProperties
3574 dependsOn jalviewjsSyncCore
3578 task jalviewjsBuildSite {
3580 description "Builds the whole website including transpiled code"
3581 dependsOn jalviewjsCopyTransferSiteJs
3582 dependsOn jalviewjsPrepareSite
3586 task cleanJalviewjsTransferSite {
3588 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3589 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3590 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3591 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3596 task cleanJalviewjsSite {
3597 dependsOn cleanJalviewjsTransferSite
3599 delete "${jalviewDir}/${jalviewjsSiteDir}"
3604 task jalviewjsSiteTar(type: Tar) {
3606 description "Creates a tar.gz file for the website"
3607 dependsOn jalviewjsBuildSite
3608 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3609 archiveFileName = outputFilename
3611 compression Compression.GZIP
3613 from "${jalviewDir}/${jalviewjsSiteDir}"
3614 into jalviewjs_site_dir // this is inside the tar file
3616 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3620 task jalviewjsServer {
3622 def filename = "jalviewjsTest.html"
3623 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3624 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3629 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3630 factory = f.newInstance()
3631 } catch (ClassNotFoundException e) {
3632 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3634 def port = Integer.valueOf(jalviewjs_server_port)
3639 while(port < start+1000 && !running) {
3641 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3642 jalviewjsServer = factory.start(doc_root, port)
3644 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3645 println("SERVER STARTED with document root ${doc_root}.")
3646 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3647 println("For debug: "+url+"?j2sdebug")
3648 println("For verbose: "+url+"?j2sverbose")
3649 } catch (Exception e) {
3654 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3655 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3656 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3658 jalviewjsCoreClasslists.each { cl ->
3659 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3661 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3663 println("For core ${cl.name}: "+urlcore)
3666 file(htmlFile).text = htmlText
3669 outputs.file(htmlFile)
3670 outputs.upToDateWhen({false})
3674 task cleanJalviewjsAll {
3676 description "Delete all configuration and build artifacts to do with JalviewJS build"
3677 dependsOn cleanJalviewjsSite
3678 dependsOn jalviewjsEclipsePaths
3681 delete "${jalviewDir}/${jalviewjsBuildDir}"
3682 delete "${jalviewDir}/${eclipse_bin_dir}"
3683 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3684 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3686 delete jalviewjsJ2sAltSettingsFileName
3689 outputs.upToDateWhen( { false } )
3693 task jalviewjsIDE_checkJ2sPlugin {
3694 group "00 JalviewJS in Eclipse"
3695 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3698 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3699 def j2sPluginFile = file(j2sPlugin)
3700 def eclipseHome = System.properties["eclipse.home.location"]
3701 if (eclipseHome == null || ! IN_ECLIPSE) {
3702 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3704 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3705 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3706 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3707 eclipseJ2sPluginDirs += altPluginsDir
3709 def foundPlugin = false
3710 def j2sPluginFileName = j2sPluginFile.getName()
3711 def eclipseJ2sPlugin
3712 def eclipseJ2sPluginFile
3713 eclipseJ2sPluginDirs.any { dir ->
3714 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3715 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3716 if (eclipseJ2sPluginFile.exists()) {
3722 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3723 System.err.println(msg)
3724 throw new StopExecutionException(msg)
3727 def digest = MessageDigest.getInstance("MD5")
3729 digest.update(j2sPluginFile.text.bytes)
3730 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3732 digest.update(eclipseJ2sPluginFile.text.bytes)
3733 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3735 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3736 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3737 System.err.println(msg)
3738 throw new StopExecutionException(msg)
3740 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3746 task jalviewjsIDE_copyJ2sPlugin {
3747 group "00 JalviewJS in Eclipse"
3748 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3751 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3752 def j2sPluginFile = file(j2sPlugin)
3753 def eclipseHome = System.properties["eclipse.home.location"]
3754 if (eclipseHome == null || ! IN_ECLIPSE) {
3755 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3757 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3758 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3759 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3760 System.err.println(msg)
3763 eclipseJ2sPluginFile.getParentFile().mkdirs()
3764 into eclipseJ2sPluginFile.getParent()
3770 task jalviewjsIDE_j2sFile {
3771 group "00 JalviewJS in Eclipse"
3772 description "Creates the .j2s file"
3773 dependsOn jalviewjsCreateJ2sSettings
3777 task jalviewjsIDE_SyncCore {
3778 group "00 JalviewJS in Eclipse"
3779 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3780 dependsOn jalviewjsSyncCore
3784 task jalviewjsIDE_SyncSiteAll {
3785 dependsOn jalviewjsSyncAllLibs
3786 dependsOn jalviewjsSyncResources
3787 dependsOn jalviewjsSyncSiteResources
3788 dependsOn jalviewjsSyncBuildProperties
3792 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3795 task jalviewjsIDE_PrepareSite {
3796 group "00 JalviewJS in Eclipse"
3797 description "Sync libs and resources to site dir, but not closure cores"
3799 dependsOn jalviewjsIDE_SyncSiteAll
3800 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3804 task jalviewjsIDE_AssembleSite {
3805 group "00 JalviewJS in Eclipse"
3806 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3807 dependsOn jalviewjsPrepareSite
3811 task jalviewjsIDE_SiteClean {
3812 group "00 JalviewJS in Eclipse"
3813 description "Deletes the Eclipse transpiled site"
3814 dependsOn cleanJalviewjsSite
3818 task jalviewjsIDE_Server {
3819 group "00 JalviewJS in Eclipse"
3820 description "Starts a webserver on localhost to test the website"
3821 dependsOn jalviewjsServer
3825 // buildship runs this at import or gradle refresh
3826 task eclipseSynchronizationTask {
3827 //dependsOn eclipseSetup
3828 dependsOn createBuildProperties
3830 dependsOn jalviewjsIDE_j2sFile
3831 dependsOn jalviewjsIDE_checkJ2sPlugin
3832 dependsOn jalviewjsIDE_PrepareSite
3837 // buildship runs this at build time or project refresh
3838 task eclipseAutoBuildTask {
3839 //dependsOn jalviewjsIDE_checkJ2sPlugin
3840 //dependsOn jalviewjsIDE_PrepareSite
3846 description "Build the site"
3847 dependsOn jalviewjsBuildSite