source: josm/trunk/test/unit/org/openstreetmap/josm/testutils/PluginServer.java

Last change on this file was 18974, checked in by taylor.smock, 2 years ago

Fix #23465: Remove custom checkstyle plugin

TopLevelJavadocCheck.java is duplicating functionality from MissingJavadocType.
Our custom class is from #14794 (closed 2017-10-16). The check that makes it
redundant was added in checkstyle 8.20 (released 2019-04-28).

This adds the missing javadocs for the more comprehensive checkstyle version.

  • Property svn:eol-style set to native
File size: 9.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.testutils;
3
4import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
5
6import java.io.File;
7import java.io.IOException;
8import java.nio.file.Path;
9import java.util.Arrays;
10import java.util.HashMap;
11import java.util.List;
12import java.util.Map;
13import java.util.Objects;
14import java.util.jar.JarFile;
15import java.util.stream.Collectors;
16import java.util.stream.StreamSupport;
17
18import com.github.tomakehurst.wiremock.client.MappingBuilder;
19import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
20import com.github.tomakehurst.wiremock.client.WireMock;
21import com.github.tomakehurst.wiremock.core.Options;
22import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
23import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
24import org.openstreetmap.josm.TestUtils;
25import org.openstreetmap.josm.tools.Logging;
26
27/**
28 * Serve "remote" test plugins for tests
29 */
30public class PluginServer {
31 /**
32 * A holder class for a "remote" plugin for tests
33 */
34 public static class RemotePlugin {
35 private final File srcJar;
36 private final Map<String, String> attrOverrides;
37 private final String pluginName;
38 private final String pluginURL;
39
40 public RemotePlugin(
41 final File srcJar
42 ) {
43 this(srcJar, null, null, null);
44 }
45
46 public RemotePlugin(
47 final File srcJar,
48 final Map<String, String> attrOverrides
49 ) {
50 this(srcJar, attrOverrides, null, null);
51 }
52
53 public RemotePlugin(
54 final File srcJar,
55 final Map<String, String> attrOverrides,
56 final String pluginName
57 ) {
58 this(srcJar, attrOverrides, pluginName, null);
59 }
60
61 public RemotePlugin(
62 final File srcJar,
63 final Map<String, String> attrOverrides,
64 final String pluginName,
65 final String pluginURL
66 ) {
67 this.srcJar = srcJar;
68 this.attrOverrides = attrOverrides;
69 this.pluginName = pluginName;
70 this.pluginURL = pluginURL;
71 }
72
73 @Override
74 public int hashCode() {
75 return Objects.hash(this.srcJar, this.attrOverrides, this.pluginName, this.pluginURL, this.getClass());
76 }
77
78 public String getRemotePluginsListManifestSection() {
79 final Map<String, String> attrs = new HashMap<>();
80 JarFile jarFile = null;
81
82 if (srcJar != null) {
83 try {
84 jarFile = new JarFile(srcJar, false);
85 jarFile.getManifest().getMainAttributes()
86 .forEach((key, value) -> attrs.put(key.toString(), value.toString()));
87 } catch (IOException e) {
88 Logging.warn(
89 "Failed to open {0} as a jar file. Using empty initial manifest. Error was: {1}",
90 srcJar,
91 e
92 );
93 } finally {
94 if (jarFile != null) {
95 try {
96 jarFile.close();
97 } catch (IOException e) {
98 Logging.warn(
99 "Somehow failed to close jar file {0}. Error was: {1}",
100 srcJar,
101 e
102 );
103 }
104 }
105 }
106 }
107
108 if (this.attrOverrides != null) {
109 attrs.putAll(this.attrOverrides);
110 }
111
112 return attrs.entrySet().stream().filter(entry -> entry.getValue() != null).map(
113 entry -> String.format("\t%s: %s\n", entry.getKey(), entry.getValue())
114 ).collect(Collectors.joining());
115 }
116
117 private String getJarPathBeneathFilesDir() {
118 if (this.srcJar != null) {
119 final Path jarPath = this.srcJar.toPath().toAbsolutePath().normalize();
120 final Path filesRootPath = new File(TestUtils.getTestDataRoot()).toPath().toAbsolutePath().resolve("__files").normalize();
121
122 if (jarPath.startsWith(filesRootPath)) {
123 // would just use .toString() but need to force use of *forward slash* path separators on all platforms
124 final Path path = filesRootPath.relativize(jarPath);
125 return StreamSupport.stream(path.spliterator(), false)
126 .map(Path::toString)
127 .collect(Collectors.joining("/"));
128 }
129 }
130 return null;
131 }
132
133 protected String getPluginURLPath() {
134 final String jarPathBeneathFilesDir = this.getJarPathBeneathFilesDir();
135
136 if (jarPathBeneathFilesDir != null) {
137 return "/" + jarPathBeneathFilesDir;
138 }
139
140 return String.format("/%h/%s.jar", this.hashCode(), pluginName != null ? pluginName : Integer.toHexString(this.hashCode()));
141 }
142
143 public String getPluginURL(WireMockRuntimeInfo wireMock) {
144 if (this.pluginURL != null) {
145 return this.pluginURL;
146 } else if (wireMock != null && this.getJarPathBeneathFilesDir() != null) {
147 return wireMock.getHttpBaseUrl() + this.getPluginURLPath();
148 }
149 return "http://example.com" + this.getPluginURLPath();
150 }
151
152 public String getName() {
153 if (this.pluginName != null) {
154 return this.pluginName;
155 } else if (this.srcJar != null) {
156 return this.srcJar.getName().split("\\.", 2)[0];
157 }
158 return Integer.toHexString(this.hashCode());
159 }
160
161 public String getRemotePluginsListSection(WireMockRuntimeInfo wireMock) {
162 return String.format(
163 "%s.jar;%s\n%s",
164 this.getName(),
165 this.getPluginURL(wireMock),
166 this.getRemotePluginsListManifestSection()
167 );
168 }
169
170 public MappingBuilder getMappingBuilder() {
171 final String jarPathBeneathFilesDir = this.getJarPathBeneathFilesDir();
172
173 if (jarPathBeneathFilesDir != null) {
174 return WireMock.get(WireMock.urlMatching(this.getPluginURLPath()));
175 }
176 return null;
177 }
178
179 public ResponseDefinitionBuilder getResponseDefinitionBuilder() {
180 final String jarPathBeneathFilesDir = this.getJarPathBeneathFilesDir();
181
182 if (jarPathBeneathFilesDir != null) {
183 return WireMock.aResponse().withStatus(200).withHeader("Content-Type", "application/java-archive").withBodyFile(
184 jarPathBeneathFilesDir
185 );
186 }
187 return null;
188 }
189 }
190
191 protected final List<RemotePlugin> pluginList;
192
193 public PluginServer(RemotePlugin... remotePlugins) {
194 this.pluginList = Arrays.asList(remotePlugins);
195 }
196
197 public void applyToWireMockServer(WireMockRuntimeInfo wireMock) {
198 final WireMock wireMockServer = wireMock.getWireMock();
199 // first add the plugins list
200 wireMockServer.register(
201 WireMock.get(WireMock.urlEqualTo("/plugins")).willReturn(
202 WireMock.aResponse().withStatus(200).withHeader("Content-Type", "text/plain").withBody(
203 this.pluginList.stream().map(
204 remotePlugin -> remotePlugin.getRemotePluginsListSection(wireMock)
205 ).collect(Collectors.joining())
206 )
207 )
208 );
209
210 // now add each file that we're able to serve
211 for (final RemotePlugin remotePlugin : this.pluginList) {
212 final MappingBuilder mappingBuilder = remotePlugin.getMappingBuilder();
213 final ResponseDefinitionBuilder responseDefinitionBuilder = remotePlugin.getResponseDefinitionBuilder();
214
215 if (mappingBuilder != null && responseDefinitionBuilder != null) {
216 wireMockServer.register(
217 remotePlugin.getMappingBuilder().willReturn(remotePlugin.getResponseDefinitionBuilder())
218 );
219 }
220 }
221 }
222
223 public PluginServerRule asWireMockRule() {
224 return this.asWireMockRule(
225 options().dynamicPort().usingFilesUnderDirectory(TestUtils.getTestDataRoot()),
226 true
227 );
228 }
229
230 public PluginServerRule asWireMockRule(Options ruleOptions, boolean failOnUnmatchedRequests) {
231 return new PluginServerRule(ruleOptions, failOnUnmatchedRequests);
232 }
233
234 /**
235 * A wiremock server rule for serving plugins
236 */
237 public class PluginServerRule extends WireMockExtension {
238 public PluginServerRule(Options ruleOptions, boolean failOnUnmatchedRequests) {
239 super(extensionOptions().options(ruleOptions).failOnUnmatchedRequests(failOnUnmatchedRequests));
240 }
241
242 public PluginServer getPluginServer() {
243 return PluginServer.this;
244 }
245
246 @Override
247 protected void onBeforeEach(WireMockRuntimeInfo wireMockRuntimeInfo) {
248 PluginServer.this.applyToWireMockServer(wireMockRuntimeInfo);
249 }
250 }
251}
Note: See TracBrowser for help on using the repository browser.