1 /* Convention for properties. Read from gradle.properties, use lower_case_underlines for property names.
2 * For properties set within build.gradle, use camelCaseNoSpace.
4 import org.apache.tools.ant.filters.ReplaceTokens
5 import org.gradle.internal.os.OperatingSystem
6 import org.gradle.plugins.ide.internal.generator.PropertiesPersistableConfigurationObject
7 import org.gradle.api.internal.PropertiesTransformer
8 import org.gradle.util.ConfigureUtil
9 import org.gradle.plugins.ide.eclipse.model.Output
10 import org.gradle.plugins.ide.eclipse.model.Library
11 import java.security.MessageDigest
12 import groovy.transform.ExternalizeMethods
13 import groovy.util.XmlParser
14 import groovy.xml.XmlUtil
15 import groovy.json.JsonBuilder
16 import com.vladsch.flexmark.util.ast.Node
17 import com.vladsch.flexmark.html.HtmlRenderer
18 import com.vladsch.flexmark.parser.Parser
19 import com.vladsch.flexmark.util.data.MutableDataSet
20 import com.vladsch.flexmark.ext.gfm.tasklist.TaskListExtension
21 import com.vladsch.flexmark.ext.tables.TablesExtension
22 import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension
23 import com.vladsch.flexmark.ext.autolink.AutolinkExtension
24 import com.vladsch.flexmark.ext.anchorlink.AnchorLinkExtension
25 import com.vladsch.flexmark.ext.toc.TocExtension
26 import com.google.common.hash.HashCode
27 import com.google.common.hash.Hashing
28 import com.google.common.io.Files
29 import org.jsoup.Jsoup
30 import org.jsoup.nodes.Element
38 classpath "com.vladsch.flexmark:flexmark-all:0.62.0"
39 classpath "org.jsoup:jsoup:1.14.3"
48 id "com.diffplug.gradle.spotless" version "3.28.0"
49 id 'com.github.johnrengelman.shadow' version '4.0.3'
50 id 'com.install4j.gradle' version '9.0.6'
51 id 'com.dorongold.task-tree' version '1.5' // only needed to display task dependency tree with gradle task1 [task2 ...] taskTree
52 id 'com.palantir.git-version' version '0.13.0' apply false
63 // in ext the values are cast to Object. Ensure string values are cast as String (and not GStringImpl) for later use
64 def string(Object o) {
65 return o == null ? "" : o.toString()
68 def overrideProperties(String propsFileName, boolean output = false) {
69 if (propsFileName == null) {
72 def propsFile = file(propsFileName)
73 if (propsFile != null && propsFile.exists()) {
74 println("Using properties from file '${propsFileName}'")
76 def p = new Properties()
77 def localPropsFIS = new FileInputStream(propsFile)
83 if (project.hasProperty(key)) {
84 oldval = project.findProperty(key)
85 project.setProperty(key, val)
87 println("Overriding property '${key}' ('${oldval}') with ${file(propsFile).getName()} value '${val}'")
90 ext.setProperty(key, val)
92 println("Setting ext property '${key}' with ${file(propsFile).getName()}s value '${val}'")
96 } catch (Exception e) {
97 println("Exception reading local.properties")
104 jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath()
105 jalviewDirRelativePath = jalviewDir
108 getdownChannelName = CHANNEL.toLowerCase()
109 // default to "default". Currently only has different cosmetics for "develop", "release", "default"
110 propertiesChannelName = ["develop", "release", "test-release", "jalviewjs", "jalviewjs-release" ].contains(getdownChannelName) ? getdownChannelName : "default"
111 // Import channel_properties
112 channelDir = string("${jalviewDir}/${channel_properties_dir}/${propertiesChannelName}")
113 channelGradleProperties = string("${channelDir}/channel_gradle.properties")
114 channelPropsFile = string("${channelDir}/${resource_dir}/${channel_props}")
115 overrideProperties(channelGradleProperties, false)
116 // local build environment properties
117 // can be "projectDir/local.properties"
118 overrideProperties("${projectDir}/local.properties", true)
119 // or "../projectDir_local.properties"
120 overrideProperties(projectDir.getParent() + "/" + projectDir.getName() + "_local.properties", true)
123 // Import releaseProps from the RELEASE file
124 // or a file specified via JALVIEW_RELEASE_FILE if defined
125 // Expect jalview.version and target release branch in jalview.release
126 releaseProps = new Properties();
127 def releasePropFile = findProperty("JALVIEW_RELEASE_FILE");
128 def defaultReleasePropFile = "${jalviewDirAbsolutePath}/RELEASE";
130 (new File(releasePropFile!=null ? releasePropFile : defaultReleasePropFile)).withInputStream {
131 releaseProps.load(it)
133 } catch (Exception fileLoadError) {
134 throw new Error("Couldn't load release properties file "+(releasePropFile==null ? defaultReleasePropFile : "from custom location: releasePropFile"),fileLoadError);
137 // Set JALVIEW_VERSION if it is not already set
138 if (findProperty("JALVIEW_VERSION")==null || "".equals(JALVIEW_VERSION)) {
139 JALVIEW_VERSION = releaseProps.get("jalview.version")
142 // this property set when running Eclipse headlessly
143 j2sHeadlessBuildProperty = string("net.sf.j2s.core.headlessbuild")
144 // this property set by Eclipse
145 eclipseApplicationProperty = string("eclipse.application")
146 // CHECK IF RUNNING FROM WITHIN ECLIPSE
147 def eclipseApplicationPropertyVal = System.properties[eclipseApplicationProperty]
148 IN_ECLIPSE = eclipseApplicationPropertyVal != null && eclipseApplicationPropertyVal.startsWith("org.eclipse.ui.")
149 // BUT WITHOUT THE HEADLESS BUILD PROPERTY SET
150 if (System.properties[j2sHeadlessBuildProperty].equals("true")) {
151 println("Setting IN_ECLIPSE to ${IN_ECLIPSE} as System.properties['${j2sHeadlessBuildProperty}'] == '${System.properties[j2sHeadlessBuildProperty]}'")
155 println("WITHIN ECLIPSE IDE")
157 println("HEADLESS BUILD")
160 J2S_ENABLED = (project.hasProperty('j2s.compiler.status') && project['j2s.compiler.status'] != null && project['j2s.compiler.status'] == "enable")
162 println("J2S ENABLED")
165 System.properties.sort { it.key }.each {
166 key, val -> println("SYSTEM PROPERTY ${key}='${val}'")
169 if (false && IN_ECLIPSE) {
170 jalviewDir = jalviewDirAbsolutePath
175 buildDate = new Date().format("yyyyMMdd")
178 bareSourceDir = string(source_dir)
179 sourceDir = string("${jalviewDir}/${bareSourceDir}")
180 resourceDir = string("${jalviewDir}/${resource_dir}")
181 bareTestSourceDir = string(test_source_dir)
182 testDir = string("${jalviewDir}/${bareTestSourceDir}")
184 classesDir = string("${jalviewDir}/${classes_dir}")
187 useClover = clover.equals("true")
188 cloverBuildDir = "${buildDir}/clover"
189 cloverInstrDir = file("${cloverBuildDir}/clover-instr")
190 cloverClassesDir = file("${cloverBuildDir}/clover-classes")
191 cloverReportDir = file("${buildDir}/reports/clover")
192 cloverTestInstrDir = file("${cloverBuildDir}/clover-test-instr")
193 cloverTestClassesDir = file("${cloverBuildDir}/clover-test-classes")
194 //cloverTestClassesDir = cloverClassesDir
195 cloverDb = string("${cloverBuildDir}/clover.db")
197 testSourceDir = useClover ? cloverTestInstrDir : testDir
198 testClassesDir = useClover ? cloverTestClassesDir : "${jalviewDir}/${test_output_dir}"
200 getdownChannelDir = string("${getdown_website_dir}/${propertiesChannelName}")
201 getdownAppBaseDir = string("${jalviewDir}/${getdownChannelDir}/${JAVA_VERSION}")
202 getdownArchiveDir = string("${jalviewDir}/${getdown_archive_dir}")
203 getdownFullArchiveDir = null
204 getdownTextLines = []
205 getdownLaunchJvl = null
206 getdownVersionLaunchJvl = null
208 buildProperties = null
210 // the following values might be overridden by the CHANNEL switch
211 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
212 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
213 getdownArchiveAppBase = getdown_archive_base
214 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}")
215 getdownAppDistDir = getdown_app_dir_alt
216 getdownImagesDir = string("${jalviewDir}/${getdown_images_dir}")
217 getdownSetAppBaseProperty = false // whether to pass the appbase and appdistdir to the application
218 reportRsyncCommand = false
219 jvlChannelName = CHANNEL.toLowerCase()
220 install4jSuffix = CHANNEL.substring(0, 1).toUpperCase() + CHANNEL.substring(1).toLowerCase(); // BUILD -> Build
221 install4jDMGDSStore = "${install4j_images_dir}/${install4j_dmg_ds_store}"
222 install4jDMGBackgroundImage = "${install4j_images_dir}/${install4j_dmg_background}"
223 install4jInstallerName = "${jalview_name} Non-Release Installer"
224 install4jExecutableName = install4j_executable_name
225 install4jExtraScheme = "jalviewx"
226 install4jMacIconsFile = string("${install4j_images_dir}/${install4j_mac_icons_file}")
227 install4jWindowsIconsFile = string("${install4j_images_dir}/${install4j_windows_icons_file}")
228 install4jPngIconFile = string("${install4j_images_dir}/${install4j_png_icon_file}")
229 install4jBackground = string("${install4j_images_dir}/${install4j_background}")
230 install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
231 install4jCheckSums = true
233 applicationName = "${jalview_name}"
237 // TODO: get bamboo build artifact URL for getdown artifacts
238 getdown_channel_base = bamboo_channelbase
239 getdownChannelName = string("${bamboo_planKey}/${JAVA_VERSION}")
240 getdownAppBase = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
241 jvlChannelName += "_${getdownChannelName}"
242 // automatically add the test group Not-bamboo for exclusion
243 if ("".equals(testng_excluded_groups)) {
244 testng_excluded_groups = "Not-bamboo"
246 install4jExtraScheme = "jalviewb"
249 case [ "RELEASE", "JALVIEWJS-RELEASE" ]:
250 getdownAppDistDir = getdown_app_dir_release
251 getdownSetAppBaseProperty = true
252 reportRsyncCommand = true
254 install4jInstallerName = "${jalview_name} Installer"
258 getdownChannelName = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
259 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
260 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
261 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
262 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
264 package_dir = string("${ARCHIVEDIR}/${package_dir}")
265 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
268 reportRsyncCommand = true
269 install4jExtraScheme = "jalviewa"
273 getdownChannelName = string("archive/${JALVIEW_VERSION}")
274 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
275 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
276 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
277 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
279 package_dir = string("${ARCHIVEDIR}/${package_dir}")
280 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
283 reportRsyncCommand = true
284 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
285 install4jSuffix = "Archive"
286 install4jExtraScheme = "jalviewa"
290 reportRsyncCommand = true
291 getdownSetAppBaseProperty = true
292 // DEVELOP-RELEASE is usually associated with a Jalview release series so set the version
293 JALVIEW_VERSION=JALVIEW_VERSION+"-d${buildDate}"
295 install4jSuffix = "Develop"
296 install4jExtraScheme = "jalviewd"
297 install4jInstallerName = "${jalview_name} Develop Installer"
301 reportRsyncCommand = true
302 getdownSetAppBaseProperty = true
303 // Don't ignore transpile errors for release build
304 if (jalviewjs_ignore_transpile_errors.equals("true")) {
305 jalviewjs_ignore_transpile_errors = "false"
306 println("Setting jalviewjs_ignore_transpile_errors to 'false'")
308 JALVIEW_VERSION = JALVIEW_VERSION+"-test"
309 install4jSuffix = "Test"
310 install4jExtraScheme = "jalviewt"
311 install4jInstallerName = "${jalview_name} Test Installer"
314 case ~/^SCRATCH(|-[-\w]*)$/:
315 getdownChannelName = CHANNEL
316 JALVIEW_VERSION = JALVIEW_VERSION+"-"+CHANNEL
318 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
319 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
320 reportRsyncCommand = true
321 install4jSuffix = "Scratch"
325 if (!file("${LOCALDIR}").exists()) {
326 throw new GradleException("Must provide a LOCALDIR value to produce a local distribution")
328 getdownAppBase = file(file("${LOCALDIR}").getAbsolutePath()).toURI().toString()
329 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
331 JALVIEW_VERSION = "TEST"
332 install4jSuffix = "Test-Local"
333 install4jExtraScheme = "jalviewt"
334 install4jInstallerName = "${jalview_name} Test Installer"
337 case [ "LOCAL", "JALVIEWJS" ]:
338 JALVIEW_VERSION = "TEST"
339 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
340 getdownArchiveAppBase = file("${jalviewDir}/${getdown_archive_dir}").toURI().toString()
341 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
342 install4jExtraScheme = "jalviewl"
343 install4jCheckSums = false
346 default: // something wrong specified
347 throw new GradleException("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
351 JALVIEW_VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
352 hugoDataJsonFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_data_installers_dir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
353 hugoArchiveMdFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_version_archive_dir}/Version-${JALVIEW_VERSION_UNDERSCORES}/_index.md")
354 // override getdownAppBase if requested
355 if (findProperty("getdown_appbase_override") != null) {
356 // revert to LOCAL if empty string
357 if (string(getdown_appbase_override) == "") {
358 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
359 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
360 } else if (string(getdown_appbase_override).startsWith("file://")) {
361 getdownAppBase = string(getdown_appbase_override)
362 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
364 getdownAppBase = string(getdown_appbase_override)
366 println("Overriding getdown appbase with '${getdownAppBase}'")
368 // sanitise file name for jalview launcher file for this channel
369 jvlChannelName = jvlChannelName.replaceAll("[^\\w\\-]+", "_")
370 // install4j application and folder names
371 if (install4jSuffix == "") {
372 install4jBundleId = "${install4j_bundle_id}"
373 install4jWinApplicationId = install4j_release_win_application_id
375 applicationName = "${jalview_name} ${install4jSuffix}"
376 install4jBundleId = "${install4j_bundle_id}-" + install4jSuffix.toLowerCase()
377 // add int hash of install4jSuffix to the last part of the application_id
378 def id = install4j_release_win_application_id
379 def idsplitreverse = id.split("-").reverse()
380 idsplitreverse[0] = idsplitreverse[0].toInteger() + install4jSuffix.hashCode()
381 install4jWinApplicationId = idsplitreverse.reverse().join("-")
383 // sanitise folder and id names
384 // install4jApplicationFolder = e.g. "Jalview Build"
385 install4jApplicationFolder = applicationName
386 .replaceAll("[\"'~:/\\\\\\s]", "_") // replace all awkward filename chars " ' ~ : / \
387 .replaceAll("_+", "_") // collapse __
388 install4jInternalId = applicationName
390 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
391 .replaceAll("_+", "") // collapse __
392 //.replaceAll("_*-_*", "-") // collapse _-_
393 install4jUnixApplicationFolder = applicationName
395 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
396 .replaceAll("_+", "_") // collapse __
397 .replaceAll("_*-_*", "-") // collapse _-_
400 getdownWrapperLink = install4jUnixApplicationFolder // e.g. "jalview_local"
401 getdownAppDir = string("${getdownAppBaseDir}/${getdownAppDistDir}")
402 //getdownJ11libDir = "${getdownAppBaseDir}/${getdown_j11lib_dir}"
403 getdownResourceDir = string("${getdownAppBaseDir}/${getdown_resource_dir}")
404 getdownInstallDir = string("${getdownAppBaseDir}/${getdown_install_dir}")
405 getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
406 getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
407 /* compile without modules -- using classpath libraries
408 modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
409 modules_runtimeClasspath = modules_compileClasspath
415 apply plugin: "com.palantir.git-version"
416 def details = versionDetails()
417 gitHash = details.gitHash
418 gitBranch = details.branchName
419 } catch(org.gradle.api.internal.plugins.PluginApplicationException e) {
420 println("Not in a git repository. Using git values from RELEASE properties file.")
421 gitHash = releaseProps.getProperty("git.hash")
422 gitBranch = releaseProps.getProperty("git.branch")
423 } catch(java.lang.RuntimeException e1) {
424 throw new GradleException("Error with git-version plugin. Directory '.git' exists but versionDetails() cannot be found.")
427 println("Using a ${CHANNEL} profile.")
429 additional_compiler_args = []
430 // configure classpath/args for j8/j11 compilation
431 if (JAVA_VERSION.equals("1.8")) {
432 JAVA_INTEGER_VERSION = string("8")
435 libDistDir = j8libDir
436 compile_source_compatibility = 1.8
437 compile_target_compatibility = 1.8
438 // these are getdown.txt properties defined dependent on the JAVA_VERSION
439 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
440 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
441 // this property is assigned below and expanded to multiple lines in the getdown task
442 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
443 // this property is for the Java library used in eclipse
444 eclipseJavaRuntimeName = string("JavaSE-1.8")
445 } else if (JAVA_VERSION.equals("11")) {
446 JAVA_INTEGER_VERSION = string("11")
448 libDistDir = j11libDir
449 compile_source_compatibility = 11
450 compile_target_compatibility = 11
451 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
452 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
453 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
454 eclipseJavaRuntimeName = string("JavaSE-11")
455 /* compile without modules -- using classpath libraries
456 additional_compiler_args += [
457 '--module-path', modules_compileClasspath.asPath,
458 '--add-modules', j11modules
461 } else if (JAVA_VERSION.equals("17")) {
462 JAVA_INTEGER_VERSION = string("17")
464 libDistDir = j17libDir
465 compile_source_compatibility = 17
466 compile_target_compatibility = 17
467 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
468 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
469 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
470 eclipseJavaRuntimeName = string("JavaSE-17")
471 /* compile without modules -- using classpath libraries
472 additional_compiler_args += [
473 '--module-path', modules_compileClasspath.asPath,
474 '--add-modules', j11modules
478 throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
483 JAVA_MIN_VERSION = JAVA_VERSION
484 JAVA_MAX_VERSION = JAVA_VERSION
485 def jreInstallsDir = string(jre_installs_dir)
486 if (jreInstallsDir.startsWith("~/")) {
487 jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
489 macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
490 windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
491 linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
492 macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_mac_x64.tar.gz")
493 windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_windows_x64.tar.gz")
494 linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_linux_x64.tar.gz")
495 install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
496 install4jConfFileName = string("jalview-install4j-conf.install4j")
497 install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
498 install4jHomeDir = install4j_home_dir
499 if (install4jHomeDir.startsWith("~/")) {
500 install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
503 resourceBuildDir = string("${buildDir}/resources")
504 resourcesBuildDir = string("${resourceBuildDir}/resources_build")
505 helpBuildDir = string("${resourceBuildDir}/help_build")
506 docBuildDir = string("${resourceBuildDir}/doc_build")
508 if (buildProperties == null) {
509 buildProperties = string("${resourcesBuildDir}/${build_properties_file}")
511 buildingHTML = string("${jalviewDir}/${doc_dir}/building.html")
512 helpParentDir = string("${jalviewDir}/${help_parent_dir}")
513 helpSourceDir = string("${helpParentDir}/${help_dir}")
514 helpFile = string("${helpBuildDir}/${help_dir}/help.jhm")
517 relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
518 jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
519 jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
521 jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
523 jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
525 jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
526 jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
527 jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
528 jalviewjsJalviewCoreHtmlFile = string("")
529 jalviewjsJalviewCoreName = string(jalviewjs_core_name)
530 jalviewjsCoreClasslists = []
531 jalviewjsJalviewTemplateName = string(jalviewjs_name)
532 jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
533 jalviewjsJ2sAltSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_alt_settings}")
534 jalviewjsJ2sProps = null
535 jalviewjsJ2sPlugin = jalviewjs_j2s_plugin
537 eclipseWorkspace = null
538 eclipseBinary = string("")
539 eclipseVersion = string("")
549 outputDir = file(classesDir)
553 srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ]
556 compileClasspath = files(sourceSets.main.java.outputDir)
557 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
559 runtimeClasspath = compileClasspath
560 runtimeClasspath += files(sourceSets.main.resources.srcDirs)
565 srcDirs cloverInstrDir
566 outputDir = cloverClassesDir
570 srcDirs = sourceSets.main.resources.srcDirs
573 compileClasspath = files( sourceSets.clover.java.outputDir )
574 //compileClasspath += files( testClassesDir )
575 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
576 compileClasspath += fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
577 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
579 runtimeClasspath = compileClasspath
584 srcDirs testSourceDir
585 outputDir = file(testClassesDir)
589 srcDirs = useClover ? sourceSets.clover.resources.srcDirs : sourceSets.main.resources.srcDirs
592 compileClasspath = files( sourceSets.test.java.outputDir )
593 compileClasspath += useClover ? sourceSets.clover.compileClasspath : sourceSets.main.compileClasspath
594 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
596 runtimeClasspath = compileClasspath
597 runtimeClasspath += files(sourceSets.test.resources.srcDirs)
603 // eclipse project and settings files creation, also used by buildship
606 name = eclipse_project_name
608 natures 'org.eclipse.jdt.core.javanature',
609 'org.eclipse.jdt.groovy.core.groovyNature',
610 'org.eclipse.buildship.core.gradleprojectnature'
612 buildCommand 'org.eclipse.jdt.core.javabuilder'
613 buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
617 //defaultOutputDir = sourceSets.main.java.outputDir
618 configurations.each{ c->
619 if (c.isCanBeResolved()) {
620 minusConfigurations += [c]
624 plusConfigurations = [ ]
628 def removeTheseToo = []
629 HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
630 cp.entries.each { entry ->
631 // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
632 // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
633 // we add the resources and help/help dirs in as libs afterwards (see below)
634 if (entry.kind == 'src') {
635 if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
636 removeTheseToo += entry
638 alreadyAddedSrcPath.putAt(entry.path, true)
643 cp.entries.removeAll(removeTheseToo)
645 //cp.entries += new Output("${eclipse_bin_dir}/main")
646 if (file(helpParentDir).isDirectory()) {
647 cp.entries += new Library(fileReference(helpParentDir))
649 if (file(resourceDir).isDirectory()) {
650 cp.entries += new Library(fileReference(resourceDir))
653 HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
655 sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
656 //don't want to add outputDir as eclipse is using its own output dir in bin/main
657 if (it.isDirectory() || ! it.exists()) {
658 // don't add dirs to classpath, especially if they don't exist
659 return false // groovy "continue" in .any closure
661 def itPath = it.toString()
662 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
663 // make relative path
664 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
666 if (alreadyAddedLibPath.get(itPath)) {
667 //println("Not adding duplicate entry "+itPath)
669 //println("Adding entry "+itPath)
670 cp.entries += new Library(fileReference(itPath))
671 alreadyAddedLibPath.put(itPath, true)
675 sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
676 //no longer want to add outputDir as eclipse is using its own output dir in bin/main
677 if (it.isDirectory() || ! it.exists()) {
678 // don't add dirs to classpath
679 return false // groovy "continue" in .any closure
682 def itPath = it.toString()
683 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
684 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
686 if (alreadyAddedLibPath.get(itPath)) {
689 def lib = new Library(fileReference(itPath))
690 lib.entryAttributes["test"] = "true"
692 alreadyAddedLibPath.put(itPath, true)
700 containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
705 // for the IDE, use java 11 compatibility
706 sourceCompatibility = compile_source_compatibility
707 targetCompatibility = compile_target_compatibility
708 javaRuntimeName = eclipseJavaRuntimeName
710 // add in jalview project specific properties/preferences into eclipse core preferences
712 withProperties { props ->
713 def jalview_prefs = new Properties()
714 def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
715 jalview_prefs.load(ins)
717 jalview_prefs.forEach { t, v ->
718 if (props.getAt(t) == null) {
722 // codestyle file -- overrides previous formatter prefs
723 def csFile = file("${jalviewDirAbsolutePath}/${eclipse_codestyle_file}")
724 if (csFile.exists()) {
725 XmlParser parser = new XmlParser()
726 def profiles = parser.parse(csFile)
727 def profile = profiles.'profile'.find { p -> (p.'@kind' == "CodeFormatterProfile" && p.'@name' == "Jalview") }
728 if (profile != null) {
729 profile.'setting'.each { s ->
731 def value = s.'@value'
732 if (id != null && value != null) {
733 props.putAt(id, value)
744 // Don't want these to be activated if in headless build
745 synchronizationTasks "eclipseSynchronizationTask"
746 //autoBuildTasks "eclipseAutoBuildTask"
752 /* hack to change eclipse prefs in .settings files other than org.eclipse.jdt.core.prefs */
753 // Class to allow updating arbitrary properties files
754 class PropertiesFile extends PropertiesPersistableConfigurationObject {
755 public PropertiesFile(PropertiesTransformer t) { super(t); }
756 @Override protected void load(Properties properties) { }
757 @Override protected void store(Properties properties) { }
758 @Override protected String getDefaultResourceName() { return ""; }
759 // This is necessary, because PropertiesPersistableConfigurationObject fails
760 // if no default properties file exists.
761 @Override public void loadDefaults() { load(new StringBufferInputStream("")); }
764 // Task to update arbitrary properties files (set outputFile)
765 class PropertiesFileTask extends PropertiesGeneratorTask<PropertiesFile> {
766 private final PropertiesFileContentMerger file;
767 public PropertiesFileTask() { file = new PropertiesFileContentMerger(getTransformer()); }
768 protected PropertiesFile create() { return new PropertiesFile(getTransformer()); }
769 protected void configure(PropertiesFile props) {
770 file.getBeforeMerged().execute(props); file.getWhenMerged().execute(props);
772 public void file(Closure closure) { ConfigureUtil.configure(closure, file); }
775 task eclipseUIPreferences(type: PropertiesFileTask) {
776 description = "Generate Eclipse additional settings"
777 def filename = "org.eclipse.jdt.ui.prefs"
778 outputFile = "$projectDir/.settings/${filename}" as File
781 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
786 task eclipseGroovyCorePreferences(type: PropertiesFileTask) {
787 description = "Generate Eclipse additional settings"
788 def filename = "org.eclipse.jdt.groovy.core.prefs"
789 outputFile = "$projectDir/.settings/${filename}" as File
792 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
797 task eclipseAllPreferences {
799 dependsOn eclipseUIPreferences
800 dependsOn eclipseGroovyCorePreferences
803 eclipseUIPreferences.mustRunAfter eclipseJdt
804 eclipseGroovyCorePreferences.mustRunAfter eclipseJdt
806 /* end of eclipse preferences hack */
814 delete cloverBuildDir
815 delete cloverReportDir
820 task cloverInstrJava(type: JavaExec) {
821 group = "Verification"
822 description = "Create clover instrumented source java files"
824 dependsOn cleanClover
826 inputs.files(sourceSets.main.allJava)
827 outputs.dir(cloverInstrDir)
829 //classpath = fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
830 classpath = sourceSets.clover.compileClasspath
831 main = "com.atlassian.clover.CloverInstr"
839 cloverInstrDir.getPath(),
841 def srcFiles = sourceSets.main.allJava.files
844 { file -> file.absolutePath }
847 args argsList.toArray()
850 delete cloverInstrDir
851 println("Clover: About to instrument "+srcFiles.size() +" files")
856 task cloverInstrTests(type: JavaExec) {
857 group = "Verification"
858 description = "Create clover instrumented source test files"
860 dependsOn cleanClover
862 inputs.files(testDir)
863 outputs.dir(cloverTestInstrDir)
865 classpath = sourceSets.clover.compileClasspath
866 main = "com.atlassian.clover.CloverInstr"
876 cloverTestInstrDir.getPath(),
878 args argsList.toArray()
881 delete cloverTestInstrDir
882 println("Clover: About to instrument test files")
888 group = "Verification"
889 description = "Create clover instrumented all source files"
891 dependsOn cloverInstrJava
892 dependsOn cloverInstrTests
896 cloverClasses.dependsOn cloverInstr
899 task cloverConsoleReport(type: JavaExec) {
900 group = "Verification"
901 description = "Creates clover console report"
904 file(cloverDb).exists()
907 inputs.dir cloverClassesDir
909 classpath = sourceSets.clover.runtimeClasspath
910 main = "com.atlassian.clover.reporters.console.ConsoleReporter"
912 if (cloverreport_mem.length() > 0) {
913 maxHeapSize = cloverreport_mem
915 if (cloverreport_jvmargs.length() > 0) {
916 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
926 args argsList.toArray()
930 task cloverHtmlReport(type: JavaExec) {
931 group = "Verification"
932 description = "Creates clover HTML report"
935 file(cloverDb).exists()
938 def cloverHtmlDir = cloverReportDir
939 inputs.dir cloverClassesDir
940 outputs.dir cloverHtmlDir
942 classpath = sourceSets.clover.runtimeClasspath
943 main = "com.atlassian.clover.reporters.html.HtmlReporter"
945 if (cloverreport_mem.length() > 0) {
946 maxHeapSize = cloverreport_mem
948 if (cloverreport_jvmargs.length() > 0) {
949 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
960 if (cloverreport_html_options.length() > 0) {
961 argsList += cloverreport_html_options.split(" ")
964 args argsList.toArray()
968 task cloverXmlReport(type: JavaExec) {
969 group = "Verification"
970 description = "Creates clover XML report"
973 file(cloverDb).exists()
976 def cloverXmlFile = "${cloverReportDir}/clover.xml"
977 inputs.dir cloverClassesDir
978 outputs.file cloverXmlFile
980 classpath = sourceSets.clover.runtimeClasspath
981 main = "com.atlassian.clover.reporters.xml.XMLReporter"
983 if (cloverreport_mem.length() > 0) {
984 maxHeapSize = cloverreport_mem
986 if (cloverreport_jvmargs.length() > 0) {
987 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
998 if (cloverreport_xml_options.length() > 0) {
999 argsList += cloverreport_xml_options.split(" ")
1002 args argsList.toArray()
1007 group = "Verification"
1008 description = "Creates clover reports"
1010 dependsOn cloverXmlReport
1011 dependsOn cloverHtmlReport
1018 sourceCompatibility = compile_source_compatibility
1019 targetCompatibility = compile_target_compatibility
1020 options.compilerArgs += additional_compiler_args
1021 print ("Setting target compatibility to "+targetCompatibility+"\n")
1023 //classpath += configurations.cloverRuntime
1029 // JBP->BS should the print statement in doFirst refer to compile_target_compatibility ?
1030 sourceCompatibility = compile_source_compatibility
1031 targetCompatibility = compile_target_compatibility
1032 options.compilerArgs = additional_compiler_args
1033 options.encoding = "UTF-8"
1035 print ("Setting target compatibility to "+compile_target_compatibility+"\n")
1042 sourceCompatibility = compile_source_compatibility
1043 targetCompatibility = compile_target_compatibility
1044 options.compilerArgs = additional_compiler_args
1046 print ("Setting target compatibility to "+targetCompatibility+"\n")
1053 delete sourceSets.main.java.outputDir
1059 dependsOn cleanClover
1061 delete sourceSets.test.java.outputDir
1066 // format is a string like date.format("dd MMMM yyyy")
1067 def getDate(format) {
1068 return date.format(format)
1072 def convertMdToHtml (FileTree mdFiles, File cssFile) {
1073 MutableDataSet options = new MutableDataSet()
1075 def extensions = new ArrayList<>()
1076 extensions.add(AnchorLinkExtension.create())
1077 extensions.add(AutolinkExtension.create())
1078 extensions.add(StrikethroughExtension.create())
1079 extensions.add(TaskListExtension.create())
1080 extensions.add(TablesExtension.create())
1081 extensions.add(TocExtension.create())
1083 options.set(Parser.EXTENSIONS, extensions)
1085 // set GFM table parsing options
1086 options.set(TablesExtension.WITH_CAPTION, false)
1087 options.set(TablesExtension.COLUMN_SPANS, false)
1088 options.set(TablesExtension.MIN_HEADER_ROWS, 1)
1089 options.set(TablesExtension.MAX_HEADER_ROWS, 1)
1090 options.set(TablesExtension.APPEND_MISSING_COLUMNS, true)
1091 options.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
1092 options.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
1094 options.set(AnchorLinkExtension.ANCHORLINKS_SET_ID, false)
1095 options.set(AnchorLinkExtension.ANCHORLINKS_ANCHOR_CLASS, "anchor")
1096 options.set(AnchorLinkExtension.ANCHORLINKS_SET_NAME, true)
1097 options.set(AnchorLinkExtension.ANCHORLINKS_TEXT_PREFIX, "<span class=\"octicon octicon-link\"></span>")
1099 Parser parser = Parser.builder(options).build()
1100 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1102 mdFiles.each { mdFile ->
1103 // add table of contents
1104 def mdText = "[TOC]\n"+mdFile.text
1106 // grab the first top-level title
1108 def titleRegex = /(?m)^#(\s+|([^#]))(.*)/
1109 def matcher = mdText =~ titleRegex
1110 if (matcher.size() > 0) {
1111 // matcher[0][2] is the first character of the title if there wasn't any whitespace after the #
1112 title = (matcher[0][2] != null ? matcher[0][2] : "")+matcher[0][3]
1114 // or use the filename if none found
1115 if (title == null) {
1116 title = mdFile.getName()
1119 Node document = parser.parse(mdText)
1120 String htmlBody = renderer.render(document)
1121 def htmlText = '''<html>
1122 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1123 <html xmlns="http://www.w3.org/1999/xhtml">
1125 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1126 <meta http-equiv="Content-Style-Type" content="text/css" />
1127 <meta name="generator" content="flexmark" />
1129 htmlText += ((title != null) ? " <title>${title}</title>" : '' )
1131 <style type="text/css">code{white-space: pre;}</style>
1133 htmlText += ((cssFile != null) ? cssFile.text : '')
1134 htmlText += '''</head>
1137 htmlText += htmlBody
1143 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1144 def htmlFile = file(htmlFilePath)
1145 println("Creating ${htmlFilePath}")
1146 htmlFile.text = htmlText
1151 task copyDocs(type: Copy) {
1152 def inputDir = "${jalviewDir}/${doc_dir}"
1153 def outputDir = "${docBuildDir}/${doc_dir}"
1157 include('**/*.html')
1159 filter(ReplaceTokens,
1163 'Version-Rel': JALVIEW_VERSION,
1164 'Year-Rel': getDate("yyyy")
1171 exclude('**/*.html')
1176 inputs.dir(inputDir)
1177 outputs.dir(outputDir)
1181 task convertMdFiles {
1183 def mdFiles = fileTree(dir: docBuildDir, include: "**/*.md")
1184 def cssFile = file("${jalviewDir}/${flexmark_css}")
1187 convertMdToHtml(mdFiles, cssFile)
1190 inputs.files(mdFiles)
1191 inputs.file(cssFile)
1194 mdFiles.each { mdFile ->
1195 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1196 htmlFiles.add(file(htmlFilePath))
1198 outputs.files(htmlFiles)
1202 task copyHelp(type: Copy) {
1203 def inputDir = helpSourceDir
1204 def outputDir = "${helpBuildDir}/${help_dir}"
1208 include('**/*.html')
1212 filter(ReplaceTokens,
1216 'Version-Rel': JALVIEW_VERSION,
1217 'Year-Rel': getDate("yyyy")
1224 exclude('**/*.html')
1231 inputs.dir(inputDir)
1232 outputs.files(helpFile)
1233 outputs.dir(outputDir)
1237 task copyResources(type: Copy) {
1239 description = "Copy (and make text substitutions in) the resources dir to the build area"
1241 def inputDir = resourceDir
1242 def outputDir = resourcesBuildDir
1246 include('**/*.html')
1248 filter(ReplaceTokens,
1252 'Version-Rel': JALVIEW_VERSION,
1253 'Year-Rel': getDate("yyyy")
1260 exclude('**/*.html')
1265 inputs.dir(inputDir)
1266 outputs.dir(outputDir)
1269 task copyChannelResources(type: Copy) {
1270 dependsOn copyResources
1272 description = "Copy the channel resources dir to the build resources area"
1274 def inputDir = "${channelDir}/${resource_dir}"
1275 def outputDir = resourcesBuildDir
1279 inputs.dir(inputDir)
1280 outputs.dir(outputDir)
1283 task createBuildProperties(type: WriteProperties) {
1284 dependsOn copyResources
1286 description = "Create the ${buildProperties} file"
1288 inputs.dir(sourceDir)
1289 inputs.dir(resourcesBuildDir)
1290 outputFile (buildProperties)
1291 // taking time specific comment out to allow better incremental builds
1292 comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
1293 //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
1294 property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
1295 property "VERSION", JALVIEW_VERSION
1296 property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
1297 if (getdownSetAppBaseProperty) {
1298 property "GETDOWNAPPBASE", getdownAppBase
1299 property "GETDOWNAPPDISTDIR", getdownAppDistDir
1301 outputs.file(outputFile)
1305 task buildIndices(type: JavaExec) {
1307 classpath = sourceSets.main.compileClasspath
1308 main = "com.sun.java.help.search.Indexer"
1309 workingDir = "${helpBuildDir}/${help_dir}"
1312 inputs.dir("${workingDir}/${argDir}")
1314 outputs.dir("${classesDir}/doc")
1315 outputs.dir("${classesDir}/help")
1316 outputs.file("${workingDir}/JavaHelpSearch/DOCS")
1317 outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
1318 outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
1319 outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
1320 outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
1321 outputs.file("${workingDir}/JavaHelpSearch/TMAP")
1324 task buildResources {
1325 dependsOn copyResources
1326 dependsOn copyChannelResources
1327 dependsOn createBuildProperties
1331 dependsOn buildResources
1334 dependsOn convertMdFiles
1335 dependsOn buildIndices
1339 compileJava.dependsOn prepare
1340 run.dependsOn compileJava
1341 //run.dependsOn prepare
1344 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1349 dependsOn cloverClasses
1351 dependsOn compileJava //?
1355 includeGroups testng_groups
1356 excludeGroups testng_excluded_groups
1358 useDefaultListeners=true
1361 maxHeapSize = "1024m"
1363 workingDir = jalviewDir
1364 def testLaf = project.findProperty("test_laf")
1365 if (testLaf != null) {
1366 println("Setting Test LaF to '${testLaf}'")
1367 systemProperty "laf", testLaf
1369 def testHiDPIScale = project.findProperty("test_HiDPIScale")
1370 if (testHiDPIScale != null) {
1371 println("Setting Test HiDPI Scale to '${testHiDPIScale}'")
1372 systemProperty "sun.java2d.uiScale", testHiDPIScale
1374 sourceCompatibility = compile_source_compatibility
1375 targetCompatibility = compile_target_compatibility
1376 jvmArgs += additional_compiler_args
1380 println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1386 task compileLinkCheck(type: JavaCompile) {
1388 classpath = files("${jalviewDir}/${utils_dir}")
1389 destinationDir = file("${jalviewDir}/${utils_dir}")
1390 source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1392 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1393 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1394 outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1395 outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1399 task linkCheck(type: JavaExec) {
1401 dependsOn compileLinkCheck
1403 def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1404 classpath = files("${jalviewDir}/${utils_dir}")
1405 main = "HelpLinksChecker"
1406 workingDir = jalviewDir
1407 args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1409 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1410 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1413 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1417 inputs.dir(helpBuildDir)
1418 outputs.file(helpLinksCheckerOutFile)
1422 // import the pubhtmlhelp target
1423 ant.properties.basedir = "${jalviewDir}"
1424 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1425 ant.importBuild "${utils_dir}/publishHelp.xml"
1428 task cleanPackageDir(type: Delete) {
1430 delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1440 attributes "Main-Class": main_class,
1441 "Permissions": "all-permissions",
1442 "Application-Name": applicationName,
1443 "Codebase": application_codebase,
1444 "Implementation-Version": JALVIEW_VERSION
1447 def outputDir = "${jalviewDir}/${package_dir}"
1448 destinationDirectory = file(outputDir)
1449 archiveFileName = rootProject.name+".jar"
1450 duplicatesStrategy "EXCLUDE"
1457 exclude "**/*.jar.*"
1459 inputs.dir(sourceSets.main.java.outputDir)
1460 sourceSets.main.resources.srcDirs.each{ dir ->
1463 outputs.file("${outputDir}/${archiveFileName}")
1467 task copyJars(type: Copy) {
1468 from fileTree(dir: classesDir, include: "**/*.jar").files
1469 into "${jalviewDir}/${package_dir}"
1473 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1474 task syncJars(type: Sync) {
1476 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1477 into "${jalviewDir}/${package_dir}"
1479 include jar.archiveFileName.getOrNull()
1486 description = "Put all required libraries in dist"
1487 // order of "cleanPackageDir", "copyJars", "jar" important!
1488 jar.mustRunAfter cleanPackageDir
1489 syncJars.mustRunAfter cleanPackageDir
1490 dependsOn cleanPackageDir
1493 outputs.dir("${jalviewDir}/${package_dir}")
1498 dependsOn cleanPackageDir
1505 group = "distribution"
1506 description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1510 from ("${jalviewDir}/${libDistDir}") {
1514 attributes "Implementation-Version": JALVIEW_VERSION,
1515 "Application-Name": applicationName
1518 duplicatesStrategy "INCLUDE"
1520 mainClassName = shadow_jar_main_class
1522 classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1527 task getdownWebsite() {
1528 group = "distribution"
1529 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1534 def getdownWebsiteResourceFilenames = []
1535 def getdownResourceDir = getdownResourceDir
1536 def getdownResourceFilenames = []
1539 // clean the getdown website and files dir before creating getdown folders
1540 delete getdownAppBaseDir
1541 delete getdownFilesDir
1544 from buildProperties
1545 rename(file(buildProperties).getName(), getdown_build_properties)
1548 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1551 from channelPropsFile
1552 into getdownAppBaseDir
1554 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
1556 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
1557 def props = project.properties.sort { it.key }
1558 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
1559 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
1561 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
1562 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
1564 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
1565 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
1567 if (getdownImagesDir != null && file(getdownImagesDir).exists()) {
1568 props.put("getdown_txt_ui.background_image", "${getdownImagesDir}/${getdown_background_image}")
1569 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesDir}/${getdown_instant_background_image}")
1570 props.put("getdown_txt_ui.error_background", "${getdownImagesDir}/${getdown_error_background}")
1571 props.put("getdown_txt_ui.progress_image", "${getdownImagesDir}/${getdown_progress_image}")
1572 props.put("getdown_txt_ui.icon", "${getdownImagesDir}/${getdown_icon}")
1573 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesDir}/${getdown_mac_dock_icon}")
1576 props.put("getdown_txt_title", jalview_name)
1577 props.put("getdown_txt_ui.name", applicationName)
1579 // start with appbase
1580 getdownTextLines += "appbase = ${getdownAppBase}"
1581 props.each{ prop, val ->
1582 if (prop.startsWith("getdown_txt_") && val != null) {
1583 if (prop.startsWith("getdown_txt_multi_")) {
1584 def key = prop.substring(18)
1585 val.split(",").each{ v ->
1586 def line = "${key} = ${v}"
1587 getdownTextLines += line
1590 // file values rationalised
1591 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
1593 if (val.indexOf('/') == 0) {
1596 } else if (val.indexOf('/') > 0) {
1597 // relative path (relative to jalviewDir)
1598 r = file( "${jalviewDir}/${val}" )
1601 val = "${getdown_resource_dir}/" + r.getName()
1602 getdownWebsiteResourceFilenames += val
1603 getdownResourceFilenames += r.getPath()
1606 if (! prop.startsWith("getdown_txt_resource")) {
1607 def line = prop.substring(12) + " = ${val}"
1608 getdownTextLines += line
1614 getdownWebsiteResourceFilenames.each{ filename ->
1615 getdownTextLines += "resource = ${filename}"
1617 getdownResourceFilenames.each{ filename ->
1620 into getdownResourceDir
1624 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
1625 getdownWrapperScripts.each{ script ->
1626 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
1630 into "${getdownAppBaseDir}/${getdown_wrapper_script_dir}"
1632 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
1637 fileTree(file(package_dir)).each{ f ->
1638 if (f.isDirectory()) {
1639 def files = fileTree(dir: f, include: ["*"]).getFiles()
1641 } else if (f.exists()) {
1645 def jalviewJar = jar.archiveFileName.getOrNull()
1646 // put jalview.jar first for CLASSPATH and .properties files reasons
1647 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
1648 def name = f.getName()
1649 def line = "code = ${getdownAppDistDir}/${name}"
1650 getdownTextLines += line
1657 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
1659 if (JAVA_VERSION.equals("11")) {
1660 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
1661 j11libFiles.sort().each{f ->
1662 def name = f.getName()
1663 def line = "code = ${getdown_j11lib_dir}/${name}"
1664 getdownTextLines += line
1667 into getdownJ11libDir
1673 // 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.
1674 //getdownTextLines += "class = " + file(getdownLauncher).getName()
1675 getdownTextLines += "resource = ${getdown_launcher_new}"
1676 getdownTextLines += "class = ${main_class}"
1677 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
1678 if (getdownSetAppBaseProperty) {
1679 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
1680 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
1683 def getdownTxt = file("${getdownAppBaseDir}/getdown.txt")
1684 getdownTxt.write(getdownTextLines.join("\n"))
1686 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
1687 def launchJvl = file("${getdownAppBaseDir}/${getdownLaunchJvl}")
1688 launchJvl.write("appbase=${getdownAppBase}")
1690 // files going into the getdown website dir: getdown-launcher.jar
1692 from getdownLauncher
1693 rename(file(getdownLauncher).getName(), getdown_launcher_new)
1694 into getdownAppBaseDir
1697 // files going into the getdown website dir: getdown-launcher(-local).jar
1699 from getdownLauncher
1700 if (file(getdownLauncher).getName() != getdown_launcher) {
1701 rename(file(getdownLauncher).getName(), getdown_launcher)
1703 into getdownAppBaseDir
1706 // files going into the getdown website dir: ./install dir and files
1707 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
1710 from getdownLauncher
1711 from "${getdownAppDir}/${getdown_build_properties}"
1712 if (file(getdownLauncher).getName() != getdown_launcher) {
1713 rename(file(getdownLauncher).getName(), getdown_launcher)
1715 into getdownInstallDir
1718 // and make a copy in the getdown files dir (these are not downloaded by getdown)
1720 from getdownInstallDir
1721 into getdownFilesInstallDir
1725 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
1729 from getdownLauncher
1730 from "${getdownAppBaseDir}/${getdown_build_properties}"
1731 from "${getdownAppBaseDir}/${channel_props}"
1732 if (file(getdownLauncher).getName() != getdown_launcher) {
1733 rename(file(getdownLauncher).getName(), getdown_launcher)
1735 into getdownFilesDir
1738 // and ./resource (not all downloaded by getdown)
1740 from getdownResourceDir
1741 into "${getdownFilesDir}/${getdown_resource_dir}"
1746 inputs.dir("${jalviewDir}/${package_dir}")
1748 outputs.dir(getdownAppBaseDir)
1749 outputs.dir(getdownFilesDir)
1753 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
1754 task getdownDigestDir(type: JavaExec) {
1756 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
1758 def digestDirPropertyName = "DIGESTDIR"
1760 classpath = files(getdownLauncher)
1761 def digestDir = findProperty(digestDirPropertyName)
1762 if (digestDir == null) {
1763 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
1767 main = "com.threerings.getdown.tools.Digester"
1771 task getdownDigest(type: JavaExec) {
1772 group = "distribution"
1773 description = "Digest the getdown website folder"
1774 dependsOn getdownWebsite
1776 classpath = files(getdownLauncher)
1778 main = "com.threerings.getdown.tools.Digester"
1779 args getdownAppBaseDir
1780 inputs.dir(getdownAppBaseDir)
1781 outputs.file("${getdownAppBaseDir}/digest2.txt")
1786 group = "distribution"
1787 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
1788 dependsOn getdownDigest
1790 if (reportRsyncCommand) {
1791 def fromDir = getdownAppBaseDir + (getdownAppBaseDir.endsWith('/')?'':'/')
1792 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
1793 println "LIKELY RSYNC COMMAND:"
1794 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
1795 if (RUNRSYNC == "true") {
1797 commandLine "mkdir", "-p", toDir
1800 commandLine "rsync", "-avh", "--delete", fromDir, toDir
1808 task getdownArchiveBuild() {
1809 group = "distribution"
1810 description = "Put files in the archive dir to go on the website"
1812 dependsOn getdownWebsite
1814 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
1815 def vDir = "${getdownArchiveDir}/${v}"
1816 getdownFullArchiveDir = "${vDir}/getdown"
1817 getdownVersionLaunchJvl = "${vDir}/jalview-${v}.jvl"
1819 def vAltDir = "alt_${v}"
1820 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
1823 // cleanup old "old" dir
1824 delete getdownArchiveDir
1826 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
1827 getdownArchiveTxt.getParentFile().mkdirs()
1828 def getdownArchiveTextLines = []
1829 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
1833 from "${getdownAppBaseDir}/${getdownAppDistDir}"
1834 into "${getdownFullArchiveDir}/${vAltDir}"
1837 getdownTextLines.each { line ->
1838 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
1839 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
1840 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
1841 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
1842 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
1843 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
1844 // remove the existing resource = resource/ or bin/ lines
1845 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
1846 getdownArchiveTextLines += line
1850 // the resource dir -- add these files as resource lines in getdown.txt
1852 from "${archiveImagesDir}"
1853 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
1855 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
1859 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
1861 def vLaunchJvl = file(getdownVersionLaunchJvl)
1862 vLaunchJvl.getParentFile().mkdirs()
1863 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
1864 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
1865 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
1866 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
1867 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
1868 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
1870 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
1872 from getdownLauncher
1873 from "${getdownAppBaseDir}/${getdownLaunchJvl}"
1874 from "${getdownAppBaseDir}/${getdown_launcher_new}"
1875 from "${getdownAppBaseDir}/${channel_props}"
1876 if (file(getdownLauncher).getName() != getdown_launcher) {
1877 rename(file(getdownLauncher).getName(), getdown_launcher)
1879 into getdownFullArchiveDir
1885 task getdownArchiveDigest(type: JavaExec) {
1886 group = "distribution"
1887 description = "Digest the getdown archive folder"
1889 dependsOn getdownArchiveBuild
1892 classpath = files(getdownLauncher)
1893 args getdownFullArchiveDir
1895 main = "com.threerings.getdown.tools.Digester"
1896 inputs.dir(getdownFullArchiveDir)
1897 outputs.file("${getdownFullArchiveDir}/digest2.txt")
1900 task getdownArchive() {
1901 group = "distribution"
1902 description = "Build the website archive dir with getdown digest"
1904 dependsOn getdownArchiveBuild
1905 dependsOn getdownArchiveDigest
1908 tasks.withType(JavaCompile) {
1909 options.encoding = 'UTF-8'
1915 delete getdownAppBaseDir
1916 delete getdownFilesDir
1917 delete getdownArchiveDir
1923 if (file(install4jHomeDir).exists()) {
1925 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
1926 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
1927 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
1928 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
1930 installDir(file(install4jHomeDir))
1932 mediaTypes = Arrays.asList(install4j_media_types.split(","))
1936 task copyInstall4jTemplate {
1937 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
1938 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
1939 inputs.file(install4jTemplateFile)
1940 inputs.file(install4jFileAssociationsFile)
1941 inputs.property("CHANNEL", { CHANNEL })
1942 outputs.file(install4jConfFile)
1945 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
1947 // turn off code signing if no OSX_KEYPASS
1948 if (OSX_KEYPASS == "") {
1949 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
1950 codeSigning.'@macEnabled' = "false"
1952 install4jConfigXml.'**'.windows.each { windows ->
1953 windows.'@runPostProcessor' = "false"
1957 // disable install screen for OSX dmg (for 2.11.2.0)
1958 install4jConfigXml.'**'.macosArchive.each { macosArchive ->
1959 macosArchive.attributes().remove('executeSetupApp')
1960 macosArchive.attributes().remove('setupAppId')
1963 // turn off checksum creation for LOCAL channel
1964 def e = install4jConfigXml.application[0]
1965 e.'@createChecksums' = string(install4jCheckSums)
1967 // put file association actions where placeholder action is
1968 def install4jFileAssociationsText = install4jFileAssociationsFile.text
1969 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
1970 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
1971 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
1972 def parent = a.parent()
1974 fileAssociationActions.each { faa ->
1977 // don't need to continue in .any loop once replacements have been made
1982 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
1983 // NB we're deleting the /other/ one!
1984 // Also remove the examples subdir from non-release versions
1985 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
1986 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
1987 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
1988 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
1990 // remove the examples subdir from Full File Set
1991 def files = install4jConfigXml.files[0]
1992 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
1993 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
1994 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
1995 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
1996 dirEntry.parent().remove(dirEntry)
1998 install4jConfigXml.'**'.action.any { a ->
1999 if (a.'@customizedId' == customizedIdToDelete) {
2000 def parent = a.parent()
2006 // write install4j file
2007 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
2014 delete install4jConfFile
2018 task cleanInstallersDataFiles {
2019 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2020 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2021 def hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
2023 delete installersOutputTxt
2024 delete installersSha256
2025 delete hugoDataJsonFile
2029 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2030 group = "distribution"
2031 description = "Create the install4j installers"
2033 dependsOn copyInstall4jTemplate
2034 dependsOn cleanInstallersDataFiles
2036 projectFile = install4jConfFile
2038 // create an md5 for the input files to use as version for install4j conf file
2039 def digest = MessageDigest.getInstance("MD5")
2041 (file("${install4jDir}/${install4j_template}").text +
2042 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2043 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2044 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2045 if (filesMd5.length() >= 8) {
2046 filesMd5 = filesMd5.substring(0,8)
2048 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2051 'JALVIEW_NAME': jalview_name,
2052 'JALVIEW_APPLICATION_NAME': applicationName,
2053 'JALVIEW_DIR': "../..",
2054 'OSX_KEYSTORE': OSX_KEYSTORE,
2055 'OSX_APPLEID': OSX_APPLEID,
2056 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2057 'JSIGN_SH': JSIGN_SH,
2058 'JRE_DIR': getdown_app_dir_java,
2059 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2060 'JALVIEW_VERSION': JALVIEW_VERSION,
2061 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2062 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2063 'JAVA_VERSION': JAVA_VERSION,
2064 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2065 'VERSION': JALVIEW_VERSION,
2066 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2067 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2068 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2069 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2070 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2071 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2072 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2073 'BUNDLE_ID': install4jBundleId,
2074 'INTERNAL_ID': install4jInternalId,
2075 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2076 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2077 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
2078 'WRAPPER_LINK': getdownWrapperLink,
2079 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2080 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2081 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2082 'INSTALLER_NAME': install4jInstallerName,
2083 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2084 'GETDOWN_CHANNEL_DIR': getdownChannelDir,
2085 'GETDOWN_FILES_DIR': getdown_files_dir,
2086 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2087 'GETDOWN_DIST_DIR': getdownAppDistDir,
2088 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2089 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2090 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2091 'BUILD_DIR': install4jBuildDir,
2092 'APPLICATION_CATEGORIES': install4j_application_categories,
2093 'APPLICATION_FOLDER': install4jApplicationFolder,
2094 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2095 'EXECUTABLE_NAME': install4jExecutableName,
2096 'EXTRA_SCHEME': install4jExtraScheme,
2097 'MAC_ICONS_FILE': install4jMacIconsFile,
2098 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2099 'PNG_ICON_FILE': install4jPngIconFile,
2100 'BACKGROUND': install4jBackground,
2104 //println("INSTALL4J VARIABLES:")
2105 //variables.each{k,v->println("${k}=${v}")}
2107 destination = "${jalviewDir}/${install4jBuildDir}"
2108 buildSelected = true
2110 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2112 disableSigning = true
2113 disableNotarization = true
2117 macKeystorePassword = OSX_KEYPASS
2120 if (OSX_ALTOOLPASS) {
2121 appleIdPassword = OSX_ALTOOLPASS
2122 disableNotarization = false
2124 disableNotarization = true
2128 println("Using projectFile "+projectFile)
2129 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2133 inputs.dir(getdownAppBaseDir)
2134 inputs.file(install4jConfFile)
2135 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2136 inputs.dir(macosJavaVMDir)
2137 inputs.dir(windowsJavaVMDir)
2138 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2141 def getDataHash(File myFile) {
2142 HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
2143 return myFile.exists()
2145 "file" : myFile.getName(),
2146 "filesize" : myFile.length(),
2147 "sha256" : hash.toString()
2152 def writeDataJsonFile(File installersOutputTxt, File installersSha256, File dataJsonFile) {
2154 "channel" : getdownChannelName,
2155 "date" : getDate("yyyy-MM-dd HH:mm:ss"),
2156 "git-commit" : "${gitHash} [${gitBranch}]",
2157 "version" : JALVIEW_VERSION
2159 // install4j installer files
2160 if (installersOutputTxt.exists()) {
2162 installersOutputTxt.readLines().each { def line ->
2163 if (line.startsWith("#")) {
2166 line.replaceAll("\n","")
2167 def vals = line.split("\t")
2168 def filename = vals[3]
2169 def filesize = file(filename).length()
2170 filename = filename.replaceAll(/^.*\//, "")
2171 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2172 idHash."${filename}" = vals[0]
2174 if (install4jCheckSums && installersSha256.exists()) {
2175 installersSha256.readLines().each { def line ->
2176 if (line.startsWith("#")) {
2179 line.replaceAll("\n","")
2180 def vals = line.split(/\s+\*?/)
2181 def filename = vals[1]
2182 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2188 "JAR": shadowJar.archiveFile, // executable JAR
2189 "JVL": getdownVersionLaunchJvl, // version JVL
2190 "SOURCE": sourceDist.archiveFile // source TGZ
2191 ].each { key, value ->
2192 def file = file(value)
2193 if (file.exists()) {
2194 def fileHash = getDataHash(file)
2195 if (fileHash != null) {
2196 hash."${key}" = fileHash;
2200 return dataJsonFile.write(new JsonBuilder(hash).toPrettyString())
2203 task staticMakeInstallersJsonFile {
2205 def output = findProperty("i4j_output")
2206 def sha256 = findProperty("i4j_sha256")
2207 def json = findProperty("i4j_json")
2208 if (output == null || sha256 == null || json == null) {
2209 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2211 writeDataJsonFile(file(output), file(sha256), file(json))
2216 dependsOn installerFiles
2222 eclipse().configFile(eclipse_codestyle_file)
2226 task createSourceReleaseProperties(type: WriteProperties) {
2227 group = "distribution"
2228 description = "Create the source RELEASE properties file"
2230 def sourceTarBuildDir = "${buildDir}/sourceTar"
2231 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2232 outputFile (sourceReleasePropertiesFile)
2235 releaseProps.each{ key, val -> property key, val }
2236 property "git.branch", gitBranch
2237 property "git.hash", gitHash
2240 outputs.file(outputFile)
2243 task sourceDist(type: Tar) {
2244 group "distribution"
2245 description "Create a source .tar.gz file for distribution"
2247 dependsOn createBuildProperties
2248 dependsOn convertMdFiles
2249 dependsOn eclipseAllPreferences
2250 dependsOn createSourceReleaseProperties
2253 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2254 archiveFileName = outputFileName
2256 compression Compression.GZIP
2271 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2273 "utils/InstallAnywhere",
2288 "gradle.properties",
2300 ".settings/org.eclipse.buildship.core.prefs",
2301 ".settings/org.eclipse.jdt.core.prefs"
2305 exclude (EXCLUDE_FILES)
2306 include (PROCESS_FILES)
2307 filter(ReplaceTokens,
2311 'Version-Rel': JALVIEW_VERSION,
2312 'Year-Rel': getDate("yyyy")
2317 exclude (EXCLUDE_FILES)
2318 exclude (PROCESS_FILES)
2319 exclude ("appletlib")
2320 exclude ("**/*locales")
2321 exclude ("*locales/**")
2322 exclude ("utils/InstallAnywhere")
2324 exclude (getdown_files_dir)
2325 // getdown_website_dir and getdown_archive_dir moved to build/website/docroot/getdown
2326 //exclude (getdown_website_dir)
2327 //exclude (getdown_archive_dir)
2329 // exluding these as not using jars as modules yet
2330 exclude ("${j11modDir}/**/*.jar")
2333 include(INCLUDE_FILES)
2335 // from (jalviewDir) {
2336 // // explicit includes for stuff that seemed to not get included
2337 // include(fileTree("test/**/*."))
2338 // exclude(EXCLUDE_FILES)
2339 // exclude(PROCESS_FILES)
2342 from(file(buildProperties).getParent()) {
2343 include(file(buildProperties).getName())
2344 rename(file(buildProperties).getName(), "build_properties")
2346 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2350 def sourceTarBuildDir = "${buildDir}/sourceTar"
2351 from(sourceTarBuildDir) {
2352 // this includes the appended RELEASE properties file
2356 task dataInstallersJson {
2358 description "Create the installers-VERSION.json data file for installer files created"
2360 mustRunAfter installers
2361 mustRunAfter shadowJar
2362 mustRunAfter sourceDist
2363 mustRunAfter getdownArchive
2365 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2366 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2368 if (installersOutputTxt.exists()) {
2369 inputs.file(installersOutputTxt)
2371 if (install4jCheckSums && installersSha256.exists()) {
2372 inputs.file(installersSha256)
2375 shadowJar.archiveFile, // executable JAR
2376 getdownVersionLaunchJvl, // version JVL
2377 sourceDist.archiveFile // source TGZ
2378 ].each { fileName ->
2379 if (file(fileName).exists()) {
2380 inputs.file(fileName)
2384 outputs.file(hugoDataJsonFile)
2387 writeDataJsonFile(installersOutputTxt, installersSha256, hugoDataJsonFile)
2391 def hugoTemplateSubstitutions(String input, Map extras=null) {
2392 def replacements = [
2393 DATE: getDate("yyyy-MM-dd"),
2394 CHANNEL: propertiesChannelName,
2395 APPLICATION_NAME: applicationName,
2397 GIT_BRANCH: gitBranch,
2398 VERSION: JALVIEW_VERSION,
2399 JAVA_VERSION: JAVA_VERSION,
2400 VERSION_UNDERSCORES: JALVIEW_VERSION_UNDERSCORES,
2405 if (extras != null) {
2406 extras.each{ k, v ->
2407 output = output.replaceAll("__${k}__", ((v == null)?"":v))
2410 replacements.each{ k, v ->
2411 output = output.replaceAll("__${k}__", ((v == null)?"":v))
2416 def mdFileComponents(File mdFile, def dateOnly=false) {
2419 if (mdFile.exists()) {
2420 def inFrontMatter = false
2421 def firstLine = true
2422 mdFile.eachLine { line ->
2423 if (line.matches("---")) {
2424 def prev = inFrontMatter
2425 inFrontMatter = firstLine
2426 if (inFrontMatter != prev)
2429 if (inFrontMatter) {
2431 if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/) {
2432 map["date"] = new Date().parse("yyyy-MM-dd HH:mm:ss", m[0][1])
2433 } else if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2})/) {
2434 map["date"] = new Date().parse("yyyy-MM-dd", m[0][1])
2435 } else if (m = line =~ /^channel:\s*(\S+)/) {
2436 map["channel"] = m[0][1]
2437 } else if (m = line =~ /^version:\s*(\S+)/) {
2438 map["version"] = m[0][1]
2439 } else if (m = line =~ /^\s*([^:]+)\s*:\s*(\S.*)/) {
2440 map[ m[0][1] ] = m[0][2]
2442 if (dateOnly && map["date"] != null) {
2448 content += line+"\n"
2453 return dateOnly ? map["date"] : [map, content]
2456 task hugoTemplates {
2458 description "Create partially populated md pages for hugo website build"
2460 def hugoTemplatesDir = file("${jalviewDir}/${hugo_templates_dir}")
2461 def hugoBuildDir = "${jalviewDir}/${hugo_build_dir}"
2462 def templateFiles = fileTree(dir: hugoTemplatesDir)
2463 def releaseMdFile = file("${jalviewDir}/${releases_dir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
2464 def whatsnewMdFile = file("${jalviewDir}/${whatsnew_dir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
2465 def oldJvlFile = file("${jalviewDir}/${hugo_old_jvl}")
2466 def jalviewjsFile = file("${jalviewDir}/${hugo_jalviewjs}")
2469 // specific release template for version archive
2472 def givenDate = null
2473 def givenChannel = null
2474 def givenVersion = null
2475 if (CHANNEL == "RELEASE") {
2476 def (map, content) = mdFileComponents(releaseMdFile)
2477 givenDate = map.date
2478 givenChannel = map.channel
2479 givenVersion = map.version
2481 if (givenVersion != null && givenVersion != JALVIEW_VERSION) {
2482 throw new GradleException("'version' header (${givenVersion}) found in ${releaseMdFile} does not match JALVIEW_VERSION (${JALVIEW_VERSION})")
2485 if (whatsnewMdFile.exists())
2486 whatsnew = whatsnewMdFile.text
2489 def oldJvl = oldJvlFile.exists() ? oldJvlFile.collect{it} : []
2490 def jalviewjsLink = jalviewjsFile.exists() ? jalviewjsFile.collect{it} : []
2492 def changesHugo = null
2493 if (changes != null) {
2494 changesHugo = '<div class="release_notes">\n\n'
2495 def inSection = false
2496 changes.eachLine { line ->
2498 if (m = line =~ /^##([^#].*)$/) {
2500 changesHugo += "</div>\n\n"
2502 def section = m[0][1].trim()
2503 section = section.toLowerCase()
2504 section = section.replaceAll(/ +/, "_")
2505 section = section.replaceAll(/[^a-z0-9_\-]/, "")
2506 changesHugo += "<div class=\"${section}\">\n\n"
2508 } else if (m = line =~ /^(\s*-\s*)<!--([^>]+)-->(.*?)(<br\/?>)?\s*$/) {
2509 def comment = m[0][2].trim()
2510 if (comment != "") {
2511 comment = comment.replaceAll('"', """)
2513 comment.eachMatch(/JAL-\d+/) { jal -> issuekeys += jal }
2514 def newline = m[0][1]
2515 if (comment.trim() != "")
2516 newline += "{{<comment>}}${comment}{{</comment>}} "
2517 newline += m[0][3].trim()
2518 if (issuekeys.size() > 0)
2519 newline += " {{< jal issue=\"${issuekeys.join(",")}\" alt=\"${comment}\" >}}"
2520 if (m[0][4] != null)
2525 changesHugo += line+"\n"
2528 changesHugo += "\n</div>\n\n"
2530 changesHugo += '</div>'
2533 templateFiles.each{ templateFile ->
2534 def newFileName = string(hugoTemplateSubstitutions(templateFile.getName()))
2535 def relPath = hugoTemplatesDir.toPath().relativize(templateFile.toPath()).getParent()
2536 def newRelPathName = hugoTemplateSubstitutions( relPath.toString() )
2538 def outPathName = string("${hugoBuildDir}/$newRelPathName")
2542 rename(templateFile.getName(), newFileName)
2546 def newFile = file("${outPathName}/${newFileName}".toString())
2547 def content = newFile.text
2548 newFile.text = hugoTemplateSubstitutions(content,
2551 CHANGES: changesHugo,
2552 DATE: givenDate == null ? "" : givenDate.format("yyyy-MM-dd"),
2553 DRAFT: givenDate == null ? "true" : "false",
2554 JALVIEWJSLINK: jalviewjsLink.contains(JALVIEW_VERSION) ? "true" : "false",
2555 JVL_HEADER: oldJvl.contains(JALVIEW_VERSION) ? "jvl: true" : ""
2562 inputs.file(oldJvlFile)
2563 inputs.dir(hugoTemplatesDir)
2564 inputs.property("JALVIEW_VERSION", { JALVIEW_VERSION })
2565 inputs.property("CHANNEL", { CHANNEL })
2568 def getMdDate(File mdFile) {
2569 return mdFileComponents(mdFile, true)
2572 def getMdSections(String content) {
2574 def sectionContent = ""
2575 def sectionName = null
2576 content.eachLine { line ->
2578 if (m = line =~ /^##([^#].*)$/) {
2579 if (sectionName != null) {
2580 sections[sectionName] = sectionContent
2584 sectionName = m[0][1].trim()
2585 sectionName = sectionName.toLowerCase()
2586 sectionName = sectionName.replaceAll(/ +/, "_")
2587 sectionName = sectionName.replaceAll(/[^a-z0-9_\-]/, "")
2588 } else if (sectionName != null) {
2589 sectionContent += line+"\n"
2592 if (sectionContent != null) {
2593 sections[sectionName] = sectionContent
2598 task releasesTemplates {
2599 def releasesTemplateFile = file("${jalviewDir}/${releases_template}")
2600 def whatsnewTemplateFile = file("${jalviewDir}/${whatsnew_template}")
2601 def releasesHtmlFile = file("${helpSourceDir}/${releases_html}")
2602 def whatsnewHtmlFile = file("${helpSourceDir}/${whatsnew_html}")
2603 def releasesMdDir = "${jalviewDir}/${releases_dir}"
2604 def whatsnewMdDir = "${jalviewDir}/${whatsnew_dir}"
2607 def releaseFiles = fileTree(dir: releasesMdDir, include: "release-*.md")
2608 def releaseFilesDates = releaseFiles.collectEntries {
2609 [(it): getMdDate(it)]
2611 releaseFiles = releaseFiles.sort { a,b -> releaseFilesDates[a].compareTo(releaseFilesDates[b]) }
2613 def releasesTemplate = releasesTemplateFile.text
2614 def m = releasesTemplate =~ /(?s)__VERSION_LOOP_START__(.*)__VERSION_LOOP_END__/
2615 def versionTemplate = m[0][1]
2617 MutableDataSet options = new MutableDataSet()
2619 def extensions = new ArrayList<>()
2620 options.set(Parser.EXTENSIONS, extensions)
2621 options.set(Parser.HTML_BLOCK_COMMENT_ONLY_FULL_LINE, true)
2623 Parser parser = Parser.builder(options).build()
2624 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
2626 def actualVersions = releaseFiles.collect { rf ->
2627 def (rfMap, rfContent) = mdFileComponents(rf)
2628 return rfMap.version
2630 def versionsHtml = ""
2631 def linkedVersions = []
2632 releaseFiles.reverse().each { rFile ->
2633 def (rMap, rContent) = mdFileComponents(rFile)
2635 def versionLink = ""
2636 def partialVersion = ""
2637 def firstPart = true
2638 rMap.version.split("\\.").each { part ->
2639 def displayPart = ( firstPart ? "" : "." ) + part
2640 partialVersion += displayPart
2642 linkedVersions.contains(partialVersion)
2643 || ( actualVersions.contains(partialVersion) && partialVersion != rMap.version )
2645 versionLink += displayPart
2647 versionLink += "<a id=\"Jalview.${partialVersion}\">${displayPart}</a>"
2648 linkedVersions += partialVersion
2652 def displayDate = releaseFilesDates[rFile].format("d MMMMM yyyy")
2654 def rContentSections = getMdSections(rContent)
2655 def rVersion = versionTemplate
2656 if (rVersion != "") {
2657 Node newFeaturesNode = parser.parse(rContentSections["new_features"])
2658 String newFeaturesHtml = renderer.render(newFeaturesNode)
2659 Node issuesResolvedNode = parser.parse(rContentSections["issues_resolved"])
2660 String issuesResolvedHtml = renderer.render(issuesResolvedNode)
2661 rVersion = hugoTemplateSubstitutions(rVersion,
2663 VERSION: rMap.version,
2664 VERSION_LINK: versionLink,
2665 DISPLAY_DATE: displayDate,
2666 NEW_FEATURES: newFeaturesHtml,
2667 ISSUES_RESOLVED: issuesResolvedHtml
2670 versionsHtml += rVersion
2674 releasesTemplate = releasesTemplate.replaceAll("(?s)__VERSION_LOOP_START__.*__VERSION_LOOP_END__", versionsHtml)
2675 releasesTemplate = hugoTemplateSubstitutions(releasesTemplate)
2676 releasesHtmlFile.text = releasesTemplate
2679 inputs.file(releasesTemplateFile)
2680 inputs.file(whatsnewTemplateFile)
2681 inputs.dir(releasesMdDir)
2682 inputs.dir(whatsnewMdDir)
2683 outputs.file(releasesHtmlFile)
2684 outputs.file(whatsnewHtmlFile)
2690 dependsOn pubhtmlhelp
2692 inputs.dir("${helpBuildDir}/${help_dir}")
2693 outputs.dir("${buildDir}/distributions/${help_dir}")
2697 task j2sSetHeadlessBuild {
2704 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2706 description "Enable the alternative J2S Config file for headless build"
2708 outputFile = jalviewjsJ2sSettingsFileName
2709 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2710 def j2sProps = new Properties()
2711 if (j2sPropsFile.exists()) {
2713 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2714 j2sProps.load(j2sPropsFileFIS)
2715 j2sPropsFileFIS.close()
2717 j2sProps.each { prop, val ->
2720 } catch (Exception e) {
2721 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2725 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2726 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2731 task jalviewjsSetEclipseWorkspace {
2732 def propKey = "jalviewjs_eclipse_workspace"
2734 if (project.hasProperty(propKey)) {
2735 propVal = project.getProperty(propKey)
2736 if (propVal.startsWith("~/")) {
2737 propVal = System.getProperty("user.home") + propVal.substring(1)
2740 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2741 def propsFile = file(propsFileName)
2742 def eclipseWsDir = propVal
2743 def props = new Properties()
2745 def writeProps = true
2746 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2747 def ins = new FileInputStream(propsFileName)
2750 if (props.getProperty(propKey, null) != null) {
2751 eclipseWsDir = props.getProperty(propKey)
2756 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2757 def tempDir = File.createTempDir()
2758 eclipseWsDir = tempDir.getAbsolutePath()
2761 eclipseWorkspace = file(eclipseWsDir)
2764 // do not run a headless transpile when we claim to be in Eclipse
2766 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2767 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2769 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2773 props.setProperty(propKey, eclipseWsDir)
2774 propsFile.parentFile.mkdirs()
2775 def bytes = new ByteArrayOutputStream()
2776 props.store(bytes, null)
2777 def propertiesString = bytes.toString()
2778 propsFile.text = propertiesString
2784 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2787 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2788 outputs.file(propsFileName)
2789 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2793 task jalviewjsEclipsePaths {
2796 def eclipseRoot = jalviewjs_eclipse_root
2797 if (eclipseRoot.startsWith("~/")) {
2798 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
2800 if (OperatingSystem.current().isMacOsX()) {
2801 eclipseRoot += "/Eclipse.app"
2802 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
2803 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
2804 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
2805 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2806 eclipseRoot += "/eclipse"
2808 eclipseBinary = "${eclipseRoot}/eclipse.exe"
2809 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2810 } else { // linux or unix
2811 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2812 eclipseRoot += "/eclipse"
2813 println("eclipseDir exists")
2815 eclipseBinary = "${eclipseRoot}/eclipse"
2816 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2819 eclipseVersion = "4.13" // default
2820 def assumedVersion = true
2821 if (file(eclipseProduct).exists()) {
2822 def fis = new FileInputStream(eclipseProduct)
2823 def props = new Properties()
2825 eclipseVersion = props.getProperty("version")
2827 assumedVersion = false
2830 def propKey = "eclipse_debug"
2831 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
2834 // do not run a headless transpile when we claim to be in Eclipse
2836 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2837 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2839 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2842 if (!assumedVersion) {
2843 println("ECLIPSE VERSION=${eclipseVersion}")
2849 task printProperties {
2851 description "Output to console all System.properties"
2853 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
2859 dependsOn eclipseProject
2860 dependsOn eclipseClasspath
2861 dependsOn eclipseJdt
2865 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
2866 task jalviewjsEclipseCopyDropins(type: Copy) {
2867 dependsOn jalviewjsEclipsePaths
2869 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
2870 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
2871 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
2878 // this eclipse -clean doesn't actually work
2879 task jalviewjsCleanEclipse(type: Exec) {
2880 dependsOn eclipseSetup
2881 dependsOn jalviewjsEclipsePaths
2882 dependsOn jalviewjsEclipseCopyDropins
2884 executable(eclipseBinary)
2885 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
2891 def inputString = """exit
2894 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
2895 standardInput = inputByteStream
2898 /* not really working yet
2899 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
2903 task jalviewjsTransferUnzipSwingJs {
2904 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
2908 from zipTree(file_zip)
2909 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2913 inputs.file file_zip
2914 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2918 task jalviewjsTransferUnzipLib {
2919 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
2922 zipFiles.each { file_zip ->
2924 from zipTree(file_zip)
2925 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2930 inputs.files zipFiles
2931 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2935 task jalviewjsTransferUnzipAllLibs {
2936 dependsOn jalviewjsTransferUnzipSwingJs
2937 dependsOn jalviewjsTransferUnzipLib
2941 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
2943 description "Create the alternative j2s file from the j2s.* properties"
2945 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
2946 def siteDirProperty = "j2s.site.directory"
2947 def setSiteDir = false
2948 jalviewjsJ2sProps.each { prop, val ->
2950 if (prop == siteDirProperty) {
2951 if (!(val.startsWith('/') || val.startsWith("file://") )) {
2952 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
2958 if (!setSiteDir) { // default site location, don't override specifically set property
2959 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
2962 outputFile = jalviewjsJ2sAltSettingsFileName
2965 inputs.properties(jalviewjsJ2sProps)
2966 outputs.file(jalviewjsJ2sAltSettingsFileName)
2971 task jalviewjsEclipseSetup {
2972 dependsOn jalviewjsEclipseCopyDropins
2973 dependsOn jalviewjsSetEclipseWorkspace
2974 dependsOn jalviewjsCreateJ2sSettings
2978 task jalviewjsSyncAllLibs (type: Sync) {
2979 dependsOn jalviewjsTransferUnzipAllLibs
2980 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
2981 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
2982 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2986 def outputFiles = []
2987 rename { filename ->
2988 outputFiles += "${outputDir}/${filename}"
2995 // should this be exclude really ?
2996 duplicatesStrategy "INCLUDE"
2998 outputs.files outputFiles
2999 inputs.files inputFiles
3003 task jalviewjsSyncResources (type: Sync) {
3004 dependsOn buildResources
3006 def inputFiles = fileTree(dir: resourcesBuildDir)
3007 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3011 def outputFiles = []
3012 rename { filename ->
3013 outputFiles += "${outputDir}/${filename}"
3019 outputs.files outputFiles
3020 inputs.files inputFiles
3024 task jalviewjsSyncSiteResources (type: Sync) {
3025 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
3026 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3030 def outputFiles = []
3031 rename { filename ->
3032 outputFiles += "${outputDir}/${filename}"
3038 outputs.files outputFiles
3039 inputs.files inputFiles
3043 task jalviewjsSyncBuildProperties (type: Sync) {
3044 dependsOn createBuildProperties
3045 def inputFiles = [file(buildProperties)]
3046 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3050 def outputFiles = []
3051 rename { filename ->
3052 outputFiles += "${outputDir}/${filename}"
3058 outputs.files outputFiles
3059 inputs.files inputFiles
3063 task jalviewjsProjectImport(type: Exec) {
3064 dependsOn eclipseSetup
3065 dependsOn jalviewjsEclipsePaths
3066 dependsOn jalviewjsEclipseSetup
3069 // do not run a headless import when we claim to be in Eclipse
3071 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3072 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3074 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3078 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
3079 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
3080 executable(eclipseBinary)
3081 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
3085 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3087 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3088 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3091 inputs.file("${jalviewDir}/.project")
3092 outputs.upToDateWhen {
3093 file(projdir).exists()
3098 task jalviewjsTranspile(type: Exec) {
3099 dependsOn jalviewjsEclipseSetup
3100 dependsOn jalviewjsProjectImport
3101 dependsOn jalviewjsEclipsePaths
3103 dependsOn jalviewjsEnableAltFileProperty
3107 // do not run a headless transpile when we claim to be in Eclipse
3109 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3110 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3112 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3116 executable(eclipseBinary)
3117 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
3121 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3123 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3124 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3130 stdout = new ByteArrayOutputStream()
3131 stderr = new ByteArrayOutputStream()
3133 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
3134 def logOutFile = file(logOutFileName)
3135 logOutFile.createNewFile()
3136 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
3137 BINARY: ${eclipseBinary}
3138 VERSION: ${eclipseVersion}
3139 WORKSPACE: ${eclipseWorkspace}
3140 DEBUG: ${eclipseDebug}
3143 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3144 // combine stdout and stderr
3145 def logErrFOS = logOutFOS
3147 if (jalviewjs_j2s_to_console.equals("true")) {
3148 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3149 new org.apache.tools.ant.util.TeeOutputStream(
3153 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3154 new org.apache.tools.ant.util.TeeOutputStream(
3159 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3162 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3169 if (stdout.toString().contains("Error processing ")) {
3170 // j2s did not complete transpile
3171 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3172 if (jalviewjs_ignore_transpile_errors.equals("true")) {
3173 println("IGNORING TRANSPILE ERRORS")
3174 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3176 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3181 inputs.dir("${jalviewDir}/${sourceDir}")
3182 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
3183 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
3187 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
3189 def stdout = new ByteArrayOutputStream()
3190 def stderr = new ByteArrayOutputStream()
3192 def coreFile = file(jsfile)
3194 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
3196 logOutFile.createNewFile()
3197 logOutFile.append(msg+"\n")
3199 def coreTop = file(prefixFile)
3200 def coreBottom = file(suffixFile)
3201 coreFile.getParentFile().mkdirs()
3202 coreFile.createNewFile()
3203 coreFile.write( coreTop.getText("UTF-8") )
3207 def t = f.getText("UTF-8")
3208 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
3209 coreFile.append( t )
3211 msg = "...file '"+f.getPath()+"' does not exist, skipping"
3213 logOutFile.append(msg+"\n")
3216 coreFile.append( coreBottom.getText("UTF-8") )
3218 msg = "Generating ${zjsfile}"
3220 logOutFile.append(msg+"\n")
3221 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3222 def logErrFOS = logOutFOS
3225 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
3226 main = "com.google.javascript.jscomp.CommandLineRunner"
3227 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
3228 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
3231 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
3233 logOutFile.append(msg+"\n")
3235 if (logOutConsole) {
3236 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3237 new org.apache.tools.ant.util.TeeOutputStream(
3241 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3242 new org.apache.tools.ant.util.TeeOutputStream(
3247 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3250 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3257 logOutFile.append(msg+"\n")
3261 task jalviewjsBuildAllCores {
3263 description "Build the core js lib closures listed in the classlists dir"
3264 dependsOn jalviewjsTranspile
3265 dependsOn jalviewjsTransferUnzipSwingJs
3267 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
3268 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
3269 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
3270 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
3271 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
3272 def prefixFile = "${jsDir}/core/coretop2.js"
3273 def suffixFile = "${jsDir}/core/corebottom2.js"
3275 inputs.file prefixFile
3276 inputs.file suffixFile
3278 def classlistFiles = []
3279 // add the classlists found int the jalviewjs_classlists_dir
3280 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
3282 def name = file.getName() - ".txt"
3289 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
3290 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
3291 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
3293 jalviewjsCoreClasslists = []
3295 classlistFiles.each {
3298 def file = hash['file']
3299 if (! file.exists()) {
3300 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
3301 return false // this is a "continue" in groovy .each closure
3303 def name = hash['name']
3305 name = file.getName() - ".txt"
3313 def list = fileTree(dir: j2sDir, includes: filelist)
3315 def jsfile = "${outputDir}/core${name}.js"
3316 def zjsfile = "${outputDir}/core${name}.z.js"
3318 jalviewjsCoreClasslists += [
3327 outputs.file(jsfile)
3328 outputs.file(zjsfile)
3331 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
3332 def stevesoftClasslistName = "_stevesoft"
3333 def stevesoftClasslist = [
3334 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
3335 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
3336 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
3337 'name': stevesoftClasslistName
3339 jalviewjsCoreClasslists += stevesoftClasslist
3340 inputs.files(stevesoftClasslist['list'])
3341 outputs.file(stevesoftClasslist['jsfile'])
3342 outputs.file(stevesoftClasslist['zjsfile'])
3345 def allClasslistName = "_all"
3346 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3347 allJsFiles += fileTree(
3351 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3352 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3353 "**/org/jmol/export/JSExporter.js"
3356 allJsFiles += fileTree(
3360 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3361 "**/sun/misc/Unsafe.js",
3362 "**/swingjs/jquery/jquery-editable-select.js",
3363 "**/swingjs/jquery/j2sComboBox.js",
3364 "**/sun/misc/FloatingDecimal.js"
3367 def allClasslist = [
3368 'jsfile': "${outputDir}/core${allClasslistName}.js",
3369 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
3371 'name': allClasslistName
3373 // not including this version of "all" core at the moment
3374 //jalviewjsCoreClasslists += allClasslist
3375 inputs.files(allClasslist['list'])
3376 outputs.file(allClasslist['jsfile'])
3377 outputs.file(allClasslist['zjsfile'])
3380 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3381 logOutFile.getParentFile().mkdirs()
3382 logOutFile.createNewFile()
3383 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3385 jalviewjsCoreClasslists.each {
3386 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3393 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3396 into file(outputFile).getParentFile()
3397 rename { filename ->
3398 if (filename.equals(inputFile.getName())) {
3399 return file(outputFile).getName()
3403 filter(ReplaceTokens,
3407 'MAIN': '"'+main_class+'"',
3409 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3410 'COREKEY': jalviewjs_core_key,
3411 'CORENAME': coreName
3418 task jalviewjsPublishCoreTemplates {
3419 dependsOn jalviewjsBuildAllCores
3420 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3421 def inputFile = file(inputFileName)
3422 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3424 def outputFiles = []
3425 jalviewjsCoreClasslists.each { cl ->
3426 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3427 cl['outputfile'] = outputFile
3428 outputFiles += outputFile
3432 jalviewjsCoreClasslists.each { cl ->
3433 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3436 inputs.file(inputFile)
3437 outputs.files(outputFiles)
3441 task jalviewjsSyncCore (type: Sync) {
3442 dependsOn jalviewjsBuildAllCores
3443 dependsOn jalviewjsPublishCoreTemplates
3444 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3445 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3449 def outputFiles = []
3450 rename { filename ->
3451 outputFiles += "${outputDir}/${filename}"
3457 outputs.files outputFiles
3458 inputs.files inputFiles
3462 // this Copy version of TransferSiteJs will delete anything else in the target dir
3463 task jalviewjsCopyTransferSiteJs(type: Copy) {
3464 dependsOn jalviewjsTranspile
3465 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3466 into "${jalviewDir}/${jalviewjsSiteDir}"
3470 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3471 task jalviewjsSyncTransferSiteJs(type: Sync) {
3472 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3474 into "${jalviewDir}/${jalviewjsSiteDir}"
3481 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3482 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3483 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3484 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3486 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3487 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3488 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3489 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3492 task jalviewjsPrepareSite {
3494 description "Prepares the website folder including unzipping files and copying resources"
3495 dependsOn jalviewjsSyncAllLibs
3496 dependsOn jalviewjsSyncResources
3497 dependsOn jalviewjsSyncSiteResources
3498 dependsOn jalviewjsSyncBuildProperties
3499 dependsOn jalviewjsSyncCore
3503 task jalviewjsBuildSite {
3505 description "Builds the whole website including transpiled code"
3506 dependsOn jalviewjsCopyTransferSiteJs
3507 dependsOn jalviewjsPrepareSite
3511 task cleanJalviewjsTransferSite {
3513 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3514 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3515 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3516 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3521 task cleanJalviewjsSite {
3522 dependsOn cleanJalviewjsTransferSite
3524 delete "${jalviewDir}/${jalviewjsSiteDir}"
3529 task jalviewjsSiteTar(type: Tar) {
3531 description "Creates a tar.gz file for the website"
3532 dependsOn jalviewjsBuildSite
3533 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3534 archiveFileName = outputFilename
3536 compression Compression.GZIP
3538 from "${jalviewDir}/${jalviewjsSiteDir}"
3539 into jalviewjs_site_dir // this is inside the tar file
3541 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3545 task jalviewjsServer {
3547 def filename = "jalviewjsTest.html"
3548 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3549 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3554 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3555 factory = f.newInstance()
3556 } catch (ClassNotFoundException e) {
3557 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3559 def port = Integer.valueOf(jalviewjs_server_port)
3564 while(port < start+1000 && !running) {
3566 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3567 jalviewjsServer = factory.start(doc_root, port)
3569 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3570 println("SERVER STARTED with document root ${doc_root}.")
3571 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3572 println("For debug: "+url+"?j2sdebug")
3573 println("For verbose: "+url+"?j2sverbose")
3574 } catch (Exception e) {
3579 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3580 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3581 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3583 jalviewjsCoreClasslists.each { cl ->
3584 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3586 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3588 println("For core ${cl.name}: "+urlcore)
3591 file(htmlFile).text = htmlText
3594 outputs.file(htmlFile)
3595 outputs.upToDateWhen({false})
3599 task cleanJalviewjsAll {
3601 description "Delete all configuration and build artifacts to do with JalviewJS build"
3602 dependsOn cleanJalviewjsSite
3603 dependsOn jalviewjsEclipsePaths
3606 delete "${jalviewDir}/${jalviewjsBuildDir}"
3607 delete "${jalviewDir}/${eclipse_bin_dir}"
3608 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3609 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3611 delete jalviewjsJ2sAltSettingsFileName
3614 outputs.upToDateWhen( { false } )
3618 task jalviewjsIDE_checkJ2sPlugin {
3619 group "00 JalviewJS in Eclipse"
3620 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3623 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3624 def j2sPluginFile = file(j2sPlugin)
3625 def eclipseHome = System.properties["eclipse.home.location"]
3626 if (eclipseHome == null || ! IN_ECLIPSE) {
3627 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3629 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3630 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3631 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3632 eclipseJ2sPluginDirs += altPluginsDir
3634 def foundPlugin = false
3635 def j2sPluginFileName = j2sPluginFile.getName()
3636 def eclipseJ2sPlugin
3637 def eclipseJ2sPluginFile
3638 eclipseJ2sPluginDirs.any { dir ->
3639 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3640 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3641 if (eclipseJ2sPluginFile.exists()) {
3647 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3648 System.err.println(msg)
3649 throw new StopExecutionException(msg)
3652 def digest = MessageDigest.getInstance("MD5")
3654 digest.update(j2sPluginFile.text.bytes)
3655 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3657 digest.update(eclipseJ2sPluginFile.text.bytes)
3658 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3660 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3661 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3662 System.err.println(msg)
3663 throw new StopExecutionException(msg)
3665 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3671 task jalviewjsIDE_copyJ2sPlugin {
3672 group "00 JalviewJS in Eclipse"
3673 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3676 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3677 def j2sPluginFile = file(j2sPlugin)
3678 def eclipseHome = System.properties["eclipse.home.location"]
3679 if (eclipseHome == null || ! IN_ECLIPSE) {
3680 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3682 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3683 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3684 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3685 System.err.println(msg)
3688 eclipseJ2sPluginFile.getParentFile().mkdirs()
3689 into eclipseJ2sPluginFile.getParent()
3695 task jalviewjsIDE_j2sFile {
3696 group "00 JalviewJS in Eclipse"
3697 description "Creates the .j2s file"
3698 dependsOn jalviewjsCreateJ2sSettings
3702 task jalviewjsIDE_SyncCore {
3703 group "00 JalviewJS in Eclipse"
3704 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3705 dependsOn jalviewjsSyncCore
3709 task jalviewjsIDE_SyncSiteAll {
3710 dependsOn jalviewjsSyncAllLibs
3711 dependsOn jalviewjsSyncResources
3712 dependsOn jalviewjsSyncSiteResources
3713 dependsOn jalviewjsSyncBuildProperties
3717 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3720 task jalviewjsIDE_PrepareSite {
3721 group "00 JalviewJS in Eclipse"
3722 description "Sync libs and resources to site dir, but not closure cores"
3724 dependsOn jalviewjsIDE_SyncSiteAll
3725 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3729 task jalviewjsIDE_AssembleSite {
3730 group "00 JalviewJS in Eclipse"
3731 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3732 dependsOn jalviewjsPrepareSite
3736 task jalviewjsIDE_SiteClean {
3737 group "00 JalviewJS in Eclipse"
3738 description "Deletes the Eclipse transpiled site"
3739 dependsOn cleanJalviewjsSite
3743 task jalviewjsIDE_Server {
3744 group "00 JalviewJS in Eclipse"
3745 description "Starts a webserver on localhost to test the website"
3746 dependsOn jalviewjsServer
3750 // buildship runs this at import or gradle refresh
3751 task eclipseSynchronizationTask {
3752 //dependsOn eclipseSetup
3753 dependsOn createBuildProperties
3755 dependsOn jalviewjsIDE_j2sFile
3756 dependsOn jalviewjsIDE_checkJ2sPlugin
3757 dependsOn jalviewjsIDE_PrepareSite
3762 // buildship runs this at build time or project refresh
3763 task eclipseAutoBuildTask {
3764 //dependsOn jalviewjsIDE_checkJ2sPlugin
3765 //dependsOn jalviewjsIDE_PrepareSite
3771 description "Build the site"
3772 dependsOn jalviewjsBuildSite