implementation of UriInfo#getMatchedResourceTemplate(s) & API JAX-B drop (#5575)
* implementation of UriInfo#getMatchedResourceTemplate
* Additional modification for Jakarta REST 4.0 API
Signed-off-by: jansupol <jan.supol@oracle.com>
Co-authored-by: Maxim Nesen <maxim.nesen@oracle.com>
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/routing/UriRoutingContext.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/routing/UriRoutingContext.java
index 40faecc..f7a9875 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/routing/UriRoutingContext.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/routing/UriRoutingContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -28,6 +28,8 @@
import java.util.regex.MatchResult;
import java.util.stream.Collectors;
+import jakarta.ws.rs.ApplicationPath;
+import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.PathSegment;
@@ -36,6 +38,7 @@
import org.glassfish.jersey.internal.util.collection.ImmutableMultivaluedMap;
import org.glassfish.jersey.message.internal.TracingLogger;
import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.internal.ServerTraceEvent;
import org.glassfish.jersey.server.internal.process.Endpoint;
import org.glassfish.jersey.server.model.Resource;
@@ -245,6 +248,40 @@
return getMatchedURIs(true);
}
+//@Override
+ public String getMatchedResourceTemplate() {
+ final StringBuilder sb = new StringBuilder();
+ for (String template : getMatchedResourceTemplates()) {
+ sb.append(template.trim());
+ }
+ return sb.toString();
+ }
+
+//@Override
+ public List<String> getMatchedResourceTemplates() {
+ final List<String> list = new ArrayList<>();
+ if (ResourceConfig.class.isInstance(requestContext.getConfiguration())) {
+ Application app = ((ResourceConfig) requestContext.getConfiguration()).getApplication();
+ while (ResourceConfig.class.isInstance(app) && ((ResourceConfig) app).getApplication() != app) {
+ app = ((ResourceConfig) app).getApplication();
+ }
+ final ApplicationPath annotation = app.getClass().getAnnotation(ApplicationPath.class);
+ if (annotation != null) {
+ String value = annotation.value();
+ list.add(value.endsWith("/") ? value.substring(0, value.length() - 1) : value);
+ }
+ }
+
+ final Iterator<UriTemplate> templateIt = templates.descendingIterator();
+ while (templateIt.hasNext()) {
+ String template = templateIt.next().getTemplate().trim();
+ if (!template.equals("/") || list.isEmpty()) { // !subresourceLocator
+ list.add(template);
+ }
+ }
+ return list;
+ }
+
private static final Function<String, String> PATH_DECODER = input -> UriComponent.decode(input, UriComponent.Type.PATH);
@Override
diff --git a/core-server/src/test/java/org/glassfish/jersey/server/GetMatchedResourceTemplateTest.java b/core-server/src/test/java/org/glassfish/jersey/server/GetMatchedResourceTemplateTest.java
new file mode 100644
index 0000000..8ba37ad
--- /dev/null
+++ b/core-server/src/test/java/org/glassfish/jersey/server/GetMatchedResourceTemplateTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.server;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.HttpMethod;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.UriInfo;
+import org.glassfish.jersey.server.internal.routing.UriRoutingContext;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.concurrent.ExecutionException;
+
+public class GetMatchedResourceTemplateTest {
+
+ public static final String ONE_POST = "{name:[a-zA-Z][a-zA-Z_0-9]*}";
+ public static final String TWO_GET = "{Prefix}{p:/?}{id: ((\\d+)?)}/abc{p2:/?}{number: (([A-Za-z0-9]*)?)}";
+ public static final String TWO_POST = "{Prefix}{p:/?}{id: ((\\d+)?)}/abc/{yeah}";
+ public static final String THREE_SUB = "{x:[a-z]}";
+
+ public static class SubGet {
+ @PUT
+ public String get(@Context UriInfo uriInfo) {
+ return ((UriRoutingContext) uriInfo).getMatchedResourceTemplate();
+ }
+ }
+
+ @Path("one")
+ public static class ResourceOne {
+ @POST
+ @Path(ONE_POST)
+ public Response post(@Context UriInfo info) {
+ return Response.ok(((UriRoutingContext) info).getMatchedResourceTemplate()).build();
+ }
+ }
+
+ @Path("two")
+ public static class ResourceTwo {
+ @GET
+ @Path(TWO_GET)
+ public Response get(@Context UriInfo info) {
+ return Response.ok(((UriRoutingContext) info).getMatchedResourceTemplate()).build();
+ }
+
+ @POST
+ @Path(TWO_POST)
+ public Response post(@Context UriInfo info) {
+ return Response.ok(((UriRoutingContext) info).getMatchedResourceTemplate()).build();
+ }
+ }
+
+ @Path("three")
+ public static class ResourceThree {
+ @Path(THREE_SUB)
+ public SubGet doAnything4() {
+ return new SubGet();
+ }
+ }
+
+ @Path("four")
+ public static class ResourceFour {
+ @Path(THREE_SUB)
+ public ResourceOne postOne() {
+ return new ResourceOne();
+ }
+ }
+
+ @Test
+ public void testPOSTone() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(ResourceOne.class));
+ Object entity = applicationHandler.apply(RequestContextBuilder.from("/one/azazaz00", HttpMethod.POST)
+ .build()).get().getEntity();
+ Assertions.assertEquals("/one/" + ONE_POST, entity);
+ }
+
+ @Test
+ public void testTWOget() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(ResourceTwo.class));
+ Object entity = applicationHandler.apply(RequestContextBuilder.from("/two/P/abc/MyNumber", HttpMethod.GET)
+ .build()).get().getEntity();
+ Assertions.assertEquals("/two/" + TWO_GET, entity);
+ }
+
+ @Test
+ public void testTWOpost() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(ResourceTwo.class));
+ Object entity = applicationHandler.apply(RequestContextBuilder.from("/two/P/abc/MyNumber", HttpMethod.POST)
+ .build()).get().getEntity();
+ Assertions.assertEquals("/two/" + TWO_POST, entity);
+ }
+
+ @Test
+ public void testPUTthree() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(ResourceThree.class));
+ Object entity = applicationHandler.apply(RequestContextBuilder.from("/three/a", HttpMethod.PUT)
+ .build()).get().getEntity();
+ Assertions.assertEquals("/three/" + THREE_SUB, entity);
+ }
+
+ @Test
+ public void testPOSTfour() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(ResourceFour.class));
+ Object entity = applicationHandler.apply(RequestContextBuilder.from("/four/a/azazaz00", HttpMethod.POST)
+ .build()).get().getEntity();
+ Assertions.assertEquals("/four/" + THREE_SUB + "/" + ONE_POST, entity);
+ }
+}
diff --git a/examples/declarative-linking/src/main/java/org/glassfish/jersey/examples/linking/representation/ItemRepresentation.java b/examples/declarative-linking/src/main/java/org/glassfish/jersey/examples/linking/representation/ItemRepresentation.java
index bfaeaa1..7e8997b 100644
--- a/examples/declarative-linking/src/main/java/org/glassfish/jersey/examples/linking/representation/ItemRepresentation.java
+++ b/examples/declarative-linking/src/main/java/org/glassfish/jersey/examples/linking/representation/ItemRepresentation.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -70,7 +70,7 @@
bindings = @Binding(name = "id", value = "${instance.id}"),
rel = "self"
)
- @XmlJavaTypeAdapter(Link.JaxbAdapter.class)
+ @XmlJavaTypeAdapter(JaxbAdapter.class)
@XmlElement(name = "link")
Link self;
@@ -91,7 +91,7 @@
)})
@XmlElement(name = "link")
@XmlElementWrapper(name = "links")
- @XmlJavaTypeAdapter(Link.JaxbAdapter.class)
+ @XmlJavaTypeAdapter(JaxbAdapter.class)
List<Link> links;
public ItemRepresentation() {
diff --git a/examples/declarative-linking/src/main/java/org/glassfish/jersey/examples/linking/representation/ItemsRepresentation.java b/examples/declarative-linking/src/main/java/org/glassfish/jersey/examples/linking/representation/ItemsRepresentation.java
index 4d702a2..aecc983 100644
--- a/examples/declarative-linking/src/main/java/org/glassfish/jersey/examples/linking/representation/ItemsRepresentation.java
+++ b/examples/declarative-linking/src/main/java/org/glassfish/jersey/examples/linking/representation/ItemsRepresentation.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -82,7 +82,7 @@
},
rel = "self"
)
- @XmlJavaTypeAdapter(Link.JaxbAdapter.class)
+ @XmlJavaTypeAdapter(JaxbAdapter.class)
@XmlElement(name = "link")
Link self;
@@ -111,7 +111,7 @@
)})
@XmlElement(name = "link")
@XmlElementWrapper(name = "links")
- @XmlJavaTypeAdapter(Link.JaxbAdapter.class)
+ @XmlJavaTypeAdapter(JaxbAdapter.class)
List<Link> links;
public ItemsRepresentation() {
diff --git a/examples/declarative-linking/src/main/java/org/glassfish/jersey/examples/linking/representation/JaxbAdapter.java b/examples/declarative-linking/src/main/java/org/glassfish/jersey/examples/linking/representation/JaxbAdapter.java
new file mode 100644
index 0000000..b6385dd
--- /dev/null
+++ b/examples/declarative-linking/src/main/java/org/glassfish/jersey/examples/linking/representation/JaxbAdapter.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0, which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.glassfish.jersey.examples.linking.representation;
+
+import jakarta.ws.rs.core.Link;
+import jakarta.xml.bind.annotation.adapters.XmlAdapter;
+
+import javax.xml.namespace.QName;
+import java.util.Map;
+
+/**
+ * An implementation of JAXB {@link XmlAdapter} that maps the JAX-RS
+ * {@link Link} type to a value that can be marshalled and unmarshalled by JAXB. The following example
+ * shows how to use this adapter on a JAXB bean class:
+ *
+ * <pre>
+ * @XmlRootElement
+ * public class MyModel {
+ *
+ * private Link link;
+ *
+ * @XmlElement(name="link")
+ * @XmlJavaTypeAdapter(JaxbAdapter.class)
+ * public Link getLink() {
+ * return link;
+ * }
+ * ...
+ * }
+ * </pre>
+ *
+ * <p>
+ * Note that usage of this class requires the Jakarta XML Binding API and an implementation. The Jakarta RESTful Web
+ * Services implementation is not required to provide these dependencies.
+ * </p>
+ * <p>
+ * The class used to be a part Jakarta REST 3.1
+ * </p>
+ *
+ * @see JaxbLink
+ * @since 4.0
+ */
+public class JaxbAdapter extends XmlAdapter<JaxbLink, Link> {
+
+ /**
+ * Convert a {@link JaxbLink} into a {@link Link}.
+ *
+ * @param v instance of type {@link JaxbLink}.
+ * @return mapped instance of type {@link JaxbLink}
+ */
+ @Override
+ public Link unmarshal(final JaxbLink v) {
+ Link.Builder lb = Link.fromUri(v.getUri());
+ for (Map.Entry<QName, Object> e : v.getParams().entrySet()) {
+ lb.param(e.getKey().getLocalPart(), e.getValue().toString());
+ }
+ return lb.build();
+ }
+
+ /**
+ * Convert a {@link Link} into a {@link JaxbLink}.
+ *
+ * @param v instance of type {@link Link}.
+ * @return mapped instance of type {@link JaxbLink}.
+ */
+ @Override
+ public JaxbLink marshal(final Link v) {
+ JaxbLink jl = new JaxbLink(v.getUri());
+ for (Map.Entry<String, String> e : v.getParams().entrySet()) {
+ final String name = e.getKey();
+ jl.getParams().put(new QName("", name), e.getValue());
+ }
+ return jl;
+ }
+}
diff --git a/examples/declarative-linking/src/main/java/org/glassfish/jersey/examples/linking/representation/JaxbLink.java b/examples/declarative-linking/src/main/java/org/glassfish/jersey/examples/linking/representation/JaxbLink.java
new file mode 100644
index 0000000..7653ffc
--- /dev/null
+++ b/examples/declarative-linking/src/main/java/org/glassfish/jersey/examples/linking/representation/JaxbLink.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.examples.linking.representation;
+
+import jakarta.xml.bind.annotation.XmlAnyAttribute;
+import jakarta.xml.bind.annotation.XmlAttribute;
+
+import javax.xml.namespace.QName;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * <p>
+ * Value type for {@link jakarta.ws.rs.core.Link} that can be marshalled and
+ * unmarshalled by JAXB.
+ * </p>
+ * <p>
+ * Note that usage of this class requires the Jakarta XML Binding API and an implementation. The Jakarta RESTful Web
+ * Services implementation is not required to provide these dependencies.
+ * </p>
+ * <p>
+ * The class used to be a part Jakarta REST API 3.1.
+ * </p>
+ *
+ * @see JaxbAdapter
+ * @since 4.0
+ */
+public class JaxbLink {
+
+ private URI uri;
+ private Map<QName, Object> params;
+
+ /**
+ * Default constructor needed during unmarshalling.
+ */
+ public JaxbLink() {
+ }
+
+ /**
+ * Construct an instance from a URI and no parameters.
+ *
+ * @param uri underlying URI.
+ */
+ public JaxbLink(final URI uri) {
+ this.uri = uri;
+ }
+
+ /**
+ * Construct an instance from a URI and some parameters.
+ *
+ * @param uri underlying URI.
+ * @param params parameters of this link.
+ */
+ public JaxbLink(final URI uri, final Map<QName, Object> params) {
+ this.uri = uri;
+ this.params = params;
+ }
+
+ /**
+ * Get the underlying URI for this link.
+ *
+ * @return underlying URI.
+ */
+ @XmlAttribute(name = "href")
+ public URI getUri() {
+ return uri;
+ }
+
+ /**
+ * Get the parameter map for this link.
+ *
+ * @return parameter map.
+ */
+ @XmlAnyAttribute
+ public Map<QName, Object> getParams() {
+ if (params == null) {
+ params = new HashMap<QName, Object>();
+ }
+ return params;
+ }
+
+ /**
+ * Set the underlying URI for this link.
+ *
+ * This setter is needed for JAXB unmarshalling.
+ */
+ void setUri(final URI uri) {
+ this.uri = uri;
+ }
+
+ /**
+ * Set the parameter map for this link.
+ *
+ * This setter is needed for JAXB unmarshalling.
+ */
+ void setParams(final Map<QName, Object> params) {
+ this.params = params;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof JaxbLink)) {
+ return false;
+ }
+
+ JaxbLink jaxbLink = (JaxbLink) o;
+
+ if (uri != null ? !uri.equals(jaxbLink.uri) : jaxbLink.uri != null) {
+ return false;
+ }
+
+ if (params == jaxbLink.params) {
+ return true;
+ }
+ if (params == null) {
+ // if this.params is 'null', consider other.params equal to empty
+ return jaxbLink.params.isEmpty();
+ }
+ if (jaxbLink.params == null) {
+ // if other.params is 'null', consider this.params equal to empty
+ return params.isEmpty();
+ }
+
+ return params.equals(jaxbLink.params);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(uri, params);
+ }
+
+}
diff --git a/incubator/declarative-linking/src/test/java/org/glassfish/jersey/linking/FieldProcessorTest.java b/incubator/declarative-linking/src/test/java/org/glassfish/jersey/linking/FieldProcessorTest.java
index bbac5b1..11458ee 100644
--- a/incubator/declarative-linking/src/test/java/org/glassfish/jersey/linking/FieldProcessorTest.java
+++ b/incubator/declarative-linking/src/test/java/org/glassfish/jersey/linking/FieldProcessorTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -147,6 +147,14 @@
throw new UnsupportedOperationException("Not supported yet.");
}
+ public String getMatchedResourceTemplate() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public List<String> getMatchedResourceTemplates() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
@Override
public List<Object> getMatchedResources() {
Object dummyResource = new Object() {
diff --git a/incubator/declarative-linking/src/test/java/org/glassfish/jersey/linking/HeaderProcessorTest.java b/incubator/declarative-linking/src/test/java/org/glassfish/jersey/linking/HeaderProcessorTest.java
index 34e0ff1..535908f 100644
--- a/incubator/declarative-linking/src/test/java/org/glassfish/jersey/linking/HeaderProcessorTest.java
+++ b/incubator/declarative-linking/src/test/java/org/glassfish/jersey/linking/HeaderProcessorTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -114,6 +114,14 @@
throw new UnsupportedOperationException("Not supported yet.");
}
+ public List<String> getMatchedResourceTemplates() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public String getMatchedResourceTemplate() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
public List<Object> getMatchedResources() {
Object dummyResource = new Object() {};
return Collections.singletonList(dummyResource);
diff --git a/pom.xml b/pom.xml
index 4be2cde..9dcdb8c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2296,7 +2296,7 @@
<jaxb.ri.version>4.0.4</jaxb.ri.version>
<jaxrs.api.spec.version>3.1</jaxrs.api.spec.version>
<jaxrs.api.impl.version>3.1.0</jaxrs.api.impl.version>
- <jakarta.rest.osgi.version>jakarta.ws.rs;version="[3.1,5)",jakarta.ws.rs.client;version="[3.1,5)",jakarta.ws.rs.container;version="[3.1,5)",jakarta.ws.rs.core;version="[3.1,5)",jakarta.ws.rs.ext;version="[3.1,5)"</jakarta.rest.osgi.version>
+ <jakarta.rest.osgi.version>jakarta.ws.rs;version="[3.1,5)",jakarta.ws.rs.client;version="[3.1,5)",jakarta.ws.rs.container;version="[3.1,5)",jakarta.ws.rs.core;version="[3.1,5)",jakarta.ws.rs.ext;version="[3.1,5)",jakarta.ws.rs.sse;version="[3.1,5)"</jakarta.rest.osgi.version>
<jetty.osgi.version>org.eclipse.jetty.*;version="[11,15)"</jetty.osgi.version>
<jetty.version>12.0.7</jetty.version>
<jetty9.version>9.4.53.v20231009</jetty9.version>
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/routing/GetMatchedResourceTemplateTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/routing/GetMatchedResourceTemplateTest.java
new file mode 100644
index 0000000..6e467d7
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/routing/GetMatchedResourceTemplateTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.server.routing;
+
+import jakarta.ws.rs.ApplicationPath;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.UriInfo;
+import org.glassfish.jersey.server.internal.routing.UriRoutingContext;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.Set;
+
+public class GetMatchedResourceTemplateTest extends JerseyTest {
+
+ @Path("/resource")
+ public static class UriInfoTestResource {
+ public static final String ONE_POST = "{name:[a-zA-Z][a-zA-Z_0-9]*}";
+ public static final String TWO_GET = "{Prefix}{p:/?}{id: ((\\d+)?)}/abc{p2:/?}{number: (([A-Za-z0-9]*)?)}";
+ public static final String TWO_POST = "{Prefix}{p:/?}{id: ((\\d+)?)}/abc/{yeah}";
+ public static final String THREE_SUB = "{x:[a-z]}";
+
+ public static class SubGet {
+ @PUT
+ public String get(@Context UriInfo uriInfo) {
+ return ((UriRoutingContext) uriInfo).getMatchedResourceTemplate();
+ }
+ }
+
+ @POST
+ @Path("one/" + ONE_POST)
+ public Response post(@Context UriInfo info) {
+ return Response.ok(((UriRoutingContext) info).getMatchedResourceTemplate()).build();
+ }
+
+ @GET
+ @Path("two/" + TWO_GET)
+ public Response get(@Context UriInfo info) {
+ return Response.ok(((UriRoutingContext) info).getMatchedResourceTemplate()).build();
+ }
+
+ @POST
+ @Path("two/" + TWO_POST)
+ public Response postTwo(@Context UriInfo info) {
+ return Response.ok(((UriRoutingContext) info).getMatchedResourceTemplate()).build();
+ }
+
+ @Path("three/" + THREE_SUB)
+ public SubGet doAnything4() {
+ return new SubGet();
+ }
+
+ @Path("four/" + THREE_SUB)
+ public UriInfoTestResource postOne() {
+ return new UriInfoTestResource();
+ }
+ }
+
+ @ApplicationPath("/app")
+ private static class App extends Application {
+ @Override
+ public Set<Class<?>> getClasses() {
+ return Collections.singleton(UriInfoTestResource.class);
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new App();
+ }
+
+ @Test
+ public void testPOSTone() {
+ try (Response r = target("app/resource/one/azazaz00").request().post(null)) {
+ Assertions.assertEquals(200, r.getStatus());
+ Assertions.assertEquals("/app/resource/one/" + UriInfoTestResource.ONE_POST, r.readEntity(String.class));
+ }
+ }
+
+ @Test
+ public void testTWOget() {
+ try (Response r = target("app/resource/two/P/abc/MyNumber").request().get()) {
+ Assertions.assertEquals(200, r.getStatus());
+ Assertions.assertEquals("/app/resource/two/" + UriInfoTestResource.TWO_GET, r.readEntity(String.class));
+ }
+ }
+
+ @Test
+ public void testTWOpost() {
+ try (Response r = target("app/resource/two/P/abc/MyNumber").request().post(null)) {
+ Assertions.assertEquals(200, r.getStatus());
+ Assertions.assertEquals("/app/resource/two/" + UriInfoTestResource.TWO_POST, r.readEntity(String.class));
+ }
+ }
+
+ @Test
+ public void testPUTthree2() {
+ try (Response r = target("app/resource/three/a").request().put(Entity.entity("", MediaType.WILDCARD_TYPE))) {
+ Assertions.assertEquals(200, r.getStatus());
+ Assertions.assertEquals("/app/resource/three/" + UriInfoTestResource.THREE_SUB, r.readEntity(String.class));
+ }
+ }
+}