We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Make script aware of 407 when downloading gradle
builds.snapcraft.io rejects downloading gradle.

```
Downloading https://services.gradle.org/distributions/gradle-4.0.2-bin.zip

Exception in thread "main" java.io.IOException: Unable to tunnel through proxy. Proxy returns "HTTP/1.1 407 Proxy Authentication Required"
```

Source: https://build.snapcraft.io/user/JabRef/jabref/67152

An issue has been submitted - see https://github.com/canonical-websites/build.snapcraft.io/issues/918. I don't know, if this will be fixed or if it is easier to quickyl adapt `gradle.py`.

I assume, gradle.py has to be adapted accordingly? https://github.com/snapcore/snapcraft/blob/master/snapcraft/plugins/gradle.py#L88; if gradlew exists, execute it. If that fails with proxy 407 error (grepping stdout?), execute gradle

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `snapcraft/plugins/ant.py`
Content:
```
1 # -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
2 #
3 # Copyright (C) 2015 Canonical Ltd
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License version 3 as
7 # published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 
17 """The ant plugin is useful for ant based parts.
18 
19 The ant build system is commonly used to build Java projects.
20 The plugin requires a build.xml in the root of the source tree.
21 
22 This plugin uses the common plugin keywords as well as those for "sources".
23 For more information check the 'plugins' topic for the former and the
24 'sources' topic for the latter.
25 
26 Additionally, this plugin uses the following plugin-specific keywords:
27 
28     - ant-properties:
29       (object)
30       A dictionary of key-value pairs. Set the following properties when
31       running ant.
32 
33     - ant-build-targets:
34       (list of strings)
35       Run the given ant targets.
36 """
37 
38 import glob
39 import logging
40 import os
41 from urllib.parse import urlsplit
42 
43 import snapcraft
44 import snapcraft.common
45 import snapcraft.plugins.jdk
46 
47 
48 logger = logging.getLogger(__name__)
49 
50 
51 class AntPlugin(snapcraft.plugins.jdk.JdkPlugin):
52 
53     @classmethod
54     def schema(cls):
55         schema = super().schema()
56         schema['properties']['ant-properties'] = {
57             'type': 'object',
58             'default': {},
59         }
60         schema['properties']['ant-build-targets'] = {
61             'type': 'array',
62             'uniqueItems': True,
63             'items': {
64                 'type': 'string',
65             },
66             'default': [],
67         }
68         return schema
69 
70     def __init__(self, name, options, project):
71         super().__init__(name, options, project)
72         self.build_packages.append('ant')
73 
74     @classmethod
75     def get_build_properties(cls):
76         # Inform Snapcraft of the properties associated with building. If these
77         # change in the YAML Snapcraft will consider the build step dirty.
78         return ['ant-build-targets', 'ant-properties']
79 
80     def build(self):
81         super().build()
82 
83         command = ['ant']
84 
85         if self.options.ant_build_targets:
86             command.extend(self.options.ant_build_targets)
87 
88         for prop, value in self.options.ant_properties.items():
89             command.extend(['-D{}={}'.format(prop, value)])
90 
91         self.run(command)
92         files = glob.glob(os.path.join(self.builddir, 'target', '*.jar'))
93         if files:
94             jardir = os.path.join(self.installdir, 'jar')
95             os.makedirs(jardir)
96             for f in files:
97                 base = os.path.basename(f)
98                 os.link(f, os.path.join(jardir, base))
99 
100     def get_proxy_options(self, scheme):
101         proxy = os.environ.get('{}_proxy'.format(scheme))
102         if proxy:
103             parsed = urlsplit(proxy)
104             if parsed.hostname is not None:
105                 yield '-D{}.proxyHost={}'.format(scheme, parsed.hostname)
106             if parsed.port is not None:
107                 yield '-D{}.proxyPort={}'.format(scheme, parsed.port)
108 
109     def env(self, root):
110         env = super().env(root)
111         jars = glob.glob(os.path.join(self.installdir, 'jar', '*.jar'))
112         if jars:
113             jars = [os.path.join(root, 'jar',
114                     os.path.basename(x)) for x in sorted(jars)]
115             env.extend(
116                 ['CLASSPATH={}:$CLASSPATH'.format(':'.join(jars))])
117         # Getting ant to use a proxy requires a little work; the JRE doesn't
118         # help as much as it should.  (java.net.useSystemProxies=true ought
119         # to do the trick, but it relies on desktop configuration rather
120         # than using the standard environment variables.)
121         ant_opts = []
122         ant_opts.extend(self.get_proxy_options('http'))
123         ant_opts.extend(self.get_proxy_options('https'))
124         if ant_opts:
125             env.append("ANT_OPTS='{}'".format(
126                 ' '.join(opt.replace("'", "'\\''") for opt in ant_opts)))
127         return env
128
```

