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
33 classpath "com.vladsch.flexmark:flexmark-all:0.62.0"
42 id "com.diffplug.gradle.spotless" version "3.28.0"
43 id 'com.github.johnrengelman.shadow' version '4.0.3'
44 id 'com.install4j.gradle' version '9.0.6'
45 id 'com.dorongold.task-tree' version '1.5' // only needed to display task dependency tree with gradle task1 [task2 ...] taskTree
46 id 'com.palantir.git-version' version '0.13.0' apply false
57 // in ext the values are cast to Object. Ensure string values are cast as String (and not GStringImpl) for later use
58 def string(Object o) {
59 return o == null ? "" : o.toString()
62 def overrideProperties(String propsFileName, boolean output = false) {
63 if (propsFileName == null) {
66 def propsFile = file(propsFileName)
67 if (propsFile != null && propsFile.exists()) {
68 println("Using properties from file '${propsFileName}'")
70 def p = new Properties()
71 def localPropsFIS = new FileInputStream(propsFile)
77 if (project.hasProperty(key)) {
78 oldval = project.findProperty(key)
79 project.setProperty(key, val)
81 println("Overriding property '${key}' ('${oldval}') with ${file(propsFile).getName()} value '${val}'")
84 ext.setProperty(key, val)
86 println("Setting ext property '${key}' with ${file(propsFile).getName()}s value '${val}'")
90 } catch (Exception e) {
91 println("Exception reading local.properties")
98 jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath()
99 jalviewDirRelativePath = jalviewDir
101 getdownChannelName = CHANNEL.toLowerCase()
102 // default to "default". Currently only has different cosmetics for "develop", "release", "default"
103 propertiesChannelName = ["develop", "release", "test-release", "jalviewjs", "jalviewjs-release" ].contains(getdownChannelName) ? getdownChannelName : "default"
104 // Import channel_properties
105 channelDir = string("${jalviewDir}/${channel_properties_dir}/${propertiesChannelName}")
106 channelGradleProperties = string("${channelDir}/channel_gradle.properties")
107 channelPropsFile = string("${channelDir}/${resource_dir}/${channel_props}")
108 overrideProperties(channelGradleProperties, false)
109 // local build environment properties
110 // can be "projectDir/local.properties"
111 overrideProperties("${projectDir}/local.properties", true)
112 // or "../projectDir_local.properties"
113 overrideProperties(projectDir.getParent() + "/" + projectDir.getName() + "_local.properties", true)
116 // Import releaseProps from the RELEASE file
117 // or a file specified via JALVIEW_RELEASE_FILE if defined
118 // Expect jalview.version and target release branch in jalview.release
119 releaseProps = new Properties();
120 def releasePropFile = findProperty("JALVIEW_RELEASE_FILE");
121 def defaultReleasePropFile = "${jalviewDirAbsolutePath}/RELEASE";
123 (new File(releasePropFile!=null ? releasePropFile : defaultReleasePropFile)).withInputStream {
124 releaseProps.load(it)
126 } catch (Exception fileLoadError) {
127 throw new Error("Couldn't load release properties file "+(releasePropFile==null ? defaultReleasePropFile : "from custom location: releasePropFile"),fileLoadError);
130 // Set JALVIEW_VERSION if it is not already set
131 if (findProperty("JALVIEW_VERSION")==null || "".equals(JALVIEW_VERSION)) {
132 JALVIEW_VERSION = releaseProps.get("jalview.version")
135 // this property set when running Eclipse headlessly
136 j2sHeadlessBuildProperty = string("net.sf.j2s.core.headlessbuild")
137 // this property set by Eclipse
138 eclipseApplicationProperty = string("eclipse.application")
139 // CHECK IF RUNNING FROM WITHIN ECLIPSE
140 def eclipseApplicationPropertyVal = System.properties[eclipseApplicationProperty]
141 IN_ECLIPSE = eclipseApplicationPropertyVal != null && eclipseApplicationPropertyVal.startsWith("org.eclipse.ui.")
142 // BUT WITHOUT THE HEADLESS BUILD PROPERTY SET
143 if (System.properties[j2sHeadlessBuildProperty].equals("true")) {
144 println("Setting IN_ECLIPSE to ${IN_ECLIPSE} as System.properties['${j2sHeadlessBuildProperty}'] == '${System.properties[j2sHeadlessBuildProperty]}'")
148 println("WITHIN ECLIPSE IDE")
150 println("HEADLESS BUILD")
153 J2S_ENABLED = (project.hasProperty('j2s.compiler.status') && project['j2s.compiler.status'] != null && project['j2s.compiler.status'] == "enable")
155 println("J2S ENABLED")
158 System.properties.sort { it.key }.each {
159 key, val -> println("SYSTEM PROPERTY ${key}='${val}'")
162 if (false && IN_ECLIPSE) {
163 jalviewDir = jalviewDirAbsolutePath
168 buildDate = new Date().format("yyyyMMdd")
171 bareSourceDir = string(source_dir)
172 sourceDir = string("${jalviewDir}/${bareSourceDir}")
173 resourceDir = string("${jalviewDir}/${resource_dir}")
174 bareTestSourceDir = string(test_source_dir)
175 testDir = string("${jalviewDir}/${bareTestSourceDir}")
177 classesDir = string("${jalviewDir}/${classes_dir}")
180 useClover = clover.equals("true")
181 cloverBuildDir = "${buildDir}/clover"
182 cloverInstrDir = file("${cloverBuildDir}/clover-instr")
183 cloverClassesDir = file("${cloverBuildDir}/clover-classes")
184 cloverReportDir = file("${buildDir}/reports/clover")
185 cloverTestInstrDir = file("${cloverBuildDir}/clover-test-instr")
186 cloverTestClassesDir = file("${cloverBuildDir}/clover-test-classes")
187 //cloverTestClassesDir = cloverClassesDir
188 cloverDb = string("${cloverBuildDir}/clover.db")
190 testSourceDir = useClover ? cloverTestInstrDir : testDir
191 testClassesDir = useClover ? cloverTestClassesDir : "${jalviewDir}/${test_output_dir}"
193 getdownWebsiteDir = string("${jalviewDir}/${getdown_website_dir}/${JAVA_VERSION}")
194 getdownArchiveDir = string("${jalviewDir}/${getdown_archive_dir}")
195 getdownFullArchiveDir = null
196 getdownTextLines = []
197 getdownLaunchJvl = null
199 buildProperties = null
201 // the following values might be overridden by the CHANNEL switch
202 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
203 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
204 getdownArchiveAppBase = null
205 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}")
206 getdownAppDistDir = getdown_app_dir_alt
207 getdownImagesDir = string("${jalviewDir}/${getdown_images_dir}")
208 getdownSetAppBaseProperty = false // whether to pass the appbase and appdistdir to the application
209 reportRsyncCommand = false
210 jvlChannelName = CHANNEL.toLowerCase()
211 install4jSuffix = CHANNEL.substring(0, 1).toUpperCase() + CHANNEL.substring(1).toLowerCase(); // BUILD -> Build
212 install4jDMGDSStore = "${install4j_images_dir}/${install4j_dmg_ds_store}"
213 install4jDMGBackgroundImage = "${install4j_images_dir}/${install4j_dmg_background}"
214 install4jInstallerName = "${jalview_name} Non-Release Installer"
215 install4jExecutableName = install4j_executable_name
216 install4jExtraScheme = "jalviewx"
217 install4jMacIconsFile = string("${install4j_images_dir}/${install4j_mac_icons_file}")
218 install4jWindowsIconsFile = string("${install4j_images_dir}/${install4j_windows_icons_file}")
219 install4jPngIconFile = string("${install4j_images_dir}/${install4j_png_icon_file}")
220 install4jBackground = string("${install4j_images_dir}/${install4j_background}")
221 install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
222 install4jCheckSums = true
226 // TODO: get bamboo build artifact URL for getdown artifacts
227 getdown_channel_base = bamboo_channelbase
228 getdownChannelName = string("${bamboo_planKey}/${JAVA_VERSION}")
229 getdownAppBase = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
230 jvlChannelName += "_${getdownChannelName}"
231 // automatically add the test group Not-bamboo for exclusion
232 if ("".equals(testng_excluded_groups)) {
233 testng_excluded_groups = "Not-bamboo"
235 install4jExtraScheme = "jalviewb"
238 case [ "RELEASE", "JALVIEWJS-RELEASE" ]:
239 getdownAppDistDir = getdown_app_dir_release
240 getdownSetAppBaseProperty = true
241 reportRsyncCommand = true
243 install4jInstallerName = "${jalview_name} Installer"
244 getdownArchiveAppBase = getdown_archive_base
248 getdownChannelName = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
249 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
250 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
251 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
252 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
254 package_dir = string("${ARCHIVEDIR}/${package_dir}")
255 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
258 reportRsyncCommand = true
259 install4jExtraScheme = "jalviewa"
263 getdownChannelName = string("archive/${JALVIEW_VERSION}")
264 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
265 getdownAppBase = file(getdownWebsiteDir).toURI().toString()
266 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
267 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
269 package_dir = string("${ARCHIVEDIR}/${package_dir}")
270 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
273 reportRsyncCommand = true
274 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
275 install4jSuffix = "Archive"
276 install4jExtraScheme = "jalviewa"
280 reportRsyncCommand = true
281 getdownSetAppBaseProperty = true
282 // DEVELOP-RELEASE is usually associated with a Jalview release series so set the version
283 JALVIEW_VERSION=JALVIEW_VERSION+"-d${buildDate}"
285 install4jSuffix = "Develop"
286 install4jExtraScheme = "jalviewd"
287 install4jInstallerName = "${jalview_name} Develop Installer"
291 reportRsyncCommand = true
292 getdownSetAppBaseProperty = true
293 // Don't ignore transpile errors for release build
294 if (jalviewjs_ignore_transpile_errors.equals("true")) {
295 jalviewjs_ignore_transpile_errors = "false"
296 println("Setting jalviewjs_ignore_transpile_errors to 'false'")
298 JALVIEW_VERSION = JALVIEW_VERSION+"-test"
299 install4jSuffix = "Test"
300 install4jExtraScheme = "jalviewt"
301 install4jInstallerName = "${jalview_name} Test Installer"
304 case ~/^SCRATCH(|-[-\w]*)$/:
305 getdownChannelName = CHANNEL
306 JALVIEW_VERSION = JALVIEW_VERSION+"-"+CHANNEL
308 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
309 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
310 reportRsyncCommand = true
311 install4jSuffix = "Scratch"
315 if (!file("${LOCALDIR}").exists()) {
316 throw new GradleException("Must provide a LOCALDIR value to produce a local distribution")
318 getdownAppBase = file(file("${LOCALDIR}").getAbsolutePath()).toURI().toString()
319 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
321 JALVIEW_VERSION = "TEST"
322 install4jSuffix = "Test-Local"
323 install4jExtraScheme = "jalviewt"
324 install4jInstallerName = "${jalview_name} Test Installer"
327 case [ "LOCAL", "JALVIEWJS" ]:
328 JALVIEW_VERSION = "TEST"
329 getdownAppBase = file(getdownWebsiteDir).toURI().toString()
330 getdownArchiveAppBase = file("${jalviewDir}/${getdown_archive_dir}").toURI().toString()
331 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
332 install4jExtraScheme = "jalviewl"
333 install4jCheckSums = false
336 default: // something wrong specified
337 throw new GradleException("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
341 JALVIEW_VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
342 // override getdownAppBase if requested
343 if (findProperty("getdown_appbase_override") != null) {
344 // revert to LOCAL if empty string
345 if (string(getdown_appbase_override) == "") {
346 getdownAppBase = file(getdownWebsiteDir).toURI().toString()
347 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
348 } else if (string(getdown_appbase_override).startsWith("file://")) {
349 getdownAppBase = string(getdown_appbase_override)
350 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
352 getdownAppBase = string(getdown_appbase_override)
354 println("Overriding getdown appbase with '${getdownAppBase}'")
356 // sanitise file name for jalview launcher file for this channel
357 jvlChannelName = jvlChannelName.replaceAll("[^\\w\\-]+", "_")
358 // install4j application and folder names
359 if (install4jSuffix == "") {
360 install4jApplicationName = "${jalview_name}"
361 install4jBundleId = "${install4j_bundle_id}"
362 install4jWinApplicationId = install4j_release_win_application_id
364 install4jApplicationName = "${jalview_name} ${install4jSuffix}"
365 install4jBundleId = "${install4j_bundle_id}-" + install4jSuffix.toLowerCase()
366 // add int hash of install4jSuffix to the last part of the application_id
367 def id = install4j_release_win_application_id
368 def idsplitreverse = id.split("-").reverse()
369 idsplitreverse[0] = idsplitreverse[0].toInteger() + install4jSuffix.hashCode()
370 install4jWinApplicationId = idsplitreverse.reverse().join("-")
372 // sanitise folder and id names
373 // install4jApplicationFolder = e.g. "Jalview Build"
374 install4jApplicationFolder = install4jApplicationName
375 .replaceAll("[\"'~:/\\\\\\s]", "_") // replace all awkward filename chars " ' ~ : / \
376 .replaceAll("_+", "_") // collapse __
377 install4jInternalId = install4jApplicationName
379 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
380 .replaceAll("_+", "") // collapse __
381 //.replaceAll("_*-_*", "-") // collapse _-_
382 install4jUnixApplicationFolder = install4jApplicationName
384 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
385 .replaceAll("_+", "_") // collapse __
386 .replaceAll("_*-_*", "-") // collapse _-_
389 getdownWrapperLink = install4jUnixApplicationFolder // e.g. "jalview_local"
390 getdownAppDir = string("${getdownWebsiteDir}/${getdownAppDistDir}")
391 //getdownJ11libDir = "${getdownWebsiteDir}/${getdown_j11lib_dir}"
392 getdownResourceDir = string("${getdownWebsiteDir}/${getdown_resource_dir}")
393 getdownInstallDir = string("${getdownWebsiteDir}/${getdown_install_dir}")
394 getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
395 getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
396 /* compile without modules -- using classpath libraries
397 modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
398 modules_runtimeClasspath = modules_compileClasspath
404 apply plugin: "com.palantir.git-version"
405 def details = versionDetails()
406 gitHash = details.gitHash
407 gitBranch = details.branchName
408 } catch(org.gradle.api.internal.plugins.PluginApplicationException e) {
409 println("Not in a git repository. Using git values from RELEASE properties file.")
410 gitHash = releaseProps.getProperty("git.hash")
411 gitBranch = releaseProps.getProperty("git.branch")
412 } catch(java.lang.RuntimeException e1) {
413 throw new GradleException("Error with git-version plugin. Directory '.git' exists but versionDetails() cannot be found.")
416 println("Using a ${CHANNEL} profile.")
418 additional_compiler_args = []
419 // configure classpath/args for j8/j11 compilation
420 if (JAVA_VERSION.equals("1.8")) {
421 JAVA_INTEGER_VERSION = string("8")
424 libDistDir = j8libDir
425 compile_source_compatibility = 1.8
426 compile_target_compatibility = 1.8
427 // these are getdown.txt properties defined dependent on the JAVA_VERSION
428 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
429 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
430 // this property is assigned below and expanded to multiple lines in the getdown task
431 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
432 // this property is for the Java library used in eclipse
433 eclipseJavaRuntimeName = string("JavaSE-1.8")
434 } else if (JAVA_VERSION.equals("11")) {
435 JAVA_INTEGER_VERSION = string("11")
437 libDistDir = j11libDir
438 compile_source_compatibility = 11
439 compile_target_compatibility = 11
440 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
441 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
442 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
443 eclipseJavaRuntimeName = string("JavaSE-11")
444 /* compile without modules -- using classpath libraries
445 additional_compiler_args += [
446 '--module-path', modules_compileClasspath.asPath,
447 '--add-modules', j11modules
450 } else if (JAVA_VERSION.equals("17")) {
451 JAVA_INTEGER_VERSION = string("17")
453 libDistDir = j17libDir
454 compile_source_compatibility = 17
455 compile_target_compatibility = 17
456 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
457 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
458 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
459 eclipseJavaRuntimeName = string("JavaSE-17")
460 /* compile without modules -- using classpath libraries
461 additional_compiler_args += [
462 '--module-path', modules_compileClasspath.asPath,
463 '--add-modules', j11modules
467 throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
472 JAVA_MIN_VERSION = JAVA_VERSION
473 JAVA_MAX_VERSION = JAVA_VERSION
474 def jreInstallsDir = string(jre_installs_dir)
475 if (jreInstallsDir.startsWith("~/")) {
476 jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
478 macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
479 windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
480 linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
481 macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_mac_x64.tar.gz")
482 windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_windows_x64.tar.gz")
483 linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_linux_x64.tar.gz")
484 install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
485 install4jConfFileName = string("jalview-install4j-conf.install4j")
486 install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
487 install4jHomeDir = install4j_home_dir
488 if (install4jHomeDir.startsWith("~/")) {
489 install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
492 resourceBuildDir = string("${buildDir}/resources")
493 resourcesBuildDir = string("${resourceBuildDir}/resources_build")
494 helpBuildDir = string("${resourceBuildDir}/help_build")
495 docBuildDir = string("${resourceBuildDir}/doc_build")
497 if (buildProperties == null) {
498 buildProperties = string("${resourcesBuildDir}/${build_properties_file}")
500 buildingHTML = string("${jalviewDir}/${doc_dir}/building.html")
501 helpParentDir = string("${jalviewDir}/${help_parent_dir}")
502 helpSourceDir = string("${helpParentDir}/${help_dir}")
503 helpFile = string("${helpBuildDir}/${help_dir}/help.jhm")
506 relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
507 jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
508 jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
510 jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
512 jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
514 jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
515 jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
516 jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
517 jalviewjsJalviewCoreHtmlFile = string("")
518 jalviewjsJalviewCoreName = string(jalviewjs_core_name)
519 jalviewjsCoreClasslists = []
520 jalviewjsJalviewTemplateName = string(jalviewjs_name)
521 jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
522 jalviewjsJ2sAltSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_alt_settings}")
523 jalviewjsJ2sProps = null
524 jalviewjsJ2sPlugin = jalviewjs_j2s_plugin
526 eclipseWorkspace = null
527 eclipseBinary = string("")
528 eclipseVersion = string("")
538 outputDir = file(classesDir)
542 srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ]
545 compileClasspath = files(sourceSets.main.java.outputDir)
546 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
548 runtimeClasspath = compileClasspath
549 runtimeClasspath += files(sourceSets.main.resources.srcDirs)
554 srcDirs cloverInstrDir
555 outputDir = cloverClassesDir
559 srcDirs = sourceSets.main.resources.srcDirs
562 compileClasspath = files( sourceSets.clover.java.outputDir )
563 //compileClasspath += files( testClassesDir )
564 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
565 compileClasspath += fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
566 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
568 runtimeClasspath = compileClasspath
573 srcDirs testSourceDir
574 outputDir = file(testClassesDir)
578 srcDirs = useClover ? sourceSets.clover.resources.srcDirs : sourceSets.main.resources.srcDirs
581 compileClasspath = files( sourceSets.test.java.outputDir )
582 compileClasspath += useClover ? sourceSets.clover.compileClasspath : sourceSets.main.compileClasspath
583 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
585 runtimeClasspath = compileClasspath
586 runtimeClasspath += files(sourceSets.test.resources.srcDirs)
592 // eclipse project and settings files creation, also used by buildship
595 name = eclipse_project_name
597 natures 'org.eclipse.jdt.core.javanature',
598 'org.eclipse.jdt.groovy.core.groovyNature',
599 'org.eclipse.buildship.core.gradleprojectnature'
601 buildCommand 'org.eclipse.jdt.core.javabuilder'
602 buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
606 //defaultOutputDir = sourceSets.main.java.outputDir
607 configurations.each{ c->
608 if (c.isCanBeResolved()) {
609 minusConfigurations += [c]
613 plusConfigurations = [ ]
617 def removeTheseToo = []
618 HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
619 cp.entries.each { entry ->
620 // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
621 // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
622 // we add the resources and help/help dirs in as libs afterwards (see below)
623 if (entry.kind == 'src') {
624 if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
625 removeTheseToo += entry
627 alreadyAddedSrcPath.putAt(entry.path, true)
632 cp.entries.removeAll(removeTheseToo)
634 //cp.entries += new Output("${eclipse_bin_dir}/main")
635 if (file(helpParentDir).isDirectory()) {
636 cp.entries += new Library(fileReference(helpParentDir))
638 if (file(resourceDir).isDirectory()) {
639 cp.entries += new Library(fileReference(resourceDir))
642 HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
644 sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
645 //don't want to add outputDir as eclipse is using its own output dir in bin/main
646 if (it.isDirectory() || ! it.exists()) {
647 // don't add dirs to classpath, especially if they don't exist
648 return false // groovy "continue" in .any closure
650 def itPath = it.toString()
651 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
652 // make relative path
653 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
655 if (alreadyAddedLibPath.get(itPath)) {
656 //println("Not adding duplicate entry "+itPath)
658 //println("Adding entry "+itPath)
659 cp.entries += new Library(fileReference(itPath))
660 alreadyAddedLibPath.put(itPath, true)
664 sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
665 //no longer want to add outputDir as eclipse is using its own output dir in bin/main
666 if (it.isDirectory() || ! it.exists()) {
667 // don't add dirs to classpath
668 return false // groovy "continue" in .any closure
671 def itPath = it.toString()
672 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
673 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
675 if (alreadyAddedLibPath.get(itPath)) {
678 def lib = new Library(fileReference(itPath))
679 lib.entryAttributes["test"] = "true"
681 alreadyAddedLibPath.put(itPath, true)
689 containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
694 // for the IDE, use java 11 compatibility
695 sourceCompatibility = compile_source_compatibility
696 targetCompatibility = compile_target_compatibility
697 javaRuntimeName = eclipseJavaRuntimeName
699 // add in jalview project specific properties/preferences into eclipse core preferences
701 withProperties { props ->
702 def jalview_prefs = new Properties()
703 def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
704 jalview_prefs.load(ins)
706 jalview_prefs.forEach { t, v ->
707 if (props.getAt(t) == null) {
711 // codestyle file -- overrides previous formatter prefs
712 def csFile = file("${jalviewDirAbsolutePath}/${eclipse_codestyle_file}")
713 if (csFile.exists()) {
714 XmlParser parser = new XmlParser()
715 def profiles = parser.parse(csFile)
716 def profile = profiles.'profile'.find { p -> (p.'@kind' == "CodeFormatterProfile" && p.'@name' == "Jalview") }
717 if (profile != null) {
718 profile.'setting'.each { s ->
720 def value = s.'@value'
721 if (id != null && value != null) {
722 props.putAt(id, value)
733 // Don't want these to be activated if in headless build
734 synchronizationTasks "eclipseSynchronizationTask"
735 //autoBuildTasks "eclipseAutoBuildTask"
741 /* hack to change eclipse prefs in .settings files other than org.eclipse.jdt.core.prefs */
742 // Class to allow updating arbitrary properties files
743 class PropertiesFile extends PropertiesPersistableConfigurationObject {
744 public PropertiesFile(PropertiesTransformer t) { super(t); }
745 @Override protected void load(Properties properties) { }
746 @Override protected void store(Properties properties) { }
747 @Override protected String getDefaultResourceName() { return ""; }
748 // This is necessary, because PropertiesPersistableConfigurationObject fails
749 // if no default properties file exists.
750 @Override public void loadDefaults() { load(new StringBufferInputStream("")); }
753 // Task to update arbitrary properties files (set outputFile)
754 class PropertiesFileTask extends PropertiesGeneratorTask<PropertiesFile> {
755 private final PropertiesFileContentMerger file;
756 public PropertiesFileTask() { file = new PropertiesFileContentMerger(getTransformer()); }
757 protected PropertiesFile create() { return new PropertiesFile(getTransformer()); }
758 protected void configure(PropertiesFile props) {
759 file.getBeforeMerged().execute(props); file.getWhenMerged().execute(props);
761 public void file(Closure closure) { ConfigureUtil.configure(closure, file); }
764 task eclipseUIPreferences(type: PropertiesFileTask) {
765 description = "Generate Eclipse additional settings"
766 def filename = "org.eclipse.jdt.ui.prefs"
767 outputFile = "$projectDir/.settings/${filename}" as File
770 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
775 task eclipseGroovyCorePreferences(type: PropertiesFileTask) {
776 description = "Generate Eclipse additional settings"
777 def filename = "org.eclipse.jdt.groovy.core.prefs"
778 outputFile = "$projectDir/.settings/${filename}" as File
781 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
786 task eclipseAllPreferences {
788 dependsOn eclipseUIPreferences
789 dependsOn eclipseGroovyCorePreferences
792 eclipseUIPreferences.mustRunAfter eclipseJdt
793 eclipseGroovyCorePreferences.mustRunAfter eclipseJdt
795 /* end of eclipse preferences hack */
803 delete cloverBuildDir
804 delete cloverReportDir
809 task cloverInstrJava(type: JavaExec) {
810 group = "Verification"
811 description = "Create clover instrumented source java files"
813 dependsOn cleanClover
815 inputs.files(sourceSets.main.allJava)
816 outputs.dir(cloverInstrDir)
818 //classpath = fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
819 classpath = sourceSets.clover.compileClasspath
820 main = "com.atlassian.clover.CloverInstr"
828 cloverInstrDir.getPath(),
830 def srcFiles = sourceSets.main.allJava.files
833 { file -> file.absolutePath }
836 args argsList.toArray()
839 delete cloverInstrDir
840 println("Clover: About to instrument "+srcFiles.size() +" files")
845 task cloverInstrTests(type: JavaExec) {
846 group = "Verification"
847 description = "Create clover instrumented source test files"
849 dependsOn cleanClover
851 inputs.files(testDir)
852 outputs.dir(cloverTestInstrDir)
854 classpath = sourceSets.clover.compileClasspath
855 main = "com.atlassian.clover.CloverInstr"
865 cloverTestInstrDir.getPath(),
867 args argsList.toArray()
870 delete cloverTestInstrDir
871 println("Clover: About to instrument test files")
877 group = "Verification"
878 description = "Create clover instrumented all source files"
880 dependsOn cloverInstrJava
881 dependsOn cloverInstrTests
885 cloverClasses.dependsOn cloverInstr
888 task cloverConsoleReport(type: JavaExec) {
889 group = "Verification"
890 description = "Creates clover console report"
893 file(cloverDb).exists()
896 inputs.dir cloverClassesDir
898 classpath = sourceSets.clover.runtimeClasspath
899 main = "com.atlassian.clover.reporters.console.ConsoleReporter"
901 if (cloverreport_mem.length() > 0) {
902 maxHeapSize = cloverreport_mem
904 if (cloverreport_jvmargs.length() > 0) {
905 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
915 args argsList.toArray()
919 task cloverHtmlReport(type: JavaExec) {
920 group = "Verification"
921 description = "Creates clover HTML report"
924 file(cloverDb).exists()
927 def cloverHtmlDir = cloverReportDir
928 inputs.dir cloverClassesDir
929 outputs.dir cloverHtmlDir
931 classpath = sourceSets.clover.runtimeClasspath
932 main = "com.atlassian.clover.reporters.html.HtmlReporter"
934 if (cloverreport_mem.length() > 0) {
935 maxHeapSize = cloverreport_mem
937 if (cloverreport_jvmargs.length() > 0) {
938 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
949 if (cloverreport_html_options.length() > 0) {
950 argsList += cloverreport_html_options.split(" ")
953 args argsList.toArray()
957 task cloverXmlReport(type: JavaExec) {
958 group = "Verification"
959 description = "Creates clover XML report"
962 file(cloverDb).exists()
965 def cloverXmlFile = "${cloverReportDir}/clover.xml"
966 inputs.dir cloverClassesDir
967 outputs.file cloverXmlFile
969 classpath = sourceSets.clover.runtimeClasspath
970 main = "com.atlassian.clover.reporters.xml.XMLReporter"
972 if (cloverreport_mem.length() > 0) {
973 maxHeapSize = cloverreport_mem
975 if (cloverreport_jvmargs.length() > 0) {
976 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
987 if (cloverreport_xml_options.length() > 0) {
988 argsList += cloverreport_xml_options.split(" ")
991 args argsList.toArray()
996 group = "Verification"
997 description = "Creates clover reports"
999 dependsOn cloverXmlReport
1000 dependsOn cloverHtmlReport
1007 sourceCompatibility = compile_source_compatibility
1008 targetCompatibility = compile_target_compatibility
1009 options.compilerArgs += additional_compiler_args
1010 print ("Setting target compatibility to "+targetCompatibility+"\n")
1012 //classpath += configurations.cloverRuntime
1018 // JBP->BS should the print statement in doFirst refer to compile_target_compatibility ?
1019 sourceCompatibility = compile_source_compatibility
1020 targetCompatibility = compile_target_compatibility
1021 options.compilerArgs = additional_compiler_args
1022 options.encoding = "UTF-8"
1024 print ("Setting target compatibility to "+compile_target_compatibility+"\n")
1031 sourceCompatibility = compile_source_compatibility
1032 targetCompatibility = compile_target_compatibility
1033 options.compilerArgs = additional_compiler_args
1035 print ("Setting target compatibility to "+targetCompatibility+"\n")
1042 delete sourceSets.main.java.outputDir
1048 dependsOn cleanClover
1050 delete sourceSets.test.java.outputDir
1055 // format is a string like date.format("dd MMMM yyyy")
1056 def getDate(format) {
1057 def date = new Date()
1058 return date.format(format)
1062 def convertMdToHtml (FileTree mdFiles, File cssFile) {
1063 MutableDataSet options = new MutableDataSet()
1065 def extensions = new ArrayList<>()
1066 extensions.add(AnchorLinkExtension.create())
1067 extensions.add(AutolinkExtension.create())
1068 extensions.add(StrikethroughExtension.create())
1069 extensions.add(TaskListExtension.create())
1070 extensions.add(TablesExtension.create())
1071 extensions.add(TocExtension.create())
1073 options.set(Parser.EXTENSIONS, extensions)
1075 // set GFM table parsing options
1076 options.set(TablesExtension.WITH_CAPTION, false)
1077 options.set(TablesExtension.COLUMN_SPANS, false)
1078 options.set(TablesExtension.MIN_HEADER_ROWS, 1)
1079 options.set(TablesExtension.MAX_HEADER_ROWS, 1)
1080 options.set(TablesExtension.APPEND_MISSING_COLUMNS, true)
1081 options.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
1082 options.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
1084 options.set(AnchorLinkExtension.ANCHORLINKS_SET_ID, false)
1085 options.set(AnchorLinkExtension.ANCHORLINKS_ANCHOR_CLASS, "anchor")
1086 options.set(AnchorLinkExtension.ANCHORLINKS_SET_NAME, true)
1087 options.set(AnchorLinkExtension.ANCHORLINKS_TEXT_PREFIX, "<span class=\"octicon octicon-link\"></span>")
1089 Parser parser = Parser.builder(options).build()
1090 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1092 mdFiles.each { mdFile ->
1093 // add table of contents
1094 def mdText = "[TOC]\n"+mdFile.text
1096 // grab the first top-level title
1098 def titleRegex = /(?m)^#(\s+|([^#]))(.*)/
1099 def matcher = mdText =~ titleRegex
1100 if (matcher.size() > 0) {
1101 // matcher[0][2] is the first character of the title if there wasn't any whitespace after the #
1102 title = (matcher[0][2] != null ? matcher[0][2] : "")+matcher[0][3]
1104 // or use the filename if none found
1105 if (title == null) {
1106 title = mdFile.getName()
1109 Node document = parser.parse(mdText)
1110 String htmlBody = renderer.render(document)
1111 def htmlText = '''<html>
1112 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1113 <html xmlns="http://www.w3.org/1999/xhtml">
1115 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1116 <meta http-equiv="Content-Style-Type" content="text/css" />
1117 <meta name="generator" content="flexmark" />
1119 htmlText += ((title != null) ? " <title>${title}</title>" : '' )
1121 <style type="text/css">code{white-space: pre;}</style>
1123 htmlText += ((cssFile != null) ? cssFile.text : '')
1124 htmlText += '''</head>
1127 htmlText += htmlBody
1133 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1134 def htmlFile = file(htmlFilePath)
1135 println("Creating ${htmlFilePath}")
1136 htmlFile.text = htmlText
1141 task copyDocs(type: Copy) {
1142 def inputDir = "${jalviewDir}/${doc_dir}"
1143 def outputDir = "${docBuildDir}/${doc_dir}"
1147 include('**/*.html')
1149 filter(ReplaceTokens,
1153 'Version-Rel': JALVIEW_VERSION,
1154 'Year-Rel': getDate("yyyy")
1161 exclude('**/*.html')
1166 inputs.dir(inputDir)
1167 outputs.dir(outputDir)
1171 task convertMdFiles {
1173 def mdFiles = fileTree(dir: docBuildDir, include: "**/*.md")
1174 def cssFile = file("${jalviewDir}/${flexmark_css}")
1177 convertMdToHtml(mdFiles, cssFile)
1180 inputs.files(mdFiles)
1181 inputs.file(cssFile)
1184 mdFiles.each { mdFile ->
1185 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1186 htmlFiles.add(file(htmlFilePath))
1188 outputs.files(htmlFiles)
1192 task copyHelp(type: Copy) {
1193 def inputDir = helpSourceDir
1194 def outputDir = "${helpBuildDir}/${help_dir}"
1198 include('**/*.html')
1202 filter(ReplaceTokens,
1206 'Version-Rel': JALVIEW_VERSION,
1207 'Year-Rel': getDate("yyyy")
1214 exclude('**/*.html')
1221 inputs.dir(inputDir)
1222 outputs.files(helpFile)
1223 outputs.dir(outputDir)
1227 task copyResources(type: Copy) {
1229 description = "Copy (and make text substitutions in) the resources dir to the build area"
1231 def inputDir = resourceDir
1232 def outputDir = resourcesBuildDir
1236 include('**/*.html')
1238 filter(ReplaceTokens,
1242 'Version-Rel': JALVIEW_VERSION,
1243 'Year-Rel': getDate("yyyy")
1250 exclude('**/*.html')
1255 inputs.dir(inputDir)
1256 outputs.dir(outputDir)
1259 task copyChannelResources(type: Copy) {
1260 dependsOn copyResources
1262 description = "Copy the channel resources dir to the build resources area"
1264 def inputDir = "${channelDir}/${resource_dir}"
1265 def outputDir = resourcesBuildDir
1269 inputs.dir(inputDir)
1270 outputs.dir(outputDir)
1273 task createBuildProperties(type: WriteProperties) {
1274 dependsOn copyResources
1276 description = "Create the ${buildProperties} file"
1278 inputs.dir(sourceDir)
1279 inputs.dir(resourcesBuildDir)
1280 outputFile (buildProperties)
1281 // taking time specific comment out to allow better incremental builds
1282 comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
1283 //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
1284 property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
1285 property "VERSION", JALVIEW_VERSION
1286 property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
1287 if (getdownSetAppBaseProperty) {
1288 property "GETDOWNAPPBASE", getdownAppBase
1289 property "GETDOWNAPPDISTDIR", getdownAppDistDir
1291 outputs.file(outputFile)
1295 task buildIndices(type: JavaExec) {
1297 classpath = sourceSets.main.compileClasspath
1298 main = "com.sun.java.help.search.Indexer"
1299 workingDir = "${helpBuildDir}/${help_dir}"
1302 inputs.dir("${workingDir}/${argDir}")
1304 outputs.dir("${classesDir}/doc")
1305 outputs.dir("${classesDir}/help")
1306 outputs.file("${workingDir}/JavaHelpSearch/DOCS")
1307 outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
1308 outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
1309 outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
1310 outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
1311 outputs.file("${workingDir}/JavaHelpSearch/TMAP")
1314 task buildResources {
1315 dependsOn copyResources
1316 dependsOn copyChannelResources
1317 dependsOn createBuildProperties
1321 dependsOn buildResources
1324 dependsOn convertMdFiles
1325 dependsOn buildIndices
1329 compileJava.dependsOn prepare
1330 run.dependsOn compileJava
1331 //run.dependsOn prepare
1334 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1339 dependsOn cloverClasses
1341 dependsOn compileJava //?
1345 includeGroups testng_groups
1346 excludeGroups testng_excluded_groups
1348 useDefaultListeners=true
1351 maxHeapSize = "1024m"
1353 workingDir = jalviewDir
1354 def testLaf = project.findProperty("test_laf")
1355 if (testLaf != null) {
1356 println("Setting Test LaF to '${testLaf}'")
1357 systemProperty "laf", testLaf
1359 def testHiDPIScale = project.findProperty("test_HiDPIScale")
1360 if (testHiDPIScale != null) {
1361 println("Setting Test HiDPI Scale to '${testHiDPIScale}'")
1362 systemProperty "sun.java2d.uiScale", testHiDPIScale
1364 sourceCompatibility = compile_source_compatibility
1365 targetCompatibility = compile_target_compatibility
1366 jvmArgs += additional_compiler_args
1370 println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1376 task compileLinkCheck(type: JavaCompile) {
1378 classpath = files("${jalviewDir}/${utils_dir}")
1379 destinationDir = file("${jalviewDir}/${utils_dir}")
1380 source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1382 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1383 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1384 outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1385 outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1389 task linkCheck(type: JavaExec) {
1391 dependsOn compileLinkCheck
1393 def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1394 classpath = files("${jalviewDir}/${utils_dir}")
1395 main = "HelpLinksChecker"
1396 workingDir = jalviewDir
1397 args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1399 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1400 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1403 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1407 inputs.dir(helpBuildDir)
1408 outputs.file(helpLinksCheckerOutFile)
1412 // import the pubhtmlhelp target
1413 ant.properties.basedir = "${jalviewDir}"
1414 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1415 ant.importBuild "${utils_dir}/publishHelp.xml"
1418 task cleanPackageDir(type: Delete) {
1420 delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1430 attributes "Main-Class": main_class,
1431 "Permissions": "all-permissions",
1432 "Application-Name": install4jApplicationName,
1433 "Codebase": application_codebase,
1434 "Implementation-Version": JALVIEW_VERSION
1437 def outputDir = "${jalviewDir}/${package_dir}"
1438 destinationDirectory = file(outputDir)
1439 archiveFileName = rootProject.name+".jar"
1440 duplicatesStrategy "EXCLUDE"
1447 exclude "**/*.jar.*"
1449 inputs.dir(sourceSets.main.java.outputDir)
1450 sourceSets.main.resources.srcDirs.each{ dir ->
1453 outputs.file("${outputDir}/${archiveFileName}")
1457 task copyJars(type: Copy) {
1458 from fileTree(dir: classesDir, include: "**/*.jar").files
1459 into "${jalviewDir}/${package_dir}"
1463 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1464 task syncJars(type: Sync) {
1466 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1467 into "${jalviewDir}/${package_dir}"
1469 include jar.archiveFileName.getOrNull()
1476 description = "Put all required libraries in dist"
1477 // order of "cleanPackageDir", "copyJars", "jar" important!
1478 jar.mustRunAfter cleanPackageDir
1479 syncJars.mustRunAfter cleanPackageDir
1480 dependsOn cleanPackageDir
1483 outputs.dir("${jalviewDir}/${package_dir}")
1488 dependsOn cleanPackageDir
1495 group = "distribution"
1496 description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1500 from ("${jalviewDir}/${libDistDir}") {
1504 attributes "Implementation-Version": JALVIEW_VERSION,
1505 "Application-Name": install4jApplicationName
1508 duplicatesStrategy "INCLUDE"
1510 mainClassName = shadow_jar_main_class
1512 classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1517 task getdownWebsite() {
1518 group = "distribution"
1519 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1524 def getdownWebsiteResourceFilenames = []
1525 def getdownResourceDir = getdownResourceDir
1526 def getdownResourceFilenames = []
1529 // clean the getdown website and files dir before creating getdown folders
1530 delete getdownWebsiteDir
1531 delete getdownFilesDir
1534 from buildProperties
1535 rename(file(buildProperties).getName(), getdown_build_properties)
1538 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1541 from channelPropsFile
1542 into getdownWebsiteDir
1544 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
1546 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
1547 def props = project.properties.sort { it.key }
1548 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
1549 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
1551 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
1552 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
1554 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
1555 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
1557 if (getdownImagesDir != null && file(getdownImagesDir).exists()) {
1558 props.put("getdown_txt_ui.background_image", "${getdownImagesDir}/${getdown_background_image}")
1559 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesDir}/${getdown_instant_background_image}")
1560 props.put("getdown_txt_ui.error_background", "${getdownImagesDir}/${getdown_error_background}")
1561 props.put("getdown_txt_ui.progress_image", "${getdownImagesDir}/${getdown_progress_image}")
1562 props.put("getdown_txt_ui.icon", "${getdownImagesDir}/${getdown_icon}")
1563 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesDir}/${getdown_mac_dock_icon}")
1566 props.put("getdown_txt_title", jalview_name)
1567 props.put("getdown_txt_ui.name", install4jApplicationName)
1569 // start with appbase
1570 getdownTextLines += "appbase = ${getdownAppBase}"
1571 props.each{ prop, val ->
1572 if (prop.startsWith("getdown_txt_") && val != null) {
1573 if (prop.startsWith("getdown_txt_multi_")) {
1574 def key = prop.substring(18)
1575 val.split(",").each{ v ->
1576 def line = "${key} = ${v}"
1577 getdownTextLines += line
1580 // file values rationalised
1581 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
1583 if (val.indexOf('/') == 0) {
1586 } else if (val.indexOf('/') > 0) {
1587 // relative path (relative to jalviewDir)
1588 r = file( "${jalviewDir}/${val}" )
1591 val = "${getdown_resource_dir}/" + r.getName()
1592 getdownWebsiteResourceFilenames += val
1593 getdownResourceFilenames += r.getPath()
1596 if (! prop.startsWith("getdown_txt_resource")) {
1597 def line = prop.substring(12) + " = ${val}"
1598 getdownTextLines += line
1604 getdownWebsiteResourceFilenames.each{ filename ->
1605 getdownTextLines += "resource = ${filename}"
1607 getdownResourceFilenames.each{ filename ->
1610 into getdownResourceDir
1614 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
1615 getdownWrapperScripts.each{ script ->
1616 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
1620 into "${getdownWebsiteDir}/${getdown_wrapper_script_dir}"
1622 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
1627 fileTree(file(package_dir)).each{ f ->
1628 if (f.isDirectory()) {
1629 def files = fileTree(dir: f, include: ["*"]).getFiles()
1631 } else if (f.exists()) {
1635 def jalviewJar = jar.archiveFileName.getOrNull()
1636 // put jalview.jar first for CLASSPATH and .properties files reasons
1637 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
1638 def name = f.getName()
1639 def line = "code = ${getdownAppDistDir}/${name}"
1640 getdownTextLines += line
1647 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
1649 if (JAVA_VERSION.equals("11")) {
1650 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
1651 j11libFiles.sort().each{f ->
1652 def name = f.getName()
1653 def line = "code = ${getdown_j11lib_dir}/${name}"
1654 getdownTextLines += line
1657 into getdownJ11libDir
1663 // 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.
1664 //getdownTextLines += "class = " + file(getdownLauncher).getName()
1665 getdownTextLines += "resource = ${getdown_launcher_new}"
1666 getdownTextLines += "class = ${main_class}"
1667 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
1668 if (getdownSetAppBaseProperty) {
1669 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
1670 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
1673 def getdownTxt = file("${getdownWebsiteDir}/getdown.txt")
1674 getdownTxt.write(getdownTextLines.join("\n"))
1676 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
1677 def launchJvl = file("${getdownWebsiteDir}/${getdownLaunchJvl}")
1678 launchJvl.write("appbase=${getdownAppBase}")
1680 // files going into the getdown website dir: getdown-launcher.jar
1682 from getdownLauncher
1683 rename(file(getdownLauncher).getName(), getdown_launcher_new)
1684 into getdownWebsiteDir
1687 // files going into the getdown website dir: getdown-launcher(-local).jar
1689 from getdownLauncher
1690 if (file(getdownLauncher).getName() != getdown_launcher) {
1691 rename(file(getdownLauncher).getName(), getdown_launcher)
1693 into getdownWebsiteDir
1696 // files going into the getdown website dir: ./install dir and files
1697 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
1700 from getdownLauncher
1701 from "${getdownAppDir}/${getdown_build_properties}"
1702 if (file(getdownLauncher).getName() != getdown_launcher) {
1703 rename(file(getdownLauncher).getName(), getdown_launcher)
1705 into getdownInstallDir
1708 // and make a copy in the getdown files dir (these are not downloaded by getdown)
1710 from getdownInstallDir
1711 into getdownFilesInstallDir
1715 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
1719 from getdownLauncher
1720 from "${getdownWebsiteDir}/${getdown_build_properties}"
1721 from "${getdownWebsiteDir}/${channel_props}"
1722 if (file(getdownLauncher).getName() != getdown_launcher) {
1723 rename(file(getdownLauncher).getName(), getdown_launcher)
1725 into getdownFilesDir
1728 // and ./resource (not all downloaded by getdown)
1730 from getdownResourceDir
1731 into "${getdownFilesDir}/${getdown_resource_dir}"
1736 inputs.dir("${jalviewDir}/${package_dir}")
1738 outputs.dir(getdownWebsiteDir)
1739 outputs.dir(getdownFilesDir)
1743 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
1744 task getdownDigestDir(type: JavaExec) {
1746 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
1748 def digestDirPropertyName = "DIGESTDIR"
1750 classpath = files(getdownLauncher)
1751 def digestDir = findProperty(digestDirPropertyName)
1752 if (digestDir == null) {
1753 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
1757 main = "com.threerings.getdown.tools.Digester"
1761 task getdownDigest(type: JavaExec) {
1762 group = "distribution"
1763 description = "Digest the getdown website folder"
1764 dependsOn getdownWebsite
1766 classpath = files(getdownLauncher)
1768 main = "com.threerings.getdown.tools.Digester"
1769 args getdownWebsiteDir
1770 inputs.dir(getdownWebsiteDir)
1771 outputs.file("${getdownWebsiteDir}/digest2.txt")
1776 group = "distribution"
1777 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
1778 dependsOn getdownDigest
1780 if (reportRsyncCommand) {
1781 def fromDir = getdownWebsiteDir + (getdownWebsiteDir.endsWith('/')?'':'/')
1782 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
1783 println "LIKELY RSYNC COMMAND:"
1784 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
1785 if (RUNRSYNC == "true") {
1787 commandLine "mkdir", "-p", toDir
1790 commandLine "rsync", "-avh", "--delete", fromDir, toDir
1798 task getdownArchiveBuild() {
1799 group = "distribution"
1800 description = "Put files in the archive dir to go on the website"
1802 dependsOn getdownWebsite
1804 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
1805 def vDir = "${getdownArchiveDir}/${v}"
1806 getdownFullArchiveDir = "${vDir}/getdown"
1807 def vLaunchVersionJvl = "${vDir}/jalview-${v}.jvl"
1808 def vAltDir = "alt_${v}"
1809 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
1812 if (getdownArchiveAppBase == null) {
1813 throw new StopExecutionException("Cannot create getdownArchive for CHANNEL=${CHANNEL}")
1816 // cleanup old "old" dir
1817 delete getdownArchiveDir
1819 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
1820 getdownArchiveTxt.getParentFile().mkdirs()
1821 def getdownArchiveTextLines = []
1822 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
1826 from "${getdownWebsiteDir}/${getdownAppDistDir}"
1827 into "${getdownFullArchiveDir}/${vAltDir}"
1830 getdownTextLines.each { line ->
1831 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
1832 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
1833 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
1834 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
1835 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
1836 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
1837 // remove the existing resource = resource/ or bin/ lines
1838 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
1839 getdownArchiveTextLines += line
1843 // the resource dir -- add these files as resource lines in getdown.txt
1845 from "${archiveImagesDir}"
1846 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
1848 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
1852 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
1854 def vLaunchJvl = file(vLaunchVersionJvl)
1855 vLaunchJvl.getParentFile().mkdirs()
1856 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
1857 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
1858 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
1859 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
1860 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
1861 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
1863 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
1865 from getdownLauncher
1866 from "${getdownWebsiteDir}/${getdownLaunchJvl}"
1867 from "${getdownWebsiteDir}/${getdown_launcher_new}"
1868 from "${getdownWebsiteDir}/${channel_props}"
1869 if (file(getdownLauncher).getName() != getdown_launcher) {
1870 rename(file(getdownLauncher).getName(), getdown_launcher)
1872 into getdownFullArchiveDir
1878 task getdownArchiveDigest(type: JavaExec) {
1879 group = "distribution"
1880 description = "Digest the getdown archive folder"
1882 dependsOn getdownArchiveBuild
1885 classpath = files(getdownLauncher)
1886 args getdownFullArchiveDir
1888 main = "com.threerings.getdown.tools.Digester"
1889 inputs.dir(getdownFullArchiveDir)
1890 outputs.file("${getdownFullArchiveDir}/digest2.txt")
1893 task getdownArchive() {
1894 group = "distribution"
1895 description = "Build the website archive dir with getdown digest"
1897 dependsOn getdownArchiveBuild
1898 dependsOn getdownArchiveDigest
1901 tasks.withType(JavaCompile) {
1902 options.encoding = 'UTF-8'
1908 delete getdownWebsiteDir
1909 delete getdownFilesDir
1910 delete getdownArchiveDir
1916 if (file(install4jHomeDir).exists()) {
1918 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
1919 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
1920 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
1921 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
1923 installDir(file(install4jHomeDir))
1925 mediaTypes = Arrays.asList(install4j_media_types.split(","))
1929 task copyInstall4jTemplate {
1930 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
1931 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
1932 inputs.file(install4jTemplateFile)
1933 inputs.file(install4jFileAssociationsFile)
1934 inputs.property("CHANNEL", { CHANNEL })
1935 outputs.file(install4jConfFile)
1938 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
1940 // turn off code signing if no OSX_KEYPASS
1941 if (OSX_KEYPASS == "") {
1942 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
1943 codeSigning.'@macEnabled' = "false"
1945 install4jConfigXml.'**'.windows.each { windows ->
1946 windows.'@runPostProcessor' = "false"
1950 // disable install screen for OSX dmg (for 2.11.2.0)
1951 install4jConfigXml.'**'.macosArchive.each { macosArchive ->
1952 macosArchive.attributes().remove('executeSetupApp')
1953 macosArchive.attributes().remove('setupAppId')
1956 // turn off checksum creation for LOCAL channel
1957 def e = install4jConfigXml.application[0]
1958 e.'@createChecksums' = string(install4jCheckSums)
1960 // put file association actions where placeholder action is
1961 def install4jFileAssociationsText = install4jFileAssociationsFile.text
1962 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
1963 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
1964 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
1965 def parent = a.parent()
1967 fileAssociationActions.each { faa ->
1970 // don't need to continue in .any loop once replacements have been made
1975 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
1976 // NB we're deleting the /other/ one!
1977 // Also remove the examples subdir from non-release versions
1978 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
1979 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
1980 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
1981 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
1983 // remove the examples subdir from Full File Set
1984 def files = install4jConfigXml.files[0]
1985 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
1986 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
1987 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
1988 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
1989 dirEntry.parent().remove(dirEntry)
1991 install4jConfigXml.'**'.action.any { a ->
1992 if (a.'@customizedId' == customizedIdToDelete) {
1993 def parent = a.parent()
1999 // write install4j file
2000 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
2007 delete install4jConfFile
2011 task cleanInstallersDataFiles {
2012 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2013 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2014 def VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
2015 def installersJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${VERSION_UNDERSCORES}.json")
2017 delete installersOutputTxt
2018 delete installersSha256
2019 delete installersJsonFile
2023 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2024 group = "distribution"
2025 description = "Create the install4j installers"
2027 dependsOn copyInstall4jTemplate
2028 dependsOn cleanInstallersDataFiles
2030 projectFile = install4jConfFile
2032 // create an md5 for the input files to use as version for install4j conf file
2033 def digest = MessageDigest.getInstance("MD5")
2035 (file("${install4jDir}/${install4j_template}").text +
2036 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2037 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2038 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2039 if (filesMd5.length() >= 8) {
2040 filesMd5 = filesMd5.substring(0,8)
2042 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2045 'JALVIEW_NAME': jalview_name,
2046 'JALVIEW_APPLICATION_NAME': install4jApplicationName,
2047 'JALVIEW_DIR': "../..",
2048 'OSX_KEYSTORE': OSX_KEYSTORE,
2049 'OSX_APPLEID': OSX_APPLEID,
2050 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2051 'JSIGN_SH': JSIGN_SH,
2052 'JRE_DIR': getdown_app_dir_java,
2053 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2054 'JALVIEW_VERSION': JALVIEW_VERSION,
2055 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2056 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2057 'JAVA_VERSION': JAVA_VERSION,
2058 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2059 'VERSION': JALVIEW_VERSION,
2060 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2061 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2062 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2063 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2064 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2065 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2066 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2067 'BUNDLE_ID': install4jBundleId,
2068 'INTERNAL_ID': install4jInternalId,
2069 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2070 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2071 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
2072 'WRAPPER_LINK': getdownWrapperLink,
2073 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2074 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2075 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2076 'INSTALLER_NAME': install4jInstallerName,
2077 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2078 'GETDOWN_WEBSITE_DIR': getdown_website_dir,
2079 'GETDOWN_FILES_DIR': getdown_files_dir,
2080 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2081 'GETDOWN_DIST_DIR': getdownAppDistDir,
2082 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2083 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2084 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2085 'BUILD_DIR': install4jBuildDir,
2086 'APPLICATION_CATEGORIES': install4j_application_categories,
2087 'APPLICATION_FOLDER': install4jApplicationFolder,
2088 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2089 'EXECUTABLE_NAME': install4jExecutableName,
2090 'EXTRA_SCHEME': install4jExtraScheme,
2091 'MAC_ICONS_FILE': install4jMacIconsFile,
2092 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2093 'PNG_ICON_FILE': install4jPngIconFile,
2094 'BACKGROUND': install4jBackground,
2098 //println("INSTALL4J VARIABLES:")
2099 //variables.each{k,v->println("${k}=${v}")}
2101 destination = "${jalviewDir}/${install4jBuildDir}"
2102 buildSelected = true
2104 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2106 disableSigning = true
2107 disableNotarization = true
2111 macKeystorePassword = OSX_KEYPASS
2114 if (OSX_ALTOOLPASS) {
2115 appleIdPassword = OSX_ALTOOLPASS
2116 disableNotarization = false
2118 disableNotarization = true
2122 println("Using projectFile "+projectFile)
2123 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2127 inputs.dir(getdownWebsiteDir)
2128 inputs.file(install4jConfFile)
2129 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2130 inputs.dir(macosJavaVMDir)
2131 inputs.dir(windowsJavaVMDir)
2132 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2135 def writeInstallersJsonFile(File installersOutputTxt, File installersSha256, File installersJsonFile) {
2136 if (!installersOutputTxt.exists()) {
2137 throw new GradleException("Required input file '${installersOutputTxt.getPath()}' doesn't exist.")
2140 if (install4jCheckSums && (!installersSha256)) {
2141 throw new GradleException("Required input file '${installersSha256.getPath()}' doesn't exist.")
2146 installersOutputTxt.readLines().each { def line ->
2147 if (line.startsWith("#")) {
2150 line.replaceAll("\n","")
2151 def vals = line.split("\t")
2152 def filename = vals[3]
2153 def filesize = file(filename).length()
2154 filename = filename.replaceAll(/^.*\//, "")
2155 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2156 idHash."${filename}" = vals[0]
2158 if (install4jCheckSums) {
2159 installersSha256.readLines().each { def line ->
2160 if (line.startsWith("#")) {
2163 line.replaceAll("\n","")
2164 def vals = line.split(/\s+\*?/)
2165 def filename = vals[1]
2166 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2169 return installersJsonFile.write(new JsonBuilder(hash).toPrettyString())
2172 task makeInstallersJsonFile {
2173 dependsOn installerFiles
2175 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2176 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2177 def VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
2178 def installersJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${VERSION_UNDERSCORES}.json")
2180 inputs.file(installersOutputTxt)
2181 if (install4jCheckSums) {
2182 inputs.file(installersSha256)
2184 outputs.file(installersJsonFile)
2187 writeInstallersJsonFile(installersOutputTxt, installersSha256, installersJsonFile)
2191 task staticMakeInstallersJsonFile {
2193 def output = findProperty("i4j_output")
2194 def sha256 = findProperty("i4j_sha256")
2195 def json = findProperty("i4j_json")
2196 if (output == null || sha256 == null || json == null) {
2197 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2199 writeInstallersJsonFile(file(output), file(sha256), file(json))
2204 dependsOn installerFiles
2205 dependsOn makeInstallersJsonFile
2211 eclipse().configFile(eclipse_codestyle_file)
2215 task createSourceReleaseProperties(type: WriteProperties) {
2216 group = "distribution"
2217 description = "Create the source RELEASE properties file"
2219 def sourceTarBuildDir = "${buildDir}/sourceTar"
2220 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2221 outputFile (sourceReleasePropertiesFile)
2224 releaseProps.each{ key, val -> property key, val }
2225 property "git.branch", gitBranch
2226 property "git.hash", gitHash
2229 outputs.file(outputFile)
2232 task sourceDist(type: Tar) {
2233 group "distribution"
2234 description "Create a source .tar.gz file for distribution"
2236 dependsOn createBuildProperties
2237 dependsOn convertMdFiles
2238 dependsOn eclipseAllPreferences
2239 dependsOn createSourceReleaseProperties
2242 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2243 archiveFileName = outputFileName
2245 compression Compression.GZIP
2260 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2262 "utils/InstallAnywhere",
2277 "gradle.properties",
2289 ".settings/org.eclipse.buildship.core.prefs",
2290 ".settings/org.eclipse.jdt.core.prefs"
2294 exclude (EXCLUDE_FILES)
2295 include (PROCESS_FILES)
2296 filter(ReplaceTokens,
2300 'Version-Rel': JALVIEW_VERSION,
2301 'Year-Rel': getDate("yyyy")
2306 exclude (EXCLUDE_FILES)
2307 exclude (PROCESS_FILES)
2308 exclude ("appletlib")
2309 exclude ("**/*locales")
2310 exclude ("*locales/**")
2311 exclude ("utils/InstallAnywhere")
2313 exclude (getdown_files_dir)
2314 exclude (getdown_website_dir)
2316 // exluding these as not using jars as modules yet
2317 exclude ("${j11modDir}/**/*.jar")
2320 include(INCLUDE_FILES)
2322 // from (jalviewDir) {
2323 // // explicit includes for stuff that seemed to not get included
2324 // include(fileTree("test/**/*."))
2325 // exclude(EXCLUDE_FILES)
2326 // exclude(PROCESS_FILES)
2329 from(file(buildProperties).getParent()) {
2330 include(file(buildProperties).getName())
2331 rename(file(buildProperties).getName(), "build_properties")
2333 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2337 def sourceTarBuildDir = "${buildDir}/sourceTar"
2338 from(sourceTarBuildDir) {
2339 // this includes the appended RELEASE properties file
2346 dependsOn pubhtmlhelp
2348 inputs.dir("${helpBuildDir}/${help_dir}")
2349 outputs.dir("${buildDir}/distributions/${help_dir}")
2353 task j2sSetHeadlessBuild {
2360 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2362 description "Enable the alternative J2S Config file for headless build"
2364 outputFile = jalviewjsJ2sSettingsFileName
2365 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2366 def j2sProps = new Properties()
2367 if (j2sPropsFile.exists()) {
2369 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2370 j2sProps.load(j2sPropsFileFIS)
2371 j2sPropsFileFIS.close()
2373 j2sProps.each { prop, val ->
2376 } catch (Exception e) {
2377 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2381 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2382 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2387 task jalviewjsSetEclipseWorkspace {
2388 def propKey = "jalviewjs_eclipse_workspace"
2390 if (project.hasProperty(propKey)) {
2391 propVal = project.getProperty(propKey)
2392 if (propVal.startsWith("~/")) {
2393 propVal = System.getProperty("user.home") + propVal.substring(1)
2396 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2397 def propsFile = file(propsFileName)
2398 def eclipseWsDir = propVal
2399 def props = new Properties()
2401 def writeProps = true
2402 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2403 def ins = new FileInputStream(propsFileName)
2406 if (props.getProperty(propKey, null) != null) {
2407 eclipseWsDir = props.getProperty(propKey)
2412 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2413 def tempDir = File.createTempDir()
2414 eclipseWsDir = tempDir.getAbsolutePath()
2417 eclipseWorkspace = file(eclipseWsDir)
2420 // do not run a headless transpile when we claim to be in Eclipse
2422 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2423 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2425 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2429 props.setProperty(propKey, eclipseWsDir)
2430 propsFile.parentFile.mkdirs()
2431 def bytes = new ByteArrayOutputStream()
2432 props.store(bytes, null)
2433 def propertiesString = bytes.toString()
2434 propsFile.text = propertiesString
2440 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2443 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2444 outputs.file(propsFileName)
2445 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2449 task jalviewjsEclipsePaths {
2452 def eclipseRoot = jalviewjs_eclipse_root
2453 if (eclipseRoot.startsWith("~/")) {
2454 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
2456 if (OperatingSystem.current().isMacOsX()) {
2457 eclipseRoot += "/Eclipse.app"
2458 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
2459 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
2460 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
2461 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2462 eclipseRoot += "/eclipse"
2464 eclipseBinary = "${eclipseRoot}/eclipse.exe"
2465 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2466 } else { // linux or unix
2467 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2468 eclipseRoot += "/eclipse"
2469 println("eclipseDir exists")
2471 eclipseBinary = "${eclipseRoot}/eclipse"
2472 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2475 eclipseVersion = "4.13" // default
2476 def assumedVersion = true
2477 if (file(eclipseProduct).exists()) {
2478 def fis = new FileInputStream(eclipseProduct)
2479 def props = new Properties()
2481 eclipseVersion = props.getProperty("version")
2483 assumedVersion = false
2486 def propKey = "eclipse_debug"
2487 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
2490 // do not run a headless transpile when we claim to be in Eclipse
2492 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2493 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2495 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2498 if (!assumedVersion) {
2499 println("ECLIPSE VERSION=${eclipseVersion}")
2505 task printProperties {
2507 description "Output to console all System.properties"
2509 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
2515 dependsOn eclipseProject
2516 dependsOn eclipseClasspath
2517 dependsOn eclipseJdt
2521 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
2522 task jalviewjsEclipseCopyDropins(type: Copy) {
2523 dependsOn jalviewjsEclipsePaths
2525 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
2526 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
2527 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
2534 // this eclipse -clean doesn't actually work
2535 task jalviewjsCleanEclipse(type: Exec) {
2536 dependsOn eclipseSetup
2537 dependsOn jalviewjsEclipsePaths
2538 dependsOn jalviewjsEclipseCopyDropins
2540 executable(eclipseBinary)
2541 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
2547 def inputString = """exit
2550 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
2551 standardInput = inputByteStream
2554 /* not really working yet
2555 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
2559 task jalviewjsTransferUnzipSwingJs {
2560 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
2564 from zipTree(file_zip)
2565 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2569 inputs.file file_zip
2570 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2574 task jalviewjsTransferUnzipLib {
2575 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
2578 zipFiles.each { file_zip ->
2580 from zipTree(file_zip)
2581 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2586 inputs.files zipFiles
2587 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2591 task jalviewjsTransferUnzipAllLibs {
2592 dependsOn jalviewjsTransferUnzipSwingJs
2593 dependsOn jalviewjsTransferUnzipLib
2597 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
2599 description "Create the alternative j2s file from the j2s.* properties"
2601 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
2602 def siteDirProperty = "j2s.site.directory"
2603 def setSiteDir = false
2604 jalviewjsJ2sProps.each { prop, val ->
2606 if (prop == siteDirProperty) {
2607 if (!(val.startsWith('/') || val.startsWith("file://") )) {
2608 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
2614 if (!setSiteDir) { // default site location, don't override specifically set property
2615 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
2618 outputFile = jalviewjsJ2sAltSettingsFileName
2621 inputs.properties(jalviewjsJ2sProps)
2622 outputs.file(jalviewjsJ2sAltSettingsFileName)
2627 task jalviewjsEclipseSetup {
2628 dependsOn jalviewjsEclipseCopyDropins
2629 dependsOn jalviewjsSetEclipseWorkspace
2630 dependsOn jalviewjsCreateJ2sSettings
2634 task jalviewjsSyncAllLibs (type: Sync) {
2635 dependsOn jalviewjsTransferUnzipAllLibs
2636 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
2637 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
2638 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2642 def outputFiles = []
2643 rename { filename ->
2644 outputFiles += "${outputDir}/${filename}"
2651 // should this be exclude really ?
2652 duplicatesStrategy "INCLUDE"
2654 outputs.files outputFiles
2655 inputs.files inputFiles
2659 task jalviewjsSyncResources (type: Sync) {
2660 dependsOn buildResources
2662 def inputFiles = fileTree(dir: resourcesBuildDir)
2663 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
2667 def outputFiles = []
2668 rename { filename ->
2669 outputFiles += "${outputDir}/${filename}"
2675 outputs.files outputFiles
2676 inputs.files inputFiles
2680 task jalviewjsSyncSiteResources (type: Sync) {
2681 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
2682 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2686 def outputFiles = []
2687 rename { filename ->
2688 outputFiles += "${outputDir}/${filename}"
2694 outputs.files outputFiles
2695 inputs.files inputFiles
2699 task jalviewjsSyncBuildProperties (type: Sync) {
2700 dependsOn createBuildProperties
2701 def inputFiles = [file(buildProperties)]
2702 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
2706 def outputFiles = []
2707 rename { filename ->
2708 outputFiles += "${outputDir}/${filename}"
2714 outputs.files outputFiles
2715 inputs.files inputFiles
2719 task jalviewjsProjectImport(type: Exec) {
2720 dependsOn eclipseSetup
2721 dependsOn jalviewjsEclipsePaths
2722 dependsOn jalviewjsEclipseSetup
2725 // do not run a headless import when we claim to be in Eclipse
2727 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2728 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2730 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2734 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
2735 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
2736 executable(eclipseBinary)
2737 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
2741 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
2743 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
2744 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
2747 inputs.file("${jalviewDir}/.project")
2748 outputs.upToDateWhen {
2749 file(projdir).exists()
2754 task jalviewjsTranspile(type: Exec) {
2755 dependsOn jalviewjsEclipseSetup
2756 dependsOn jalviewjsProjectImport
2757 dependsOn jalviewjsEclipsePaths
2759 dependsOn jalviewjsEnableAltFileProperty
2763 // do not run a headless transpile when we claim to be in Eclipse
2765 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2766 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2768 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2772 executable(eclipseBinary)
2773 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
2777 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
2779 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
2780 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
2786 stdout = new ByteArrayOutputStream()
2787 stderr = new ByteArrayOutputStream()
2789 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
2790 def logOutFile = file(logOutFileName)
2791 logOutFile.createNewFile()
2792 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
2793 BINARY: ${eclipseBinary}
2794 VERSION: ${eclipseVersion}
2795 WORKSPACE: ${eclipseWorkspace}
2796 DEBUG: ${eclipseDebug}
2799 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
2800 // combine stdout and stderr
2801 def logErrFOS = logOutFOS
2803 if (jalviewjs_j2s_to_console.equals("true")) {
2804 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2805 new org.apache.tools.ant.util.TeeOutputStream(
2809 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2810 new org.apache.tools.ant.util.TeeOutputStream(
2815 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2818 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2825 if (stdout.toString().contains("Error processing ")) {
2826 // j2s did not complete transpile
2827 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2828 if (jalviewjs_ignore_transpile_errors.equals("true")) {
2829 println("IGNORING TRANSPILE ERRORS")
2830 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2832 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2837 inputs.dir("${jalviewDir}/${sourceDir}")
2838 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
2839 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
2843 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
2845 def stdout = new ByteArrayOutputStream()
2846 def stderr = new ByteArrayOutputStream()
2848 def coreFile = file(jsfile)
2850 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
2852 logOutFile.createNewFile()
2853 logOutFile.append(msg+"\n")
2855 def coreTop = file(prefixFile)
2856 def coreBottom = file(suffixFile)
2857 coreFile.getParentFile().mkdirs()
2858 coreFile.createNewFile()
2859 coreFile.write( coreTop.getText("UTF-8") )
2863 def t = f.getText("UTF-8")
2864 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
2865 coreFile.append( t )
2867 msg = "...file '"+f.getPath()+"' does not exist, skipping"
2869 logOutFile.append(msg+"\n")
2872 coreFile.append( coreBottom.getText("UTF-8") )
2874 msg = "Generating ${zjsfile}"
2876 logOutFile.append(msg+"\n")
2877 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
2878 def logErrFOS = logOutFOS
2881 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
2882 main = "com.google.javascript.jscomp.CommandLineRunner"
2883 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
2884 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
2887 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
2889 logOutFile.append(msg+"\n")
2891 if (logOutConsole) {
2892 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2893 new org.apache.tools.ant.util.TeeOutputStream(
2897 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2898 new org.apache.tools.ant.util.TeeOutputStream(
2903 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2906 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2913 logOutFile.append(msg+"\n")
2917 task jalviewjsBuildAllCores {
2919 description "Build the core js lib closures listed in the classlists dir"
2920 dependsOn jalviewjsTranspile
2921 dependsOn jalviewjsTransferUnzipSwingJs
2923 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
2924 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
2925 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
2926 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
2927 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
2928 def prefixFile = "${jsDir}/core/coretop2.js"
2929 def suffixFile = "${jsDir}/core/corebottom2.js"
2931 inputs.file prefixFile
2932 inputs.file suffixFile
2934 def classlistFiles = []
2935 // add the classlists found int the jalviewjs_classlists_dir
2936 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
2938 def name = file.getName() - ".txt"
2945 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
2946 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
2947 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
2949 jalviewjsCoreClasslists = []
2951 classlistFiles.each {
2954 def file = hash['file']
2955 if (! file.exists()) {
2956 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
2957 return false // this is a "continue" in groovy .each closure
2959 def name = hash['name']
2961 name = file.getName() - ".txt"
2969 def list = fileTree(dir: j2sDir, includes: filelist)
2971 def jsfile = "${outputDir}/core${name}.js"
2972 def zjsfile = "${outputDir}/core${name}.z.js"
2974 jalviewjsCoreClasslists += [
2983 outputs.file(jsfile)
2984 outputs.file(zjsfile)
2987 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
2988 def stevesoftClasslistName = "_stevesoft"
2989 def stevesoftClasslist = [
2990 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
2991 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
2992 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
2993 'name': stevesoftClasslistName
2995 jalviewjsCoreClasslists += stevesoftClasslist
2996 inputs.files(stevesoftClasslist['list'])
2997 outputs.file(stevesoftClasslist['jsfile'])
2998 outputs.file(stevesoftClasslist['zjsfile'])
3001 def allClasslistName = "_all"
3002 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3003 allJsFiles += fileTree(
3007 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3008 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3009 "**/org/jmol/export/JSExporter.js"
3012 allJsFiles += fileTree(
3016 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3017 "**/sun/misc/Unsafe.js",
3018 "**/swingjs/jquery/jquery-editable-select.js",
3019 "**/swingjs/jquery/j2sComboBox.js",
3020 "**/sun/misc/FloatingDecimal.js"
3023 def allClasslist = [
3024 'jsfile': "${outputDir}/core${allClasslistName}.js",
3025 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
3027 'name': allClasslistName
3029 // not including this version of "all" core at the moment
3030 //jalviewjsCoreClasslists += allClasslist
3031 inputs.files(allClasslist['list'])
3032 outputs.file(allClasslist['jsfile'])
3033 outputs.file(allClasslist['zjsfile'])
3036 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3037 logOutFile.getParentFile().mkdirs()
3038 logOutFile.createNewFile()
3039 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3041 jalviewjsCoreClasslists.each {
3042 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3049 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3052 into file(outputFile).getParentFile()
3053 rename { filename ->
3054 if (filename.equals(inputFile.getName())) {
3055 return file(outputFile).getName()
3059 filter(ReplaceTokens,
3063 'MAIN': '"'+main_class+'"',
3065 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3066 'COREKEY': jalviewjs_core_key,
3067 'CORENAME': coreName
3074 task jalviewjsPublishCoreTemplates {
3075 dependsOn jalviewjsBuildAllCores
3076 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3077 def inputFile = file(inputFileName)
3078 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3080 def outputFiles = []
3081 jalviewjsCoreClasslists.each { cl ->
3082 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3083 cl['outputfile'] = outputFile
3084 outputFiles += outputFile
3088 jalviewjsCoreClasslists.each { cl ->
3089 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3092 inputs.file(inputFile)
3093 outputs.files(outputFiles)
3097 task jalviewjsSyncCore (type: Sync) {
3098 dependsOn jalviewjsBuildAllCores
3099 dependsOn jalviewjsPublishCoreTemplates
3100 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3101 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3105 def outputFiles = []
3106 rename { filename ->
3107 outputFiles += "${outputDir}/${filename}"
3113 outputs.files outputFiles
3114 inputs.files inputFiles
3118 // this Copy version of TransferSiteJs will delete anything else in the target dir
3119 task jalviewjsCopyTransferSiteJs(type: Copy) {
3120 dependsOn jalviewjsTranspile
3121 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3122 into "${jalviewDir}/${jalviewjsSiteDir}"
3126 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3127 task jalviewjsSyncTransferSiteJs(type: Sync) {
3128 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3130 into "${jalviewDir}/${jalviewjsSiteDir}"
3137 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3138 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3139 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3140 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3142 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3143 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3144 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3145 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3148 task jalviewjsPrepareSite {
3150 description "Prepares the website folder including unzipping files and copying resources"
3151 dependsOn jalviewjsSyncAllLibs
3152 dependsOn jalviewjsSyncResources
3153 dependsOn jalviewjsSyncSiteResources
3154 dependsOn jalviewjsSyncBuildProperties
3155 dependsOn jalviewjsSyncCore
3159 task jalviewjsBuildSite {
3161 description "Builds the whole website including transpiled code"
3162 dependsOn jalviewjsCopyTransferSiteJs
3163 dependsOn jalviewjsPrepareSite
3167 task cleanJalviewjsTransferSite {
3169 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3170 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3171 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3172 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3177 task cleanJalviewjsSite {
3178 dependsOn cleanJalviewjsTransferSite
3180 delete "${jalviewDir}/${jalviewjsSiteDir}"
3185 task jalviewjsSiteTar(type: Tar) {
3187 description "Creates a tar.gz file for the website"
3188 dependsOn jalviewjsBuildSite
3189 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3190 archiveFileName = outputFilename
3192 compression Compression.GZIP
3194 from "${jalviewDir}/${jalviewjsSiteDir}"
3195 into jalviewjs_site_dir // this is inside the tar file
3197 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3201 task jalviewjsServer {
3203 def filename = "jalviewjsTest.html"
3204 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3205 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3210 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3211 factory = f.newInstance()
3212 } catch (ClassNotFoundException e) {
3213 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3215 def port = Integer.valueOf(jalviewjs_server_port)
3220 while(port < start+1000 && !running) {
3222 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3223 jalviewjsServer = factory.start(doc_root, port)
3225 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3226 println("SERVER STARTED with document root ${doc_root}.")
3227 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3228 println("For debug: "+url+"?j2sdebug")
3229 println("For verbose: "+url+"?j2sverbose")
3230 } catch (Exception e) {
3235 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3236 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3237 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3239 jalviewjsCoreClasslists.each { cl ->
3240 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3242 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3244 println("For core ${cl.name}: "+urlcore)
3247 file(htmlFile).text = htmlText
3250 outputs.file(htmlFile)
3251 outputs.upToDateWhen({false})
3255 task cleanJalviewjsAll {
3257 description "Delete all configuration and build artifacts to do with JalviewJS build"
3258 dependsOn cleanJalviewjsSite
3259 dependsOn jalviewjsEclipsePaths
3262 delete "${jalviewDir}/${jalviewjsBuildDir}"
3263 delete "${jalviewDir}/${eclipse_bin_dir}"
3264 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3265 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3267 delete jalviewjsJ2sAltSettingsFileName
3270 outputs.upToDateWhen( { false } )
3274 task jalviewjsIDE_checkJ2sPlugin {
3275 group "00 JalviewJS in Eclipse"
3276 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3279 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3280 def j2sPluginFile = file(j2sPlugin)
3281 def eclipseHome = System.properties["eclipse.home.location"]
3282 if (eclipseHome == null || ! IN_ECLIPSE) {
3283 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3285 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3286 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3287 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3288 eclipseJ2sPluginDirs += altPluginsDir
3290 def foundPlugin = false
3291 def j2sPluginFileName = j2sPluginFile.getName()
3292 def eclipseJ2sPlugin
3293 def eclipseJ2sPluginFile
3294 eclipseJ2sPluginDirs.any { dir ->
3295 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3296 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3297 if (eclipseJ2sPluginFile.exists()) {
3303 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3304 System.err.println(msg)
3305 throw new StopExecutionException(msg)
3308 def digest = MessageDigest.getInstance("MD5")
3310 digest.update(j2sPluginFile.text.bytes)
3311 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3313 digest.update(eclipseJ2sPluginFile.text.bytes)
3314 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3316 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3317 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3318 System.err.println(msg)
3319 throw new StopExecutionException(msg)
3321 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3327 task jalviewjsIDE_copyJ2sPlugin {
3328 group "00 JalviewJS in Eclipse"
3329 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3332 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3333 def j2sPluginFile = file(j2sPlugin)
3334 def eclipseHome = System.properties["eclipse.home.location"]
3335 if (eclipseHome == null || ! IN_ECLIPSE) {
3336 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3338 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3339 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3340 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3341 System.err.println(msg)
3344 eclipseJ2sPluginFile.getParentFile().mkdirs()
3345 into eclipseJ2sPluginFile.getParent()
3351 task jalviewjsIDE_j2sFile {
3352 group "00 JalviewJS in Eclipse"
3353 description "Creates the .j2s file"
3354 dependsOn jalviewjsCreateJ2sSettings
3358 task jalviewjsIDE_SyncCore {
3359 group "00 JalviewJS in Eclipse"
3360 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3361 dependsOn jalviewjsSyncCore
3365 task jalviewjsIDE_SyncSiteAll {
3366 dependsOn jalviewjsSyncAllLibs
3367 dependsOn jalviewjsSyncResources
3368 dependsOn jalviewjsSyncSiteResources
3369 dependsOn jalviewjsSyncBuildProperties
3373 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3376 task jalviewjsIDE_PrepareSite {
3377 group "00 JalviewJS in Eclipse"
3378 description "Sync libs and resources to site dir, but not closure cores"
3380 dependsOn jalviewjsIDE_SyncSiteAll
3381 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3385 task jalviewjsIDE_AssembleSite {
3386 group "00 JalviewJS in Eclipse"
3387 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3388 dependsOn jalviewjsPrepareSite
3392 task jalviewjsIDE_SiteClean {
3393 group "00 JalviewJS in Eclipse"
3394 description "Deletes the Eclipse transpiled site"
3395 dependsOn cleanJalviewjsSite
3399 task jalviewjsIDE_Server {
3400 group "00 JalviewJS in Eclipse"
3401 description "Starts a webserver on localhost to test the website"
3402 dependsOn jalviewjsServer
3406 // buildship runs this at import or gradle refresh
3407 task eclipseSynchronizationTask {
3408 //dependsOn eclipseSetup
3409 dependsOn createBuildProperties
3411 dependsOn jalviewjsIDE_j2sFile
3412 dependsOn jalviewjsIDE_checkJ2sPlugin
3413 dependsOn jalviewjsIDE_PrepareSite
3418 // buildship runs this at build time or project refresh
3419 task eclipseAutoBuildTask {
3420 //dependsOn jalviewjsIDE_checkJ2sPlugin
3421 //dependsOn jalviewjsIDE_PrepareSite
3427 description "Build the site"
3428 dependsOn jalviewjsBuildSite