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 com.vladsch.flexmark.util.ast.Node
16 import com.vladsch.flexmark.html.HtmlRenderer
17 import com.vladsch.flexmark.parser.Parser
18 import com.vladsch.flexmark.util.data.MutableDataSet
19 import com.vladsch.flexmark.ext.gfm.tasklist.TaskListExtension
20 import com.vladsch.flexmark.ext.tables.TablesExtension
21 import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension
22 import com.vladsch.flexmark.ext.autolink.AutolinkExtension
23 import com.vladsch.flexmark.ext.anchorlink.AnchorLinkExtension
24 import com.vladsch.flexmark.ext.toc.TocExtension
32 classpath "com.vladsch.flexmark:flexmark-all:0.62.0"
41 id "com.diffplug.gradle.spotless" version "3.28.0"
42 id 'com.github.johnrengelman.shadow' version '4.0.3'
43 id 'com.install4j.gradle' version '9.0.6'
44 id 'com.dorongold.task-tree' version '1.5' // only needed to display task dependency tree with gradle task1 [task2 ...] taskTree
45 id 'com.palantir.git-version' version '0.12.3'
56 // in ext the values are cast to Object. Ensure string values are cast as String (and not GStringImpl) for later use
57 def string(Object o) {
58 return o == null ? "" : o.toString()
61 def overrideProperties(String propsFileName, boolean output = false) {
62 if (propsFileName == null) {
65 def propsFile = file(propsFileName)
66 if (propsFile != null && propsFile.exists()) {
67 println("Using properties from file '${propsFileName}'")
69 def p = new Properties()
70 def localPropsFIS = new FileInputStream(propsFile)
76 if (project.hasProperty(key)) {
77 oldval = project.findProperty(key)
78 project.setProperty(key, val)
80 println("Overriding property '${key}' ('${oldval}') with ${file(propsFile).getName()} value '${val}'")
83 ext.setProperty(key, val)
85 println("Setting ext property '${key}' with ${file(propsFile).getName()}s value '${val}'")
89 } catch (Exception e) {
90 println("Exception reading local.properties")
97 jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath()
98 jalviewDirRelativePath = jalviewDir
100 getdownChannelName = CHANNEL.toLowerCase()
101 // default to "default". Currently only has different cosmetics for "develop", "release", "default"
102 propertiesChannelName = ["develop", "release", "test-release", "jalviewjs", "jalviewjs-release" ].contains(getdownChannelName) ? getdownChannelName : "default"
103 // Import channel_properties
104 channelDir = string("${jalviewDir}/${channel_properties_dir}/${propertiesChannelName}")
105 channelGradleProperties = string("${channelDir}/channel_gradle.properties")
106 channelPropsFile = string("${channelDir}/${resource_dir}/${channel_props}")
107 overrideProperties(channelGradleProperties, false)
108 // local build environment properties
109 // can be "projectDir/local.properties"
110 overrideProperties("${projectDir}/local.properties", true)
111 // or "../projectDir_local.properties"
112 overrideProperties(projectDir.getParent() + "/" + projectDir.getName() + "_local.properties", true)
115 // Import releaseProps from the RELEASE file
116 // or a file specified via JALVIEW_RELEASE_FILE if defined
117 // Expect jalview.version and target release branch in jalview.release
118 def releaseProps = new Properties();
119 def releasePropFile = findProperty("JALVIEW_RELEASE_FILE");
120 def defaultReleasePropFile = "${jalviewDirAbsolutePath}/RELEASE";
122 (new File(releasePropFile!=null ? releasePropFile : defaultReleasePropFile)).withInputStream {
123 releaseProps.load(it)
125 } catch (Exception fileLoadError) {
126 throw new Error("Couldn't load release properties file "+(releasePropFile==null ? defaultReleasePropFile : "from custom location: releasePropFile"),fileLoadError);
129 // Set JALVIEW_VERSION if it is not already set
130 if (findProperty("JALVIEW_VERSION")==null || "".equals(JALVIEW_VERSION)) {
131 JALVIEW_VERSION = releaseProps.get("jalview.version")
134 // this property set when running Eclipse headlessly
135 j2sHeadlessBuildProperty = string("net.sf.j2s.core.headlessbuild")
136 // this property set by Eclipse
137 eclipseApplicationProperty = string("eclipse.application")
138 // CHECK IF RUNNING FROM WITHIN ECLIPSE
139 def eclipseApplicationPropertyVal = System.properties[eclipseApplicationProperty]
140 IN_ECLIPSE = eclipseApplicationPropertyVal != null && eclipseApplicationPropertyVal.startsWith("org.eclipse.ui.")
141 // BUT WITHOUT THE HEADLESS BUILD PROPERTY SET
142 if (System.properties[j2sHeadlessBuildProperty].equals("true")) {
143 println("Setting IN_ECLIPSE to ${IN_ECLIPSE} as System.properties['${j2sHeadlessBuildProperty}'] == '${System.properties[j2sHeadlessBuildProperty]}'")
147 println("WITHIN ECLIPSE IDE")
149 println("HEADLESS BUILD")
152 J2S_ENABLED = (project.hasProperty('j2s.compiler.status') && project['j2s.compiler.status'] != null && project['j2s.compiler.status'] == "enable")
154 println("J2S ENABLED")
157 System.properties.sort { it.key }.each {
158 key, val -> println("SYSTEM PROPERTY ${key}='${val}'")
161 if (false && IN_ECLIPSE) {
162 jalviewDir = jalviewDirAbsolutePath
167 buildDate = new Date().format("yyyyMMdd")
170 bareSourceDir = string(source_dir)
171 sourceDir = string("${jalviewDir}/${bareSourceDir}")
172 resourceDir = string("${jalviewDir}/${resource_dir}")
173 bareTestSourceDir = string(test_source_dir)
174 testDir = string("${jalviewDir}/${bareTestSourceDir}")
176 classesDir = string("${jalviewDir}/${classes_dir}")
179 useClover = clover.equals("true")
180 cloverBuildDir = "${buildDir}/clover"
181 cloverInstrDir = file("${cloverBuildDir}/clover-instr")
182 cloverClassesDir = file("${cloverBuildDir}/clover-classes")
183 cloverReportDir = file("${buildDir}/reports/clover")
184 cloverTestInstrDir = file("${cloverBuildDir}/clover-test-instr")
185 cloverTestClassesDir = file("${cloverBuildDir}/clover-test-classes")
186 //cloverTestClassesDir = cloverClassesDir
187 cloverDb = string("${cloverBuildDir}/clover.db")
189 testSourceDir = useClover ? cloverTestInstrDir : testDir
190 testClassesDir = useClover ? cloverTestClassesDir : "${jalviewDir}/${test_output_dir}"
192 getdownWebsiteDir = string("${jalviewDir}/${getdown_website_dir}/${JAVA_VERSION}")
193 getdownArchiveDir = string("${jalviewDir}/${getdown_archive_dir}")
194 getdownFullArchiveDir = null
195 getdownTextLines = []
196 getdownLaunchJvl = null
198 buildProperties = null
200 // the following values might be overridden by the CHANNEL switch
201 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
202 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
203 getdownArchiveAppBase = null
204 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}")
205 getdownAppDistDir = getdown_app_dir_alt
206 getdownImagesDir = string("${jalviewDir}/${getdown_images_dir}")
207 getdownSetAppBaseProperty = false // whether to pass the appbase and appdistdir to the application
208 reportRsyncCommand = false
209 jvlChannelName = CHANNEL.toLowerCase()
210 install4jSuffix = CHANNEL.substring(0, 1).toUpperCase() + CHANNEL.substring(1).toLowerCase(); // BUILD -> Build
211 install4jDMGDSStore = "${install4j_images_dir}/${install4j_dmg_ds_store}"
212 install4jDMGBackgroundImage = "${install4j_images_dir}/${install4j_dmg_background}"
213 install4jInstallerName = "${jalview_name} Non-Release Installer"
214 install4jExecutableName = install4j_executable_name
215 install4jExtraScheme = "jalviewx"
216 install4jMacIconsFile = string("${install4j_images_dir}/${install4j_mac_icons_file}")
217 install4jWindowsIconsFile = string("${install4j_images_dir}/${install4j_windows_icons_file}")
218 install4jPngIconFile = string("${install4j_images_dir}/${install4j_png_icon_file}")
219 install4jBackground = string("${install4j_images_dir}/${install4j_background}")
223 // TODO: get bamboo build artifact URL for getdown artifacts
224 getdown_channel_base = bamboo_channelbase
225 getdownChannelName = string("${bamboo_planKey}/${JAVA_VERSION}")
226 getdownAppBase = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
227 jvlChannelName += "_${getdownChannelName}"
228 // automatically add the test group Not-bamboo for exclusion
229 if ("".equals(testng_excluded_groups)) {
230 testng_excluded_groups = "Not-bamboo"
232 install4jExtraScheme = "jalviewb"
235 case [ "RELEASE", "JALVIEWJS-RELEASE" ]:
236 getdownAppDistDir = getdown_app_dir_release
237 getdownSetAppBaseProperty = true
238 reportRsyncCommand = true
240 install4jInstallerName = "${jalview_name} Installer"
241 getdownArchiveAppBase = getdown_archive_base
245 getdownChannelName = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
246 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
247 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
248 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
249 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
251 package_dir = string("${ARCHIVEDIR}/${package_dir}")
252 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
255 reportRsyncCommand = true
256 install4jExtraScheme = "jalviewa"
260 getdownChannelName = string("archive/${JALVIEW_VERSION}")
261 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
262 getdownAppBase = file(getdownWebsiteDir).toURI().toString()
263 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
264 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
266 package_dir = string("${ARCHIVEDIR}/${package_dir}")
267 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
270 reportRsyncCommand = true
271 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
272 install4jSuffix = "Archive"
273 install4jExtraScheme = "jalviewa"
277 reportRsyncCommand = true
278 getdownSetAppBaseProperty = true
279 // DEVELOP-RELEASE is usually associated with a Jalview release series so set the version
280 JALVIEW_VERSION=JALVIEW_VERSION+"-d${buildDate}"
282 install4jSuffix = "Develop"
283 install4jExtraScheme = "jalviewd"
284 install4jInstallerName = "${jalview_name} Develop Installer"
288 reportRsyncCommand = true
289 getdownSetAppBaseProperty = true
290 // Don't ignore transpile errors for release build
291 if (jalviewjs_ignore_transpile_errors.equals("true")) {
292 jalviewjs_ignore_transpile_errors = "false"
293 println("Setting jalviewjs_ignore_transpile_errors to 'false'")
295 JALVIEW_VERSION = JALVIEW_VERSION+"-test"
296 install4jSuffix = "Test"
297 install4jExtraScheme = "jalviewt"
298 install4jInstallerName = "${jalview_name} Test Installer"
301 case ~/^SCRATCH(|-[-\w]*)$/:
302 getdownChannelName = CHANNEL
303 JALVIEW_VERSION = JALVIEW_VERSION+"-"+CHANNEL
305 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
306 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
307 reportRsyncCommand = true
308 install4jSuffix = "Scratch"
312 if (!file("${LOCALDIR}").exists()) {
313 throw new GradleException("Must provide a LOCALDIR value to produce a local distribution")
315 getdownAppBase = file(file("${LOCALDIR}").getAbsolutePath()).toURI().toString()
316 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
318 JALVIEW_VERSION = "TEST"
319 install4jSuffix = "Test-Local"
320 install4jExtraScheme = "jalviewt"
321 install4jInstallerName = "${jalview_name} Test Installer"
324 case [ "LOCAL", "JALVIEWJS" ]:
325 JALVIEW_VERSION = "TEST"
326 getdownAppBase = file(getdownWebsiteDir).toURI().toString()
327 getdownArchiveAppBase = file("${jalviewDir}/${getdown_archive_dir}").toURI().toString()
328 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
329 install4jExtraScheme = "jalviewl"
332 default: // something wrong specified
333 throw new GradleException("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
337 JALVIEW_VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
338 // override getdownAppBase if requested
339 if (findProperty("getdown_appbase_override") != null) {
340 // revert to LOCAL if empty string
341 if (string(getdown_appbase_override) == "") {
342 getdownAppBase = file(getdownWebsiteDir).toURI().toString()
343 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
344 } else if (string(getdown_appbase_override).startsWith("file://")) {
345 getdownAppBase = string(getdown_appbase_override)
346 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
348 getdownAppBase = string(getdown_appbase_override)
350 println("Overriding getdown appbase with '${getdownAppBase}'")
352 // sanitise file name for jalview launcher file for this channel
353 jvlChannelName = jvlChannelName.replaceAll("[^\\w\\-]+", "_")
354 // install4j application and folder names
355 if (install4jSuffix == "") {
356 install4jApplicationName = "${jalview_name}"
357 install4jBundleId = "${install4j_bundle_id}"
358 install4jWinApplicationId = install4j_release_win_application_id
360 install4jApplicationName = "${jalview_name} ${install4jSuffix}"
361 install4jBundleId = "${install4j_bundle_id}-" + install4jSuffix.toLowerCase()
362 // add int hash of install4jSuffix to the last part of the application_id
363 def id = install4j_release_win_application_id
364 def idsplitreverse = id.split("-").reverse()
365 idsplitreverse[0] = idsplitreverse[0].toInteger() + install4jSuffix.hashCode()
366 install4jWinApplicationId = idsplitreverse.reverse().join("-")
368 // sanitise folder and id names
369 // install4jApplicationFolder = e.g. "Jalview Build"
370 install4jApplicationFolder = install4jApplicationName
371 .replaceAll("[\"'~:/\\\\\\s]", "_") // replace all awkward filename chars " ' ~ : / \
372 .replaceAll("_+", "_") // collapse __
373 install4jInternalId = install4jApplicationName
375 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
376 .replaceAll("_+", "") // collapse __
377 //.replaceAll("_*-_*", "-") // collapse _-_
378 install4jUnixApplicationFolder = install4jApplicationName
380 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
381 .replaceAll("_+", "_") // collapse __
382 .replaceAll("_*-_*", "-") // collapse _-_
385 getdownWrapperLink = install4jUnixApplicationFolder // e.g. "jalview_local"
386 getdownAppDir = string("${getdownWebsiteDir}/${getdownAppDistDir}")
387 //getdownJ11libDir = "${getdownWebsiteDir}/${getdown_j11lib_dir}"
388 getdownResourceDir = string("${getdownWebsiteDir}/${getdown_resource_dir}")
389 getdownInstallDir = string("${getdownWebsiteDir}/${getdown_install_dir}")
390 getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
391 getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
392 /* compile without modules -- using classpath libraries
393 modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
394 modules_runtimeClasspath = modules_compileClasspath
396 def details = versionDetails()
397 gitHash = details.gitHash
398 gitBranch = details.branchName
400 println("Using a ${CHANNEL} profile.")
402 additional_compiler_args = []
403 // configure classpath/args for j8/j11 compilation
404 if (JAVA_VERSION.equals("1.8")) {
405 JAVA_INTEGER_VERSION = string("8")
408 libDistDir = j8libDir
409 compile_source_compatibility = 1.8
410 compile_target_compatibility = 1.8
411 // these are getdown.txt properties defined dependent on the JAVA_VERSION
412 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
413 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
414 // this property is assigned below and expanded to multiple lines in the getdown task
415 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
416 // this property is for the Java library used in eclipse
417 eclipseJavaRuntimeName = string("JavaSE-1.8")
418 } else if (JAVA_VERSION.equals("11")) {
419 JAVA_INTEGER_VERSION = string("11")
421 libDistDir = j11libDir
422 compile_source_compatibility = 11
423 compile_target_compatibility = 11
424 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
425 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
426 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
427 eclipseJavaRuntimeName = string("JavaSE-11")
428 /* compile without modules -- using classpath libraries
429 additional_compiler_args += [
430 '--module-path', modules_compileClasspath.asPath,
431 '--add-modules', j11modules
434 } else if (JAVA_VERSION.equals("17")) {
435 JAVA_INTEGER_VERSION = string("17")
437 libDistDir = j17libDir
438 compile_source_compatibility = 17
439 compile_target_compatibility = 17
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-17")
444 /* compile without modules -- using classpath libraries
445 additional_compiler_args += [
446 '--module-path', modules_compileClasspath.asPath,
447 '--add-modules', j11modules
451 throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
456 JAVA_MIN_VERSION = JAVA_VERSION
457 JAVA_MAX_VERSION = JAVA_VERSION
458 def jreInstallsDir = string(jre_installs_dir)
459 if (jreInstallsDir.startsWith("~/")) {
460 jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
462 macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
463 windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
464 linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
465 macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_mac_x64.tar.gz")
466 windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_windows_x64.tar.gz")
467 linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_linux_x64.tar.gz")
468 install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
469 install4jConfFileName = string("jalview-install4j-conf.install4j")
470 install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
471 install4jHomeDir = install4j_home_dir
472 if (install4jHomeDir.startsWith("~/")) {
473 install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
476 resourceBuildDir = string("${buildDir}/resources")
477 resourcesBuildDir = string("${resourceBuildDir}/resources_build")
478 helpBuildDir = string("${resourceBuildDir}/help_build")
479 docBuildDir = string("${resourceBuildDir}/doc_build")
481 if (buildProperties == null) {
482 buildProperties = string("${resourcesBuildDir}/${build_properties_file}")
484 buildingHTML = string("${jalviewDir}/${doc_dir}/building.html")
485 helpParentDir = string("${jalviewDir}/${help_parent_dir}")
486 helpSourceDir = string("${helpParentDir}/${help_dir}")
487 helpFile = string("${helpBuildDir}/${help_dir}/help.jhm")
490 relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
491 jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
492 jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
494 jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
496 jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
498 jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
499 jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
500 jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
501 jalviewjsJalviewCoreHtmlFile = string("")
502 jalviewjsJalviewCoreName = string(jalviewjs_core_name)
503 jalviewjsCoreClasslists = []
504 jalviewjsJalviewTemplateName = string(jalviewjs_name)
505 jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
506 jalviewjsJ2sAltSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_alt_settings}")
507 jalviewjsJ2sProps = null
508 jalviewjsJ2sPlugin = jalviewjs_j2s_plugin
510 eclipseWorkspace = null
511 eclipseBinary = string("")
512 eclipseVersion = string("")
522 outputDir = file(classesDir)
526 srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ]
529 compileClasspath = files(sourceSets.main.java.outputDir)
530 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
532 runtimeClasspath = compileClasspath
533 runtimeClasspath += files(sourceSets.main.resources.srcDirs)
538 srcDirs cloverInstrDir
539 outputDir = cloverClassesDir
543 srcDirs = sourceSets.main.resources.srcDirs
546 compileClasspath = files( sourceSets.clover.java.outputDir )
547 //compileClasspath += files( testClassesDir )
548 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
549 compileClasspath += fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
550 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
552 runtimeClasspath = compileClasspath
557 srcDirs testSourceDir
558 outputDir = file(testClassesDir)
562 srcDirs = useClover ? sourceSets.clover.resources.srcDirs : sourceSets.main.resources.srcDirs
565 compileClasspath = files( sourceSets.test.java.outputDir )
566 compileClasspath += useClover ? sourceSets.clover.compileClasspath : sourceSets.main.compileClasspath
567 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
569 runtimeClasspath = compileClasspath
570 runtimeClasspath += files(sourceSets.test.resources.srcDirs)
576 // eclipse project and settings files creation, also used by buildship
579 name = eclipse_project_name
581 natures 'org.eclipse.jdt.core.javanature',
582 'org.eclipse.jdt.groovy.core.groovyNature',
583 'org.eclipse.buildship.core.gradleprojectnature'
585 buildCommand 'org.eclipse.jdt.core.javabuilder'
586 buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
590 //defaultOutputDir = sourceSets.main.java.outputDir
591 configurations.each{ c->
592 if (c.isCanBeResolved()) {
593 minusConfigurations += [c]
597 plusConfigurations = [ ]
601 def removeTheseToo = []
602 HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
603 cp.entries.each { entry ->
604 // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
605 // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
606 // we add the resources and help/help dirs in as libs afterwards (see below)
607 if (entry.kind == 'src') {
608 if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
609 removeTheseToo += entry
611 alreadyAddedSrcPath.putAt(entry.path, true)
616 cp.entries.removeAll(removeTheseToo)
618 //cp.entries += new Output("${eclipse_bin_dir}/main")
619 if (file(helpParentDir).isDirectory()) {
620 cp.entries += new Library(fileReference(helpParentDir))
622 if (file(resourceDir).isDirectory()) {
623 cp.entries += new Library(fileReference(resourceDir))
626 HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
628 sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
629 //don't want to add outputDir as eclipse is using its own output dir in bin/main
630 if (it.isDirectory() || ! it.exists()) {
631 // don't add dirs to classpath, especially if they don't exist
632 return false // groovy "continue" in .any closure
634 def itPath = it.toString()
635 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
636 // make relative path
637 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
639 if (alreadyAddedLibPath.get(itPath)) {
640 //println("Not adding duplicate entry "+itPath)
642 //println("Adding entry "+itPath)
643 cp.entries += new Library(fileReference(itPath))
644 alreadyAddedLibPath.put(itPath, true)
648 sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
649 //no longer want to add outputDir as eclipse is using its own output dir in bin/main
650 if (it.isDirectory() || ! it.exists()) {
651 // don't add dirs to classpath
652 return false // groovy "continue" in .any closure
655 def itPath = it.toString()
656 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
657 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
659 if (alreadyAddedLibPath.get(itPath)) {
662 def lib = new Library(fileReference(itPath))
663 lib.entryAttributes["test"] = "true"
665 alreadyAddedLibPath.put(itPath, true)
673 containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
678 // for the IDE, use java 11 compatibility
679 sourceCompatibility = compile_source_compatibility
680 targetCompatibility = compile_target_compatibility
681 javaRuntimeName = eclipseJavaRuntimeName
683 // add in jalview project specific properties/preferences into eclipse core preferences
685 withProperties { props ->
686 def jalview_prefs = new Properties()
687 def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
688 jalview_prefs.load(ins)
690 jalview_prefs.forEach { t, v ->
691 if (props.getAt(t) == null) {
695 // codestyle file -- overrides previous formatter prefs
696 def csFile = file("${jalviewDirAbsolutePath}/${eclipse_codestyle_file}")
697 if (csFile.exists()) {
698 XmlParser parser = new XmlParser()
699 def profiles = parser.parse(csFile)
700 def profile = profiles.'profile'.find { p -> (p.'@kind' == "CodeFormatterProfile" && p.'@name' == "Jalview") }
701 if (profile != null) {
702 profile.'setting'.each { s ->
704 def value = s.'@value'
705 if (id != null && value != null) {
706 props.putAt(id, value)
717 // Don't want these to be activated if in headless build
718 synchronizationTasks "eclipseSynchronizationTask"
719 //autoBuildTasks "eclipseAutoBuildTask"
725 /* hack to change eclipse prefs in .settings files other than org.eclipse.jdt.core.prefs */
726 // Class to allow updating arbitrary properties files
727 class PropertiesFile extends PropertiesPersistableConfigurationObject {
728 public PropertiesFile(PropertiesTransformer t) { super(t); }
729 @Override protected void load(Properties properties) { }
730 @Override protected void store(Properties properties) { }
731 @Override protected String getDefaultResourceName() { return ""; }
732 // This is necessary, because PropertiesPersistableConfigurationObject fails
733 // if no default properties file exists.
734 @Override public void loadDefaults() { load(new StringBufferInputStream("")); }
737 // Task to update arbitrary properties files (set outputFile)
738 class PropertiesFileTask extends PropertiesGeneratorTask<PropertiesFile> {
739 private final PropertiesFileContentMerger file;
740 public PropertiesFileTask() { file = new PropertiesFileContentMerger(getTransformer()); }
741 protected PropertiesFile create() { return new PropertiesFile(getTransformer()); }
742 protected void configure(PropertiesFile props) {
743 file.getBeforeMerged().execute(props); file.getWhenMerged().execute(props);
745 public void file(Closure closure) { ConfigureUtil.configure(closure, file); }
748 task eclipseUIPreferences(type: PropertiesFileTask) {
749 description = "Generate Eclipse additional settings"
750 def filename = "org.eclipse.jdt.ui.prefs"
751 outputFile = "$projectDir/.settings/${filename}" as File
754 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
759 task eclipseGroovyCorePreferences(type: PropertiesFileTask) {
760 description = "Generate Eclipse additional settings"
761 def filename = "org.eclipse.jdt.groovy.core.prefs"
762 outputFile = "$projectDir/.settings/${filename}" as File
765 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
770 task eclipseAllPreferences {
772 dependsOn eclipseUIPreferences
773 dependsOn eclipseGroovyCorePreferences
776 eclipseUIPreferences.mustRunAfter eclipseJdt
777 eclipseGroovyCorePreferences.mustRunAfter eclipseJdt
779 /* end of eclipse preferences hack */
787 delete cloverBuildDir
788 delete cloverReportDir
793 task cloverInstrJava(type: JavaExec) {
794 group = "Verification"
795 description = "Create clover instrumented source java files"
797 dependsOn cleanClover
799 inputs.files(sourceSets.main.allJava)
800 outputs.dir(cloverInstrDir)
802 //classpath = fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
803 classpath = sourceSets.clover.compileClasspath
804 main = "com.atlassian.clover.CloverInstr"
812 cloverInstrDir.getPath(),
814 def srcFiles = sourceSets.main.allJava.files
817 { file -> file.absolutePath }
820 args argsList.toArray()
823 delete cloverInstrDir
824 println("Clover: About to instrument "+srcFiles.size() +" files")
829 task cloverInstrTests(type: JavaExec) {
830 group = "Verification"
831 description = "Create clover instrumented source test files"
833 dependsOn cleanClover
835 inputs.files(testDir)
836 outputs.dir(cloverTestInstrDir)
838 classpath = sourceSets.clover.compileClasspath
839 main = "com.atlassian.clover.CloverInstr"
849 cloverTestInstrDir.getPath(),
851 args argsList.toArray()
854 delete cloverTestInstrDir
855 println("Clover: About to instrument test files")
861 group = "Verification"
862 description = "Create clover instrumented all source files"
864 dependsOn cloverInstrJava
865 dependsOn cloverInstrTests
869 cloverClasses.dependsOn cloverInstr
872 task cloverConsoleReport(type: JavaExec) {
873 group = "Verification"
874 description = "Creates clover console report"
877 file(cloverDb).exists()
880 inputs.dir cloverClassesDir
882 classpath = sourceSets.clover.runtimeClasspath
883 main = "com.atlassian.clover.reporters.console.ConsoleReporter"
885 if (cloverreport_mem.length() > 0) {
886 maxHeapSize = cloverreport_mem
888 if (cloverreport_jvmargs.length() > 0) {
889 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
899 args argsList.toArray()
903 task cloverHtmlReport(type: JavaExec) {
904 group = "Verification"
905 description = "Creates clover HTML report"
908 file(cloverDb).exists()
911 def cloverHtmlDir = cloverReportDir
912 inputs.dir cloverClassesDir
913 outputs.dir cloverHtmlDir
915 classpath = sourceSets.clover.runtimeClasspath
916 main = "com.atlassian.clover.reporters.html.HtmlReporter"
918 if (cloverreport_mem.length() > 0) {
919 maxHeapSize = cloverreport_mem
921 if (cloverreport_jvmargs.length() > 0) {
922 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
933 if (cloverreport_html_options.length() > 0) {
934 argsList += cloverreport_html_options.split(" ")
937 args argsList.toArray()
941 task cloverXmlReport(type: JavaExec) {
942 group = "Verification"
943 description = "Creates clover XML report"
946 file(cloverDb).exists()
949 def cloverXmlFile = "${cloverReportDir}/clover.xml"
950 inputs.dir cloverClassesDir
951 outputs.file cloverXmlFile
953 classpath = sourceSets.clover.runtimeClasspath
954 main = "com.atlassian.clover.reporters.xml.XMLReporter"
956 if (cloverreport_mem.length() > 0) {
957 maxHeapSize = cloverreport_mem
959 if (cloverreport_jvmargs.length() > 0) {
960 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
971 if (cloverreport_xml_options.length() > 0) {
972 argsList += cloverreport_xml_options.split(" ")
975 args argsList.toArray()
980 group = "Verification"
981 description = "Creates clover reports"
983 dependsOn cloverXmlReport
984 dependsOn cloverHtmlReport
991 sourceCompatibility = compile_source_compatibility
992 targetCompatibility = compile_target_compatibility
993 options.compilerArgs += additional_compiler_args
994 print ("Setting target compatibility to "+targetCompatibility+"\n")
996 //classpath += configurations.cloverRuntime
1002 // JBP->BS should the print statement in doFirst refer to compile_target_compatibility ?
1003 sourceCompatibility = compile_source_compatibility
1004 targetCompatibility = compile_target_compatibility
1005 options.compilerArgs = additional_compiler_args
1006 options.encoding = "UTF-8"
1008 print ("Setting target compatibility to "+compile_target_compatibility+"\n")
1015 sourceCompatibility = compile_source_compatibility
1016 targetCompatibility = compile_target_compatibility
1017 options.compilerArgs = additional_compiler_args
1019 print ("Setting target compatibility to "+targetCompatibility+"\n")
1026 delete sourceSets.main.java.outputDir
1032 dependsOn cleanClover
1034 delete sourceSets.test.java.outputDir
1039 // format is a string like date.format("dd MMMM yyyy")
1040 def getDate(format) {
1041 def date = new Date()
1042 return date.format(format)
1046 def convertMdToHtml (FileTree mdFiles, File cssFile) {
1047 MutableDataSet options = new MutableDataSet()
1049 def extensions = new ArrayList<>()
1050 extensions.add(AnchorLinkExtension.create())
1051 extensions.add(AutolinkExtension.create())
1052 extensions.add(StrikethroughExtension.create())
1053 extensions.add(TaskListExtension.create())
1054 extensions.add(TablesExtension.create())
1055 extensions.add(TocExtension.create())
1057 options.set(Parser.EXTENSIONS, extensions)
1059 // set GFM table parsing options
1060 options.set(TablesExtension.WITH_CAPTION, false)
1061 options.set(TablesExtension.COLUMN_SPANS, false)
1062 options.set(TablesExtension.MIN_HEADER_ROWS, 1)
1063 options.set(TablesExtension.MAX_HEADER_ROWS, 1)
1064 options.set(TablesExtension.APPEND_MISSING_COLUMNS, true)
1065 options.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
1066 options.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
1068 options.set(AnchorLinkExtension.ANCHORLINKS_SET_ID, false)
1069 options.set(AnchorLinkExtension.ANCHORLINKS_ANCHOR_CLASS, "anchor")
1070 options.set(AnchorLinkExtension.ANCHORLINKS_SET_NAME, true)
1071 options.set(AnchorLinkExtension.ANCHORLINKS_TEXT_PREFIX, "<span class=\"octicon octicon-link\"></span>")
1073 Parser parser = Parser.builder(options).build()
1074 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1076 mdFiles.each { mdFile ->
1077 // add table of contents
1078 def mdText = "[TOC]\n"+mdFile.text
1080 // grab the first top-level title
1082 def titleRegex = /(?m)^#(\s+|([^#]))(.*)/
1083 def matcher = mdText =~ titleRegex
1084 if (matcher.size() > 0) {
1085 // matcher[0][2] is the first character of the title if there wasn't any whitespace after the #
1086 title = (matcher[0][2] != null ? matcher[0][2] : "")+matcher[0][3]
1088 // or use the filename if none found
1089 if (title == null) {
1090 title = mdFile.getName()
1093 Node document = parser.parse(mdText)
1094 String htmlBody = renderer.render(document)
1095 def htmlText = '''<html>
1096 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1097 <html xmlns="http://www.w3.org/1999/xhtml">
1099 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1100 <meta http-equiv="Content-Style-Type" content="text/css" />
1101 <meta name="generator" content="flexmark" />
1103 htmlText += ((title != null) ? " <title>${title}</title>" : '' )
1105 <style type="text/css">code{white-space: pre;}</style>
1107 htmlText += ((cssFile != null) ? cssFile.text : '')
1108 htmlText += '''</head>
1111 htmlText += htmlBody
1117 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1118 def htmlFile = file(htmlFilePath)
1119 println("Creating ${htmlFilePath}")
1120 htmlFile.text = htmlText
1125 task copyDocs(type: Copy) {
1126 def inputDir = "${jalviewDir}/${doc_dir}"
1127 def outputDir = "${docBuildDir}/${doc_dir}"
1131 include('**/*.html')
1133 filter(ReplaceTokens,
1137 'Version-Rel': JALVIEW_VERSION,
1138 'Year-Rel': getDate("yyyy")
1145 exclude('**/*.html')
1150 inputs.dir(inputDir)
1151 outputs.dir(outputDir)
1155 task convertMdFiles {
1157 def mdFiles = fileTree(dir: docBuildDir, include: "**/*.md")
1158 def cssFile = file("${jalviewDir}/${flexmark_css}")
1161 convertMdToHtml(mdFiles, cssFile)
1164 inputs.files(mdFiles)
1165 inputs.file(cssFile)
1168 mdFiles.each { mdFile ->
1169 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1170 htmlFiles.add(file(htmlFilePath))
1172 outputs.files(htmlFiles)
1176 task copyHelp(type: Copy) {
1177 def inputDir = helpSourceDir
1178 def outputDir = "${helpBuildDir}/${help_dir}"
1182 include('**/*.html')
1186 filter(ReplaceTokens,
1190 'Version-Rel': JALVIEW_VERSION,
1191 'Year-Rel': getDate("yyyy")
1198 exclude('**/*.html')
1205 inputs.dir(inputDir)
1206 outputs.files(helpFile)
1207 outputs.dir(outputDir)
1211 task copyResources(type: Copy) {
1213 description = "Copy (and make text substitutions in) the resources dir to the build area"
1215 def inputDir = resourceDir
1216 def outputDir = resourcesBuildDir
1220 include('**/*.html')
1222 filter(ReplaceTokens,
1226 'Version-Rel': JALVIEW_VERSION,
1227 'Year-Rel': getDate("yyyy")
1234 exclude('**/*.html')
1239 inputs.dir(inputDir)
1240 outputs.dir(outputDir)
1243 task copyChannelResources(type: Copy) {
1244 dependsOn copyResources
1246 description = "Copy the channel resources dir to the build resources area"
1248 def inputDir = "${channelDir}/${resource_dir}"
1249 def outputDir = resourcesBuildDir
1253 inputs.dir(inputDir)
1254 outputs.dir(outputDir)
1257 task createBuildProperties(type: WriteProperties) {
1258 dependsOn copyResources
1260 description = "Create the ${buildProperties} file"
1262 inputs.dir(sourceDir)
1263 inputs.dir(resourcesBuildDir)
1264 outputFile (buildProperties)
1265 // taking time specific comment out to allow better incremental builds
1266 comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
1267 //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
1268 property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
1269 property "VERSION", JALVIEW_VERSION
1270 property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
1271 if (getdownSetAppBaseProperty) {
1272 property "GETDOWNAPPBASE", getdownAppBase
1273 property "GETDOWNAPPDISTDIR", getdownAppDistDir
1275 outputs.file(outputFile)
1279 task buildIndices(type: JavaExec) {
1281 classpath = sourceSets.main.compileClasspath
1282 main = "com.sun.java.help.search.Indexer"
1283 workingDir = "${helpBuildDir}/${help_dir}"
1286 inputs.dir("${workingDir}/${argDir}")
1288 outputs.dir("${classesDir}/doc")
1289 outputs.dir("${classesDir}/help")
1290 outputs.file("${workingDir}/JavaHelpSearch/DOCS")
1291 outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
1292 outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
1293 outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
1294 outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
1295 outputs.file("${workingDir}/JavaHelpSearch/TMAP")
1298 task buildResources {
1299 dependsOn copyResources
1300 dependsOn copyChannelResources
1301 dependsOn createBuildProperties
1305 dependsOn buildResources
1308 dependsOn convertMdFiles
1309 dependsOn buildIndices
1313 compileJava.dependsOn prepare
1314 run.dependsOn compileJava
1315 //run.dependsOn prepare
1318 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1323 dependsOn cloverClasses
1325 dependsOn compileJava //?
1329 includeGroups testng_groups
1330 excludeGroups testng_excluded_groups
1332 useDefaultListeners=true
1335 maxHeapSize = "1024m"
1337 workingDir = jalviewDir
1338 def testLaf = project.findProperty("test_laf")
1339 if (testLaf != null) {
1340 println("Setting Test LaF to '${testLaf}'")
1341 systemProperty "laf", testLaf
1343 def testHiDPIScale = project.findProperty("test_HiDPIScale")
1344 if (testHiDPIScale != null) {
1345 println("Setting Test HiDPI Scale to '${testHiDPIScale}'")
1346 systemProperty "sun.java2d.uiScale", testHiDPIScale
1348 sourceCompatibility = compile_source_compatibility
1349 targetCompatibility = compile_target_compatibility
1350 jvmArgs += additional_compiler_args
1354 println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1360 task compileLinkCheck(type: JavaCompile) {
1362 classpath = files("${jalviewDir}/${utils_dir}")
1363 destinationDir = file("${jalviewDir}/${utils_dir}")
1364 source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1366 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1367 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1368 outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1369 outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1373 task linkCheck(type: JavaExec) {
1375 dependsOn compileLinkCheck
1377 def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1378 classpath = files("${jalviewDir}/${utils_dir}")
1379 main = "HelpLinksChecker"
1380 workingDir = jalviewDir
1381 args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1383 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1384 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1387 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1391 inputs.dir(helpBuildDir)
1392 outputs.file(helpLinksCheckerOutFile)
1396 // import the pubhtmlhelp target
1397 ant.properties.basedir = "${jalviewDir}"
1398 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1399 ant.importBuild "${utils_dir}/publishHelp.xml"
1402 task cleanPackageDir(type: Delete) {
1404 delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1414 attributes "Main-Class": main_class,
1415 "Permissions": "all-permissions",
1416 "Application-Name": install4jApplicationName,
1417 "Codebase": application_codebase,
1418 "Implementation-Version": JALVIEW_VERSION
1421 def outputDir = "${jalviewDir}/${package_dir}"
1422 destinationDirectory = file(outputDir)
1423 archiveFileName = rootProject.name+".jar"
1424 duplicatesStrategy "EXCLUDE"
1431 exclude "**/*.jar.*"
1433 inputs.dir(sourceSets.main.java.outputDir)
1434 sourceSets.main.resources.srcDirs.each{ dir ->
1437 outputs.file("${outputDir}/${archiveFileName}")
1441 task copyJars(type: Copy) {
1442 from fileTree(dir: classesDir, include: "**/*.jar").files
1443 into "${jalviewDir}/${package_dir}"
1447 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1448 task syncJars(type: Sync) {
1450 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1451 into "${jalviewDir}/${package_dir}"
1453 include jar.archiveFileName.getOrNull()
1460 description = "Put all required libraries in dist"
1461 // order of "cleanPackageDir", "copyJars", "jar" important!
1462 jar.mustRunAfter cleanPackageDir
1463 syncJars.mustRunAfter cleanPackageDir
1464 dependsOn cleanPackageDir
1467 outputs.dir("${jalviewDir}/${package_dir}")
1472 dependsOn cleanPackageDir
1479 group = "distribution"
1480 description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1484 from ("${jalviewDir}/${libDistDir}") {
1488 attributes "Implementation-Version": JALVIEW_VERSION,
1489 "Application-Name": install4jApplicationName
1492 duplicatesStrategy "INCLUDE"
1494 mainClassName = shadow_jar_main_class
1496 classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1501 task getdownWebsite() {
1502 group = "distribution"
1503 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1508 def getdownWebsiteResourceFilenames = []
1509 def getdownResourceDir = getdownResourceDir
1510 def getdownResourceFilenames = []
1513 // clean the getdown website and files dir before creating getdown folders
1514 delete getdownWebsiteDir
1515 delete getdownFilesDir
1518 from buildProperties
1519 rename(file(buildProperties).getName(), getdown_build_properties)
1522 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1525 from channelPropsFile
1526 into getdownWebsiteDir
1528 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
1530 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
1531 def props = project.properties.sort { it.key }
1532 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
1533 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
1535 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
1536 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
1538 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
1539 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
1541 if (getdownImagesDir != null && file(getdownImagesDir).exists()) {
1542 props.put("getdown_txt_ui.background_image", "${getdownImagesDir}/${getdown_background_image}")
1543 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesDir}/${getdown_instant_background_image}")
1544 props.put("getdown_txt_ui.error_background", "${getdownImagesDir}/${getdown_error_background}")
1545 props.put("getdown_txt_ui.progress_image", "${getdownImagesDir}/${getdown_progress_image}")
1546 props.put("getdown_txt_ui.icon", "${getdownImagesDir}/${getdown_icon}")
1547 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesDir}/${getdown_mac_dock_icon}")
1550 props.put("getdown_txt_title", jalview_name)
1551 props.put("getdown_txt_ui.name", install4jApplicationName)
1553 // start with appbase
1554 getdownTextLines += "appbase = ${getdownAppBase}"
1555 props.each{ prop, val ->
1556 if (prop.startsWith("getdown_txt_") && val != null) {
1557 if (prop.startsWith("getdown_txt_multi_")) {
1558 def key = prop.substring(18)
1559 val.split(",").each{ v ->
1560 def line = "${key} = ${v}"
1561 getdownTextLines += line
1564 // file values rationalised
1565 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
1567 if (val.indexOf('/') == 0) {
1570 } else if (val.indexOf('/') > 0) {
1571 // relative path (relative to jalviewDir)
1572 r = file( "${jalviewDir}/${val}" )
1575 val = "${getdown_resource_dir}/" + r.getName()
1576 getdownWebsiteResourceFilenames += val
1577 getdownResourceFilenames += r.getPath()
1580 if (! prop.startsWith("getdown_txt_resource")) {
1581 def line = prop.substring(12) + " = ${val}"
1582 getdownTextLines += line
1588 getdownWebsiteResourceFilenames.each{ filename ->
1589 getdownTextLines += "resource = ${filename}"
1591 getdownResourceFilenames.each{ filename ->
1594 into getdownResourceDir
1598 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
1599 getdownWrapperScripts.each{ script ->
1600 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
1604 into "${getdownWebsiteDir}/${getdown_wrapper_script_dir}"
1606 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
1611 fileTree(file(package_dir)).each{ f ->
1612 if (f.isDirectory()) {
1613 def files = fileTree(dir: f, include: ["*"]).getFiles()
1615 } else if (f.exists()) {
1619 def jalviewJar = jar.archiveFileName.getOrNull()
1620 // put jalview.jar first for CLASSPATH and .properties files reasons
1621 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
1622 def name = f.getName()
1623 def line = "code = ${getdownAppDistDir}/${name}"
1624 getdownTextLines += line
1631 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
1633 if (JAVA_VERSION.equals("11")) {
1634 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
1635 j11libFiles.sort().each{f ->
1636 def name = f.getName()
1637 def line = "code = ${getdown_j11lib_dir}/${name}"
1638 getdownTextLines += line
1641 into getdownJ11libDir
1647 // 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.
1648 //getdownTextLines += "class = " + file(getdownLauncher).getName()
1649 getdownTextLines += "resource = ${getdown_launcher_new}"
1650 getdownTextLines += "class = ${main_class}"
1651 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
1652 if (getdownSetAppBaseProperty) {
1653 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
1654 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
1657 def getdownTxt = file("${getdownWebsiteDir}/getdown.txt")
1658 getdownTxt.write(getdownTextLines.join("\n"))
1660 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
1661 def launchJvl = file("${getdownWebsiteDir}/${getdownLaunchJvl}")
1662 launchJvl.write("appbase=${getdownAppBase}")
1664 // files going into the getdown website dir: getdown-launcher.jar
1666 from getdownLauncher
1667 rename(file(getdownLauncher).getName(), getdown_launcher_new)
1668 into getdownWebsiteDir
1671 // files going into the getdown website dir: getdown-launcher(-local).jar
1673 from getdownLauncher
1674 if (file(getdownLauncher).getName() != getdown_launcher) {
1675 rename(file(getdownLauncher).getName(), getdown_launcher)
1677 into getdownWebsiteDir
1680 // files going into the getdown website dir: ./install dir and files
1681 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
1684 from getdownLauncher
1685 from "${getdownAppDir}/${getdown_build_properties}"
1686 if (file(getdownLauncher).getName() != getdown_launcher) {
1687 rename(file(getdownLauncher).getName(), getdown_launcher)
1689 into getdownInstallDir
1692 // and make a copy in the getdown files dir (these are not downloaded by getdown)
1694 from getdownInstallDir
1695 into getdownFilesInstallDir
1699 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
1703 from getdownLauncher
1704 from "${getdownWebsiteDir}/${getdown_build_properties}"
1705 from "${getdownWebsiteDir}/${channel_props}"
1706 if (file(getdownLauncher).getName() != getdown_launcher) {
1707 rename(file(getdownLauncher).getName(), getdown_launcher)
1709 into getdownFilesDir
1712 // and ./resource (not all downloaded by getdown)
1714 from getdownResourceDir
1715 into "${getdownFilesDir}/${getdown_resource_dir}"
1720 inputs.dir("${jalviewDir}/${package_dir}")
1722 outputs.dir(getdownWebsiteDir)
1723 outputs.dir(getdownFilesDir)
1727 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
1728 task getdownDigestDir(type: JavaExec) {
1730 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
1732 def digestDirPropertyName = "DIGESTDIR"
1734 classpath = files(getdownLauncher)
1735 def digestDir = findProperty(digestDirPropertyName)
1736 if (digestDir == null) {
1737 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
1741 main = "com.threerings.getdown.tools.Digester"
1745 task getdownDigest(type: JavaExec) {
1746 group = "distribution"
1747 description = "Digest the getdown website folder"
1748 dependsOn getdownWebsite
1750 classpath = files(getdownLauncher)
1752 main = "com.threerings.getdown.tools.Digester"
1753 args getdownWebsiteDir
1754 inputs.dir(getdownWebsiteDir)
1755 outputs.file("${getdownWebsiteDir}/digest2.txt")
1760 group = "distribution"
1761 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
1762 dependsOn getdownDigest
1764 if (reportRsyncCommand) {
1765 def fromDir = getdownWebsiteDir + (getdownWebsiteDir.endsWith('/')?'':'/')
1766 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
1767 println "LIKELY RSYNC COMMAND:"
1768 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
1769 if (RUNRSYNC == "true") {
1771 commandLine "mkdir", "-p", toDir
1774 commandLine "rsync", "-avh", "--delete", fromDir, toDir
1782 task getdownArchiveBuild() {
1783 group = "distribution"
1784 description = "Put files in the archive dir to go on the website"
1786 dependsOn getdownWebsite
1788 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
1789 def vDir = "${getdownArchiveDir}/${v}"
1790 getdownFullArchiveDir = "${vDir}/getdown"
1791 def vLaunchVersionJvl = "${vDir}/jalview-${v}.jvl"
1792 def vAltDir = "alt_${v}"
1793 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
1796 if (getdownArchiveAppBase == null) {
1797 throw new StopExecutionException("Cannot create getdownArchive for CHANNEL=${CHANNEL}")
1800 // cleanup old "old" dir
1801 delete getdownArchiveDir
1803 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
1804 getdownArchiveTxt.getParentFile().mkdirs()
1805 def getdownArchiveTextLines = []
1806 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
1810 from "${getdownWebsiteDir}/${getdownAppDistDir}"
1811 into "${getdownFullArchiveDir}/${vAltDir}"
1814 getdownTextLines.each { line ->
1815 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
1816 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
1817 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
1818 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
1819 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
1820 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
1821 // remove the existing resource = resource/ or bin/ lines
1822 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
1823 getdownArchiveTextLines += line
1827 // the resource dir -- add these files as resource lines in getdown.txt
1829 from "${archiveImagesDir}"
1830 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
1832 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
1836 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
1838 def vLaunchJvl = file(vLaunchVersionJvl)
1839 vLaunchJvl.getParentFile().mkdirs()
1840 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
1841 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
1842 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
1843 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
1844 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
1845 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
1847 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
1849 from getdownLauncher
1850 from "${getdownWebsiteDir}/${getdownLaunchJvl}"
1851 from "${getdownWebsiteDir}/${getdown_launcher_new}"
1852 from "${getdownWebsiteDir}/${channel_props}"
1853 if (file(getdownLauncher).getName() != getdown_launcher) {
1854 rename(file(getdownLauncher).getName(), getdown_launcher)
1856 into getdownFullArchiveDir
1862 task getdownArchiveDigest(type: JavaExec) {
1863 group = "distribution"
1864 description = "Digest the getdown archive folder"
1866 dependsOn getdownArchiveBuild
1869 classpath = files(getdownLauncher)
1870 args getdownFullArchiveDir
1872 main = "com.threerings.getdown.tools.Digester"
1873 inputs.dir(getdownFullArchiveDir)
1874 outputs.file("${getdownFullArchiveDir}/digest2.txt")
1877 task getdownArchive() {
1878 group = "distribution"
1879 description = "Build the website archive dir with getdown digest"
1881 dependsOn getdownArchiveBuild
1882 dependsOn getdownArchiveDigest
1885 tasks.withType(JavaCompile) {
1886 options.encoding = 'UTF-8'
1892 delete getdownWebsiteDir
1893 delete getdownFilesDir
1894 delete getdownArchiveDir
1900 if (file(install4jHomeDir).exists()) {
1902 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
1903 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
1904 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
1905 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
1907 installDir(file(install4jHomeDir))
1909 mediaTypes = Arrays.asList(install4j_media_types.split(","))
1913 task copyInstall4jTemplate {
1914 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
1915 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
1916 inputs.file(install4jTemplateFile)
1917 inputs.file(install4jFileAssociationsFile)
1918 inputs.property("CHANNEL", { CHANNEL })
1919 outputs.file(install4jConfFile)
1922 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
1924 // turn off code signing if no OSX_KEYPASS
1925 if (OSX_KEYPASS == "") {
1926 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
1927 codeSigning.'@macEnabled' = "false"
1929 install4jConfigXml.'**'.windows.each { windows ->
1930 windows.'@runPostProcessor' = "false"
1934 // disable install screen for OSX dmg (for 2.11.2.0)
1935 install4jConfigXml.'**'.macosArchive.each { macosArchive ->
1936 macosArchive.attributes().remove('executeSetupApp')
1937 macosArchive.attributes().remove('setupAppId')
1940 // turn off checksum creation for LOCAL channel
1941 def e = install4jConfigXml.application[0]
1942 if (CHANNEL == "LOCAL") {
1943 e.'@createChecksums' = "false"
1945 e.'@createChecksums' = "true"
1948 // put file association actions where placeholder action is
1949 def install4jFileAssociationsText = install4jFileAssociationsFile.text
1950 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
1951 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
1952 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
1953 def parent = a.parent()
1955 fileAssociationActions.each { faa ->
1958 // don't need to continue in .any loop once replacements have been made
1963 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
1964 // NB we're deleting the /other/ one!
1965 // Also remove the examples subdir from non-release versions
1966 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
1967 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
1968 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
1969 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
1971 // remove the examples subdir from Full File Set
1972 def files = install4jConfigXml.files[0]
1973 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
1974 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
1975 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
1976 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
1977 dirEntry.parent().remove(dirEntry)
1979 install4jConfigXml.'**'.action.any { a ->
1980 if (a.'@customizedId' == customizedIdToDelete) {
1981 def parent = a.parent()
1987 // write install4j file
1988 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
1995 delete install4jConfFile
2000 task installers(type: com.install4j.gradle.Install4jTask) {
2001 group = "distribution"
2002 description = "Create the install4j installers"
2004 dependsOn copyInstall4jTemplate
2006 projectFile = install4jConfFile
2008 // create an md5 for the input files to use as version for install4j conf file
2009 def digest = MessageDigest.getInstance("MD5")
2011 (file("${install4jDir}/${install4j_template}").text +
2012 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2013 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2014 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2015 if (filesMd5.length() >= 8) {
2016 filesMd5 = filesMd5.substring(0,8)
2018 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2019 // make install4jBuildDir relative to jalviewDir
2020 def install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
2023 'JALVIEW_NAME': jalview_name,
2024 'JALVIEW_APPLICATION_NAME': install4jApplicationName,
2025 'JALVIEW_DIR': "../..",
2026 'OSX_KEYSTORE': OSX_KEYSTORE,
2027 'OSX_APPLEID': OSX_APPLEID,
2028 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2029 'JSIGN_SH': JSIGN_SH,
2030 'JRE_DIR': getdown_app_dir_java,
2031 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2032 'JALVIEW_VERSION': JALVIEW_VERSION,
2033 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2034 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2035 'JAVA_VERSION': JAVA_VERSION,
2036 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2037 'VERSION': JALVIEW_VERSION,
2038 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2039 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2040 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2041 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2042 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2043 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2044 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2045 'BUNDLE_ID': install4jBundleId,
2046 'INTERNAL_ID': install4jInternalId,
2047 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2048 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2049 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
2050 'WRAPPER_LINK': getdownWrapperLink,
2051 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2052 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2053 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2054 'INSTALLER_NAME': install4jInstallerName,
2055 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2056 'GETDOWN_WEBSITE_DIR': getdown_website_dir,
2057 'GETDOWN_FILES_DIR': getdown_files_dir,
2058 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2059 'GETDOWN_DIST_DIR': getdownAppDistDir,
2060 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2061 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2062 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2063 'BUILD_DIR': install4jBuildDir,
2064 'APPLICATION_CATEGORIES': install4j_application_categories,
2065 'APPLICATION_FOLDER': install4jApplicationFolder,
2066 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2067 'EXECUTABLE_NAME': install4jExecutableName,
2068 'EXTRA_SCHEME': install4jExtraScheme,
2069 'MAC_ICONS_FILE': install4jMacIconsFile,
2070 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2071 'PNG_ICON_FILE': install4jPngIconFile,
2072 'BACKGROUND': install4jBackground,
2076 //println("INSTALL4J VARIABLES:")
2077 //variables.each{k,v->println("${k}=${v}")}
2079 destination = "${jalviewDir}/${install4jBuildDir}"
2080 buildSelected = true
2082 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2084 disableSigning = true
2085 disableNotarization = true
2089 macKeystorePassword = OSX_KEYPASS
2092 if (OSX_ALTOOLPASS) {
2093 appleIdPassword = OSX_ALTOOLPASS
2094 disableNotarization = false
2096 disableNotarization = true
2100 println("Using projectFile "+projectFile)
2101 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2105 inputs.dir(getdownWebsiteDir)
2106 inputs.file(install4jConfFile)
2107 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2108 inputs.dir(macosJavaVMDir)
2109 inputs.dir(windowsJavaVMDir)
2110 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2116 eclipse().configFile(eclipse_codestyle_file)
2121 task sourceDist(type: Tar) {
2122 group "distribution"
2123 description "Create a source .tar.gz file for distribution"
2125 dependsOn createBuildProperties
2126 dependsOn convertMdFiles
2128 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2129 archiveFileName = outputFileName
2131 compression Compression.GZIP
2146 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2148 "utils/InstallAnywhere",
2163 "gradle.properties",
2174 ".settings/org.eclipse.jdt.core.jalview.prefs",
2178 exclude (EXCLUDE_FILES)
2179 include (PROCESS_FILES)
2180 filter(ReplaceTokens,
2184 'Version-Rel': JALVIEW_VERSION,
2185 'Year-Rel': getDate("yyyy")
2190 exclude (EXCLUDE_FILES)
2191 exclude (PROCESS_FILES)
2192 exclude ("appletlib")
2193 exclude ("**/*locales")
2194 exclude ("*locales/**")
2195 exclude ("utils/InstallAnywhere")
2197 exclude (getdown_files_dir)
2198 exclude (getdown_website_dir)
2200 // exluding these as not using jars as modules yet
2201 exclude ("${j11modDir}/**/*.jar")
2204 include(INCLUDE_FILES)
2206 // from (jalviewDir) {
2207 // // explicit includes for stuff that seemed to not get included
2208 // include(fileTree("test/**/*."))
2209 // exclude(EXCLUDE_FILES)
2210 // exclude(PROCESS_FILES)
2213 from(file(buildProperties).getParent()) {
2214 include(file(buildProperties).getName())
2215 rename(file(buildProperties).getName(), "build_properties")
2217 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2226 dependsOn pubhtmlhelp
2228 inputs.dir("${helpBuildDir}/${help_dir}")
2229 outputs.dir("${buildDir}/distributions/${help_dir}")
2233 task j2sSetHeadlessBuild {
2240 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2242 description "Enable the alternative J2S Config file for headless build"
2244 outputFile = jalviewjsJ2sSettingsFileName
2245 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2246 def j2sProps = new Properties()
2247 if (j2sPropsFile.exists()) {
2249 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2250 j2sProps.load(j2sPropsFileFIS)
2251 j2sPropsFileFIS.close()
2253 j2sProps.each { prop, val ->
2256 } catch (Exception e) {
2257 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2261 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2262 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2267 task jalviewjsSetEclipseWorkspace {
2268 def propKey = "jalviewjs_eclipse_workspace"
2270 if (project.hasProperty(propKey)) {
2271 propVal = project.getProperty(propKey)
2272 if (propVal.startsWith("~/")) {
2273 propVal = System.getProperty("user.home") + propVal.substring(1)
2276 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2277 def propsFile = file(propsFileName)
2278 def eclipseWsDir = propVal
2279 def props = new Properties()
2281 def writeProps = true
2282 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2283 def ins = new FileInputStream(propsFileName)
2286 if (props.getProperty(propKey, null) != null) {
2287 eclipseWsDir = props.getProperty(propKey)
2292 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2293 def tempDir = File.createTempDir()
2294 eclipseWsDir = tempDir.getAbsolutePath()
2297 eclipseWorkspace = file(eclipseWsDir)
2300 // do not run a headless transpile when we claim to be in Eclipse
2302 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2303 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2305 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2309 props.setProperty(propKey, eclipseWsDir)
2310 propsFile.parentFile.mkdirs()
2311 def bytes = new ByteArrayOutputStream()
2312 props.store(bytes, null)
2313 def propertiesString = bytes.toString()
2314 propsFile.text = propertiesString
2320 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2323 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2324 outputs.file(propsFileName)
2325 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2329 task jalviewjsEclipsePaths {
2332 def eclipseRoot = jalviewjs_eclipse_root
2333 if (eclipseRoot.startsWith("~/")) {
2334 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
2336 if (OperatingSystem.current().isMacOsX()) {
2337 eclipseRoot += "/Eclipse.app"
2338 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
2339 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
2340 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
2341 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2342 eclipseRoot += "/eclipse"
2344 eclipseBinary = "${eclipseRoot}/eclipse.exe"
2345 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2346 } else { // linux or unix
2347 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2348 eclipseRoot += "/eclipse"
2349 println("eclipseDir exists")
2351 eclipseBinary = "${eclipseRoot}/eclipse"
2352 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2355 eclipseVersion = "4.13" // default
2356 def assumedVersion = true
2357 if (file(eclipseProduct).exists()) {
2358 def fis = new FileInputStream(eclipseProduct)
2359 def props = new Properties()
2361 eclipseVersion = props.getProperty("version")
2363 assumedVersion = false
2366 def propKey = "eclipse_debug"
2367 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
2370 // do not run a headless transpile when we claim to be in Eclipse
2372 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2373 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2375 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2378 if (!assumedVersion) {
2379 println("ECLIPSE VERSION=${eclipseVersion}")
2385 task printProperties {
2387 description "Output to console all System.properties"
2389 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
2395 dependsOn eclipseProject
2396 dependsOn eclipseClasspath
2397 dependsOn eclipseJdt
2401 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
2402 task jalviewjsEclipseCopyDropins(type: Copy) {
2403 dependsOn jalviewjsEclipsePaths
2405 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
2406 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
2407 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
2414 // this eclipse -clean doesn't actually work
2415 task jalviewjsCleanEclipse(type: Exec) {
2416 dependsOn eclipseSetup
2417 dependsOn jalviewjsEclipsePaths
2418 dependsOn jalviewjsEclipseCopyDropins
2420 executable(eclipseBinary)
2421 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
2427 def inputString = """exit
2430 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
2431 standardInput = inputByteStream
2434 /* not really working yet
2435 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
2439 task jalviewjsTransferUnzipSwingJs {
2440 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
2444 from zipTree(file_zip)
2445 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2449 inputs.file file_zip
2450 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2454 task jalviewjsTransferUnzipLib {
2455 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
2458 zipFiles.each { file_zip ->
2460 from zipTree(file_zip)
2461 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2466 inputs.files zipFiles
2467 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2471 task jalviewjsTransferUnzipAllLibs {
2472 dependsOn jalviewjsTransferUnzipSwingJs
2473 dependsOn jalviewjsTransferUnzipLib
2477 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
2479 description "Create the alternative j2s file from the j2s.* properties"
2481 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
2482 def siteDirProperty = "j2s.site.directory"
2483 def setSiteDir = false
2484 jalviewjsJ2sProps.each { prop, val ->
2486 if (prop == siteDirProperty) {
2487 if (!(val.startsWith('/') || val.startsWith("file://") )) {
2488 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
2494 if (!setSiteDir) { // default site location, don't override specifically set property
2495 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
2498 outputFile = jalviewjsJ2sAltSettingsFileName
2501 inputs.properties(jalviewjsJ2sProps)
2502 outputs.file(jalviewjsJ2sAltSettingsFileName)
2507 task jalviewjsEclipseSetup {
2508 dependsOn jalviewjsEclipseCopyDropins
2509 dependsOn jalviewjsSetEclipseWorkspace
2510 dependsOn jalviewjsCreateJ2sSettings
2514 task jalviewjsSyncAllLibs (type: Sync) {
2515 dependsOn jalviewjsTransferUnzipAllLibs
2516 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
2517 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
2518 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2522 def outputFiles = []
2523 rename { filename ->
2524 outputFiles += "${outputDir}/${filename}"
2531 // should this be exclude really ?
2532 duplicatesStrategy "INCLUDE"
2534 outputs.files outputFiles
2535 inputs.files inputFiles
2539 task jalviewjsSyncResources (type: Sync) {
2540 dependsOn buildResources
2542 def inputFiles = fileTree(dir: resourcesBuildDir)
2543 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
2547 def outputFiles = []
2548 rename { filename ->
2549 outputFiles += "${outputDir}/${filename}"
2555 outputs.files outputFiles
2556 inputs.files inputFiles
2560 task jalviewjsSyncSiteResources (type: Sync) {
2561 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
2562 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2566 def outputFiles = []
2567 rename { filename ->
2568 outputFiles += "${outputDir}/${filename}"
2574 outputs.files outputFiles
2575 inputs.files inputFiles
2579 task jalviewjsSyncBuildProperties (type: Sync) {
2580 dependsOn createBuildProperties
2581 def inputFiles = [file(buildProperties)]
2582 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
2586 def outputFiles = []
2587 rename { filename ->
2588 outputFiles += "${outputDir}/${filename}"
2594 outputs.files outputFiles
2595 inputs.files inputFiles
2599 task jalviewjsProjectImport(type: Exec) {
2600 dependsOn eclipseSetup
2601 dependsOn jalviewjsEclipsePaths
2602 dependsOn jalviewjsEclipseSetup
2605 // do not run a headless import when we claim to be in Eclipse
2607 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2608 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2610 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2614 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
2615 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
2616 executable(eclipseBinary)
2617 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
2621 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
2623 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
2624 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
2627 inputs.file("${jalviewDir}/.project")
2628 outputs.upToDateWhen {
2629 file(projdir).exists()
2634 task jalviewjsTranspile(type: Exec) {
2635 dependsOn jalviewjsEclipseSetup
2636 dependsOn jalviewjsProjectImport
2637 dependsOn jalviewjsEclipsePaths
2639 dependsOn jalviewjsEnableAltFileProperty
2643 // do not run a headless transpile when we claim to be in Eclipse
2645 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2646 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2648 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2652 executable(eclipseBinary)
2653 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
2657 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
2659 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
2660 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
2666 stdout = new ByteArrayOutputStream()
2667 stderr = new ByteArrayOutputStream()
2669 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
2670 def logOutFile = file(logOutFileName)
2671 logOutFile.createNewFile()
2672 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
2673 BINARY: ${eclipseBinary}
2674 VERSION: ${eclipseVersion}
2675 WORKSPACE: ${eclipseWorkspace}
2676 DEBUG: ${eclipseDebug}
2679 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
2680 // combine stdout and stderr
2681 def logErrFOS = logOutFOS
2683 if (jalviewjs_j2s_to_console.equals("true")) {
2684 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2685 new org.apache.tools.ant.util.TeeOutputStream(
2689 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2690 new org.apache.tools.ant.util.TeeOutputStream(
2695 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2698 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2705 if (stdout.toString().contains("Error processing ")) {
2706 // j2s did not complete transpile
2707 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2708 if (jalviewjs_ignore_transpile_errors.equals("true")) {
2709 println("IGNORING TRANSPILE ERRORS")
2710 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2712 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2717 inputs.dir("${jalviewDir}/${sourceDir}")
2718 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
2719 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
2723 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
2725 def stdout = new ByteArrayOutputStream()
2726 def stderr = new ByteArrayOutputStream()
2728 def coreFile = file(jsfile)
2730 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
2732 logOutFile.createNewFile()
2733 logOutFile.append(msg+"\n")
2735 def coreTop = file(prefixFile)
2736 def coreBottom = file(suffixFile)
2737 coreFile.getParentFile().mkdirs()
2738 coreFile.createNewFile()
2739 coreFile.write( coreTop.getText("UTF-8") )
2743 def t = f.getText("UTF-8")
2744 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
2745 coreFile.append( t )
2747 msg = "...file '"+f.getPath()+"' does not exist, skipping"
2749 logOutFile.append(msg+"\n")
2752 coreFile.append( coreBottom.getText("UTF-8") )
2754 msg = "Generating ${zjsfile}"
2756 logOutFile.append(msg+"\n")
2757 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
2758 def logErrFOS = logOutFOS
2761 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
2762 main = "com.google.javascript.jscomp.CommandLineRunner"
2763 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
2764 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
2767 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
2769 logOutFile.append(msg+"\n")
2771 if (logOutConsole) {
2772 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2773 new org.apache.tools.ant.util.TeeOutputStream(
2777 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2778 new org.apache.tools.ant.util.TeeOutputStream(
2783 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2786 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2793 logOutFile.append(msg+"\n")
2797 task jalviewjsBuildAllCores {
2799 description "Build the core js lib closures listed in the classlists dir"
2800 dependsOn jalviewjsTranspile
2801 dependsOn jalviewjsTransferUnzipSwingJs
2803 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
2804 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
2805 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
2806 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
2807 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
2808 def prefixFile = "${jsDir}/core/coretop2.js"
2809 def suffixFile = "${jsDir}/core/corebottom2.js"
2811 inputs.file prefixFile
2812 inputs.file suffixFile
2814 def classlistFiles = []
2815 // add the classlists found int the jalviewjs_classlists_dir
2816 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
2818 def name = file.getName() - ".txt"
2825 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
2826 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
2827 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
2829 jalviewjsCoreClasslists = []
2831 classlistFiles.each {
2834 def file = hash['file']
2835 if (! file.exists()) {
2836 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
2837 return false // this is a "continue" in groovy .each closure
2839 def name = hash['name']
2841 name = file.getName() - ".txt"
2849 def list = fileTree(dir: j2sDir, includes: filelist)
2851 def jsfile = "${outputDir}/core${name}.js"
2852 def zjsfile = "${outputDir}/core${name}.z.js"
2854 jalviewjsCoreClasslists += [
2863 outputs.file(jsfile)
2864 outputs.file(zjsfile)
2867 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
2868 def stevesoftClasslistName = "_stevesoft"
2869 def stevesoftClasslist = [
2870 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
2871 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
2872 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
2873 'name': stevesoftClasslistName
2875 jalviewjsCoreClasslists += stevesoftClasslist
2876 inputs.files(stevesoftClasslist['list'])
2877 outputs.file(stevesoftClasslist['jsfile'])
2878 outputs.file(stevesoftClasslist['zjsfile'])
2881 def allClasslistName = "_all"
2882 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
2883 allJsFiles += fileTree(
2887 // these exlusions are files that the closure-compiler produces errors for. Should fix them
2888 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
2889 "**/org/jmol/export/JSExporter.js"
2892 allJsFiles += fileTree(
2896 // these exlusions are files that the closure-compiler produces errors for. Should fix them
2897 "**/sun/misc/Unsafe.js",
2898 "**/swingjs/jquery/jquery-editable-select.js",
2899 "**/swingjs/jquery/j2sComboBox.js",
2900 "**/sun/misc/FloatingDecimal.js"
2903 def allClasslist = [
2904 'jsfile': "${outputDir}/core${allClasslistName}.js",
2905 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
2907 'name': allClasslistName
2909 // not including this version of "all" core at the moment
2910 //jalviewjsCoreClasslists += allClasslist
2911 inputs.files(allClasslist['list'])
2912 outputs.file(allClasslist['jsfile'])
2913 outputs.file(allClasslist['zjsfile'])
2916 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
2917 logOutFile.getParentFile().mkdirs()
2918 logOutFile.createNewFile()
2919 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
2921 jalviewjsCoreClasslists.each {
2922 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
2929 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
2932 into file(outputFile).getParentFile()
2933 rename { filename ->
2934 if (filename.equals(inputFile.getName())) {
2935 return file(outputFile).getName()
2939 filter(ReplaceTokens,
2943 'MAIN': '"'+main_class+'"',
2945 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
2946 'COREKEY': jalviewjs_core_key,
2947 'CORENAME': coreName
2954 task jalviewjsPublishCoreTemplates {
2955 dependsOn jalviewjsBuildAllCores
2956 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
2957 def inputFile = file(inputFileName)
2958 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
2960 def outputFiles = []
2961 jalviewjsCoreClasslists.each { cl ->
2962 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
2963 cl['outputfile'] = outputFile
2964 outputFiles += outputFile
2968 jalviewjsCoreClasslists.each { cl ->
2969 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
2972 inputs.file(inputFile)
2973 outputs.files(outputFiles)
2977 task jalviewjsSyncCore (type: Sync) {
2978 dependsOn jalviewjsBuildAllCores
2979 dependsOn jalviewjsPublishCoreTemplates
2980 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
2981 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2985 def outputFiles = []
2986 rename { filename ->
2987 outputFiles += "${outputDir}/${filename}"
2993 outputs.files outputFiles
2994 inputs.files inputFiles
2998 // this Copy version of TransferSiteJs will delete anything else in the target dir
2999 task jalviewjsCopyTransferSiteJs(type: Copy) {
3000 dependsOn jalviewjsTranspile
3001 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3002 into "${jalviewDir}/${jalviewjsSiteDir}"
3006 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3007 task jalviewjsSyncTransferSiteJs(type: Sync) {
3008 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3010 into "${jalviewDir}/${jalviewjsSiteDir}"
3017 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3018 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3019 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3020 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3022 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3023 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3024 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3025 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3028 task jalviewjsPrepareSite {
3030 description "Prepares the website folder including unzipping files and copying resources"
3031 dependsOn jalviewjsSyncAllLibs
3032 dependsOn jalviewjsSyncResources
3033 dependsOn jalviewjsSyncSiteResources
3034 dependsOn jalviewjsSyncBuildProperties
3035 dependsOn jalviewjsSyncCore
3039 task jalviewjsBuildSite {
3041 description "Builds the whole website including transpiled code"
3042 dependsOn jalviewjsCopyTransferSiteJs
3043 dependsOn jalviewjsPrepareSite
3047 task cleanJalviewjsTransferSite {
3049 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3050 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3051 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3052 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3057 task cleanJalviewjsSite {
3058 dependsOn cleanJalviewjsTransferSite
3060 delete "${jalviewDir}/${jalviewjsSiteDir}"
3065 task jalviewjsSiteTar(type: Tar) {
3067 description "Creates a tar.gz file for the website"
3068 dependsOn jalviewjsBuildSite
3069 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3070 archiveFileName = outputFilename
3072 compression Compression.GZIP
3074 from "${jalviewDir}/${jalviewjsSiteDir}"
3075 into jalviewjs_site_dir // this is inside the tar file
3077 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3081 task jalviewjsServer {
3083 def filename = "jalviewjsTest.html"
3084 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3085 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3090 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3091 factory = f.newInstance()
3092 } catch (ClassNotFoundException e) {
3093 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3095 def port = Integer.valueOf(jalviewjs_server_port)
3100 while(port < start+1000 && !running) {
3102 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3103 jalviewjsServer = factory.start(doc_root, port)
3105 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3106 println("SERVER STARTED with document root ${doc_root}.")
3107 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3108 println("For debug: "+url+"?j2sdebug")
3109 println("For verbose: "+url+"?j2sverbose")
3110 } catch (Exception e) {
3115 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3116 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3117 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3119 jalviewjsCoreClasslists.each { cl ->
3120 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3122 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3124 println("For core ${cl.name}: "+urlcore)
3127 file(htmlFile).text = htmlText
3130 outputs.file(htmlFile)
3131 outputs.upToDateWhen({false})
3135 task cleanJalviewjsAll {
3137 description "Delete all configuration and build artifacts to do with JalviewJS build"
3138 dependsOn cleanJalviewjsSite
3139 dependsOn jalviewjsEclipsePaths
3142 delete "${jalviewDir}/${jalviewjsBuildDir}"
3143 delete "${jalviewDir}/${eclipse_bin_dir}"
3144 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3145 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3147 delete jalviewjsJ2sAltSettingsFileName
3150 outputs.upToDateWhen( { false } )
3154 task jalviewjsIDE_checkJ2sPlugin {
3155 group "00 JalviewJS in Eclipse"
3156 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3159 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3160 def j2sPluginFile = file(j2sPlugin)
3161 def eclipseHome = System.properties["eclipse.home.location"]
3162 if (eclipseHome == null || ! IN_ECLIPSE) {
3163 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3165 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3166 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3167 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3168 eclipseJ2sPluginDirs += altPluginsDir
3170 def foundPlugin = false
3171 def j2sPluginFileName = j2sPluginFile.getName()
3172 def eclipseJ2sPlugin
3173 def eclipseJ2sPluginFile
3174 eclipseJ2sPluginDirs.any { dir ->
3175 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3176 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3177 if (eclipseJ2sPluginFile.exists()) {
3183 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3184 System.err.println(msg)
3185 throw new StopExecutionException(msg)
3188 def digest = MessageDigest.getInstance("MD5")
3190 digest.update(j2sPluginFile.text.bytes)
3191 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3193 digest.update(eclipseJ2sPluginFile.text.bytes)
3194 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3196 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3197 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3198 System.err.println(msg)
3199 throw new StopExecutionException(msg)
3201 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3207 task jalviewjsIDE_copyJ2sPlugin {
3208 group "00 JalviewJS in Eclipse"
3209 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3212 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3213 def j2sPluginFile = file(j2sPlugin)
3214 def eclipseHome = System.properties["eclipse.home.location"]
3215 if (eclipseHome == null || ! IN_ECLIPSE) {
3216 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3218 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3219 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3220 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3221 System.err.println(msg)
3224 eclipseJ2sPluginFile.getParentFile().mkdirs()
3225 into eclipseJ2sPluginFile.getParent()
3231 task jalviewjsIDE_j2sFile {
3232 group "00 JalviewJS in Eclipse"
3233 description "Creates the .j2s file"
3234 dependsOn jalviewjsCreateJ2sSettings
3238 task jalviewjsIDE_SyncCore {
3239 group "00 JalviewJS in Eclipse"
3240 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3241 dependsOn jalviewjsSyncCore
3245 task jalviewjsIDE_SyncSiteAll {
3246 dependsOn jalviewjsSyncAllLibs
3247 dependsOn jalviewjsSyncResources
3248 dependsOn jalviewjsSyncSiteResources
3249 dependsOn jalviewjsSyncBuildProperties
3253 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3256 task jalviewjsIDE_PrepareSite {
3257 group "00 JalviewJS in Eclipse"
3258 description "Sync libs and resources to site dir, but not closure cores"
3260 dependsOn jalviewjsIDE_SyncSiteAll
3261 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3265 task jalviewjsIDE_AssembleSite {
3266 group "00 JalviewJS in Eclipse"
3267 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3268 dependsOn jalviewjsPrepareSite
3272 task jalviewjsIDE_SiteClean {
3273 group "00 JalviewJS in Eclipse"
3274 description "Deletes the Eclipse transpiled site"
3275 dependsOn cleanJalviewjsSite
3279 task jalviewjsIDE_Server {
3280 group "00 JalviewJS in Eclipse"
3281 description "Starts a webserver on localhost to test the website"
3282 dependsOn jalviewjsServer
3286 // buildship runs this at import or gradle refresh
3287 task eclipseSynchronizationTask {
3288 //dependsOn eclipseSetup
3289 dependsOn createBuildProperties
3291 dependsOn jalviewjsIDE_j2sFile
3292 dependsOn jalviewjsIDE_checkJ2sPlugin
3293 dependsOn jalviewjsIDE_PrepareSite
3298 // buildship runs this at build time or project refresh
3299 task eclipseAutoBuildTask {
3300 //dependsOn jalviewjsIDE_checkJ2sPlugin
3301 //dependsOn jalviewjsIDE_PrepareSite
3307 description "Build the site"
3308 dependsOn jalviewjsBuildSite