diff --git a/appserver/tests/application/pom.xml b/appserver/tests/application/pom.xml index e8254f07296..3c6eab72eeb 100755 --- a/appserver/tests/application/pom.xml +++ b/appserver/tests/application/pom.xml @@ -71,6 +71,11 @@ jakarta.annotation-api provided + + jakarta.enterprise + jakarta.enterprise.cdi-api + provided + jakarta.enterprise.concurrent jakarta.enterprise.concurrent-api diff --git a/appserver/tests/application/src/main/java/org/glassfish/main/test/app/rest/convert/webapp/ParamConverterApplication.java b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/rest/convert/webapp/ParamConverterApplication.java new file mode 100644 index 00000000000..17d554aa5e5 --- /dev/null +++ b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/rest/convert/webapp/ParamConverterApplication.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation. + * + * 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.main.test.app.rest.convert.webapp; + +import jakarta.ws.rs.ApplicationPath; +import jakarta.ws.rs.core.Application; + +import java.util.Set; + +@ApplicationPath("/") +public class ParamConverterApplication extends Application { + + @Override + public Set> getClasses() { + return Set.of(ParamConverterResource.class, PatternParamConverterProvider.class); + } +} diff --git a/appserver/tests/application/src/main/java/org/glassfish/main/test/app/rest/convert/webapp/ParamConverterResource.java b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/rest/convert/webapp/ParamConverterResource.java new file mode 100644 index 00000000000..17a75fed76f --- /dev/null +++ b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/rest/convert/webapp/ParamConverterResource.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation. + * + * 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.main.test.app.rest.convert.webapp; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; + +import java.util.regex.Pattern; + +@Path("pattern") +public class ParamConverterResource { + + @GET + @Path("{pattern}") + public String find( + @PathParam("pattern") + Pattern pattern) { + + return "1234"; + } +} diff --git a/appserver/tests/application/src/main/java/org/glassfish/main/test/app/rest/convert/webapp/PatternParamConverterProvider.java b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/rest/convert/webapp/PatternParamConverterProvider.java new file mode 100644 index 00000000000..b4084deb56d --- /dev/null +++ b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/rest/convert/webapp/PatternParamConverterProvider.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation. + * + * 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.main.test.app.rest.convert.webapp; + +import jakarta.inject.Singleton; +import jakarta.ws.rs.ext.ParamConverter; +import jakarta.ws.rs.ext.ParamConverterProvider; +import jakarta.ws.rs.ext.Provider; + +import java.lang.System.Logger; +import java.lang.System.Logger.Level; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.regex.Pattern; + +@Provider +@Singleton +public class PatternParamConverterProvider implements ParamConverterProvider { + private static final Logger LOG = System.getLogger(PatternParamConverterProvider.class.getName()); + + @Override + public ParamConverter getConverter(final Class rawType, final Type genericType, final Annotation[] annotations) { + LOG.log(Level.INFO, () -> "getConverter(rawType=" + rawType + ", genericType=" + genericType + ", annotations=" + + Arrays.toString(annotations) + ")"); + if (rawType.isAssignableFrom(Pattern.class)) { + return new PatternConverter<>(); + } + return null; + } + + private static class PatternConverter implements ParamConverter { + + private static final Logger LOG = System.getLogger(PatternConverter.class.getName()); + + @Override + public final T fromString(final String regex) { + LOG.log(Level.INFO, "fromString(regex={0})", regex); + if (regex == null) { + throw new IllegalArgumentException("Expected IAE exception"); + } + return (T) Pattern.compile(regex); + } + + + @Override + public final String toString(final T pattern) { + LOG.log(Level.INFO, "toString(pattern={0})", pattern); + return pattern == null ? null : pattern.toString(); + } + } +} diff --git a/appserver/tests/application/src/test/java/org/glassfish/main/test/app/rest/convert/RestParamConverterTest.java b/appserver/tests/application/src/test/java/org/glassfish/main/test/app/rest/convert/RestParamConverterTest.java new file mode 100644 index 00000000000..744c8cb46c0 --- /dev/null +++ b/appserver/tests/application/src/test/java/org/glassfish/main/test/app/rest/convert/RestParamConverterTest.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation. + * + * 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.main.test.app.rest.convert; + +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.Response; + +import java.io.File; +import java.io.IOException; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; + +import org.glassfish.main.itest.tools.GlassFishTestEnvironment; +import org.glassfish.main.itest.tools.asadmin.Asadmin; +import org.glassfish.main.itest.tools.asadmin.AsadminResult; +import org.glassfish.main.itest.tools.asadmin.AsadminResultMatcher; +import org.glassfish.main.test.app.rest.convert.webapp.ParamConverterResource; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.exporter.ZipExporter; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static jakarta.ws.rs.core.MediaType.TEXT_PLAIN_TYPE; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class RestParamConverterTest { + + private static final Logger LOG = System.getLogger(RestParamConverterTest.class.getName()); + + private static final String APP_NAME = RestParamConverterTest.class.getSimpleName(); + private static final Asadmin ASADMIN = GlassFishTestEnvironment.getAsadmin(); + + @BeforeAll + static void deploy() { + File war = createDeployment(); + try { + AsadminResult result = ASADMIN.exec("deploy", "--contextroot", "/", "--name", APP_NAME, + war.getAbsolutePath()); + assertThat(result, AsadminResultMatcher.asadminOK()); + } finally { + war.delete(); + } + } + + + @AfterAll + static void undeploy() { + AsadminResult result = ASADMIN.exec("undeploy", APP_NAME); + assertThat(result, AsadminResultMatcher.asadminOK()); + } + + + @Test + public void testValidPattern() throws Exception { + try (Client client = ClientBuilder.newClient()) { + WebTarget target = client.target("http://localhost:8080/"); + Response response = target.path("pattern").path("[a-z]+").request(TEXT_PLAIN_TYPE).buildGet().invoke(); + assertEquals(200, response.getStatus()); + assertEquals("1234", response.readEntity(String.class)); + } + } + + + @Test + public void testEmptyPattern() throws Exception { + try (Client client = ClientBuilder.newClient()) { + WebTarget target = client.target("http://localhost:8080/"); + assertEquals(404, + target.path("pattern").path("").request().buildGet().invoke().getStatus()); + } + } + + + @Test + public void testInvalidPattern() throws Exception { + try (Client client = ClientBuilder.newClient()) { + WebTarget target = client.target("http://localhost:8080/"); + assertEquals(404, + target.path("pattern").path("[a-z").request().buildGet().invoke().getStatus()); + } + } + + + private static File createDeployment() { + WebArchive war = ShrinkWrap.create(WebArchive.class, "RestParamConverter.war") + .addPackage(ParamConverterResource.class.getPackage()); + LOG.log(Level.INFO, war.toString(true)); + try { + File tempFile = File.createTempFile(APP_NAME, ".war"); + war.as(ZipExporter.class).exportTo(tempFile, true); + return tempFile; + } catch (IOException e) { + throw new IllegalStateException("Deployment failed - cannot load the input archive!", e); + } + } +}