diff --git a/.gitignore b/.gitignore
index d6a84d10f09..a7ed4fb2470 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,9 @@ status.md
# Install4J
install4j6/
+# Python
+__pycache__/
+
# Snap
parts/
stage/
diff --git a/snap/plugins/x_gradle.py b/snap/plugins/x_gradle.py
new file mode 100644
index 00000000000..899d6567712
--- /dev/null
+++ b/snap/plugins/x_gradle.py
@@ -0,0 +1,301 @@
+# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
+#
+# Copyright (C) 2016, 2018 Canonical Ltd
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 3 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+"""This plugin is useful for building parts that use gradle.
+
+The gradle build system is commonly used to build Java projects.
+The plugin requires a pom.xml in the root of the source tree.
+
+This plugin uses the common plugin keywords as well as those for "sources".
+For more information check the 'plugins' topic for the former and the
+'sources' topic for the latter.
+
+Additionally, this plugin uses the following plugin-specific keywords:
+
+ - gradle-options:
+ (list of strings)
+ Flags to pass to the build using the gradle semantics for parameters.
+ The 'jar' option is always passed in as the last parameter.
+
+ - gradle-output-dir:
+ (string; default: 'build/libs')
+ The output directory where the resulting jar or war files from gradle[w]
+ are generated.
+
+ - gradle-version:
+ (string)
+ The version of gradle you want to use to build the source artifacts.
+ Defaults to the current release downloadable from
+ https://services.gradle.org/distributions/
+ The entry is ignored if gradlew is found.
+
+ - gradle-version-checksum:
+ (string)
+ The checksum for gradle-version in the form of /.
+ As an example "sha512/2a803f578f341e164f6753e410413d16ab60fab...".
+
+ - gradle-openjdk-version:
+ (string)
+ openjdk version available to the base to use. If not set the latest
+ version available to the base will be used.
+"""
+
+import logging
+import os
+import urllib.parse
+from glob import glob
+from typing import Sequence
+
+import snapcraft
+from snapcraft import file_utils, formatting_utils
+from snapcraft.internal import errors, sources
+
+logger = logging.getLogger(__name__)
+
+
+_DEFAULT_GRADLE_VERSION = "4.10.2"
+_DEFAULT_GRADLE_CHECKSUM = (
+ "sha256/b49c6da1b2cb67a0caf6c7480630b51c70a11ca2016ff2f555eaeda863143a29"
+)
+_GRADLE_URL = "https://services.gradle.org/distributions/gradle-{version}-bin.zip"
+
+
+class UnsupportedJDKVersionError(errors.SnapcraftError):
+
+ fmt = (
+ "The gradle-openjdk-version plugin property was set to {version!r}.\n"
+ "Valid values for the {base!r} base are: {valid_versions}."
+ )
+
+ def __init__(
+ self, *, base: str, version: str, valid_versions: Sequence[str]
+ ) -> None:
+ super().__init__(
+ base=base,
+ version=version,
+ valid_versions=formatting_utils.humanize_list(
+ valid_versions, conjunction="or"
+ ),
+ )
+
+
+class GradlePlugin(snapcraft.BasePlugin):
+ @classmethod
+ def schema(cls):
+ schema = super().schema()
+ schema["properties"]["gradle-options"] = {
+ "type": "array",
+ "minitems": 1,
+ "uniqueItems": True,
+ "items": {"type": "string"},
+ "default": [],
+ }
+ schema["properties"]["gradle-output-dir"] = {
+ "type": "string",
+ "default": "build/libs",
+ }
+
+ schema["properties"]["gradle-version"] = {"type": "string"}
+
+ schema["properties"]["gradle-version-checksum"] = {"type": "string"}
+
+ schema["properties"]["gradle-openjdk-version"] = {
+ "type": "string",
+ "default": "",
+ }
+
+ schema["required"] = ["source"]
+
+ return schema
+
+ @classmethod
+ def get_pull_properties(cls):
+ # Inform Snapcraft of the properties associated with pulling. If these
+ # change in the YAML Snapcraft will consider the pull step dirty.
+ return ["gradle-version", "gradle-version-checksum", "gradle-openjdk-version"]
+
+ @classmethod
+ def get_build_properties(cls):
+ # Inform Snapcraft of the properties associated with building. If these
+ # change in the YAML Snapcraft will consider the build step dirty.
+ return super().get_build_properties() + ["gradle-options", "gradle-output-dir"]
+
+ @property
+ def _gradle_tar(self):
+ if self._gradle_tar_handle is None:
+ gradle_uri = _GRADLE_URL.format(version=self._gradle_version)
+ self._gradle_tar_handle = sources.Zip(
+ gradle_uri, self._gradle_dir, source_checksum=self._gradle_checksum
+ )
+ return self._gradle_tar_handle
+
+ def __init__(self, name, options, project):
+ super().__init__(name, options, project)
+
+ self._setup_gradle()
+ self._setup_base_tools(project.info.get_build_base())
+
+ def _setup_base_tools(self, base):
+ if base not in ("core", "core16", "core18"):
+ raise errors.PluginBaseError(
+ part_name=self.name, base=self.project.info.get_build_base()
+ )
+
+ if base in ("core", "core16"):
+ valid_versions = ["8", "9"]
+ elif base == "core18":
+ valid_versions = ["8", "11"]
+
+ version = self.options.gradle_openjdk_version
+ if not version:
+ version = valid_versions[-1]
+ elif version not in valid_versions:
+ raise UnsupportedJDKVersionError(
+ version=version, base=base, valid_versions=valid_versions
+ )
+
+ self.stage_packages.append("openjdk-{}-jre-headless".format(version))
+ self.build_packages.append("openjdk-{}-jdk-headless".format(version))
+ self.build_packages.append("ca-certificates-java")
+ self._java_version = version
+
+ def _using_gradlew(self) -> bool:
+ return os.path.isfile(os.path.join(self.sourcedir, "gradlew"))
+
+ def _setup_gradle(self):
+ self._gradle_tar_handle = None
+ self._gradle_dir = os.path.join(self.partdir, "gradle")
+ if self.options.gradle_version:
+ self._gradle_version = self.options.gradle_version
+ self._gradle_checksum = self.options.gradle_version_checksum
+ else:
+ self._gradle_version = _DEFAULT_GRADLE_VERSION
+ self._gradle_checksum = _DEFAULT_GRADLE_CHECKSUM
+
+ def pull(self):
+ super().pull()
+
+ if self._using_gradlew():
+ logger.info("Found gradlew, skipping gradle setup.")
+ return
+
+ os.makedirs(self._gradle_dir, exist_ok=True)
+ self._gradle_tar.download()
+
+ def build(self):
+ super().build()
+
+ if self._using_gradlew():
+ gradle_cmd = ["./gradlew"]
+ else:
+ self._gradle_tar.provision(self._gradle_dir, keep_zip=True)
+ gradle_cmd = ["gradle"]
+ self.run(
+ gradle_cmd
+ + self._get_proxy_options()
+ + self.options.gradle_options,
+ rootdir=self.builddir,
+ )
+
+ src = os.path.join(self.builddir, self.options.gradle_output_dir)
+ basedir = "jabref"
+ # jarfiles = glob(os.path.join(src, "*.jar"))
+ # warfiles = glob(os.path.join(src, "*.war"))
+
+ # if len(jarfiles) > 0:
+ # basedir = "jar"
+ # elif len(warfiles) > 0:
+ # basedir = "war"
+ # jarfiles = warfiles
+ # else:
+ # raise RuntimeError("Could not find any built jar files for part")
+
+ file_utils.link_or_copy_tree(
+ src,
+ os.path.join(self.installdir, basedir),
+ copy_function=lambda src, dst: file_utils.link_or_copy(
+ src, dst, self.installdir
+ ),
+ )
+
+ self._create_symlinks()
+
+ def _create_symlinks(self):
+ if self.project.info.get_build_base() not in ("core18", "core16", "core"):
+ raise errors.PluginBaseError(
+ part_name=self.name, base=self.project.info.get_build_base()
+ )
+
+ os.makedirs(os.path.join(self.installdir, "bin"), exist_ok=True)
+ java_bin = glob(
+ os.path.join(
+ self.installdir,
+ "usr",
+ "lib",
+ "jvm",
+ "java-{}-openjdk-*".format(self._java_version),
+ "bin",
+ "java",
+ )
+ )[0]
+ os.symlink(
+ os.path.relpath(java_bin, os.path.join(self.installdir, "bin")),
+ os.path.join(self.installdir, "bin", "java"),
+ )
+
+ def run(self, cmd, rootdir):
+ super().run(cmd, cwd=rootdir, env=self._build_environment())
+
+ def _build_environment(self):
+ if self._using_gradlew():
+ return
+
+ env = os.environ.copy()
+ gradle_bin = os.path.join(
+ self._gradle_dir, "gradle-{}".format(self._gradle_version), "bin"
+ )
+ print(gradle_bin)
+
+ if env.get("PATH"):
+ new_path = "{}:{}".format(gradle_bin, env.get("PATH"))
+ else:
+ new_path = gradle_bin
+
+ env["PATH"] = new_path
+ return env
+
+ def _get_proxy_options(self):
+ proxy_options = []
+ for var in ("http", "https"):
+ proxy = os.environ.get("{}_proxy".format(var), False)
+ if proxy:
+ parsed_url = urllib.parse.urlparse(proxy)
+ proxy_options.append(
+ "-D{}.proxyHost={}".format(var, parsed_url.hostname)
+ )
+ if parsed_url.port:
+ proxy_options.append(
+ "-D{}.proxyPort={}".format(var, parsed_url.port)
+ )
+ if parsed_url.username:
+ proxy_options.append(
+ "-D{}.proxyUser={}".format(var, parsed_url.username)
+ )
+ if parsed_url.password:
+ proxy_options.append(
+ "-D{}.proxyPassword={}".format(var, parsed_url.password)
+ )
+ return proxy_options
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
index 78f97120e62..23dba498ae5 100644
--- a/snap/snapcraft.yaml
+++ b/snap/snapcraft.yaml
@@ -14,7 +14,7 @@ architectures:
apps:
jabref:
- command: desktop-launch java -jar $SNAP/jar/JabRef-$SNAP_VERSION.jar
+ command: desktop-launch $SNAP/jabref/bin/JabRefMain
environment:
_JAVA_OPTIONS: "-Duser.home=$SNAP_USER_DATA"
plugs:
@@ -37,15 +37,15 @@ plugs:
parts:
jabref:
- plugin: gradle
+ plugin: x_gradle
source: .
source-type: git
stage-packages:
- openjdk-11-jre
- openjfx
- x11-utils
- gradle-options: [snapJar, -xtest]
- gradle-output-dir: 'build/releases'
+ gradle-options: [jlink, -xtest]
+ gradle-output-dir: 'build/image'
desktop-gnome-platform:
source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
source-subdir: gtk