redactUserInfo(String url) {
66 | if (!url.startsWith("http")) {
67 | return Optional.of(url);
68 | }
69 |
70 | try {
71 | URI uri = new URI(url);
72 | URI redactedUri = new URI(
73 | uri.getScheme(),
74 | uri.getUserInfo() == null || uri.getUserInfo().isEmpty() ? null : "******",
75 | uri.getHost(),
76 | uri.getPort(),
77 | uri.getRawPath(),
78 | uri.getRawQuery(),
79 | uri.getRawFragment());
80 | return Optional.of(redactedUri.toString());
81 | } catch (URISyntaxException e) {
82 | return Optional.empty();
83 | }
84 | }
85 |
86 | static Properties readPropertiesFile(String name) {
87 | try (InputStream input = new FileInputStream(name)) {
88 | Properties properties = new Properties();
89 | properties.load(input);
90 | return properties;
91 | } catch (IOException e) {
92 | throw new RuntimeException(e);
93 | }
94 | }
95 |
96 | static boolean execAndCheckSuccess(String... args) {
97 | Runtime runtime = Runtime.getRuntime();
98 | Process process = null;
99 | try {
100 | process = runtime.exec(args);
101 | boolean finished = process.waitFor(10, TimeUnit.SECONDS);
102 | return finished && process.exitValue() == 0;
103 | } catch (IOException | InterruptedException ignored) {
104 | return false;
105 | } finally {
106 | if (process != null) {
107 | process.destroyForcibly();
108 | }
109 | }
110 | }
111 |
112 | static String execAndGetStdOut(String... args) {
113 | Runtime runtime = Runtime.getRuntime();
114 | Process process;
115 | try {
116 | process = runtime.exec(args);
117 | } catch (IOException e) {
118 | throw new RuntimeException(e);
119 | }
120 |
121 | try (Reader standard = new BufferedReader(new InputStreamReader(process.getInputStream(), Charset.defaultCharset()))) {
122 | try (Reader error = new BufferedReader(new InputStreamReader(process.getErrorStream(), Charset.defaultCharset()))) {
123 | String standardText = readFully(standard);
124 | String ignore = readFully(error);
125 |
126 | boolean finished = process.waitFor(10, TimeUnit.SECONDS);
127 | return finished && process.exitValue() == 0 ? trimAtEnd(standardText) : null;
128 | }
129 | } catch (IOException | InterruptedException e) {
130 | throw new RuntimeException(e);
131 | } finally {
132 | process.destroyForcibly();
133 | }
134 | }
135 |
136 | /**
137 | * Construct a repo {@link URI} from a git URL in the format of
138 | * git://github.com/acme-inc/my-project.git
. If the URL cannot be parsed, {@link Optional#empty()} is
139 | * returned.
140 | *
141 | * The scheme can be any of git://
, https://
, or ssh
.
142 | */
143 | static Optional toWebRepoUri(String gitRepoUri) {
144 | Matcher matcher = GIT_REPO_URI_PATTERN.matcher(gitRepoUri);
145 | if (matcher.matches()) {
146 | String scheme = "https";
147 | String host = matcher.group(1);
148 | String path = matcher.group(2).startsWith("/") ? matcher.group(2) : "/" + matcher.group(2);
149 | return toUri(scheme, host, path);
150 | } else {
151 | return Optional.empty();
152 | }
153 | }
154 |
155 | static Optional toUri(String scheme, String host, String path) {
156 | try {
157 | return Optional.of(new URI(scheme, host, path, null));
158 | } catch (URISyntaxException e) {
159 | return Optional.empty();
160 | }
161 | }
162 |
163 | private static String readFully(Reader reader) throws IOException {
164 | StringBuilder sb = new StringBuilder();
165 | char[] buf = new char[1024];
166 | int nRead;
167 | while ((nRead = reader.read(buf)) != -1) {
168 | sb.append(buf, 0, nRead);
169 | }
170 | return sb.toString();
171 | }
172 |
173 | private static String trimAtEnd(String str) {
174 | return ('x' + str).trim().substring(1);
175 | }
176 |
177 | private Utils() {
178 | }
179 |
180 | }
181 |
--------------------------------------------------------------------------------
/src/main/resources/META-INF/plexus/components.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | com.gradle.develocity.agent.maven.api.DevelocityListener
5 | common-custom-user-data-develocity-listener
6 | com.gradle.CommonCustomUserDataDevelocityListener
7 | Captures common custom user data in Maven Build Scan
8 | false
9 |
10 |
11 | com.gradle.maven.extension.api.GradleEnterpriseListener
12 | common-custom-user-data-gradle-enterprise-listener
13 | com.gradle.CommonCustomUserDataGradleEnterpriseListener
14 | Captures common custom user data in Maven Build Scan
15 | false
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/test/java/com/gradle/UtilsTest.java:
--------------------------------------------------------------------------------
1 | package com.gradle;
2 |
3 |
4 | import org.junit.jupiter.api.extension.ExtensionContext;
5 | import org.junit.jupiter.params.ParameterizedTest;
6 | import org.junit.jupiter.params.provider.Arguments;
7 | import org.junit.jupiter.params.provider.ArgumentsProvider;
8 | import org.junit.jupiter.params.provider.ArgumentsSource;
9 |
10 | import java.net.URI;
11 | import java.util.HashMap;
12 | import java.util.Map;
13 | import java.util.Optional;
14 | import java.util.Set;
15 | import java.util.stream.Collectors;
16 | import java.util.stream.Stream;
17 |
18 | import static com.gradle.Utils.toWebRepoUri;
19 | import static org.junit.jupiter.api.Assertions.assertEquals;
20 |
21 | public class UtilsTest {
22 |
23 | @ParameterizedTest
24 | @ArgumentsSource(WebRepoUriArgumentsProvider.class)
25 | public void testToWebRepoUri(String repositoryHost, String repositoryUri) {
26 | URI expectedWebRepoUri = URI.create(String.format("https://%s.com/acme-inc/my-project", repositoryHost));
27 | assertEquals(Optional.of(expectedWebRepoUri), toWebRepoUri(String.format(repositoryUri, repositoryHost)));
28 | }
29 |
30 | @ParameterizedTest
31 | @ArgumentsSource(EnterpriseWebRepoUriArgumentsProvider.class)
32 | public void testToWebRepoUri_enterpriseUri(String repositoryHost, String repositoryUri) {
33 | URI expectedWebRepoUri = URI.create(String.format("https://%s.acme.com/acme-inc/my-project", repositoryHost));
34 | assertEquals(Optional.of(expectedWebRepoUri), toWebRepoUri(String.format(repositoryUri, repositoryHost)));
35 | }
36 |
37 | @ParameterizedTest
38 | @ArgumentsSource(UserInfoArgumentsProvider.class)
39 | public void testUserInfoRedacted(String inputUrl, String expectedRedactedUrl) {
40 | assertEquals(expectedRedactedUrl, Utils.redactUserInfo(inputUrl).orElse(null));
41 | }
42 |
43 | private static class WebRepoUriArgumentsProvider implements ArgumentsProvider {
44 |
45 | @Override
46 | public Stream extends Arguments> provideArguments(ExtensionContext context) {
47 | Set host = Stream.of("github", "gitlab").collect(Collectors.toSet());
48 | Set remoteRepositoryUris = Stream.of(
49 | "https://%s.com/acme-inc/my-project",
50 | "https://%s.com:443/acme-inc/my-project",
51 | "https://user:secret@%s.com/acme-inc/my-project",
52 | "https://user:secret%%1Fpassword@%s.com/acme-inc/my-project",
53 | "https://user:secret%%1password@%s.com/acme-inc/my-project",
54 | "ssh://git@%s.com/acme-inc/my-project.git",
55 | "ssh://git@%s.com:22/acme-inc/my-project.git",
56 | "git://%s.com/acme-inc/my-project.git",
57 | "git@%s.com/acme-inc/my-project.git"
58 | ).collect(Collectors.toSet());
59 | return host.stream().flatMap(h -> remoteRepositoryUris.stream().map(r -> Arguments.arguments(h, r)));
60 | }
61 | }
62 |
63 | private static class EnterpriseWebRepoUriArgumentsProvider implements ArgumentsProvider {
64 |
65 | @Override
66 | public Stream extends Arguments> provideArguments(ExtensionContext context) {
67 | Set host = Stream.of("github", "gitlab").collect(Collectors.toSet());
68 | Set remoteRepositoryUris = Stream.of(
69 | "https://%s.acme.com/acme-inc/my-project",
70 | "git@%s.acme.com/acme-inc/my-project.git"
71 | ).collect(Collectors.toSet());
72 | return host.stream().flatMap(h -> remoteRepositoryUris.stream().map(r -> Arguments.arguments(h, r)));
73 | }
74 | }
75 |
76 | private static class UserInfoArgumentsProvider implements ArgumentsProvider {
77 |
78 | @Override
79 | public Stream extends Arguments> provideArguments(ExtensionContext context) {
80 | Map cases = new HashMap<>();
81 | cases.put("https://user:password@acme.com/acme-inc/my-project", "https://******@acme.com/acme-inc/my-project");
82 | cases.put("https://user%1Fname:password@acme.com/acme-inc/my-project", "https://******@acme.com/acme-inc/my-project");
83 | cases.put("https://user:secret%1Fpassword@acme.com/acme-inc/my-project", "https://******@acme.com/acme-inc/my-project");
84 | cases.put("https://user:secret%1password@acme.com/acme-inc/my-project", null);
85 | cases.put("git@github.com:gradle/common-custom-user-data-gradle-plugin.git", "git@github.com:gradle/common-custom-user-data-gradle-plugin.git");
86 |
87 | return cases.entrySet().stream()
88 | .map(entry -> Arguments.arguments(entry.getKey(), entry.getValue()));
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------