PathProvider supports Path entities, in preparation for future default support in JAX-RS 4.x / Jersey 4.x.
Signed-off-by: Markus KARG <markus@headcrashing.eu>
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/PathProvider.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/PathProvider.java
new file mode 100644
index 0000000..461a4f8
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/PathProvider.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2024 Markus KARG and others.
+ *
+ * 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 static jakarta.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
+import static jakarta.ws.rs.core.MediaType.WILDCARD;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+
+import jakarta.inject.Singleton;
+
+/**
+ * Provider for marshalling/un-marshalling of {@code application/octet-stream}
+ * entity type to/from a {@link Path} instance.
+ *
+ * @author Markus KARG
+ */
+@Produces({APPLICATION_OCTET_STREAM, WILDCARD})
+@Consumes({APPLICATION_OCTET_STREAM, WILDCARD})
+@Singleton
+public final class PathProvider extends AbstractMessageReaderWriterProvider<Path> {
+
+ @Override
+ public final boolean isReadable(final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType) {
+ return Path.class == type;
+ }
+
+ @Override
+ public final Path readFrom(final Class<Path> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType,
+ final MultivaluedMap<String, String> httpHeaders,
+ final InputStream entityStream) throws IOException {
+ final var path = Utils.createTempFile().toPath();
+ Files.copy(entityStream, path, StandardCopyOption.REPLACE_EXISTING);
+ return path;
+ }
+
+ @Override
+ public final boolean isWriteable(final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType) {
+ return Path.class.isAssignableFrom(type);
+ }
+
+ @Override
+ public final void writeTo(final Path t,
+ final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException {
+ Files.copy(t, entityStream);
+ }
+}
diff --git a/core-common/src/main/resources/META-INF/native-image/org.glassfish.jersey.core/jersey-common/reflect-config.json b/core-common/src/main/resources/META-INF/native-image/org.glassfish.jersey.core/jersey-common/reflect-config.json
index ef2ae4d..184402f 100644
--- a/core-common/src/main/resources/META-INF/native-image/org.glassfish.jersey.core/jersey-common/reflect-config.json
+++ b/core-common/src/main/resources/META-INF/native-image/org.glassfish.jersey.core/jersey-common/reflect-config.json
@@ -58,6 +58,12 @@
"allDeclaredConstructors":true
},
{
+ "name":"org.glassfish.jersey.message.internal.PathProvider",
+ "allDeclaredFields":true,
+ "allDeclaredMethods":true,
+ "allDeclaredConstructors":true
+ },
+ {
"name":"org.glassfish.jersey.message.internal.FormMultivaluedMapProvider",
"allDeclaredFields":true,
"allDeclaredMethods":true,
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EntityTypesTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EntityTypesTest.java
index 77a74a6..2a8f199 100644
--- a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EntityTypesTest.java
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EntityTypesTest.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
@@ -72,6 +72,7 @@
import org.glassfish.jersey.internal.util.collection.MultivaluedStringMap;
import org.glassfish.jersey.jettison.JettisonFeature;
import org.glassfish.jersey.message.internal.FileProvider;
+import org.glassfish.jersey.message.internal.PathProvider;
import org.glassfish.jersey.server.ResourceConfig;
import org.codehaus.jettison.json.JSONArray;
@@ -325,13 +326,13 @@
@Override
protected Application configure() {
- return ((ResourceConfig) super.configure()).register(new JettisonFeature());
+ return ((ResourceConfig) super.configure()).register(new JettisonFeature()).register(new PathProvider());
}
@Override
protected void configureClient(final ClientConfig config) {
super.configureClient(config);
- config.register(new JettisonFeature());
+ config.register(new JettisonFeature()).register(new PathProvider());
}
@Test
@@ -431,6 +432,20 @@
_test(in, FileResource.class);
}
+ @Path("PathResource")
+ public static class PathResource extends AResource<java.nio.file.Path> {
+ }
+
+ @Test
+ @Execution(ExecutionMode.CONCURRENT)
+ public void testPathRepresentation() throws IOException {
+ final var pp = new PathProvider();
+ final var in = pp.readFrom(java.nio.file.Path.class, java.nio.file.Path.class, null, null, null,
+ new ByteArrayInputStream("CONTENT".getBytes()));
+
+ _test(in, PathResource.class);
+ }
+
@Produces("application/x-www-form-urlencoded")
@Consumes("application/x-www-form-urlencoded")
@Path("FormResource")