Path: `snapcraft/plugins/gradle.py`
Content:
```
1 # -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
2 #
3 # Copyright (C) 2016 Canonical Ltd
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License version 3 as
7 # published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 
17 """This plugin is useful for building parts that use gradle.
18 
19 The gradle build system is commonly used to build Java projects.
20 The plugin requires a pom.xml in the root of the source tree.
21 
22 This plugin uses the common plugin keywords as well as those for "sources".
23 For more information check the 'plugins' topic for the former and the
24 'sources' topic for the latter.
25 
26 Additionally, this plugin uses the following plugin-specific keywords:
27 
28     - gradle-options:
29       (list of strings)
30       Flags to pass to the build using the gradle semantics for parameters.
31       The 'jar' option is always passed in as the last parameter.
32 
33     - gradle-output-dir:
34       (string; default: 'build/libs')
35       The output directory where the resulting jar or war files from gradle[w]
36       are generated.
37 """
38 
39 import glob
40 import logging
41 import os
42 import urllib.parse
43 import snapcraft
44 import snapcraft.common
45 import snapcraft.plugins.jdk
46 
47 
48 logger = logging.getLogger(__name__)
49 
50 
51 class GradlePlugin(snapcraft.plugins.jdk.JdkPlugin):
52 
53     @classmethod
54     def schema(cls):
55         schema = super().schema()
56         schema['properties']['gradle-options'] = {
57             'type': 'array',
58             'minitems': 1,
59             'uniqueItems': True,
60             'items': {
61                 'type': 'string',
62             },
63             'default': [],
64         }
65         schema['properties']['gradle-output-dir'] = {
66             'type': 'string',
67             'default': 'build/libs',
68         }
69 
70         return schema
71 
72     def __init__(self, name, options, project):
73         super().__init__(name, options, project)
74         filename = os.path.join(os.getcwd(), 'gradlew')
75         if not os.path.isfile(filename):
76             self.build_packages.append('gradle')
77         self.build_packages.append('ca-certificates-java')
78 
79     @classmethod
80     def get_build_properties(cls):
81         # Inform Snapcraft of the properties associated with building. If these
82         # change in the YAML Snapcraft will consider the build step dirty.
83         return super().get_build_properties() + ['gradle-options',
84                                                  'gradle-output-dir']
85 
86     def build(self):
87         super().build()
88         filename = os.path.join(os.getcwd(), 'gradlew')
89         if os.path.isfile(filename):
90             gradle_cmd = ['./gradlew']
91         else:
92             gradle_cmd = ['gradle']
93         self.run(gradle_cmd +
94                  self._get_proxy_options() +
95                  self.options.gradle_options + ['jar'])
96 
97         src = os.path.join(self.builddir, self.options.gradle_output_dir)
98         jarfiles = glob.glob(os.path.join(src, '*.jar'))
99         warfiles = glob.glob(os.path.join(src, '*.war'))
100 
101         if len(jarfiles) > 0:
102             basedir = 'jar'
103         elif len(warfiles) > 0:
104             basedir = 'war'
105             jarfiles = warfiles
106         else:
107             raise RuntimeError("Could not find any built jar files for part")
108 
109         snapcraft.file_utils.link_or_copy_tree(
110             src, os.path.join(self.installdir, basedir),
111             copy_function=lambda src, dst:
112                 snapcraft.file_utils.link_or_copy(src, dst, self.installdir))
113 
114     def _get_proxy_options(self):
115         # XXX This doesn't yet support username and password.
116         # -- elopio - 2016-11-17
117         proxy_options = []
118         for var in ('http', 'https'):
119             proxy = os.environ.get('{}_proxy'.format(var), False)
120             if proxy:
121                 parsed_url = urllib.parse.urlparse(proxy)
122                 proxy_options.append('-D{}.proxyHost={}'.format(
123                     var, parsed_url.hostname))
124                 if parsed_url.port:
125                     proxy_options.append(
126                         '-D{}.proxyPort={}'.format(var, parsed_url.port))
127         return proxy_options
128
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/snapcraft/plugins/ant.py b/snapcraft/plugins/ant.py
--- a/snapcraft/plugins/ant.py
+++ b/snapcraft/plugins/ant.py
@@ -105,6 +105,10 @@
                 yield '-D{}.proxyHost={}'.format(scheme, parsed.hostname)
             if parsed.port is not None:
                 yield '-D{}.proxyPort={}'.format(scheme, parsed.port)
+            if parsed.username is not None:
+                yield '-D{}.proxyUser={}'.format(scheme, parsed.username)
+            if parsed.password is not None:
+                yield '-D{}.proxyPassword={}'.format(scheme, parsed.password)
 
     def env(self, root):
         env = super().env(root)
diff --git a/snapcraft/plugins/gradle.py b/snapcraft/plugins/gradle.py
--- a/snapcraft/plugins/gradle.py
+++ b/snapcraft/plugins/gradle.py
@@ -112,8 +112,6 @@
                 snapcraft.file_utils.link_or_copy(src, dst, self.installdir))
 
     def _get_proxy_options(self):
-        # XXX This doesn't yet support username and password.
-        # -- elopio - 2016-11-17
         proxy_options = []
         for var in ('http', 'https'):
             proxy = os.environ.get('{}_proxy'.format(var), False)
@@ -124,4 +122,11 @@
                 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

{"golden_diff": "diff --git a/snapcraft/plugins/ant.py b/snapcraft/plugins/ant.py\n--- a/snapcraft/plugins/ant.py\n+++ b/snapcraft/plugins/ant.py\n@@ -105,6 +105,10 @@\n                 yield '-D{}.proxyHost={}'.format(scheme, parsed.hostname)\n             if parsed.port is not None:\n                 yield '-D{}.proxyPort={}'.format(scheme, parsed.port)\n+            if parsed.username is not None:\n+                yield '-D{}.proxyUser={}'.format(scheme, parsed.username)\n+            if parsed.password is not None:\n+                yield '-D{}.proxyPassword={}'.format(scheme, parsed.password)\n \n     def env(self, root):\n         env = super().env(root)\ndiff --git a/snapcraft/plugins/gradle.py b/snapcraft/plugins/gradle.py\n--- a/snapcraft/plugins/gradle.py\n+++ b/snapcraft/plugins/gradle.py\n@@ -112,8 +112,6 @@\n                 snapcraft.file_utils.link_or_copy(src, dst, self.installdir))\n \n     def _get_proxy_options(self):\n-        # XXX This doesn't yet support username and password.\n-        # -- elopio - 2016-11-17\n         proxy_options = []\n         for var in ('http', 'https'):\n             proxy = os.environ.get('{}_proxy'.format(var), False)\n@@ -124,4 +122,11 @@\n                 if parsed_url.port:\n                     proxy_options.append(\n                         '-D{}.proxyPort={}'.format(var, parsed_url.port))\n+                if parsed_url.username:\n+                    proxy_options.append(\n+                        '-D{}.proxyUser={}'.format(var, parsed_url.username))\n+                if parsed_url.password:\n+                    proxy_options.append(\n+                        '-D{}.proxyPassword={}'.format(\n+                            var, parsed_url.password))\n         return proxy_options\n", "issue": "Make script aware of 407 when downloading gradle\nbuilds.snapcraft.io rejects downloading gradle.\r\n\r\n```\r\nDownloading https://services.gradle.org/distributions/gradle-4.0.2-bin.zip\r\n\r\nException in thread \"main\" java.io.IOException: Unable to tunnel through proxy. Proxy returns \"HTTP/1.1 407 Proxy Authentication Required\"\r\n```\r\n\r\nSource: https://build.snapcraft.io/user/JabRef/jabref/67152\r\n\r\nAn issue has been submitted - see https://github.com/canonical-websites/build.snapcraft.io/issues/918. I don't know, if this will be fixed or if it is easier to quickyl adapt `gradle.py`.\r\n\r\nI assume, gradle.py has to be adapted accordingly? https://github.com/snapcore/snapcraft/blob/master/snapcraft/plugins/gradle.py#L88; if gradlew exists, execute it. If that fails with proxy 407 error (grepping stdout?), execute gradle\n", "before_files": [{"content": "# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-\n#\n# Copyright (C) 2015 Canonical Ltd\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License version 3 as\n# published by the Free Software Foundation.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"The ant plugin is useful for ant based parts.\n\nThe ant build system is commonly used to build Java projects.\nThe plugin requires a build.xml in the root of the source tree.\n\nThis plugin uses the common plugin keywords as well as those for \"sources\".\nFor more information check the 'plugins' topic for the former and the\n'sources' topic for the latter.\n\nAdditionally, this plugin uses the following plugin-specific keywords:\n\n    - ant-properties:\n      (object)\n      A dictionary of key-value pairs. Set the following properties when\n      running ant.\n\n    - ant-build-targets:\n      (list of strings)\n      Run the given ant targets.\n\"\"\"\n\nimport glob\nimport logging\nimport os\nfrom urllib.parse import urlsplit\n\nimport snapcraft\nimport snapcraft.common\nimport snapcraft.plugins.jdk\n\n\nlogger = logging.getLogger(__name__)\n\n\nclass AntPlugin(snapcraft.plugins.jdk.JdkPlugin):\n\n    @classmethod\n    def schema(cls):\n        schema = super().schema()\n        schema['properties']['ant-properties'] = {\n            'type': 'object',\n            'default': {},\n        }\n        schema['properties']['ant-build-targets'] = {\n            'type': 'array',\n            'uniqueItems': True,\n            'items': {\n                'type': 'string',\n            },\n            'default': [],\n        }\n        return schema\n\n    def __init__(self, name, options, project):\n        super().__init__(name, options, project)\n        self.build_packages.append('ant')\n\n    @classmethod\n    def get_build_properties(cls):\n        # Inform Snapcraft of the properties associated with building. If these\n        # change in the YAML Snapcraft will consider the build step dirty.\n        return ['ant-build-targets', 'ant-properties']\n\n    def build(self):\n        super().build()\n\n        command = ['ant']\n\n        if self.options.ant_build_targets:\n            command.extend(self.options.ant_build_targets)\n\n        for prop, value in self.options.ant_properties.items():\n            command.extend(['-D{}={}'.format(prop, value)])\n\n        self.run(command)\n        files = glob.glob(os.path.join(self.builddir, 'target', '*.jar'))\n        if files:\n            jardir = os.path.join(self.installdir, 'jar')\n            os.makedirs(jardir)\n            for f in files:\n                base = os.path.basename(f)\n                os.link(f, os.path.join(jardir, base))\n\n    def get_proxy_options(self, scheme):\n        proxy = os.environ.get('{}_proxy'.format(scheme))\n        if proxy:\n            parsed = urlsplit(proxy)\n            if parsed.hostname is not None:\n                yield '-D{}.proxyHost={}'.format(scheme, parsed.hostname)\n            if parsed.port is not None:\n                yield '-D{}.proxyPort={}'.format(scheme, parsed.port)\n\n    def env(self, root):\n        env = super().env(root)\n        jars = glob.glob(os.path.join(self.installdir, 'jar', '*.jar'))\n        if jars:\n            jars = [os.path.join(root, 'jar',\n                    os.path.basename(x)) for x in sorted(jars)]\n            env.extend(\n                ['CLASSPATH={}:$CLASSPATH'.format(':'.join(jars))])\n        # Getting ant to use a proxy requires a little work; the JRE doesn't\n        # help as much as it should.  (java.net.useSystemProxies=true ought\n        # to do the trick, but it relies on desktop configuration rather\n        # than using the standard environment variables.)\n        ant_opts = []\n        ant_opts.extend(self.get_proxy_options('http'))\n        ant_opts.extend(self.get_proxy_options('https'))\n        if ant_opts:\n            env.append(\"ANT_OPTS='{}'\".format(\n                ' '.join(opt.replace(\"'\", \"'\\\\''\") for opt in ant_opts)))\n        return env\n", "path": "snapcraft/plugins/ant.py"}, {"content": "# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-\n#\n# Copyright (C) 2016 Canonical Ltd\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License version 3 as\n# published by the Free Software Foundation.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"This plugin is useful for building parts that use gradle.\n\nThe gradle build system is commonly used to build Java projects.\nThe plugin requires a pom.xml in the root of the source tree.\n\nThis plugin uses the common plugin keywords as well as those for \"sources\".\nFor more information check the 'plugins' topic for the former and the\n'sources' topic for the latter.\n\nAdditionally, this plugin uses the following plugin-specific keywords:\n\n    - gradle-options:\n      (list of strings)\n      Flags to pass to the build using the gradle semantics for parameters.\n      The 'jar' option is always passed in as the last parameter.\n\n    - gradle-output-dir:\n      (string; default: 'build/libs')\n      The output directory where the resulting jar or war files from gradle[w]\n      are generated.\n\"\"\"\n\nimport glob\nimport logging\nimport os\nimport urllib.parse\nimport snapcraft\nimport snapcraft.common\nimport snapcraft.plugins.jdk\n\n\nlogger = logging.getLogger(__name__)\n\n\nclass GradlePlugin(snapcraft.plugins.jdk.JdkPlugin):\n\n    @classmethod\n    def schema(cls):\n        schema = super().schema()\n        schema['properties']['gradle-options'] = {\n            'type': 'array',\n            'minitems': 1,\n            'uniqueItems': True,\n            'items': {\n                'type': 'string',\n            },\n            'default': [],\n        }\n        schema['properties']['gradle-output-dir'] = {\n            'type': 'string',\n            'default': 'build/libs',\n        }\n\n        return schema\n\n    def __init__(self, name, options, project):\n        super().__init__(name, options, project)\n        filename = os.path.join(os.getcwd(), 'gradlew')\n        if not os.path.isfile(filename):\n            self.build_packages.append('gradle')\n        self.build_packages.append('ca-certificates-java')\n\n    @classmethod\n    def get_build_properties(cls):\n        # Inform Snapcraft of the properties associated with building. If these\n        # change in the YAML Snapcraft will consider the build step dirty.\n        return super().get_build_properties() + ['gradle-options',\n                                                 'gradle-output-dir']\n\n    def build(self):\n        super().build()\n        filename = os.path.join(os.getcwd(), 'gradlew')\n        if os.path.isfile(filename):\n            gradle_cmd = ['./gradlew']\n        else:\n            gradle_cmd = ['gradle']\n        self.run(gradle_cmd +\n                 self._get_proxy_options() +\n                 self.options.gradle_options + ['jar'])\n\n        src = os.path.join(self.builddir, self.options.gradle_output_dir)\n        jarfiles = glob.glob(os.path.join(src, '*.jar'))\n        warfiles = glob.glob(os.path.join(src, '*.war'))\n\n        if len(jarfiles) > 0:\n            basedir = 'jar'\n        elif len(warfiles) > 0:\n            basedir = 'war'\n            jarfiles = warfiles\n        else:\n            raise RuntimeError(\"Could not find any built jar files for part\")\n\n        snapcraft.file_utils.link_or_copy_tree(\n            src, os.path.join(self.installdir, basedir),\n            copy_function=lambda src, dst:\n                snapcraft.file_utils.link_or_copy(src, dst, self.installdir))\n\n    def _get_proxy_options(self):\n        # XXX This doesn't yet support username and password.\n        # -- elopio - 2016-11-17\n        proxy_options = []\n        for var in ('http', 'https'):\n            proxy = os.environ.get('{}_proxy'.format(var), False)\n            if proxy:\n                parsed_url = urllib.parse.urlparse(proxy)\n                proxy_options.append('-D{}.proxyHost={}'.format(\n                    var, parsed_url.hostname))\n                if parsed_url.port:\n                    proxy_options.append(\n                        '-D{}.proxyPort={}'.format(var, parsed_url.port))\n        return proxy_options\n", "path": "snapcraft/plugins/gradle.py"}], "after_files": [{"content": "# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-\n#\n# Copyright (C) 2015 Canonical Ltd\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License version 3 as\n# published by the Free Software Foundation.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"The ant plugin is useful for ant based parts.\n\nThe ant build system is commonly used to build Java projects.\nThe plugin requires a build.xml in the root of the source tree.\n\nThis plugin uses the common plugin keywords as well as those for \"sources\".\nFor more information check the 'plugins' topic for the former and the\n'sources' topic for the latter.\n\nAdditionally, this plugin uses the following plugin-specific keywords:\n\n    - ant-properties:\n      (object)\n      A dictionary of key-value pairs. Set the following properties when\n      running ant.\n\n    - ant-build-targets:\n      (list of strings)\n      Run the given ant targets.\n\"\"\"\n\nimport glob\nimport logging\nimport os\nfrom urllib.parse import urlsplit\n\nimport snapcraft\nimport snapcraft.common\nimport snapcraft.plugins.jdk\n\n\nlogger = logging.getLogger(__name__)\n\n\nclass AntPlugin(snapcraft.plugins.jdk.JdkPlugin):\n\n    @classmethod\n    def schema(cls):\n        schema = super().schema()\n        schema['properties']['ant-properties'] = {\n            'type': 'object',\n            'default': {},\n        }\n        schema['properties']['ant-build-targets'] = {\n            'type': 'array',\n            'uniqueItems': True,\n            'items': {\n                'type': 'string',\n            },\n            'default': [],\n        }\n        return schema\n\n    def __init__(self, name, options, project):\n        super().__init__(name, options, project)\n        self.build_packages.append('ant')\n\n    @classmethod\n    def get_build_properties(cls):\n        # Inform Snapcraft of the properties associated with building. If these\n        # change in the YAML Snapcraft will consider the build step dirty.\n        return ['ant-build-targets', 'ant-properties']\n\n    def build(self):\n        super().build()\n\n        command = ['ant']\n\n        if self.options.ant_build_targets:\n            command.extend(self.options.ant_build_targets)\n\n        for prop, value in self.options.ant_properties.items():\n            command.extend(['-D{}={}'.format(prop, value)])\n\n        self.run(command)\n        files = glob.glob(os.path.join(self.builddir, 'target', '*.jar'))\n        if files:\n            jardir = os.path.join(self.installdir, 'jar')\n            os.makedirs(jardir)\n            for f in files:\n                base = os.path.basename(f)\n                os.link(f, os.path.join(jardir, base))\n\n    def get_proxy_options(self, scheme):\n        proxy = os.environ.get('{}_proxy'.format(scheme))\n        if proxy:\n            parsed = urlsplit(proxy)\n            if parsed.hostname is not None:\n                yield '-D{}.proxyHost={}'.format(scheme, parsed.hostname)\n            if parsed.port is not None:\n                yield '-D{}.proxyPort={}'.format(scheme, parsed.port)\n            if parsed.username is not None:\n                yield '-D{}.proxyUser={}'.format(scheme, parsed.username)\n            if parsed.password is not None:\n                yield '-D{}.proxyPassword={}'.format(scheme, parsed.password)\n\n    def env(self, root):\n        env = super().env(root)\n        jars = glob.glob(os.path.join(self.installdir, 'jar', '*.jar'))\n        if jars:\n            jars = [os.path.join(root, 'jar',\n                    os.path.basename(x)) for x in sorted(jars)]\n            env.extend(\n                ['CLASSPATH={}:$CLASSPATH'.format(':'.join(jars))])\n        # Getting ant to use a proxy requires a little work; the JRE doesn't\n        # help as much as it should.  (java.net.useSystemProxies=true ought\n        # to do the trick, but it relies on desktop configuration rather\n        # than using the standard environment variables.)\n        ant_opts = []\n        ant_opts.extend(self.get_proxy_options('http'))\n        ant_opts.extend(self.get_proxy_options('https'))\n        if ant_opts:\n            env.append(\"ANT_OPTS='{}'\".format(\n                ' '.join(opt.replace(\"'\", \"'\\\\''\") for opt in ant_opts)))\n        return env\n", "path": "snapcraft/plugins/ant.py"}, {"content": "# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-\n#\n# Copyright (C) 2016 Canonical Ltd\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License version 3 as\n# published by the Free Software Foundation.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"This plugin is useful for building parts that use gradle.\n\nThe gradle build system is commonly used to build Java projects.\nThe plugin requires a pom.xml in the root of the source tree.\n\nThis plugin uses the common plugin keywords as well as those for \"sources\".\nFor more information check the 'plugins' topic for the former and the\n'sources' topic for the latter.\n\nAdditionally, this plugin uses the following plugin-specific keywords:\n\n    - gradle-options:\n      (list of strings)\n      Flags to pass to the build using the gradle semantics for parameters.\n      The 'jar' option is always passed in as the last parameter.\n\n    - gradle-output-dir:\n      (string; default: 'build/libs')\n      The output directory where the resulting jar or war files from gradle[w]\n      are generated.\n\"\"\"\n\nimport glob\nimport logging\nimport os\nimport urllib.parse\nimport snapcraft\nimport snapcraft.common\nimport snapcraft.plugins.jdk\n\n\nlogger = logging.getLogger(__name__)\n\n\nclass GradlePlugin(snapcraft.plugins.jdk.JdkPlugin):\n\n    @classmethod\n    def schema(cls):\n        schema = super().schema()\n        schema['properties']['gradle-options'] = {\n            'type': 'array',\n            'minitems': 1,\n            'uniqueItems': True,\n            'items': {\n                'type': 'string',\n            },\n            'default': [],\n        }\n        schema['properties']['gradle-output-dir'] = {\n            'type': 'string',\n            'default': 'build/libs',\n        }\n\n        return schema\n\n    def __init__(self, name, options, project):\n        super().__init__(name, options, project)\n        filename = os.path.join(os.getcwd(), 'gradlew')\n        if not os.path.isfile(filename):\n            self.build_packages.append('gradle')\n        self.build_packages.append('ca-certificates-java')\n\n    @classmethod\n    def get_build_properties(cls):\n        # Inform Snapcraft of the properties associated with building. If these\n        # change in the YAML Snapcraft will consider the build step dirty.\n        return super().get_build_properties() + ['gradle-options',\n                                                 'gradle-output-dir']\n\n    def build(self):\n        super().build()\n        filename = os.path.join(os.getcwd(), 'gradlew')\n        if os.path.isfile(filename):\n            gradle_cmd = ['./gradlew']\n        else:\n            gradle_cmd = ['gradle']\n        self.run(gradle_cmd +\n                 self._get_proxy_options() +\n                 self.options.gradle_options + ['jar'])\n\n        src = os.path.join(self.builddir, self.options.gradle_output_dir)\n        jarfiles = glob.glob(os.path.join(src, '*.jar'))\n        warfiles = glob.glob(os.path.join(src, '*.war'))\n\n        if len(jarfiles) > 0:\n            basedir = 'jar'\n        elif len(warfiles) > 0:\n            basedir = 'war'\n            jarfiles = warfiles\n        else:\n            raise RuntimeError(\"Could not find any built jar files for part\")\n\n        snapcraft.file_utils.link_or_copy_tree(\n            src, os.path.join(self.installdir, basedir),\n            copy_function=lambda src, dst:\n                snapcraft.file_utils.link_or_copy(src, dst, self.installdir))\n\n    def _get_proxy_options(self):\n        proxy_options = []\n        for var in ('http', 'https'):\n            proxy = os.environ.get('{}_proxy'.format(var), False)\n            if proxy:\n                parsed_url = urllib.parse.urlparse(proxy)\n                proxy_options.append('-D{}.proxyHost={}'.format(\n                    var, parsed_url.hostname))\n                if parsed_url.port:\n                    proxy_options.append(\n                        '-D{}.proxyPort={}'.format(var, parsed_url.port))\n                if parsed_url.username:\n                    proxy_options.append(\n                        '-D{}.proxyUser={}'.format(var, parsed_url.username))\n                if parsed_url.password:\n                    proxy_options.append(\n                        '-D{}.proxyPassword={}'.format(\n                            var, parsed_url.password))\n        return proxy_options\n", "path": "snapcraft/plugins/gradle.py"}]}