From 7b6d2f84391f24310baae7d8e55e644703642826 Mon Sep 17 00:00:00 2001 From: jansupol Date: Fri, 9 Apr 2021 15:37:38 +0200 Subject: [PATCH] Add a default Enum MB provider. Signed-off-by: jansupol --- .../message/internal/EnumMessageProvider.java | 72 +++++++ .../message/internal/MessagingBinders.java | 3 +- .../tests/e2e/entity/EnumEntityTest.java | 175 ++++++++++++++++++ 3 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 core-common/src/main/java/org/glassfish/jersey/message/internal/EnumMessageProvider.java create mode 100644 tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EnumEntityTest.java diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/EnumMessageProvider.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/EnumMessageProvider.java new file mode 100644 index 0000000000..bcf30bd450 --- /dev/null +++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/EnumMessageProvider.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021 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.message.internal; + +import javax.inject.Singleton; +import javax.ws.rs.Consumes; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +/** + * Default provider for enum types. + * @since 2.34 + */ +@Singleton +@Consumes(MediaType.TEXT_PLAIN) +@Produces(MediaType.TEXT_PLAIN) +final class EnumMessageProvider extends AbstractMessageReaderWriterProvider { + + @Override + public boolean isReadable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return type.isEnum(); + } + + @Override + public Enum readFrom( + Class type, + Type genericType, + Annotation[] annotations, + MediaType mediaType, + MultivaluedMap httpHeaders, + InputStream entityStream) throws IOException, WebApplicationException { + final String value = readFromAsString(entityStream, mediaType); + return Enum.valueOf(type, value); + } + + @Override + public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return type.isEnum(); + } + + @Override + public void writeTo( + Enum anEnum, Class type, + Type genericType, + Annotation[] annotations, + MediaType mediaType, + MultivaluedMap httpHeaders, + OutputStream entityStream) throws IOException, WebApplicationException { + writeToAsString(anEnum.name(), entityStream, mediaType); + } +} \ No newline at end of file diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/MessagingBinders.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/MessagingBinders.java index 8c5e67d0e9..3df2ae9d7c 100644 --- a/core-common/src/main/java/org/glassfish/jersey/message/internal/MessagingBinders.java +++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/MessagingBinders.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2021 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 @@ -89,6 +89,7 @@ protected void configure() { bindSingletonWorker(ReaderProvider.class); // bindSingletonWorker(RenderedImageProvider.class); - enabledProvidersBinder bindSingletonWorker(StringMessageProvider.class); + bindSingletonWorker(EnumMessageProvider.class); // Message body readers -- enabledProvidersBinder // bind(SourceProvider.StreamSourceReader.class).to(MessageBodyReader.class).in(Singleton.class); diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EnumEntityTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EnumEntityTest.java new file mode 100644 index 0000000000..6e842ff673 --- /dev/null +++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EnumEntityTest.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2021 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.entity; + +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.glassfish.jersey.test.util.runner.ConcurrentRunner; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +@RunWith(ConcurrentRunner.class) +public class EnumEntityTest extends JerseyTest { + + public enum SimpleEnum { + VALUE1, + VALUE2 + } + + public enum ValueEnum { + VALUE100(100), + VALUE200(200); + + private final int value; + + ValueEnum(int value) { + this.value = value; + } + } + + @Path("/") + public static class EnumResource { + @POST + @Path("/simple") + public String postSimple(SimpleEnum simpleEnum) { + return simpleEnum.name(); + } + + @POST + @Path("/value") + public String postValue(ValueEnum valueEnum) { + return valueEnum.name(); + } + + @POST + @Path("/echo") + public String echo(String value) { + return value; + } + + @PUT + @Path("/simple") + public SimpleEnum putSimple(String simple) { + return SimpleEnum.valueOf(simple); + } + + @PUT + @Path("value") + public ValueEnum putValue(String value) { + return ValueEnum.valueOf(value); + } + } + + @Override + protected Application configure() { + return new ResourceConfig(EnumResource.class); + } + + // Server side tests + + @Test + public void testSimpleEnumServerReader() { + for (SimpleEnum value : SimpleEnum.values()) { + try (Response r = target("simple").request(MediaType.TEXT_PLAIN_TYPE) + .post(Entity.entity(value.name(), MediaType.TEXT_PLAIN_TYPE))) { + Assert.assertEquals(value.name(), r.readEntity(String.class)); + } + } + } + + @Test + public void testValueEnumServerReader() { + for (ValueEnum value : ValueEnum.values()) { + try (Response r = target("value").request(MediaType.TEXT_PLAIN_TYPE) + .post(Entity.entity(value.name(), MediaType.TEXT_PLAIN_TYPE))) { + Assert.assertEquals(value.name(), r.readEntity(String.class)); + } + } + } + + @Test + public void testSimpleEnumServerWriter() { + for (SimpleEnum value : SimpleEnum.values()) { + try (Response r = target("simple").request(MediaType.TEXT_PLAIN_TYPE) + .put(Entity.entity(value.name(), MediaType.TEXT_PLAIN_TYPE))) { + Assert.assertEquals(value.name(), r.readEntity(String.class)); + } + } + } + + @Test + public void testValueEnumServerWriter() { + for (ValueEnum value : ValueEnum.values()) { + try (Response r = target("value").request(MediaType.TEXT_PLAIN_TYPE) + .put(Entity.entity(value.name(), MediaType.TEXT_PLAIN_TYPE))) { + Assert.assertEquals(value.name(), r.readEntity(String.class)); + } + } + } + + // Client side tests + + @Test + public void testSimpleEnumClientReader() { + for (SimpleEnum value : SimpleEnum.values()) { + try (Response r = target("simple").request(MediaType.TEXT_PLAIN_TYPE) + .post(Entity.entity(value.name(), MediaType.TEXT_PLAIN_TYPE))) { + Assert.assertEquals(value, r.readEntity(SimpleEnum.class)); + } + } + } + + @Test + public void testValueEnumClientReader() { + for (ValueEnum value : ValueEnum.values()) { + try (Response r = target("value").request(MediaType.TEXT_PLAIN_TYPE) + .post(Entity.entity(value.name(), MediaType.TEXT_PLAIN_TYPE))) { + Assert.assertEquals(value, r.readEntity(ValueEnum.class)); + } + } + } + + @Test + public void testSimpleEnumClientWriter() { + for (SimpleEnum value : SimpleEnum.values()) { + try (Response r = target("echo").request(MediaType.TEXT_PLAIN_TYPE) + .post(Entity.entity(value, MediaType.TEXT_PLAIN_TYPE))) { + Assert.assertEquals(value.name(), r.readEntity(String.class)); + } + } + } + + @Test + public void testValueEnumClientWriter() { + for (ValueEnum value : ValueEnum.values()) { + try (Response r = target("echo").request(MediaType.TEXT_PLAIN_TYPE) + .post(Entity.entity(value, MediaType.TEXT_PLAIN_TYPE))) { + Assert.assertEquals(value.name(), r.readEntity(String.class)); + } + } + } + +}