From ce0ab917cd4b21e0f128245b8efc808d8d063f15 Mon Sep 17 00:00:00 2001 From: Miguel Serra Date: Thu, 2 Jul 2020 16:31:33 +0100 Subject: [PATCH] Regexp on MP RestClient @Path Signed-off-by: Miguel Serra --- .../restclient/InterfaceUtil.java | 32 +++++++++++++++++++ .../microprofile/restclient/MethodModel.java | 2 +- .../restclient/InterfaceUtilTest.java | 16 ++++++++++ .../restclient/ApplicationResource.java | 10 ++++++ .../restclient/ApplicationResourceImpl.java | 9 ++++++ .../restclient/ConsumesAndProducesTest.java | 28 ++++++++++++++++ 6 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/InterfaceUtilTest.java diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/InterfaceUtil.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/InterfaceUtil.java index 83aa97a34cd..f3db1165f18 100644 --- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/InterfaceUtil.java +++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/InterfaceUtil.java @@ -59,6 +59,38 @@ static List parseParameters(String template) { return allMatches; } + static List getAllMatchingParams(String expr) { + List allMatches = new ArrayList<>(); + if (expr == null || expr.isEmpty() || expr.indexOf('{') == -1) { + return allMatches; + } + + // Traversing the Expression + boolean matching = false; + int parenthesisMatched = 0; + StringBuilder matchingParameter = new StringBuilder(); + for (int i = 0; i < expr.length(); i++) { + char x = expr.charAt(i); + + if (!matching && x == '{' && parenthesisMatched == 0) { + matching = true; + } else if (matching && x != ':' && x != '}') { + matchingParameter.append(x); + } else if (matching) { + allMatches.add(matchingParameter.toString()); + matchingParameter.setLength(0); + matching = false; + } + + if (x == '}') { + parenthesisMatched--; + } else if (x == '{') { + parenthesisMatched++; + } + } + return allMatches; + } + /** * Validates and returns proper compute method defined in {@link ClientHeaderParam}. * diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java index a3c52738ccc..c2c0657b55c 100644 --- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java +++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java @@ -655,7 +655,7 @@ MethodModel build() { private void validateParameters() { UriBuilder uriBuilder = UriBuilder.fromUri(interfaceModel.getPath()).path(pathValue); - List parameters = InterfaceUtil.parseParameters(uriBuilder.toTemplate()); + List parameters = InterfaceUtil.getAllMatchingParams(uriBuilder.toTemplate()); List methodPathParameters = new ArrayList<>(); List pathHandlingParams = parameterModels.stream() .filter(parameterModel -> parameterModel.handles(PathParam.class)) diff --git a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/InterfaceUtilTest.java b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/InterfaceUtilTest.java new file mode 100644 index 00000000000..1320ccc9224 --- /dev/null +++ b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/microprofile/restclient/InterfaceUtilTest.java @@ -0,0 +1,16 @@ +package org.glassfish.jersey.microprofile.restclient; + +import java.util.Arrays; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +public class InterfaceUtilTest { + + @Test + public void testGetAllParams() { + assertEquals(InterfaceUtil.getAllMatchingParams("{abc}/{xyzId: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}}"), Arrays.asList("abc", "xyzId")); + assertEquals(InterfaceUtil.getAllMatchingParams("{xyzId: [a-zA-Z]+}/{abc}"), Arrays.asList("xyzId", "abc")); + } +} diff --git a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResource.java b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResource.java index 5b8ef7c1a50..c9ae7464997 100644 --- a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResource.java +++ b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResource.java @@ -26,6 +26,7 @@ import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; +import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; @@ -66,4 +67,13 @@ default String sayHi() { @Path("methodContent") String methodContentType(@HeaderParam(HttpHeaders.CONTENT_TYPE) MediaType contentType, String entity); + @GET + @Path("{content: [a-zA-Z]+}") + @Produces(MediaType.TEXT_PLAIN) + String regex(@PathParam("content") String content); + + @GET + @Path("content1/{content1}/content0/{content0: [0-9]{4}}") + @Produces(MediaType.TEXT_PLAIN) + String regex0(@PathParam("content1") String context0, @PathParam("content0") String context1); } diff --git a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResourceImpl.java b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResourceImpl.java index f14e027d1ce..2f91c392ae2 100644 --- a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResourceImpl.java +++ b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResourceImpl.java @@ -62,4 +62,13 @@ public String methodContentType(MediaType contentType, String entity) { return null; } + @Override + public String regex(String content) { + return content; + } + + @Override + public String regex0(String context0, String context1) { + return context0 + "_" + context1; + } } diff --git a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ConsumesAndProducesTest.java b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ConsumesAndProducesTest.java index 2e518bc640f..fffffc29b1c 100644 --- a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ConsumesAndProducesTest.java +++ b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ConsumesAndProducesTest.java @@ -6,6 +6,7 @@ import javax.json.Json; import javax.json.JsonValue; +import javax.ws.rs.WebApplicationException; import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.ClientRequestFilter; import javax.ws.rs.core.HttpHeaders; @@ -75,6 +76,33 @@ public void testMethodContentType() throws URISyntaxException { app.methodContentType(MediaType.TEXT_XML_TYPE, "something"); } + @Test + public void testMethodWithRegexPathParam() throws URISyntaxException { + ApplicationResource app = RestClientBuilder.newBuilder() + .baseUri(new URI("http://localhost:9998")) + .build(ApplicationResource.class); + + assertEquals(app.regex("bar"), "bar"); + } + + @Test + public void testMethodWithRegexPathParam0() throws URISyntaxException { + ApplicationResource app = RestClientBuilder.newBuilder() + .baseUri(new URI("http://localhost:9998")) + .build(ApplicationResource.class); + + assertEquals(app.regex0("foo", "1234"), "foo_1234"); + } + + @Test(expected = WebApplicationException.class) + public void testMethodWithRegexPathParam0Failure() throws URISyntaxException { + ApplicationResource app = RestClientBuilder.newBuilder() + .baseUri(new URI("http://localhost:9998")) + .build(ApplicationResource.class); + + app.regex0("foo", "12345"); + } + private static class TestClientRequestFilter implements ClientRequestFilter { private final String expectedAccept;