diff --git a/examples/pom.xml b/examples/pom.xml index 6987a3651..6749d2f96 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -22,7 +22,7 @@ jakarta.ws.rs all - 3.1.0 + 4.0.0-SNAPSHOT https://github.com/jax-rs/api @@ -231,9 +231,9 @@ maven-jxr-plugin - + org.glassfish.copyright glassfish-copyright-maven-plugin diff --git a/examples/src/main/java/jaxrs/examples/async/AsyncEventResource.java b/examples/src/main/java/jaxrs/examples/async/AsyncEventResource.java index 399722fd5..9343b038e 100644 --- a/examples/src/main/java/jaxrs/examples/async/AsyncEventResource.java +++ b/examples/src/main/java/jaxrs/examples/async/AsyncEventResource.java @@ -23,7 +23,6 @@ import jakarta.ws.rs.Produces; import jakarta.ws.rs.container.AsyncResponse; import jakarta.ws.rs.container.CompletionCallback; -import jakarta.ws.rs.container.Suspended; import jakarta.ws.rs.core.MediaType; /** @@ -38,7 +37,7 @@ public class AsyncEventResource implements CompletionCallback { private static final BlockingQueue MESSAGES = new ArrayBlockingQueue(5); @GET - public void readMessage(@Suspended final AsyncResponse ar) { + public void readMessage(AsyncResponse ar) { ar.register(AsyncEventResource.class); Executors.newSingleThreadExecutor().submit(() -> { try { @@ -51,7 +50,7 @@ public void readMessage(@Suspended final AsyncResponse ar) { } @POST - public void postMessage(final String message, @Suspended final AsyncResponse asyncResponse) { + public void postMessage(final String message, AsyncResponse asyncResponse) { Executors.newSingleThreadExecutor().submit(() -> { try { MESSAGES.put(message); diff --git a/examples/src/main/java/jaxrs/examples/async/LongRunningAsyncOperationResource.java b/examples/src/main/java/jaxrs/examples/async/LongRunningAsyncOperationResource.java index 97fc9cc80..3d6de9e1f 100644 --- a/examples/src/main/java/jaxrs/examples/async/LongRunningAsyncOperationResource.java +++ b/examples/src/main/java/jaxrs/examples/async/LongRunningAsyncOperationResource.java @@ -15,14 +15,14 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; -import static java.util.concurrent.TimeUnit.SECONDS; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.container.AsyncResponse; -import jakarta.ws.rs.container.Suspended; + +import static java.util.concurrent.TimeUnit.SECONDS; /** * Long-running asynchronous processing examples. @@ -46,8 +46,7 @@ public String basicSyncExample() { @GET @Path("async") - public void asyncExample( - @Suspended final AsyncResponse ar) { + public void asyncExample(AsyncResponse ar) { ar.setTimeout(15, SECONDS); Executors.newSingleThreadExecutor().submit(() -> { try { @@ -61,7 +60,7 @@ public void asyncExample( @GET @Path("asyncSelective") - public void selectiveSuspend(@QueryParam("query") final String query, @Suspended final AsyncResponse ar) { + public void selectiveSuspend(@QueryParam("query") final String query, AsyncResponse ar) { if (!isComplex(query)) { // process simple queries synchronously ar.resume("Simple result for " + query); @@ -85,7 +84,7 @@ private boolean isComplex(String query) { @GET @Path("asyncTimeoutOverride") public void overriddenTimeoutAsync(@QueryParam("timeOut") Long timeOut, @QueryParam("timeUnit") TimeUnit timeUnit, - @Suspended final AsyncResponse ar) { + AsyncResponse ar) { if (timeOut != null && timeUnit != null) { ar.setTimeout(timeOut, timeUnit); } else { @@ -105,7 +104,7 @@ public void overriddenTimeoutAsync(@QueryParam("timeOut") Long timeOut, @QueryPa @GET @Path("asyncHandleUsage") - public void suspendHandleUsageExample(@Suspended final AsyncResponse ar) { + public void suspendHandleUsageExample(AsyncResponse ar) { ar.setTimeout(15, SECONDS); Executors.newSingleThreadExecutor().submit(() -> { try { diff --git a/examples/src/main/java/jaxrs/examples/async/LongRunningEjbResource.java b/examples/src/main/java/jaxrs/examples/async/LongRunningEjbResource.java index 02a9f356a..274d250c9 100644 --- a/examples/src/main/java/jaxrs/examples/async/LongRunningEjbResource.java +++ b/examples/src/main/java/jaxrs/examples/async/LongRunningEjbResource.java @@ -15,7 +15,6 @@ import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.container.AsyncResponse; -import jakarta.ws.rs.container.Suspended; /** * Example of a long running EJB resource. @@ -27,7 +26,7 @@ public class LongRunningEjbResource { @GET @Asynchronous - public void longRunningOperation(@Suspended AsyncResponse ar) { + public void longRunningOperation(AsyncResponse ar) { final String result = executeLongRunningOperation(); ar.resume(result); } diff --git a/examples/src/main/java/jaxrs/examples/async/SimpleAsyncEventResource.java b/examples/src/main/java/jaxrs/examples/async/SimpleAsyncEventResource.java index befddd262..62a638c01 100644 --- a/examples/src/main/java/jaxrs/examples/async/SimpleAsyncEventResource.java +++ b/examples/src/main/java/jaxrs/examples/async/SimpleAsyncEventResource.java @@ -19,7 +19,6 @@ import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.container.AsyncResponse; -import jakarta.ws.rs.container.Suspended; import jakarta.ws.rs.core.MediaType; /** @@ -34,7 +33,7 @@ public class SimpleAsyncEventResource { private static final BlockingQueue SUSPENDED = new ArrayBlockingQueue(5); @GET - public void readMessage(@Suspended final AsyncResponse ar) throws InterruptedException { + public void readMessage(AsyncResponse ar) throws InterruptedException { SUSPENDED.put(ar); } diff --git a/examples/src/main/java/jaxrs/examples/bootstrap/BasicJavaSeBootstrapExample.java b/examples/src/main/java/jaxrs/examples/bootstrap/BasicJavaSeBootstrapExample.java index f090dcdb3..fd1abc7d2 100644 --- a/examples/src/main/java/jaxrs/examples/bootstrap/BasicJavaSeBootstrapExample.java +++ b/examples/src/main/java/jaxrs/examples/bootstrap/BasicJavaSeBootstrapExample.java @@ -19,6 +19,9 @@ import java.net.URI; import jakarta.ws.rs.SeBootstrap; +import jakarta.ws.rs.SeBootstrap.Configuration; +import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.UriBuilder; /** * Basic Java SE bootstrap example. @@ -43,12 +46,21 @@ private BasicJavaSeBootstrapExample() { * @param args unused command line arguments * @throws InterruptedException when process is killed */ - public static void main(final String[] args) throws InterruptedException { - SeBootstrap.start(HelloWorld.class).thenAccept(instance -> { - instance.stopOnShutdown(stopResult -> - System.out.printf("Stop result: %s [Native stop result: %s].%n", stopResult, - stopResult.unwrap(Object.class))); - final URI uri = instance.configuration().baseUri(); + public static final void main(final String[] args) throws InterruptedException { + final Application application = new HelloWorld(); + + final SeBootstrap.Configuration requestedConfiguration = SeBootstrap.Configuration.builder().build(); + + SeBootstrap.start(application, requestedConfiguration).thenAccept(instance -> { + Runtime.getRuntime() + .addShutdownHook(new Thread(() -> instance.stop() + .thenAccept(stopResult -> System.out.printf("Stop result: %s [Native stop result: %s].%n", + stopResult, stopResult.unwrap(Object.class))))); + + final Configuration actualConfigurarion = instance.configuration(); + final URI uri = UriBuilder.newInstance().scheme(actualConfigurarion.protocol().toLowerCase()) + .host(actualConfigurarion.host()).port(actualConfigurarion.port()) + .path(actualConfigurarion.rootPath()).build(); System.out.printf("Instance %s running at %s [Native handle: %s].%n", instance, uri, instance.unwrap(Object.class)); System.out.println("Send SIGKILL to shutdown."); diff --git a/examples/src/main/java/jaxrs/examples/bootstrap/ClientAuthenticationJavaSeBootstrapExample.java b/examples/src/main/java/jaxrs/examples/bootstrap/ClientAuthenticationJavaSeBootstrapExample.java index e169075bb..3a78496de 100644 --- a/examples/src/main/java/jaxrs/examples/bootstrap/ClientAuthenticationJavaSeBootstrapExample.java +++ b/examples/src/main/java/jaxrs/examples/bootstrap/ClientAuthenticationJavaSeBootstrapExample.java @@ -19,7 +19,10 @@ import java.net.URI; import jakarta.ws.rs.SeBootstrap; +import jakarta.ws.rs.SeBootstrap.Configuration; import jakarta.ws.rs.SeBootstrap.Configuration.SSLClientAuthentication; +import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.UriBuilder; /** * Java SE Bootstrap Example using TLS Client Authentication. @@ -31,8 +34,11 @@ * (e. g. 443, 8443, or someting completely different). The actual configuration needs to be queried after * bootstrapping, otherwise callers would be unaware of the actual chosen port. If the client's certificate is invalid * or cannot be validated, the server will reject the connection. + *

*

* This example uses some basic external JSSE configuration: + *

+ *

*

    *
  • {@code javax.net.ssl.keyStore=~/.keystore} - HTTPS: Path to a keystore holding an X.509 certificate for * {@code CN=localhost}
  • @@ -40,6 +46,7 @@ *
  • Client Authentication: The default truststore ({@code $JAVA_HOME/lib/security/cacerts}) must hold the root * certificate of the CA and all intermediate certificates used for signing the client's certificate.
  • *
+ *

* * @author Markus KARG (markus@headcrashing.eu) * @since 3.1 @@ -55,15 +62,22 @@ private ClientAuthenticationJavaSeBootstrapExample() { * @param args unused command line arguments * @throws InterruptedException when process is killed */ - public static void main(final String[] args) throws InterruptedException { + public static final void main(final String[] args) throws InterruptedException { + final Application application = new HelloWorld(); + final SeBootstrap.Configuration requestedConfiguration = SeBootstrap.Configuration.builder().protocol("HTTPS") .sslClientAuthentication(SSLClientAuthentication.MANDATORY).build(); - SeBootstrap.start(HelloWorld.class, requestedConfiguration).thenAccept(instance -> { - instance.stopOnShutdown(stopResult -> - System.out.printf("Stop result: %s [Native stop result: %s].%n", stopResult, - stopResult.unwrap(Object.class))); - final URI uri = instance.configuration().baseUri(); + SeBootstrap.start(application, requestedConfiguration).thenAccept(instance -> { + Runtime.getRuntime() + .addShutdownHook(new Thread(() -> instance.stop() + .thenAccept(stopResult -> System.out.printf("Stop result: %s [Native stop result: %s].%n", + stopResult, stopResult.unwrap(Object.class))))); + + final Configuration actualConfigurarion = instance.configuration(); + final URI uri = UriBuilder.newInstance().scheme(actualConfigurarion.protocol().toLowerCase()) + .host(actualConfigurarion.host()).port(actualConfigurarion.port()) + .path(actualConfigurarion.rootPath()).build(); System.out.printf("Instance %s running at %s [Native handle: %s].%n", instance, uri, instance.unwrap(Object.class)); System.out.println("Send SIGKILL to shutdown."); diff --git a/examples/src/main/java/jaxrs/examples/bootstrap/ExplicitJavaSeBootstrapExample.java b/examples/src/main/java/jaxrs/examples/bootstrap/ExplicitJavaSeBootstrapExample.java index 3f7df46e5..62187fbf8 100644 --- a/examples/src/main/java/jaxrs/examples/bootstrap/ExplicitJavaSeBootstrapExample.java +++ b/examples/src/main/java/jaxrs/examples/bootstrap/ExplicitJavaSeBootstrapExample.java @@ -19,8 +19,10 @@ import java.net.URI; import jakarta.ws.rs.SeBootstrap; +import jakarta.ws.rs.SeBootstrap.Configuration; import jakarta.ws.rs.SeBootstrap.Configuration.SSLClientAuthentication; import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.UriBuilder; /** * Java SE bootstrap example with explicit configuration. @@ -54,7 +56,7 @@ private ExplicitJavaSeBootstrapExample() { * {@code NONE, OPTIONAL, MANDATORY}. * @throws InterruptedException when process is killed */ - public static void main(final String[] args) throws InterruptedException { + public static final void main(final String[] args) throws InterruptedException { final Application application = new HelloWorld(); final String protocol = args[0]; @@ -67,10 +69,15 @@ public static void main(final String[] args) throws InterruptedException { .port(port).rootPath(rootPath).sslClientAuthentication(clientAuth).build(); SeBootstrap.start(application, requestedConfiguration).thenAccept(instance -> { - instance.stopOnShutdown(stopResult -> - System.out.printf("Stop result: %s [Native stop result: %s].%n", stopResult, - stopResult.unwrap(Object.class))); - final URI uri = instance.configuration().baseUri(); + Runtime.getRuntime() + .addShutdownHook(new Thread(() -> instance.stop() + .thenAccept(stopResult -> System.out.printf("Stop result: %s [Native stop result: %s].%n", + stopResult, stopResult.unwrap(Object.class))))); + + final Configuration actualConfigurarion = instance.configuration(); + final URI uri = UriBuilder.newInstance().scheme(actualConfigurarion.protocol().toLowerCase()) + .host(actualConfigurarion.host()).port(actualConfigurarion.port()) + .path(actualConfigurarion.rootPath()).build(); System.out.printf("Instance %s running at %s [Native handle: %s].%n", instance, uri, instance.unwrap(Object.class)); System.out.println("Send SIGKILL to shutdown."); diff --git a/examples/src/main/java/jaxrs/examples/bootstrap/ExternalConfigJavaSeBootstrapExample.java b/examples/src/main/java/jaxrs/examples/bootstrap/ExternalConfigJavaSeBootstrapExample.java index 4642995de..e02cf81eb 100644 --- a/examples/src/main/java/jaxrs/examples/bootstrap/ExternalConfigJavaSeBootstrapExample.java +++ b/examples/src/main/java/jaxrs/examples/bootstrap/ExternalConfigJavaSeBootstrapExample.java @@ -18,11 +18,14 @@ import java.net.URI; -import jakarta.ws.rs.SeBootstrap; -import jakarta.ws.rs.core.Application; import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.ConfigProvider; +import jakarta.ws.rs.SeBootstrap; +import jakarta.ws.rs.SeBootstrap.Configuration; +import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.UriBuilder; + /** * Java SE bootstrap example utilizing an external configuration system. *

@@ -68,7 +71,7 @@ private ExternalConfigJavaSeBootstrapExample() { * @param args unused command line arguments * @throws InterruptedException when process is killed */ - public static void main(final String[] args) throws InterruptedException { + public static final void main(final String[] args) throws InterruptedException { final Application application = new HelloWorld(); final Config config = ConfigProvider.getConfig(); @@ -77,10 +80,15 @@ public static void main(final String[] args) throws InterruptedException { .build(); SeBootstrap.start(application, requestedConfiguration).thenAccept(instance -> { - instance.stopOnShutdown(stopResult -> - System.out.printf("Stop result: %s [Native stop result: %s].%n", stopResult, - stopResult.unwrap(Object.class))); - final URI uri = instance.configuration().baseUri(); + Runtime.getRuntime() + .addShutdownHook(new Thread(() -> instance.stop() + .thenAccept(stopResult -> System.out.printf("Stop result: %s [Native stop result: %s].%n", + stopResult, stopResult.unwrap(Object.class))))); + + final Configuration actualConfigurarion = instance.configuration(); + final URI uri = UriBuilder.newInstance().scheme(actualConfigurarion.protocol().toLowerCase()) + .host(actualConfigurarion.host()).port(actualConfigurarion.port()) + .path(actualConfigurarion.rootPath()).build(); System.out.printf("Instance %s running at %s [Native handle: %s].%n", instance, uri, instance.unwrap(Object.class)); System.out.println("Send SIGKILL to shutdown."); diff --git a/examples/src/main/java/jaxrs/examples/bootstrap/HttpsJavaSeBootstrapExample.java b/examples/src/main/java/jaxrs/examples/bootstrap/HttpsJavaSeBootstrapExample.java index 045bf0b23..481edd01d 100644 --- a/examples/src/main/java/jaxrs/examples/bootstrap/HttpsJavaSeBootstrapExample.java +++ b/examples/src/main/java/jaxrs/examples/bootstrap/HttpsJavaSeBootstrapExample.java @@ -19,7 +19,9 @@ import java.net.URI; import jakarta.ws.rs.SeBootstrap; +import jakarta.ws.rs.SeBootstrap.Configuration; import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.UriBuilder; /** * Java SE bootstrap example using HTTPS. @@ -29,13 +31,17 @@ * {@code https://localhost/} on an implementation-specific default IP port (e. g. 443, 8443, or someting completely * different). The actual configuration needs to be queried after bootstrapping, otherwise callers would be unaware of * the actual chosen port. + *

*

* This example uses some basic external JSSE configuration: + *

+ *

*

    *
  • {@code javax.net.ssl.keyStore=~/.keystore} - HTTPS: Path to a keystore holding an X.509 certificate for * {@code CN=localhost}
  • *
  • {@code javax.net.ssl.keyStorePassword=...} - HTTPS: Password of that keystore
  • *
+ *

* * @author Markus KARG (markus@headcrashing.eu) * @since 3.1 @@ -51,16 +57,21 @@ private HttpsJavaSeBootstrapExample() { * @param args unused command line arguments * @throws InterruptedException when process is killed */ - public static void main(final String[] args) throws InterruptedException { + public static final void main(final String[] args) throws InterruptedException { final Application application = new HelloWorld(); final SeBootstrap.Configuration requestedConfiguration = SeBootstrap.Configuration.builder().protocol("HTTPS").build(); SeBootstrap.start(application, requestedConfiguration).thenAccept(instance -> { - instance.stopOnShutdown(stopResult -> - System.out.printf("Stop result: %s [Native stop result: %s].%n", stopResult, - stopResult.unwrap(Object.class))); - final URI uri = instance.configuration().baseUri(); + Runtime.getRuntime() + .addShutdownHook(new Thread(() -> instance.stop() + .thenAccept(stopResult -> System.out.printf("Stop result: %s [Native stop result: %s].%n", + stopResult, stopResult.unwrap(Object.class))))); + + final Configuration actualConfigurarion = instance.configuration(); + final URI uri = UriBuilder.newInstance().scheme(actualConfigurarion.protocol().toLowerCase()) + .host(actualConfigurarion.host()).port(actualConfigurarion.port()) + .path(actualConfigurarion.rootPath()).build(); System.out.printf("Instance %s running at %s [Native handle: %s].%n", instance, uri, instance.unwrap(Object.class)); System.out.println("Send SIGKILL to shutdown."); diff --git a/examples/src/main/java/jaxrs/examples/bootstrap/NativeJavaSeBootstrapExample.java b/examples/src/main/java/jaxrs/examples/bootstrap/NativeJavaSeBootstrapExample.java index e36f5f361..b64b8dc3d 100644 --- a/examples/src/main/java/jaxrs/examples/bootstrap/NativeJavaSeBootstrapExample.java +++ b/examples/src/main/java/jaxrs/examples/bootstrap/NativeJavaSeBootstrapExample.java @@ -19,7 +19,9 @@ import java.net.URI; import jakarta.ws.rs.SeBootstrap; +import jakarta.ws.rs.SeBootstrap.Configuration; import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.UriBuilder; /** * Java SE bootstrap example demonstrating the use of native properties. @@ -54,7 +56,7 @@ private NativeJavaSeBootstrapExample() { * @throws InterruptedException when process is killed * @throws ClassNotFoundException when Jersey's Grizzly backend is not on the classpath */ - public static void main(final String[] args) throws InterruptedException, ClassNotFoundException { + public static final void main(final String[] args) throws InterruptedException, ClassNotFoundException { final Application application = new HelloWorld(); final SeBootstrap.Configuration requestedConfiguration = SeBootstrap.Configuration.builder() @@ -63,10 +65,15 @@ public static void main(final String[] args) throws InterruptedException, ClassN .build(); SeBootstrap.start(application, requestedConfiguration).thenAccept(instance -> { - instance.stopOnShutdown(stopResult -> - System.out.printf("Stop result: %s [Native stop result: %s].%n", stopResult, - stopResult.unwrap(Object.class))); - final URI uri = instance.configuration().baseUri(); + Runtime.getRuntime() + .addShutdownHook(new Thread(() -> instance.stop() + .thenAccept(stopResult -> System.out.printf("Stop result: %s [Native stop result: %s].%n", + stopResult, stopResult.unwrap(Object.class))))); + + final Configuration actualConfigurarion = instance.configuration(); + final URI uri = UriBuilder.newInstance().scheme(actualConfigurarion.protocol().toLowerCase()) + .host(actualConfigurarion.host()).port(actualConfigurarion.port()) + .path(actualConfigurarion.rootPath()).build(); System.out.printf("Instance %s running at %s [Native handle: %s].%n", instance, uri, instance.unwrap(Object.class)); System.out.println("Send SIGKILL to shutdown."); diff --git a/examples/src/main/java/jaxrs/examples/bootstrap/PropertyProviderJavaSeBootstrapExample.java b/examples/src/main/java/jaxrs/examples/bootstrap/PropertyProviderJavaSeBootstrapExample.java index ee213d134..af0302fd7 100644 --- a/examples/src/main/java/jaxrs/examples/bootstrap/PropertyProviderJavaSeBootstrapExample.java +++ b/examples/src/main/java/jaxrs/examples/bootstrap/PropertyProviderJavaSeBootstrapExample.java @@ -18,11 +18,14 @@ import java.net.URI; -import jakarta.ws.rs.SeBootstrap; -import jakarta.ws.rs.core.Application; import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.ConfigProvider; +import jakarta.ws.rs.SeBootstrap; +import jakarta.ws.rs.SeBootstrap.Configuration; +import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.UriBuilder; + /** * Java SE bootstrap example utilizing a property provider. *

@@ -66,7 +69,7 @@ private PropertyProviderJavaSeBootstrapExample() { * @param args unused command line arguments * @throws InterruptedException when process is killed */ - public static void main(final String[] args) throws InterruptedException { + public static final void main(final String[] args) throws InterruptedException { final Application application = new HelloWorld(); final Config config = ConfigProvider.getConfig(); @@ -75,10 +78,15 @@ public static void main(final String[] args) throws InterruptedException { .protocol("HTTPS").build(); SeBootstrap.start(application, requestedConfiguration).thenAccept(instance -> { - instance.stopOnShutdown(stopResult -> - System.out.printf("Stop result: %s [Native stop result: %s].%n", stopResult, - stopResult.unwrap(Object.class))); - final URI uri = instance.configuration().baseUri(); + Runtime.getRuntime() + .addShutdownHook(new Thread(() -> instance.stop() + .thenAccept(stopResult -> System.out.printf("Stop result: %s [Native stop result: %s].%n", + stopResult, stopResult.unwrap(Object.class))))); + + final Configuration actualConfigurarion = instance.configuration(); + final URI uri = UriBuilder.newInstance().scheme(actualConfigurarion.protocol().toLowerCase()) + .host(actualConfigurarion.host()).port(actualConfigurarion.port()) + .path(actualConfigurarion.rootPath()).build(); System.out.printf("Instance %s running at %s [Native handle: %s].%n", instance, uri, instance.unwrap(Object.class)); System.out.println("Send SIGKILL to shutdown."); diff --git a/examples/src/main/java/jaxrs/examples/bootstrap/TlsJavaSeBootstrapExample.java b/examples/src/main/java/jaxrs/examples/bootstrap/TlsJavaSeBootstrapExample.java index 88a5f1b32..32ee38a89 100644 --- a/examples/src/main/java/jaxrs/examples/bootstrap/TlsJavaSeBootstrapExample.java +++ b/examples/src/main/java/jaxrs/examples/bootstrap/TlsJavaSeBootstrapExample.java @@ -27,7 +27,9 @@ import java.security.KeyStore; import jakarta.ws.rs.SeBootstrap; +import jakarta.ws.rs.SeBootstrap.Configuration; import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.UriBuilder; /** * Java SE bootstrap example using TLS customization. @@ -54,7 +56,7 @@ private TlsJavaSeBootstrapExample() { * @throws IOException in case file access fails * @throws InterruptedException when process is killed */ - public static void main(final String[] args) + public static final void main(final String[] args) throws GeneralSecurityException, IOException, InterruptedException { final Application application = new HelloWorld(); @@ -73,10 +75,15 @@ public static void main(final String[] args) .sslContext(sslContext).build(); SeBootstrap.start(application, requestedConfiguration).thenAccept(instance -> { - instance.stopOnShutdown(stopResult -> - System.out.printf("Stop result: %s [Native stop result: %s].%n", stopResult, - stopResult.unwrap(Object.class))); - final URI uri = instance.configuration().baseUri(); + Runtime.getRuntime() + .addShutdownHook(new Thread(() -> instance.stop() + .thenAccept(stopResult -> System.out.printf("Stop result: %s [Native stop result: %s].%n", + stopResult, stopResult.unwrap(Object.class))))); + + final Configuration actualConfigurarion = instance.configuration(); + final URI uri = UriBuilder.newInstance().scheme(actualConfigurarion.protocol().toLowerCase()) + .host(actualConfigurarion.host()).port(actualConfigurarion.port()) + .path(actualConfigurarion.rootPath()).build(); System.out.printf("Instance %s running at %s [Native handle: %s].%n", instance, uri, instance.unwrap(Object.class)); System.out.println("Send SIGKILL to shutdown."); diff --git a/examples/src/main/java/jaxrs/examples/bootstrap/package-info.java b/examples/src/main/java/jaxrs/examples/bootstrap/package-info.java index 75ad1856f..6515d1f3d 100644 --- a/examples/src/main/java/jaxrs/examples/bootstrap/package-info.java +++ b/examples/src/main/java/jaxrs/examples/bootstrap/package-info.java @@ -17,6 +17,6 @@ * * @author Markus KARG (markus@headcrashing.eu) * @since 3.1 - * @see jakarta.ws.rs.SeBootstrap + * @see jakarta.ws.rs.SeBootstrap; */ package jaxrs.examples.bootstrap; diff --git a/examples/src/main/java/jaxrs/examples/link/LinkExamples.java b/examples/src/main/java/jaxrs/examples/link/LinkExamples.java index 976e68b2a..4f725ef94 100644 --- a/examples/src/main/java/jaxrs/examples/link/LinkExamples.java +++ b/examples/src/main/java/jaxrs/examples/link/LinkExamples.java @@ -51,7 +51,7 @@ public Response example2() { * 1-step process: Build Response and add a link directly to it using either a String or a URI. * * @return response. - * @throws URISyntaxException if URI is invalid + * @throws URISyntaxException */ public Response example3() throws URISyntaxException { Response r; diff --git a/examples/src/main/java/jaxrs/examples/link/ResourceExample.java b/examples/src/main/java/jaxrs/examples/link/ResourceExample.java index a6f7127b0..015369f08 100644 --- a/examples/src/main/java/jaxrs/examples/link/ResourceExample.java +++ b/examples/src/main/java/jaxrs/examples/link/ResourceExample.java @@ -10,10 +10,10 @@ package jaxrs.examples.link; +import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.Link; import jakarta.ws.rs.core.UriInfo; @@ -25,7 +25,7 @@ @Path("/myresource") public class ResourceExample { - @Context + @Inject private UriInfo uriInfo; @GET diff --git a/examples/src/main/java/jaxrs/examples/link/clusterservice/ClusterResource.java b/examples/src/main/java/jaxrs/examples/link/clusterservice/ClusterResource.java index 8b109b356..0d733796c 100644 --- a/examples/src/main/java/jaxrs/examples/link/clusterservice/ClusterResource.java +++ b/examples/src/main/java/jaxrs/examples/link/clusterservice/ClusterResource.java @@ -12,15 +12,14 @@ import java.net.URI; +import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.Link; import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.UriInfo; - import jaxrs.examples.link.clusterservice.Cluster.Status; /** @@ -31,7 +30,7 @@ @Path("/cluster") public class ClusterResource { - @Context + @Inject private UriInfo uriInfo; private Cluster cluster = Model.getCluster(); diff --git a/examples/src/main/java/jaxrs/examples/link/clusterservice/MachineResource.java b/examples/src/main/java/jaxrs/examples/link/clusterservice/MachineResource.java index da6a9f10b..1c2e1664b 100644 --- a/examples/src/main/java/jaxrs/examples/link/clusterservice/MachineResource.java +++ b/examples/src/main/java/jaxrs/examples/link/clusterservice/MachineResource.java @@ -12,17 +12,16 @@ import java.net.URI; +import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; import jakarta.ws.rs.Produces; import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.Link; import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.UriInfo; - import jaxrs.examples.link.clusterservice.Machine.Status; /** @@ -33,7 +32,7 @@ @Path("/cluster/machine/{name}") public class MachineResource { - @Context + @Inject private UriInfo uriInfo; private Machine machine; diff --git a/examples/src/main/java/jaxrs/examples/multipart/MultipartClient.java b/examples/src/main/java/jaxrs/examples/multipart/MultipartClient.java deleted file mode 100644 index 602b5d16e..000000000 --- a/examples/src/main/java/jaxrs/examples/multipart/MultipartClient.java +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************* -* Copyright (c) 2021 Eclipse Foundation -* -* This specification document is made available under the terms -* of the Eclipse Foundation Specification License v1.0, which is -* available at https://www.eclipse.org/legal/efsl.php. -*******************************************************************/ -package jaxrs.examples.multipart; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.stream.Collectors; - -import jakarta.ws.rs.client.Client; -import jakarta.ws.rs.client.ClientBuilder; -import jakarta.ws.rs.client.Entity; -import jakarta.ws.rs.client.WebTarget; -import jakarta.ws.rs.core.EntityPart; -import jakarta.ws.rs.core.GenericType; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; - - -public class MultipartClient { - private static final Logger LOG = Logger.getLogger(MultipartClient.class.getName()); - - public boolean sendPdfs(Path dir) throws IOException { - List parts = Files.list(dir).map(this::toPart).collect(Collectors.toList()); - Client client = ClientBuilder.newClient(); - WebTarget target = client.target("http://localhost:9080/multipart?dirName=abc"); - Entity> entity = Entity.entity(parts, MediaType.MULTIPART_FORM_DATA); - Response response = target.request().post(entity); - return response.getStatus() == 200; - } - - private EntityPart toPart(Path file) { - String filename = file.getFileName().toString(); - try { - return EntityPart.withName(filename) - .content(filename, Files.newInputStream(file)) - .mediaType("application/pdf") - .build(); - } catch (IOException ioex) { - LOG.log(Level.WARNING, "Failed to process file {0}", file); - return null; - } - } - - public List retrievePdfs(String remoteDirName) throws IOException { - Client client = ClientBuilder.newClient(); - WebTarget target = client.target("http://localhost:9080/multipart").queryParam("dirName", remoteDirName); - Response response = target.request(MediaType.MULTIPART_FORM_DATA).get(); - List parts = response.readEntity(new GenericType>() { }); - return parts.stream().map(part -> { - try (InputStream is = part.getContent()) { - Path file = Files.createFile(Paths.get(part.getFileName().orElse(part.getName() + ".pdf"))); - Files.copy(is, file); - return file; - } catch (IOException ioex) { - LOG.log(Level.WARNING, "Failed to process attachment part {0}", part); - return null; - } - }).collect(Collectors.toList()); - } -} diff --git a/examples/src/main/java/jaxrs/examples/multipart/MultipartResource.java b/examples/src/main/java/jaxrs/examples/multipart/MultipartResource.java deleted file mode 100644 index 4e3862670..000000000 --- a/examples/src/main/java/jaxrs/examples/multipart/MultipartResource.java +++ /dev/null @@ -1,96 +0,0 @@ -/******************************************************************* -* Copyright (c) 2021 Eclipse Foundation -* -* This specification document is made available under the terms -* of the Eclipse Foundation Specification License v1.0, which is -* available at https://www.eclipse.org/legal/efsl.php. -*******************************************************************/ -package jaxrs.examples.multipart; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.List; - -import jakarta.ws.rs.BadRequestException; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.FormParam; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.NotFoundException; -import jakarta.ws.rs.NotSupportedException; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.QueryParam; -import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.core.EntityPart; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; - -@Path("/multipart") -public class MultipartResource { - - private static final String PDF_ROOT_DIR = System.getProperty("pdf.root.dir", "/myPDFs"); - - @GET - @Produces(MediaType.MULTIPART_FORM_DATA) - public List getAllPdfFilesInDirectory(@QueryParam("dirName") String dirName) throws IOException { - File dir = getDirectoryIfExists(dirName); - List parts = new ArrayList<>(); - for (File f : dir.listFiles()) { - parts.add(EntityPart.withFileName(f.getName()).content(new FileInputStream(f)) - .mediaType("application/pdf") - .build()); - } - return parts; - } - - @POST - @Consumes(MediaType.MULTIPART_FORM_DATA) - public Response postNewPdfFiles(@QueryParam("dirName") String dirName, List parts) throws IOException { - File dir = getDirectoryIfExists(dirName); - for (EntityPart p : parts) { - File f = new File(dir, p.getFileName().orElseThrow(BadRequestException::new)); - if (f.exists()) { - throw new WebApplicationException(409); // 409 CONFLICT - } - try (InputStream content = p.getContent()) { - Files.copy(content, f.toPath()); - } - } - return Response.ok().build(); - } - - @Path("/apply") - @POST - @Consumes(MediaType.MULTIPART_FORM_DATA) - public Response applyForJob(@FormParam("name") String name, - @FormParam("recentPhoto") InputStream photoStream, - @FormParam("resume") EntityPart resume) { - - String resumeFileName = resume.getFileName().orElseThrow(NotSupportedException::new); - - if (resumeFileName.toLowerCase().endsWith(".pdf")) { - processPdfResume(resume.getContent()); - } - // handle other file types, like Word docs, etc. - - // process new application... - return Response.ok("Application received").build(); - } - - private File getDirectoryIfExists(String dirName) { - File dir = new File(PDF_ROOT_DIR, dirName); - if (!dir.exists()) { - throw new NotFoundException("dirName, " + dirName + ", does not exist"); - } - return dir; - } - - private void processPdfResume(InputStream is) { - // ... - } -} diff --git a/examples/src/main/java/jaxrs/examples/multipart/package-info.java b/examples/src/main/java/jaxrs/examples/multipart/package-info.java deleted file mode 100644 index ca0094526..000000000 --- a/examples/src/main/java/jaxrs/examples/multipart/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Async examples. - */ -package jaxrs.examples.multipart; diff --git a/examples/src/main/java/jaxrs/examples/rc/FooResource.java b/examples/src/main/java/jaxrs/examples/rc/FooResource.java index cade219e3..d53cb004b 100644 --- a/examples/src/main/java/jaxrs/examples/rc/FooResource.java +++ b/examples/src/main/java/jaxrs/examples/rc/FooResource.java @@ -14,7 +14,6 @@ import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; import jakarta.ws.rs.container.ResourceContext; -import jakarta.ws.rs.core.Context; /** * Example of using resource context to get a resource instance for a class. @@ -34,7 +33,7 @@ public String getIt() { } @Path("bar") - public BarResource getBar(@Context ResourceContext rc) { + public BarResource getBar(ResourceContext rc) { return rc.getResource(BarResource.class); } } diff --git a/examples/src/main/java/jaxrs/examples/rc/FruitsResource.java b/examples/src/main/java/jaxrs/examples/rc/FruitsResource.java index db76f2395..8053e57ce 100644 --- a/examples/src/main/java/jaxrs/examples/rc/FruitsResource.java +++ b/examples/src/main/java/jaxrs/examples/rc/FruitsResource.java @@ -10,11 +10,11 @@ package jaxrs.examples.rc; +import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; import jakarta.ws.rs.container.ResourceContext; -import jakarta.ws.rs.core.Context; /** * Example of using resource context to get a resource instance for a class. @@ -23,7 +23,8 @@ */ @Path("fruits") public class FruitsResource { - @Context + + @Inject private ResourceContext rc; @Path("good/{fruit}") diff --git a/examples/src/main/java/jaxrs/examples/resource/GreetBean.java b/examples/src/main/java/jaxrs/examples/resource/GreetBean.java new file mode 100644 index 000000000..33f547bff --- /dev/null +++ b/examples/src/main/java/jaxrs/examples/resource/GreetBean.java @@ -0,0 +1,24 @@ + +package jaxrs.examples.resource; + +import java.util.concurrent.atomic.AtomicReference; + +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class GreetBean { + + private final AtomicReference message = new AtomicReference<>(); + + public GreetBean() { + this.message.set("Hello"); + } + + String getMessage(String lang) { + return message.get(); + } + + void setMessage(String message) { + this.message.set(message); + } +} diff --git a/examples/src/main/java/jaxrs/examples/resource/SampleResource.java b/examples/src/main/java/jaxrs/examples/resource/SampleResource.java new file mode 100644 index 000000000..1f32a40ba --- /dev/null +++ b/examples/src/main/java/jaxrs/examples/resource/SampleResource.java @@ -0,0 +1,82 @@ + +package jaxrs.examples.resource; + +import java.util.concurrent.Executors; + +import jakarta.enterprise.context.RequestScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.HeaderParam; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.container.AsyncResponse; +import jakarta.ws.rs.Entity; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.UriInfo; +import jakarta.ws.rs.sse.Sse; +import jakarta.ws.rs.sse.SseEventSink; + +@Path("/greet1") // CDI bean-defining annotation +@RequestScoped // implied by default +public class SampleResource { + + // Use @Inject instead of @Context + @Inject + private UriInfo uriInfo; + + // Use of @HeaderParam as CDI qualifier + @Inject + @HeaderParam("who") + private String who; + + private final GreetBean bean; + + private final String lang; + + // CDI Injection in constructor + @Inject + public SampleResource(GreetBean bean, @QueryParam("lang") String lang) { + this.bean = bean; + this.lang = lang; + } + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String getMessage() { + return bean.getMessage(lang) + " " + who; + } + + // Use of @Entity is required + @POST + @Consumes(MediaType.TEXT_PLAIN) + public void putMessage(@QueryParam("override") boolean override, @Entity String message) { + if (bean.getMessage(lang).isEmpty() || override) { + bean.setMessage(message); + } + } + + // No need to use @Suspended with AsyncResponse + @POST + @Path("async") + @Consumes(MediaType.TEXT_PLAIN) + public void putMessageAsync(@QueryParam("override") boolean override, @Entity String message, AsyncResponse ar) { + Executors.newSingleThreadExecutor().submit(() -> { + if (bean.getMessage(lang).isEmpty() || override) { + bean.setMessage(message); + } + ar.resume("Done"); + }); + } + + // Any JAX-RS bean such as Sse or SseEventSink can be injected without @Context + // They are regular CDI beans produced by JAX-RS implementations + @GET + @Path("sse") + @Produces(MediaType.SERVER_SENT_EVENTS) + public void getMessage(@HeaderParam("who") String who, Sse sse, SseEventSink sseEventSink) { + sseEventSink.send(sse.newEvent(bean.getMessage(lang) + " " + who)); + } +} diff --git a/examples/src/main/java/jaxrs/examples/sse/ItemStoreResource.java b/examples/src/main/java/jaxrs/examples/sse/ItemStoreResource.java index 82e53365b..3e7c61f68 100644 --- a/examples/src/main/java/jaxrs/examples/sse/ItemStoreResource.java +++ b/examples/src/main/java/jaxrs/examples/sse/ItemStoreResource.java @@ -17,6 +17,8 @@ import java.util.logging.Level; import java.util.logging.Logger; +import jakarta.inject.Inject; +import jakarta.inject.Singleton; import jakarta.ws.rs.BadRequestException; import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.FormParam; @@ -27,7 +29,6 @@ import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.ServiceUnavailableException; -import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.sse.OutboundSseEvent; @@ -35,9 +36,6 @@ import jakarta.ws.rs.sse.SseBroadcaster; import jakarta.ws.rs.sse.SseEventSink; -import jakarta.inject.Inject; -import jakarta.inject.Singleton; - /** * A resource for storing named items. * @@ -85,7 +83,7 @@ public String listItems() { } /** - * Receive & process commands sent by the test client that control the internal resource state. + * Receive & process commands sent by the test client that control the internal resource state. *

* Following is the list of recognized commands: *

    @@ -136,7 +134,7 @@ public String processCommand(String command) { @Produces(MediaType.SERVER_SENT_EVENTS) public void itemEvents( @HeaderParam(HttpHeaders.LAST_EVENT_ID_HEADER) @DefaultValue("-1") int lastEventId, - @Context SseEventSink serverSink) { + SseEventSink serverSink) { if (lastEventId >= 0) { LOGGER.info("Received last event id :" + lastEventId); diff --git a/examples/src/main/java/jaxrs/examples/sse/ServerSentEventsResource.java b/examples/src/main/java/jaxrs/examples/sse/ServerSentEventsResource.java index dc19a685a..903fd29c2 100644 --- a/examples/src/main/java/jaxrs/examples/sse/ServerSentEventsResource.java +++ b/examples/src/main/java/jaxrs/examples/sse/ServerSentEventsResource.java @@ -22,7 +22,6 @@ import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.sse.Sse; import jakarta.ws.rs.sse.SseEventSink; @@ -48,7 +47,7 @@ public ServerSentEventsResource(Sse sse) { @GET @Produces(MediaType.SERVER_SENT_EVENTS) - public void getMessageQueue(@Context SseEventSink sseEventSink) { + public void getMessageQueue(SseEventSink sseEventSink) { synchronized (outputLock) { if (this.eventSink != null) { throw new IllegalStateException("Server sink already served."); @@ -78,8 +77,7 @@ public void close() throws IOException { @POST @Path("domains/{id}") @Produces(MediaType.SERVER_SENT_EVENTS) - public void startDomain(@PathParam("id") final String id, - @Context SseEventSink sseEventSink) { + public void startDomain(@PathParam("id") final String id, SseEventSink sseEventSink) { executorService.submit(() -> { try { @@ -98,10 +96,7 @@ public void startDomain(@PathParam("id") final String id, sseEventSink.close(); } catch (final InterruptedException e) { e.printStackTrace(); - } catch (IOException ioe) { - //handle I/O error } - }); } } diff --git a/jaxrs-api/.gitignore b/jaxrs-api/.gitignore deleted file mode 100644 index 414c06f02..000000000 --- a/jaxrs-api/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.checkstyle diff --git a/jaxrs-api/pom.xml b/jaxrs-api/pom.xml index efb00c8ab..d7d6736e7 100644 --- a/jaxrs-api/pom.xml +++ b/jaxrs-api/pom.xml @@ -28,7 +28,7 @@ jakarta.ws.rs all - 3.1.0 + 4.0.0-SNAPSHOT https://github.com/eclipse-ee4j/jaxrs-api @@ -294,9 +294,6 @@ maven-surefire-plugin ${maven.surefire.plugin.version} - - --add-modules jakarta.xml.bind - maven-compiler-plugin @@ -343,6 +340,16 @@ + + jakarta.inject + jakarta.inject-api + ${inject.api.version} + + + jakarta.enterprise + jakarta.enterprise.cdi-api + ${cdi.api.version} + jakarta.xml.bind jakarta.xml.bind-api @@ -390,7 +397,7 @@ 3.10.1 ${java.version} 3.3.0 - 3.0.0-M7 + 3.1.0 jakarta.ws.rs UTF-8 @@ -398,6 +405,8 @@ 3.1 + 2.0.0 + 3.0.0 4.0.0 4.0.0 2.1.0 diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/BeanParam.java b/jaxrs-api/src/main/java/jakarta/ws/rs/BeanParam.java index 59d27969a..46cae3300 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/BeanParam.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/BeanParam.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019 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 @@ -22,13 +22,15 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import jakarta.inject.Qualifier; + /** * The annotation that may be used to inject custom JAX-RS "parameter aggregator" value object into a resource class * field, property or resource method parameter. *

    * The JAX-RS runtime will instantiate the object and inject all it's fields and properties annotated with either one of * the {@code @XxxParam} annotation ({@link PathParam @PathParam}, {@link FormParam @FormParam} ...) or the - * {@link jakarta.ws.rs.core.Context @Context} annotation. For the POJO classes same instantiation and injection rules + * {@link Entity @Context} annotation. For the POJO classes same instantiation and injection rules * apply as in case of instantiation and injection of request-scoped root resource classes. *

    * For example: @@ -68,5 +70,6 @@ @Target({ ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @Documented +@Qualifier public @interface BeanParam { } diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/CookieParam.java b/jaxrs-api/src/main/java/jakarta/ws/rs/CookieParam.java index 8ec032610..4108094a4 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/CookieParam.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/CookieParam.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -22,6 +22,9 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import jakarta.enterprise.util.Nonbinding; +import jakarta.inject.Qualifier; + /** * Binds the value of a HTTP cookie to a resource method parameter, resource class field, or resource class bean * property. A default value can be specified using the {@link DefaultValue} annotation. @@ -55,6 +58,7 @@ @Target({ ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @Documented +@Qualifier public @interface CookieParam { /** @@ -63,5 +67,5 @@ * * @return HTTP cookie name. */ - String value(); + @Nonbinding String value(); } diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Context.java b/jaxrs-api/src/main/java/jakarta/ws/rs/Entity.java similarity index 54% rename from jaxrs-api/src/main/java/jakarta/ws/rs/core/Context.java rename to jaxrs-api/src/main/java/jakarta/ws/rs/Entity.java index 10fd7b658..c8858fe8e 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Context.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/Entity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved. + * 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 @@ -14,7 +14,7 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 */ -package jakarta.ws.rs.core; +package jakarta.ws.rs; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -23,24 +23,13 @@ import java.lang.annotation.Target; /** - *

    This annotation is used to inject information into a class field, bean property or method parameter.

    + *

    Annotation that identifies the entity parameter.

    * - *

    Note that future versions of this API will stop supporting injection via - * {@code Context} as part of a tighter integration and alignment with - * Jakarta CDI.

    - * - * @author Paul Sandoz - * @author Marc Hadley - * @see Application - * @see UriInfo - * @see Request - * @see HttpHeaders - * @see SecurityContext - * @see jakarta.ws.rs.ext.Providers - * @since 1.0 + * @author Santiago Pericas-Geertsen + * @since 4.0 */ -@Target({ ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD }) +@Target({ ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) @Documented -public @interface Context { +public @interface Entity { } diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/FormParam.java b/jaxrs-api/src/main/java/jakarta/ws/rs/FormParam.java index 1df6ae13b..788f7b009 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/FormParam.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/FormParam.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -22,6 +22,9 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import jakarta.enterprise.util.Nonbinding; +import jakarta.inject.Qualifier; + /** * Binds the value(s) of a form parameter contained within a request entity body to a resource method parameter. Values * are URL decoded unless this is disabled using the {@link Encoded} annotation. A default value can be specified using @@ -66,6 +69,7 @@ @Target({ ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @Documented +@Qualifier public @interface FormParam { /** @@ -76,5 +80,5 @@ * * @return form parameter name. */ - String value(); + @Nonbinding String value(); } diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/HeaderParam.java b/jaxrs-api/src/main/java/jakarta/ws/rs/HeaderParam.java index 2bdc64060..076f2c9d9 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/HeaderParam.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/HeaderParam.java @@ -22,6 +22,9 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import jakarta.enterprise.util.Nonbinding; +import jakarta.inject.Qualifier; + /** * Binds the value(s) of a HTTP header to a resource method parameter, resource class field, or resource class bean * property. A default value can be specified using the {@link DefaultValue} annotation. @@ -58,6 +61,7 @@ @Target({ ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @Documented +@Qualifier public @interface HeaderParam { /** @@ -66,5 +70,5 @@ * * @return HTTP header name. */ - String value(); + @Nonbinding String value(); } diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/MatrixParam.java b/jaxrs-api/src/main/java/jakarta/ws/rs/MatrixParam.java index 1abd05eb9..ab7af1dcc 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/MatrixParam.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/MatrixParam.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -22,6 +22,9 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import jakarta.enterprise.util.Nonbinding; +import jakarta.inject.Qualifier; + /** * Binds the value(s) of a URI matrix parameter to a resource method parameter, resource class field, or resource class * bean property. Values are URL decoded unless this is disabled using the {@link Encoded} annotation. A default value @@ -66,6 +69,7 @@ @Target({ ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @Documented +@Qualifier public @interface MatrixParam { /** @@ -76,5 +80,5 @@ * * @return URI matrix parameter name. */ - String value(); + @Nonbinding String value(); } diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/NotAuthorizedException.java b/jaxrs-api/src/main/java/jakarta/ws/rs/NotAuthorizedException.java index ed045f1e5..f59cf6df2 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/NotAuthorizedException.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/NotAuthorizedException.java @@ -16,9 +16,6 @@ package jakarta.ws.rs; -import static jakarta.ws.rs.core.HttpHeaders.WWW_AUTHENTICATE; -import static jakarta.ws.rs.core.Response.Status.UNAUTHORIZED; - import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -26,6 +23,9 @@ import jakarta.ws.rs.core.Response; +import static jakarta.ws.rs.core.HttpHeaders.WWW_AUTHENTICATE; +import static jakarta.ws.rs.core.Response.Status.UNAUTHORIZED; + /** * A runtime exception indicating request authorization failure caused by one of the following scenarios: *
      diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/PathParam.java b/jaxrs-api/src/main/java/jakarta/ws/rs/PathParam.java index 93850e82c..5c92c2019 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/PathParam.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/PathParam.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -22,6 +22,9 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import jakarta.enterprise.util.Nonbinding; +import jakarta.inject.Qualifier; + /** * Binds the value of a URI template parameter or a path segment containing the template parameter to a resource method * parameter, resource class field, or resource class bean property. The value is URL decoded unless this is disabled @@ -67,6 +70,7 @@ @Target({ ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @Documented +@Qualifier public @interface PathParam { /** @@ -80,5 +84,5 @@ * * @return resource URI template parameter name. */ - String value(); + @Nonbinding String value(); } diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/QueryParam.java b/jaxrs-api/src/main/java/jakarta/ws/rs/QueryParam.java index 423258b29..5c68dadcd 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/QueryParam.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/QueryParam.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -22,6 +22,9 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import jakarta.enterprise.util.Nonbinding; +import jakarta.inject.Qualifier; + /** * Binds the value(s) of a HTTP query parameter to a resource method parameter, resource class field, or resource class * bean property. Values are URL decoded unless this is disabled using the {@link Encoded} annotation. A default value @@ -60,6 +63,7 @@ @Target({ ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @Documented +@Qualifier public @interface QueryParam { /** @@ -70,5 +74,5 @@ * * @return HTTP query parameter name. */ - String value(); + @Nonbinding String value(); } diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/SeBootstrap.java b/jaxrs-api/src/main/java/jakarta/ws/rs/SeBootstrap.java index 5cf909305..afbef44e5 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/SeBootstrap.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/SeBootstrap.java @@ -16,16 +16,12 @@ package jakarta.ws.rs; -import java.net.URI; +import javax.net.ssl.SSLContext; import java.util.Optional; import java.util.concurrent.CompletionStage; import java.util.function.BiFunction; -import java.util.function.Consumer; - -import javax.net.ssl.SSLContext; import jakarta.ws.rs.core.Application; -import jakarta.ws.rs.core.UriBuilder; import jakarta.ws.rs.ext.RuntimeDelegate; /** @@ -143,65 +139,6 @@ static CompletionStage start(final Application application, final Conf return RuntimeDelegate.getInstance().bootstrap(application, configuration); } - /** - * Starts the provided application using a default configuration. - * - *

      - * This method is intended to be used in Java SE environments only. The outcome of invocations in Jakarta EE container - * environments is undefined. - *

      - * - * @param application The application to start up. - * @return {@code CompletionStage} (possibly asynchronously) producing handle of the running application - * {@link SeBootstrap.Instance instance}. - * @see Configuration - * @since 3.1 - */ - static CompletionStage start(final Application application) { - Configuration configuration = Configuration.builder().build(); - return start(application, configuration); - } - - /** - * Starts the provided application using the specified configuration. Creates application instance - * from class using default constructor. Injection is not supported. - * - *

      - * This method is intended to be used in Java SE environments only. The outcome of invocations in Jakarta EE container - * environments is undefined. - *

      - * - * @param clazz The application class. - * @param configuration Provides information needed for bootstrapping the application. - * @return {@code CompletionStage} (possibly asynchronously) producing handle of the running application - * {@link SeBootstrap.Instance instance}. - * @see Configuration - * @since 3.1 - */ - static CompletionStage start(final Class clazz, final Configuration configuration) { - return RuntimeDelegate.getInstance().bootstrap(clazz, configuration); - } - - /** - * Starts the provided application using a default configuration. Creates application instance - * from class using default constructor. Injection is not supported. - * - *

      - * This method is intended to be used in Java SE environments only. The outcome of invocations in Jakarta EE container - * environments is undefined. - *

      - * - * @param clazz The application class. - * @return {@code CompletionStage} (possibly asynchronously) producing handle of the running application - * {@link SeBootstrap.Instance instance}. - * @see Configuration - * @since 3.1 - */ - static CompletionStage start(final Class clazz) { - Configuration configuration = Configuration.builder().build(); - return start(clazz, configuration); - } - /** * Provides information needed by the JAX-RS implementation for bootstrapping an application. *

      @@ -213,7 +150,7 @@ static CompletionStage start(final Class clazz) * @author Markus KARG (markus@headcrashing.eu) * @since 3.1 */ - interface Configuration { + public static interface Configuration { /** * Configuration key for the protocol an application is bound to. @@ -227,7 +164,7 @@ interface Configuration { * * @since 3.1 */ - String PROTOCOL = "jakarta.ws.rs.SeBootstrap.Protocol"; + static final String PROTOCOL = "jakarta.ws.rs.SeBootstrap.Protocol"; /** * Configuration key for the hostname or IP address an application is bound to. @@ -244,7 +181,7 @@ interface Configuration { * * @since 3.1 */ - String HOST = "jakarta.ws.rs.SeBootstrap.Host"; + static final String HOST = "jakarta.ws.rs.SeBootstrap.Host"; /** * Configuration key for the TCP port an application is bound to. @@ -261,7 +198,7 @@ interface Configuration { * * @since 3.1 */ - String PORT = "jakarta.ws.rs.SeBootstrap.Port"; + static final String PORT = "jakarta.ws.rs.SeBootstrap.Port"; /** * Configuration key for the root path an application is bound to. @@ -271,7 +208,7 @@ interface Configuration { * * @since 3.1 */ - String ROOT_PATH = "jakarta.ws.rs.SeBootstrap.RootPath"; + static final String ROOT_PATH = "jakarta.ws.rs.SeBootstrap.RootPath"; /** * Configuration key for the secure socket configuration to be used. @@ -281,7 +218,7 @@ interface Configuration { * * @since 3.1 */ - String SSL_CONTEXT = "jakarta.ws.rs.SeBootstrap.SSLContext"; + static final String SSL_CONTEXT = "jakarta.ws.rs.SeBootstrap.SSLContext"; /** * Configuration key for the secure socket client authentication policy. @@ -295,7 +232,7 @@ interface Configuration { * * @since 3.1 */ - String SSL_CLIENT_AUTHENTICATION = "jakarta.ws.rs.SeBootstrap.SSLClientAuthentication"; + static final String SSL_CLIENT_AUTHENTICATION = "jakarta.ws.rs.SeBootstrap.SSLClientAuthentication"; /** * Secure socket client authentication policy @@ -309,7 +246,7 @@ interface Configuration { * @author Markus KARG (markus@headcrashing.eu) * @since 3.1 */ - enum SSLClientAuthentication { + public enum SSLClientAuthentication { /** * Server will not request client authentication. @@ -338,14 +275,14 @@ enum SSLClientAuthentication { * * @since 3.1 */ - int FREE_PORT = 0; + static final int FREE_PORT = 0; /** * Special value for {@link #PORT} property indicating that the implementation MUST use its default port. * * @since 3.1 */ - int DEFAULT_PORT = -1; + static final int DEFAULT_PORT = -1; /** * Returns the value of the property with the given name, or {@code null} if there is no property of that name. @@ -423,7 +360,7 @@ default int port() { * Same as if calling {@link #property(String) (String) property(ROOT_PATH)}. *

      * - * @return root path to be used, e.g. {@code "/"}. + * @return root path to be used, e. g. {@code "/"}. * @throws ClassCastException if root path is not a {@link String}. * @see SeBootstrap.Configuration#ROOT_PATH * @since 3.1 @@ -462,28 +399,6 @@ default SSLClientAuthentication sslClientAuthentication() { return (SSLClientAuthentication) property(SSL_CLIENT_AUTHENTICATION); } - /** - * Returns a {@link UriBuilder} that includes the application root path. - * - * @return a {@link UriBuilder} for the application. - * @since 3.1 - */ - default UriBuilder baseUriBuilder() { - return UriBuilder.newInstance().scheme(protocol().toLowerCase()) - .host(host()).port(port()).path(rootPath()); - } - - /** - * Convenience method that returns a built the {@link URI} for the application. - * - * @return a built {@link URI} for the application. - * @see Configuration#baseUriBuilder() - * @since 3.1 - */ - default URI baseUri() { - return baseUriBuilder().build(); - } - /** * Creates a new bootstrap configuration builder instance. * @@ -492,7 +407,7 @@ default URI baseUri() { */ static Builder builder() { return RuntimeDelegate.getInstance().createConfigurationBuilder(); - } + }; /** * Builder for bootstrap {@link Configuration}. @@ -500,7 +415,7 @@ static Builder builder() { * @author Markus KARG (markus@headcrashing.eu) * @since 3.1 */ - interface Builder { + static interface Builder { /** * Builds a bootstrap configuration instance from the provided property values. @@ -660,7 +575,7 @@ default Builder from(Object externalConfig) { * @author Markus KARG (markus@headcrashing.eu) * @since 3.1 */ - interface Instance { + public interface Instance { /** * Provides access to the configuration actually used by the implementation used to create this instance. @@ -674,7 +589,7 @@ interface Instance { * @return The configuration actually used to create this instance. * @since 3.1 */ - Configuration configuration(); + public Configuration configuration(); /** * Initiate immediate shutdown of running application instance. @@ -682,7 +597,7 @@ interface Instance { * @return {@code CompletionStage} asynchronously shutting down this application instance. * @since 3.1 */ - CompletionStage stop(); + public CompletionStage stop(); /** * Result of stopping the application instance. @@ -690,7 +605,7 @@ interface Instance { * @author Markus KARG (markus@headcrashing.eu) * @since 3.1 */ - interface StopResult { + public interface StopResult { /** * Provides access to the wrapped native shutdown result. @@ -706,7 +621,7 @@ interface StopResult { * @throws ClassCastException if the result is not {@code null} or is not assignable to the type {@code T}. * @since 3.1 */ - T unwrap(Class nativeClass); + public T unwrap(Class nativeClass); } /** @@ -722,18 +637,7 @@ interface StopResult { * @throws ClassCastException if the handle is not {@code null} and is not assignable to the type {@code T}. * @since 3.1 */ - T unwrap(Class nativeClass); - - /** - * Registers a consumer for a {@link StopResult} which will be executed in a new thread - * during the JVM shutdown phase. - * - * @param consumer The consumer. - * @since 3.1 - */ - default void stopOnShutdown(Consumer consumer) { - Runtime.getRuntime().addShutdownHook(new Thread(() -> stop().thenAccept(consumer))); - } + public T unwrap(Class nativeClass); } } diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/client/Client.java b/jaxrs-api/src/main/java/jakarta/ws/rs/client/Client.java index a03fe84da..cf7481773 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/client/Client.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/client/Client.java @@ -16,10 +16,9 @@ package jakarta.ws.rs.client; -import java.net.URI; - import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; +import java.net.URI; import jakarta.ws.rs.core.Configurable; import jakarta.ws.rs.core.Link; diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/client/ClientBuilder.java b/jaxrs-api/src/main/java/jakarta/ws/rs/client/ClientBuilder.java index efe304d4d..b07c2ba6f 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/client/ClientBuilder.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/client/ClientBuilder.java @@ -19,9 +19,7 @@ import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import java.net.URL; -import java.security.AccessController; import java.security.KeyStore; -import java.security.PrivilegedAction; import java.util.concurrent.ExecutorService; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -61,14 +59,16 @@ public static ClientBuilder newBuilder() { try { Object delegate = FactoryFinder.find(JAXRS_DEFAULT_CLIENT_BUILDER_PROPERTY, ClientBuilder.class); if (!(delegate instanceof ClientBuilder)) { - final CreateErrorMessageAction action = new CreateErrorMessageAction(delegate); - final String errorMessage; - if (System.getSecurityManager() == null) { - errorMessage = action.run(); - } else { - errorMessage = AccessController.doPrivileged(action); + Class pClass = ClientBuilder.class; + String classnameAsResource = pClass.getName().replace('.', '/') + ".class"; + ClassLoader loader = pClass.getClassLoader(); + if (loader == null) { + loader = ClassLoader.getSystemClassLoader(); } - throw new LinkageError(errorMessage); + URL targetTypeURL = loader.getResource(classnameAsResource); + throw new LinkageError("ClassCastException: attempting to cast" + + delegate.getClass().getClassLoader().getResource(classnameAsResource) + + " to " + targetTypeURL); } return (ClientBuilder) delegate; } catch (Exception ex) { @@ -271,26 +271,4 @@ public ClientBuilder keyStore(final KeyStore keyStore, final String password) { * @return a new client instance. */ public abstract Client build(); - - private static final class CreateErrorMessageAction implements PrivilegedAction { - private final Object delegate; - - private CreateErrorMessageAction(final Object delegate) { - this.delegate = delegate; - } - - @Override - public String run() { - Class pClass = ClientBuilder.class; - String classnameAsResource = pClass.getName().replace('.', '/') + ".class"; - ClassLoader loader = pClass.getClassLoader(); - if (loader == null) { - loader = ClassLoader.getSystemClassLoader(); - } - URL targetTypeURL = loader.getResource(classnameAsResource); - return "ClassCastException: attempting to cast" - + delegate.getClass().getClassLoader().getResource(classnameAsResource) - + " to " + targetTypeURL; - } - } } diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/client/ClientRequestContext.java b/jaxrs-api/src/main/java/jakarta/ws/rs/client/ClientRequestContext.java index 6bf01a0ba..f25280156 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/client/ClientRequestContext.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/client/ClientRequestContext.java @@ -25,7 +25,6 @@ import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.function.Predicate; import jakarta.ws.rs.core.Configuration; import jakarta.ws.rs.core.Cookie; @@ -180,7 +179,7 @@ public default boolean hasProperty(String name) { /** * Get a message header as a single string value. * - * Each single non-string header value is converted to String using a {@link jakarta.ws.rs.ext.RuntimeDelegate.HeaderDelegate} if one + * Each single header value is converted to String using a {@link jakarta.ws.rs.ext.RuntimeDelegate.HeaderDelegate} if one * is available via {@link jakarta.ws.rs.ext.RuntimeDelegate#createHeaderDelegate(java.lang.Class)} for the header value * class or using its {@code toString} method if a header delegate is not available. * @@ -193,55 +192,6 @@ public default boolean hasProperty(String name) { */ public String getHeaderString(String name); - /** - * Checks whether a header with a specific name and value (or item of the token-separated value list) exists. - * - * Each single non-string header value is converted to String using a {@link jakarta.ws.rs.ext.RuntimeDelegate.HeaderDelegate} if one - * is available via {@link jakarta.ws.rs.ext.RuntimeDelegate#createHeaderDelegate(java.lang.Class)} for the header value - * class or using its {@code toString} method if a header delegate is not available. - * - *

      - * For example: {@code containsHeaderString("cache-control", ",", "no-store"::equalsIgnoreCase)} will return {@code true} if - * a {@code Cache-Control} header exists that has the value {@code no-store}, the value {@code No-Store} or the value - * {@code Max-Age, NO-STORE, no-transform}, but {@code false} when it has the value {@code no-store;no-transform} - * (missing comma), or the value {@code no - store} (whitespace within value). - * - * @param name the message header. - * @param valueSeparatorRegex Separates the header value into single values. {@code null} does not split. - * @param valuePredicate value must fulfil this predicate. - * @return {@code true} if and only if a header with the given name exists, having either a whitespace-trimmed value - * matching the predicate, or having at least one whitespace-trimmed single value in a token-separated list of single values. - * @see #getHeaders() - * @see #getHeaderString(String) - * @since 4.0 - */ - public boolean containsHeaderString(String name, String valueSeparatorRegex, Predicate valuePredicate); - - /** - * Checks whether a header with a specific name and value (or item of the comma-separated value list) exists. - * - * Each single non-string header value is converted to String using a {@link jakarta.ws.rs.ext.RuntimeDelegate.HeaderDelegate} if one - * is available via {@link jakarta.ws.rs.ext.RuntimeDelegate#createHeaderDelegate(java.lang.Class)} for the header value - * class or using its {@code toString} method if a header delegate is not available. - * - *

      - * For example: {@code containsHeaderString("cache-control", "no-store"::equalsIgnoreCase)} will return {@code true} if - * a {@code Cache-Control} header exists that has the value {@code no-store}, the value {@code No-Store} or the value - * {@code Max-Age, NO-STORE, no-transform}, but {@code false} when it has the value {@code no-store;no-transform} - * (missing comma), or the value {@code no - store} (whitespace within value). - * - * @param name the message header. - * @param valuePredicate value must fulfil this predicate. - * @return {@code true} if and only if a header with the given name exists, having either a whitespace-trimmed value - * matching the predicate, or having at least one whitespace-trimmed single value in a comma-separated list of single values. - * @see #getHeaders() - * @see #getHeaderString(String) - * @since 4.0 - */ - public default boolean containsHeaderString(String name, Predicate valuePredicate) { - return containsHeaderString(name, ",", valuePredicate); - } - /** * Get message date. * diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/client/ClientResponseContext.java b/jaxrs-api/src/main/java/jakarta/ws/rs/client/ClientResponseContext.java index 756e4289d..87feabdd1 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/client/ClientResponseContext.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/client/ClientResponseContext.java @@ -22,7 +22,6 @@ import java.util.Locale; import java.util.Map; import java.util.Set; -import java.util.function.Predicate; import jakarta.ws.rs.core.EntityTag; import jakarta.ws.rs.core.Link; @@ -89,47 +88,6 @@ public interface ClientResponseContext { */ public String getHeaderString(String name); - /** - * Checks whether a header with a specific name and value (or item of the token-separated value list) exists. - * - *

      - * For example: {@code containsHeaderString("cache-control", ",", "no-store"::equalsIgnoreCase)} will return {@code true} if - * a {@code Cache-Control} header exists that has the value {@code no-store}, the value {@code No-Store} or the value - * {@code Max-Age, NO-STORE, no-transform}, but {@code false} when it has the value {@code no-store;no-transform} - * (missing comma), or the value {@code no - store} (whitespace within value). - * - * @param name the message header. - * @param valueSeparatorRegex Separates the header value into single values. {@code null} does not split. - * @param valuePredicate value must fulfil this predicate. - * @return {@code true} if and only if a header with the given name exists, having either a whitespace-trimmed value - * matching the predicate, or having at least one whitespace-trimmed single value in a token-separated list of single values. - * @see #getHeaders() - * @see #getHeaderString(String) - * @since 4.0 - */ - public boolean containsHeaderString(String name, String valueSeparatorRegex, Predicate valuePredicate); - - /** - * Checks whether a header with a specific name and value (or item of the comma-separated value list) exists. - * - *

      - * For example: {@code containsHeaderString("cache-control", "no-store"::equalsIgnoreCase)} will return {@code true} if - * a {@code Cache-Control} header exists that has the value {@code no-store}, the value {@code No-Store} or the value - * {@code Max-Age, NO-STORE, no-transform}, but {@code false} when it has the value {@code no-store;no-transform} - * (missing comma), or the value {@code no - store} (whitespace within value). - * - * @param name the message header. - * @param valuePredicate value must fulfil this predicate. - * @return {@code true} if and only if a header with the given name exists, having either a whitespace-trimmed value - * matching the predicate, or having at least one whitespace-trimmed single value in a comma-separated list of single values. - * @see #getHeaders() - * @see #getHeaderString(String) - * @since 4.0 - */ - public default boolean containsHeaderString(String name, Predicate valuePredicate) { - return containsHeaderString(name, ",", valuePredicate); - } - /** * Get the allowed HTTP methods from the Allow HTTP header. * diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/client/Entity.java b/jaxrs-api/src/main/java/jakarta/ws/rs/client/Entity.java index 4ec8984b6..df0d85fc8 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/client/Entity.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/client/Entity.java @@ -19,7 +19,6 @@ import java.lang.annotation.Annotation; import java.util.Arrays; import java.util.Locale; -import java.util.Objects; import jakarta.ws.rs.core.Form; import jakarta.ws.rs.core.MediaType; @@ -261,13 +260,13 @@ public boolean equals(final Object o) { Entity entity1 = (Entity) o; - if (!Objects.equals(annotations, entity1.annotations)) { + if (!Arrays.equals(annotations, entity1.annotations)) { return false; } - if (!Objects.equals(entity, entity1.entity)) { + if (entity != null ? !entity.equals(entity1.entity) : entity1.entity != null) { return false; } - if (!Objects.equals(variant, entity1.variant)) { + if (variant != null ? !variant.equals(entity1.variant) : entity1.variant != null) { return false; } @@ -276,7 +275,10 @@ public boolean equals(final Object o) { @Override public int hashCode() { - return Objects.hash(annotations, entity, variant); + int result = entity != null ? entity.hashCode() : 0; + result = 31 * result + (variant != null ? variant.hashCode() : 0); + result = 31 * result + Arrays.hashCode(annotations); + return result; } @Override diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/client/FactoryFinder.java b/jaxrs-api/src/main/java/jakarta/ws/rs/client/FactoryFinder.java index 74deb0599..9801cd87b 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/client/FactoryFinder.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/client/FactoryFinder.java @@ -21,7 +21,9 @@ import java.io.IOException; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.Iterator; import java.util.Properties; +import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import java.util.logging.Level; import java.util.logging.Logger; @@ -43,11 +45,6 @@ private FactoryFinder() { } static ClassLoader getContextClassLoader() { - // For performance reasons, check if a security manager is installed. If not there is no need to use a - // privileged action. - if (System.getSecurityManager() == null) { - return Thread.currentThread().getContextClassLoader(); - } return AccessController.doPrivileged((PrivilegedAction) () -> { ClassLoader cl = null; try { @@ -110,16 +107,24 @@ private static Object newInstance(final String className, final ClassLoader clas static Object find(final String factoryId, final Class service) throws ClassNotFoundException { ClassLoader classLoader = getContextClassLoader(); - // First try the TCCL - Object result = findFirstService(factoryId, classLoader, service); - if (result != null) { - return result; + try { + Iterator iterator = ServiceLoader.load(service, FactoryFinder.getContextClassLoader()).iterator(); + + if (iterator.hasNext()) { + return iterator.next(); + } + } catch (Exception | ServiceConfigurationError ex) { + LOGGER.log(Level.FINER, "Failed to load service " + factoryId + ".", ex); } - // Next try the class loader from the FactoryFinder - result = findFirstService(factoryId, getClassLoader(), service); - if (result != null) { - return result; + try { + Iterator iterator = ServiceLoader.load(service, FactoryFinder.class.getClassLoader()).iterator(); + + if (iterator.hasNext()) { + return iterator.next(); + } + } catch (Exception | ServiceConfigurationError ex) { + LOGGER.log(Level.FINER, "Failed to load service " + factoryId + ".", ex); } // try to read from $java.home/lib/jaxrs.properties @@ -163,29 +168,4 @@ static Object find(final String factoryId, final Class service) throws Cl throw new ClassNotFoundException( "Provider for " + factoryId + " cannot be found", null); } - - private static ClassLoader getClassLoader() { - if (System.getSecurityManager() == null) { - return FactoryFinder.class.getClassLoader(); - } - return AccessController.doPrivileged((PrivilegedAction) FactoryFinder.class::getClassLoader); - } - - private static T findFirstService(final String factoryId, final ClassLoader cl, final Class service) { - final PrivilegedAction action = () -> { - try { - final ServiceLoader loader = ServiceLoader.load(service, cl); - if (loader.iterator().hasNext()) { - return loader.iterator().next(); - } - } catch (Exception e) { - LOGGER.log(Level.FINER, "Failed to load service " + factoryId + ".", e); - } - return null; - }; - if (System.getSecurityManager() == null) { - return action.run(); - } - return AccessController.doPrivileged(action); - } } diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/client/ResponseProcessingException.java b/jaxrs-api/src/main/java/jakarta/ws/rs/client/ResponseProcessingException.java index e9b25d51b..8c24cf4a5 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/client/ResponseProcessingException.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/client/ResponseProcessingException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019 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 @@ -31,9 +31,6 @@ public class ResponseProcessingException extends ProcessingException { private static final long serialVersionUID = -4923161617935731839L; - /** - * The response instance for which the processing failed. - */ private final Response response; /** diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/container/AsyncResponse.java b/jaxrs-api/src/main/java/jakarta/ws/rs/container/AsyncResponse.java index 174ea10cb..75a174312 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/container/AsyncResponse.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/container/AsyncResponse.java @@ -25,7 +25,7 @@ * An injectable JAX-RS asynchronous response that provides means for asynchronous server side response processing. *

      * A new instance of {@code AsyncResponse} may be injected into a {@link jakarta.ws.rs.HttpMethod resource or sub-resource - * method} parameter using the {@link Suspended @Suspended} annotation. + * method} parameter. *

      * Each asynchronous response instance is bound to the running request and can be used to asynchronously provide the * request processing result or otherwise manipulate the suspended client connection. The available operations include: @@ -44,7 +44,7 @@ * private static final BlockingQueue<AsyncResponse> suspended = new ArrayBlockingQueue<AsyncResponse>(5); * * @GET - * public void readMessage(@Suspended AsyncResponse ar) throws InterruptedException { + * public void readMessage(AsyncResponse ar) throws InterruptedException { * suspended.put(ar); * } * diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/container/CompletionCallback.java b/jaxrs-api/src/main/java/jakarta/ws/rs/container/CompletionCallback.java index 43211a7d1..e66207d3d 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/container/CompletionCallback.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/container/CompletionCallback.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019 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 @@ -19,9 +19,9 @@ /** * A request processing callback that receives request processing completion events. *

      - * A completion callback is always invoked when the whole request processing is over, i.e. once a response for the request has - * been processed and sent back to the client (including processing by a custom exception mapper) or when an unmapped - * exception or error is being propagated to the default exception mapper. + * A completion callback is invoked when the whole request processing is over, i.e. once a response for the request has + * been processed and sent back to the client or in when an unmapped exception or error is being propagated to the + * container. *

      * * @author Marek Potociar @@ -29,15 +29,20 @@ */ public interface CompletionCallback { /** - * An unmapped throwable is propagated to the default exception mapper in case no {@link jakarta.ws.rs.ext.ExceptionMapper - * exception mapper} has been found for a request processing failure. In this case a non-{@code null} unmapped throwable - * instance is passed to the method. Note that the throwable instance represents the actual unmapped exception thrown during - * the request processing before it has been mapped to the response by the default exception mapper. + * A completion callback notification method that will be invoked when the request processing is finished, after a + * response is processed and is sent back to the client or when an unmapped throwable has been propagated to the hosting + * I/O container. + *

      + * An unmapped throwable is propagated to the hosting I/O container in case no {@link jakarta.ws.rs.ext.ExceptionMapper + * exception mapper} has been found for a throwable indicating a request processing failure. In this case a + * non-{@code null} unmapped throwable instance is passed to the method. Note that the throwable instance represents the + * actual unmapped exception thrown during the request processing, before it has been wrapped into an I/O + * container-specific exception that was used to propagate the throwable to the hosting I/O container. + *

      * * @param throwable is {@code null}, if the request processing has completed with a response that has been sent to the - * client (including processing by a custom exception mapper). In case the request processing resulted in an unmapped - * exception or error that has yet to be propagated to the default exception mapper, this parameter contains the unmapped - * exception instance. + * client. In case the request processing resulted in an unmapped exception or error that has been propagated to the + * hosting I/O container, this parameter contains the unmapped exception instance. */ public void onComplete(Throwable throwable); } diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/container/ContainerRequestContext.java b/jaxrs-api/src/main/java/jakarta/ws/rs/container/ContainerRequestContext.java index 9d05bbefd..b7e593e27 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/container/ContainerRequestContext.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/container/ContainerRequestContext.java @@ -23,7 +23,6 @@ import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.function.Predicate; import jakarta.ws.rs.core.Cookie; import jakarta.ws.rs.core.MediaType; @@ -229,47 +228,6 @@ public default boolean hasProperty(String name) { */ public String getHeaderString(String name); - /** - * Checks whether a header with a specific name and value (or item of the token-separated value list) exists. - * - *

      - * For example: {@code containsHeaderString("cache-control", ",", "no-store"::equalsIgnoreCase)} will return {@code true} if - * a {@code Cache-Control} header exists that has the value {@code no-store}, the value {@code No-Store} or the value - * {@code Max-Age, NO-STORE, no-transform}, but {@code false} when it has the value {@code no-store;no-transform} - * (missing comma), or the value {@code no - store} (whitespace within value). - * - * @param name the message header. - * @param valueSeparatorRegex Separates the header value into single values. {@code null} does not split. - * @param valuePredicate value must fulfil this predicate. - * @return {@code true} if and only if a header with the given name exists, having either a whitespace-trimmed value - * matching the predicate, or having at least one whitespace-trimmed single value in a token-separated list of single values. - * @see #getHeaders() - * @see #getHeaderString(String) - * @since 4.0 - */ - public boolean containsHeaderString(String name, String valueSeparatorRegex, Predicate valuePredicate); - - /** - * Checks whether a header with a specific name and value (or item of the comma-separated value list) exists. - * - *

      - * For example: {@code containsHeaderString("cache-control", "no-store"::equalsIgnoreCase)} will return {@code true} if - * a {@code Cache-Control} header exists that has the value {@code no-store}, the value {@code No-Store} or the value - * {@code Max-Age, NO-STORE, no-transform}, but {@code false} when it has the value {@code no-store;no-transform} - * (missing comma), or the value {@code no - store} (whitespace within value). - * - * @param name the message header. - * @param valuePredicate value must fulfil this predicate. - * @return {@code true} if and only if a header with the given name exists, having either a whitespace-trimmed value - * matching the predicate, or having at least one whitespace-trimmed single value in a comma-separated list of single values. - * @see #getHeaders() - * @see #getHeaderString(String) - * @since 4.0 - */ - public default boolean containsHeaderString(String name, Predicate valuePredicate) { - return containsHeaderString(name, ",", valuePredicate); - } - /** * Get message date. * diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/container/ContainerResponseContext.java b/jaxrs-api/src/main/java/jakarta/ws/rs/container/ContainerResponseContext.java index 6d6b74405..5a3246f2f 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/container/ContainerResponseContext.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/container/ContainerResponseContext.java @@ -24,7 +24,6 @@ import java.util.Locale; import java.util.Map; import java.util.Set; -import java.util.function.Predicate; import jakarta.ws.rs.core.EntityTag; import jakarta.ws.rs.core.Link; @@ -102,7 +101,7 @@ public interface ContainerResponseContext { /** * Get a message header as a single string value. * - * Each single non-string header value is converted to String using a {@link jakarta.ws.rs.ext.RuntimeDelegate.HeaderDelegate} if one + * Each single header value is converted to String using a {@link jakarta.ws.rs.ext.RuntimeDelegate.HeaderDelegate} if one * is available via {@link jakarta.ws.rs.ext.RuntimeDelegate#createHeaderDelegate(java.lang.Class)} for the header value * class or using its {@code toString} method if a header delegate is not available. * @@ -115,55 +114,6 @@ public interface ContainerResponseContext { */ public String getHeaderString(String name); - /** - * Checks whether a header with a specific name and value (or item of the token-separated value list) exists. - * - * Each single non-string header value is converted to String using a {@link jakarta.ws.rs.ext.RuntimeDelegate.HeaderDelegate} if one - * is available via {@link jakarta.ws.rs.ext.RuntimeDelegate#createHeaderDelegate(java.lang.Class)} for the header value - * class or using its {@code toString} method if a header delegate is not available. - * - *

      - * For example: {@code containsHeaderString("cache-control", ",", "no-store"::equalsIgnoreCase)} will return {@code true} if - * a {@code Cache-Control} header exists that has the value {@code no-store}, the value {@code No-Store} or the value - * {@code Max-Age, NO-STORE, no-transform}, but {@code false} when it has the value {@code no-store;no-transform} - * (missing comma), or the value {@code no - store} (whitespace within value). - * - * @param name the message header. - * @param valueSeparatorRegex Separates the header value into single values. {@code null} does not split. - * @param valuePredicate value must fulfil this predicate. - * @return {@code true} if and only if a header with the given name exists, having either a whitespace-trimmed value - * matching the predicate, or having at least one whitespace-trimmed single value in a token-separated list of single values. - * @see #getHeaders() - * @see #getHeaderString(String) - * @since 4.0 - */ - public boolean containsHeaderString(String name, String valueSeparatorRegex, Predicate valuePredicate); - - /** - * Checks whether a header with a specific name and value (or item of the comma-separated value list) exists. - * - * Each single non-string header value is converted to String using a {@link jakarta.ws.rs.ext.RuntimeDelegate.HeaderDelegate} if one - * is available via {@link jakarta.ws.rs.ext.RuntimeDelegate#createHeaderDelegate(java.lang.Class)} for the header value - * class or using its {@code toString} method if a header delegate is not available. - * - *

      - * For example: {@code containsHeaderString("cache-control", "no-store"::equalsIgnoreCase)} will return {@code true} if - * a {@code Cache-Control} header exists that has the value {@code no-store}, the value {@code No-Store} or the value - * {@code Max-Age, NO-STORE, no-transform}, but {@code false} when it has the value {@code no-store;no-transform} - * (missing comma), or the value {@code no - store} (whitespace within value). - * - * @param name the message header. - * @param valuePredicate value must fulfil this predicate. - * @return {@code true} if and only if a header with the given name exists, having either a whitespace-trimmed value - * matching the predicate, or having at least one whitespace-trimmed single value in a comma-separated list of single values. - * @see #getHeaders() - * @see #getHeaderString(String) - * @since 4.0 - */ - public default boolean containsHeaderString(String name, Predicate valuePredicate) { - return containsHeaderString(name, ",", valuePredicate); - } - /** * Get the allowed HTTP methods from the Allow HTTP header. * diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/container/ResourceContext.java b/jaxrs-api/src/main/java/jakarta/ws/rs/container/ResourceContext.java index 0cd23fea0..1d90c495b 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/container/ResourceContext.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/container/ResourceContext.java @@ -16,12 +16,12 @@ package jakarta.ws.rs.container; -import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.Entity; /** * The resource context provides access to instances of resource classes. *

      - * This interface can be injected using the {@link Context} annotation. + * This interface can be injected using the {@link Entity} annotation. *

      *

      * The resource context can be utilized when instances of managed resource classes are to be returned by sub-resource diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/container/Suspended.java b/jaxrs-api/src/main/java/jakarta/ws/rs/container/Suspended.java deleted file mode 100644 index fba0a462c..000000000 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/container/Suspended.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2012, 2019 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 jakarta.ws.rs.container; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.util.concurrent.TimeUnit; - -/** - * Inject a suspended {@link AsyncResponse} into a parameter of an invoked JAX-RS {@link jakarta.ws.rs.HttpMethod resource - * or sub-resource method}. - * - * The injected {@code AsyncResponse} instance is bound to the processing of the active request and can be used to - * resume the request processing when a response is available. - *

      - * By default there is {@link AsyncResponse#NO_TIMEOUT no suspend timeout set} and the asynchronous response is - * suspended indefinitely. The suspend timeout as well as a custom {@link TimeoutHandler timeout handler} can be - * specified programmatically using the {@link AsyncResponse#setTimeout(long, TimeUnit)} and - * {@link AsyncResponse#setTimeoutHandler(TimeoutHandler)} methods. For example: - *

      - * - *
      - *  @Stateless
      - *  @Path("/")
      - *  public class MyEjbResource {
      - *    …
      - *    @GET
      - *    @Asynchronous
      - *    public void longRunningOperation(@Suspended AsyncResponse ar) {
      - *      ar.setTimeoutHandler(customHandler);
      - *      ar.setTimeout(10, TimeUnit.SECONDS);
      - *      final String result = executeLongRunningOperation();
      - *      ar.resume(result);
      - *    }
      - *
      - *    private String executeLongRunningOperation() { … }
      - *  }
      - * 
      - *

      - * A resource or sub-resource method that injects a suspended instance of an {@code AsyncResponse} using the - * {@code @Suspended} annotation is expected be declared to return {@code void} type. Methods that inject asynchronous - * response instance using the {@code @Suspended} annotation and declare a return type other than {@code void} MUST be - * detected by the JAX-RS runtime and a warning message MUST be logged. Any response value returned from such resource - * or sub-resource method MUST be ignored by the framework: - *

      - * - *
      - * @Path("/messages/next")
      - * public class MessagingResource {
      - *     …
      - *     @GET
      - *     public String readMessage(@Suspended AsyncResponse ar) {
      - *         suspended.put(ar);
      - *         return "This response will be ignored.";
      - *     }
      - *     …
      - * }
      - * 
      - * - * @author Marek Potociar - * @since 2.0 - */ -@Target({ ElementType.PARAMETER }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface Suspended { -} diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Application.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Application.java index f336345b9..69f5e3fe0 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Application.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Application.java @@ -20,12 +20,14 @@ import java.util.Map; import java.util.Set; +import jakarta.ws.rs.Entity; + /** * Defines the components of a JAX-RS application and supplies additional meta-data. A JAX-RS application or * implementation supplies a concrete subclass of this abstract class. *

      * The implementation-created instance of an Application subclass may be injected into resource classes and providers - * using {@link jakarta.ws.rs.core.Context}. + * using {@link Entity}. *

      *

      * In case any of the {@code Application} subclass methods or it's constructor throws a {@link RuntimeException}, the @@ -62,7 +64,7 @@ public Set> getClasses() { /** * Get a set of root resource, provider and {@link Feature feature} instances. * - * Fields and properties of returned instances are injected with their declared dependencies (see {@link Context}) by + * Fields and properties of returned instances are injected with their declared dependencies (see {@link Entity}) by * the runtime prior to use. *

      * Implementations should warn about and ignore classes that do not conform to the requirements of root resource or diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/CacheControl.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/CacheControl.java index 2760ea761..7175545e3 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/CacheControl.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/CacheControl.java @@ -21,7 +21,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import jakarta.ws.rs.ext.RuntimeDelegate; import jakarta.ws.rs.ext.RuntimeDelegate.HeaderDelegate; @@ -340,8 +339,15 @@ public String toString() { */ @Override public int hashCode() { - int hash = Objects.hash(this.privateFlag, this.noCache, this.noStore, this.noTransform, this.mustRevalidate, - this.proxyRevalidate, this.maxAge, this.sMaxAge); + int hash = 7; + hash = 41 * hash + (this.privateFlag ? 1 : 0); + hash = 41 * hash + (this.noCache ? 1 : 0); + hash = 41 * hash + (this.noStore ? 1 : 0); + hash = 41 * hash + (this.noTransform ? 1 : 0); + hash = 41 * hash + (this.mustRevalidate ? 1 : 0); + hash = 41 * hash + (this.proxyRevalidate ? 1 : 0); + hash = 41 * hash + this.maxAge; + hash = 41 * hash + this.sMaxAge; hash = 41 * hash + hashCodeOf(this.privateFields); hash = 41 * hash + hashCodeOf(this.noCacheFields); hash = 41 * hash + hashCodeOf(this.cacheExtension); diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Configurable.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Configurable.java index 2d4910317..aded3ab0c 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Configurable.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Configurable.java @@ -18,6 +18,8 @@ import java.util.Map; +import jakarta.ws.rs.Entity; + /** * Represents a client or server-side configurable context in JAX-RS. * @@ -261,7 +263,7 @@ public interface Configurable { * As opposed to components registered via {@link #register(Class)} method, the lifecycle of providers registered using * this instance-based {@code register(...)} is not managed by JAX-RS runtime. The same registered component instance is * used during the whole lifespan of the configurable context. Fields and properties of all registered JAX-RS component - * instances are injected with their declared dependencies (see {@link Context}) by the JAX-RS runtime prior to use. + * instances are injected with their declared dependencies (see {@link Entity}) by the JAX-RS runtime prior to use. *

      * * @param component JAX-RS component instance to be configured in the scope of this configurable context. diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Configuration.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Configuration.java index 54a91ae39..fd9c2a2eb 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Configuration.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Configuration.java @@ -20,6 +20,7 @@ import java.util.Map; import java.util.Set; +import jakarta.ws.rs.Entity; import jakarta.ws.rs.RuntimeType; /** @@ -32,7 +33,7 @@ * component classes and/or instances. *

      *

      - * This interface can be injected using the {@link Context} annotation. + * This interface can be injected using the {@link Entity} annotation. *

      * * @author Marek Potociar @@ -174,7 +175,7 @@ public default boolean hasProperty(String name) { /** * Get the immutable set of registered JAX-RS component (such as provider or {@link Feature feature}) instances to be * utilized by the configurable instance. Fields and properties of returned instances are injected with their declared - * dependencies (see {@link Context}) by the runtime prior to use. + * dependencies (see {@link Entity}) by the runtime prior to use. *

      * For each component type, there can be only a single class-based or instance-based registration present in the * configuration context at any given time. diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Cookie.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Cookie.java index ba19e9b67..902a01289 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Cookie.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Cookie.java @@ -16,8 +16,6 @@ package jakarta.ws.rs.core; -import java.util.Objects; - import jakarta.ws.rs.ext.RuntimeDelegate; import jakarta.ws.rs.ext.RuntimeDelegate.HeaderDelegate; @@ -56,9 +54,7 @@ public class Cookie { * @param domain the host domain for which the cookie is valid. * @param version the version of the specification to which the cookie complies. * @throws IllegalArgumentException if name is {@code null}. - * @deprecated This constructor will be removed in a future version. Please use {@link Cookie.Builder} instead. */ - @Deprecated public Cookie(final String name, final String value, final String path, final String domain, final int version) throws IllegalArgumentException { if (name == null) { @@ -79,9 +75,7 @@ public Cookie(final String name, final String value, final String path, final St * @param path the URI path for which the cookie is valid. * @param domain the host domain for which the cookie is valid. * @throws IllegalArgumentException if name is {@code null}. - * @deprecated This constructor will be removed in a future version. Please use {@link Cookie.Builder} instead. */ - @Deprecated public Cookie(final String name, final String value, final String path, final String domain) throws IllegalArgumentException { this(name, value, path, domain, DEFAULT_VERSION); @@ -93,32 +87,12 @@ public Cookie(final String name, final String value, final String path, final St * @param name the name of the cookie. * @param value the value of the cookie. * @throws IllegalArgumentException if name is {@code null}. - * @deprecated This constructor will be removed in a future version. Please use {@link Cookie.Builder} instead. */ - @Deprecated public Cookie(final String name, final String value) throws IllegalArgumentException { this(name, value, null, null); } - /** - * Create a new instance from the supplied {@link AbstractCookieBuilder} instance. - * - * @param builder the builder. - * @throws IllegalArgumentException if {@code builder.name} is {@code null}. - * @since 3.1 - */ - protected Cookie(AbstractCookieBuilder builder) throws IllegalArgumentException { - if (builder.name == null) { - throw new IllegalArgumentException("name==null"); - } - this.name = builder.name; - this.value = builder.value; - this.version = builder.version; - this.domain = builder.domain; - this.path = builder.path; - } - /** * Creates a new instance of {@code Cookie} by parsing the supplied string. * @@ -199,7 +173,13 @@ public String toString() { */ @Override public int hashCode() { - return Objects.hash(this.name, this.value, this.version, this.path, this.domain); + int hash = 7; + hash = 97 * hash + (this.name != null ? this.name.hashCode() : 0); + hash = 97 * hash + (this.value != null ? this.value.hashCode() : 0); + hash = 97 * hash + this.version; + hash = 97 * hash + (this.path != null ? this.path.hashCode() : 0); + hash = 97 * hash + (this.domain != null ? this.domain.hashCode() : 0); + return hash; } /** @@ -219,141 +199,21 @@ public boolean equals(final Object obj) { return false; } final Cookie other = (Cookie) obj; - if (!Objects.equals(this.name, other.name)) { + if (this.name != other.name && (this.name == null || !this.name.equals(other.name))) { return false; } - if (!Objects.equals(this.value, other.value)) { + if (this.value != other.value && (this.value == null || !this.value.equals(other.value))) { return false; } - if (!Objects.equals(this.version, other.version)) { + if (this.version != other.version) { return false; } - if (!Objects.equals(this.path, other.path)) { + if (this.path != other.path && (this.path == null || !this.path.equals(other.path))) { return false; } - if (!Objects.equals(this.domain, other.domain)) { + if (this.domain != other.domain && (this.domain == null || !this.domain.equals(other.domain))) { return false; } return true; } - - /** - * JAX-RS {@link Cookie} builder class. - *

      - * Cookie builder provides methods that let you conveniently configure and subsequently build a new - * {@code Cookie} instance. - *

      - * For example: - * - *
      -     * Cookie cookie = new Cookie.Builder("name")
      -     *         .path("/")
      -     *         .domain("domain.com")
      -     *         .build();
      -     * 
      - * - * @since 3.1 - */ - public static class Builder extends AbstractCookieBuilder { - - /** - * Create a new instance. - * - * @param name the name of the cookie. - */ - public Builder(String name) { - super(name); - } - - @Override - public Cookie build() { - return new Cookie(this); - } - - } - - /** - * JAX-RS abstract {@link Cookie} builder class. - * - * @param the current AbstractCookieBuilder type. - * - * @since 3.1 - */ - public abstract static class AbstractCookieBuilder> { - - private final String name; - - private String value; - private int version = DEFAULT_VERSION; - private String path; - private String domain; - - /** - * Create a new instance. - * - * @param name the name of the cookie. - */ - public AbstractCookieBuilder(String name) { - this.name = name; - } - - /** - * Set the value of the cookie. - * - * @param value the value of the cookie. - * @return the updated builder instance. - */ - public T value(String value) { - this.value = value; - return self(); - } - - /** - * Set the version of the cookie. Defaults to {@link Cookie#DEFAULT_VERSION} - * - * @param version the version of the specification to which the cookie complies. - * @return the updated builder instance. - */ - public T version(int version) { - this.version = version; - return self(); - } - - /** - * Set the path of the cookie. - * - * @param path the URI path for which the cookie is valid. - * @return the updated builder instance. - */ - public T path(String path) { - this.path = path; - return self(); - } - - /** - * Set the domain of the cookie. - * - * @param domain the host domain for which the cookie is valid. - * @return the updated builder instance. - */ - public T domain(String domain) { - this.domain = domain; - return self(); - } - - @SuppressWarnings("unchecked") - private T self() { - return (T) this; - } - - /** - * Build a new {@link Cookie} instance using all the configuration previously specified in this builder. - * - * @return a new {@link Cookie} instance. - * @throws IllegalArgumentException if name is {@code null}. - */ - public abstract Cookie build(); - - } - } diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/EntityPart.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/EntityPart.java deleted file mode 100644 index 8186ed399..000000000 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/EntityPart.java +++ /dev/null @@ -1,398 +0,0 @@ -/******************************************************************* -* Copyright (c) 2021 Eclipse Foundation -* -* This specification document is made available under the terms -* of the Eclipse Foundation Specification License v1.0, which is -* available at https://www.eclipse.org/legal/efsl.php. -*******************************************************************/ -package jakarta.ws.rs.core; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Optional; - -import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.ext.RuntimeDelegate; - -/** - * A {@code EntityPart} is one part of a multipart entity. As defined in - * RFC 7578, a multipart - * request or response must have a content type of "multipart/form-data" with a - * {@code boundary} parameter indicating where one part ends the next may begin. - *

      - * Multipart entities may be received in a resource method as a collection of - * parts (e.g. {@code List}) or as a form parameter (ex: - * {@code @FormParam("part1Name") EntityPart part1}). - *

      - *

      - * Likewise, a client may receive a multipart response by reading the returned - * entity as a collection of EntityParts (ex: {@code response.readEntity(new - * GenericType>() {})}). - *

      - *

      - * In order to send a multipart entity either as a client request or a response - * from a resource method, you may create the Lists using - * {@code EntityPart.Builder}. For example: - *

      - * - *
      - * Client c = ClientBuilder.newClient();
      - *WebTarget target = c.target(someURL);
      - *List<EntityPart> parts = Arrays.asList(
      - *     EntityPart.withName("name1").fileName("file1.doc").content(stream1).build(),
      - *     EntityPart.withName("name2").fileName("file2.doc").content(stream2).build(),
      - *     EntityPart.withName("name3").fileName("file3.xml").content(myObject, MyClass.class).mediaType("application/xml").build());
      - *GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(parts){};
      - *Entity entity = Entity.entity(genericEntity, MediaType.MULTIPART_FORM_DATA);
      - *Response r = target.request().post(entity);
      - * 
      - * - * Note that when building a EntityPart, the name and content are required. - * Other properties such as headers, file name, and media type are optional. - * - * It is the responsibility of the implementation code to close the content - * input streams when sending the multipart content. Closing the stream before - * the implementation has sent it could result in unexpected exceptions. It is - * the responsibility of the calling code to close the stream when receiving the - * multipart content. - * - * @since 3.1 - */ -public interface EntityPart { - - /** - * Creates a new {@code EntityPart.Builder} instance. - * - * @param partName name of the part to create within the multipart entity - * @return {@link Builder} for building new {@link EntityPart} instances - */ - static Builder withName(String partName) { - return RuntimeDelegate.getInstance().createEntityPartBuilder(partName); - } - - /** - * Creates a new {@code EntityPart.Builder} instance that sets the part - * {@code name} and {@code fileName} to the passed in {@code partAndFileName} - * value. - *

      - * Logically, this is the same as {@code EntityPart.withName(x).fileName(x)}. - *

      - * - * @param partAndFileName name and filename of the part to create within the - * multipart entity - * @return {@link Builder} for building new {@link EntityPart} instances - */ - static Builder withFileName(String partAndFileName) { - return RuntimeDelegate.getInstance().createEntityPartBuilder(partAndFileName).fileName(partAndFileName); - } - - /** - * Returns the name of this part within the multipart entity. This will be the - * "name" attribute of the {@code Content-Disposition} header for this part. - * - * @return the part name - */ - String getName(); - - /** - * Returns the filename of this part. This will be the "filename" attribute of - * the {@code Content-Disposition} header for this part. A filename is not - * required in a part, so if a filename is not present it will return - * {@code Optional.empty()}. - * - * @return an {@code Optional} indicating the filename if present - */ - Optional getFileName(); - - /** - * Returns the input stream for this part. This is the content body of the part - * and is accessed as a stream to avoid loading potentially large amounts of - * data into the heap. - * - * It is the responsibility of the calling code to close this stream after - * receiving it. - * - * @return an {@code InputStream} representing the content of this part - */ - InputStream getContent(); - - /** - * Converts the content stream for this part to the specified class and returns - * it. The implementation must convert the stream by finding a - * {@link jakarta.ws.rs.ext.MessageBodyReader} that handles the specified type - * as well as the {@link MediaType} of the part. If no - * {@link jakarta.ws.rs.ext.MessageBodyReader} can be found to perform the - * conversion, this method will throw an {@code IllegalArgumentException}. - * - * The implementation is required to close the content stream when this method - * is invoked, so it may only be invoked once. Subsequent invocations will - * result in an {@code IllegalStateException}. Likewise this method will throw - * an {@code IllegalStateException} if it is called after calling - * {@link #getContent} or {@link #getContent(GenericType)}. - * - * @param type the {@code Class} that the implementation should convert this - * part to - * @param the entity type - * @return an instance of the specified {@code Class} representing the content - * of this part - * @throws IllegalArgumentException if no - * {@link jakarta.ws.rs.ext.MessageBodyReader} - * can handle the conversion of this part to - * the specified type - * @throws IllegalStateException if this method or any of the other - * {@code getContent} methods has already been - * invoked - * @throws IOException if the - * {@link jakarta.ws.rs.ext.MessageBodyReader#readFrom(Class, - * java.lang.reflect.Type, java.lang.annotation.Annotation[], MediaType, MultivaluedMap, InputStream)} - * method throws an {@code IOException} - * @throws WebApplicationException if the - * {@link jakarta.ws.rs.ext.MessageBodyReader#readFrom(Class, - * java.lang.reflect.Type, java.lang.annotation.Annotation[], MediaType, MultivaluedMap, InputStream)} - * method throws an - * {@code WebApplicationException} - */ - //CHECKSTYLE:OFF - More than 3 Exceptions are desired here - T getContent(Class type) throws IllegalArgumentException, IllegalStateException, IOException, - WebApplicationException; - //CHECKSTYLE:ON - - /** - * Converts the content stream for this part to the specified type and returns - * it. The implementation must convert the stream by finding a - * {@link jakarta.ws.rs.ext.MessageBodyReader} that handles the specified type - * as well as the {@link MediaType} of the part. If no - * {@link jakarta.ws.rs.ext.MessageBodyReader} can be found to perform the - * conversion, this method will throw an {@code IllegalArgumentException}. - * - * The implementation is required to close the content stream when this method - * is invoked, so it may only be invoked once. Subsequent invocations will - * result in an {@code IllegalStateException}. Likewise this method will throw - * an {@code IllegalStateException} if it is called after calling - * {@link #getContent} or {@link #getContent(Class)}. - * - * @param type the generic type that the implementation should convert this part - * to - * @param the entity type - * @return an instance of the specified generic type representing the content of - * this part - * @throws IllegalArgumentException if no - * {@link jakarta.ws.rs.ext.MessageBodyReader} - * can handle the conversion of this part to - * the specified type - * @throws IllegalStateException if this method or any of the other - * {@code getContent} methods has already been - * invoked - * @throws IOException if the - * {@link jakarta.ws.rs.ext.MessageBodyReader#readFrom(Class, - * java.lang.reflect.Type, java.lang.annotation.Annotation[], MediaType, MultivaluedMap, InputStream)} - * method throws an {@code IOException} - * @throws WebApplicationException if the - * {@link jakarta.ws.rs.ext.MessageBodyReader#readFrom(Class, - * java.lang.reflect.Type, java.lang.annotation.Annotation[], MediaType, MultivaluedMap, InputStream)} - * method throws an - * {@code WebApplicationException} - */ - //CHECKSTYLE:OFF - More than 3 Exceptions are desired here - T getContent(GenericType type) throws IllegalArgumentException, IllegalStateException, IOException, - WebApplicationException; - //CHECKSTYLE:ON - - /** - * Returns an immutable multivalued map of headers for this specific part. - * - * @return immutable {@code MultivaluedMap} of part headers - */ - MultivaluedMap getHeaders(); - - /** - * Returns the content type of this part, and equivalent to calling - * {@code MediaType.valueOf(part.getHeaders().getFirst(HttpHeaders.CONTENT_TYPE))}. - * - * @return the media type for this part - */ - MediaType getMediaType(); - - /** - * Builder for {@link EntityPart} instances. - * - * @since 3.1 - */ - interface Builder { - - /** - * Sets the media type for the EntityPart. This will also set the - * {@code Content-Type} header for this part. - * - * @param mediaType the media type for the part to be built - * @return the updated builder - * @throws IllegalArgumentException if {@code mediaType} is {@code null} - */ - Builder mediaType(MediaType mediaType) throws IllegalArgumentException; - - /** - * Convenience method for setting the media type for the EntityPart. This will - * also set the {@code Content-Type} header for this part. This call is - * effectively the same as - * {@code mediaType(MediaType.valueOf(mediaTypeString))}. - * - * @param mediaTypeString the media type for the part to be built - * @return the updated builder - * @throws IllegalArgumentException if {@code mediaTypeString} cannot be parsed - * or is {@code null} - */ - Builder mediaType(String mediaTypeString) throws IllegalArgumentException; - - /** - * Adds a new header or replaces a previously added header and sets the header - * value(s). - * - * @param headerName the header name - * @param headerValues the header value(s) - * @return the updated builder - * @throws IllegalArgumentException if {@code headerName} is {@code null} - */ - Builder header(String headerName, String... headerValues) throws IllegalArgumentException; - - /** - * Adds new headers or replaces previously added headers. The behavior of this - * method would be the same as if iterating over the entry set and invoking the - * {@link #header(String, String...)} method. - * - * @param newHeaders the multivalued map of headers to add to this part - * @return the updated builder - * @throws IllegalArgumentException if {@code newHeaders} is {@code null} - */ - Builder headers(MultivaluedMap newHeaders) throws IllegalArgumentException; - - /** - * Sets the file name for this part. The file name will be specified as an - * attribute in the {@code Content-Disposition} header of this part. When this - * method is called, the default media type used for the built part will be - * "application/octet-stream" if not otherwise specified. - * - * @param fileName the file name for this part - * @return the updated builder - * @throws IllegalArgumentException if {@code fileName} is {@code null} - */ - Builder fileName(String fileName) throws IllegalArgumentException; - - /** - * Sets the content for this part. The content of this builder must be specified - * before invoking the {@link #build()} method. - *

      - * The {@code InputStream} will be closed by the implementation code after - * sending the multipart data. Closing the stream before it is sent could result - * in unexpected behavior. - *

      - * - * @param content {@code InputStream} of the content of this part - * @return the updated builder - * @throws IllegalArgumentException if {@code content} is {@code null} - */ - Builder content(InputStream content) throws IllegalArgumentException; - - /** - * Convenience method, equivalent to calling - * {@code fileName(fileName).content(content)}. - * - * @param fileName the filename of the part. - * @param content the content stream of the part. - * @return the updated builder. - * @throws IllegalArgumentException if either parameter is {@code null}. - */ - default Builder content(String fileName, InputStream content) throws IllegalArgumentException { - return this.fileName(fileName).content(content); - } - - /** - * Sets the content for this part. The content of this builder must be specified - * before invoking the {@link #build()} method. - *

      - * If the content is specified using this method, then the {@link #build()} - * method is responsible for finding a registered - * {@link jakarta.ws.rs.ext.MessageBodyWriter} that is capable of writing the - * object type specified here using the default {@link MediaType} or the - * {@link MediaType} specified in the {@link #mediaType(MediaType)} or - * {@link #mediaType(String)} methods and using any headers specified via the - * {@link #header(String, String...)} or {@link #headers(MultivaluedMap)} - * methods. - *

      - * - * @param content the object to be used as the content - * @param type the type of this object which will be used when selecting the - * appropriate {@link jakarta.ws.rs.ext.MessageBodyWriter} - * @param the entity type - * @return the updated builder. - * @throws IllegalArgumentException if {@code content} is {@code null} - */ - Builder content(T content, Class type) throws IllegalArgumentException; - - /** - * Sets the content for this part. The content of this builder must be specified - * before invoking the {@link #build()} method. - *

      - * If the content is specified using this method, then the {@link #build()} - * method is responsible for finding a registered - * {@link jakarta.ws.rs.ext.MessageBodyWriter} that is capable of writing the - * object's class type specified here using the default {@link MediaType} or the - * {@link MediaType} specified in the {@link #mediaType(MediaType)} or - * {@link #mediaType(String)} methods and using any headers specified via the - * {@link #header(String, String...)} or {@link #headers(MultivaluedMap)} - * methods. - *

      - *

      - * This is the equivalent of calling - * {@code content(content, content.getClass())}. - *

      - * - * @param content the object to be used as the content - * @throws IllegalArgumentException if {@code content} is {@code null} - * @return the updated builder. - */ - default Builder content(Object content) throws IllegalArgumentException { - return this.content(content, content.getClass()); - } - - /** - * Sets the content for this part. The content of this builder must be specified - * before invoking the {@link #build()} method. - *

      - * If the content is specified using this method, then the {@link #build()} - * method is responsible for finding a registered - * {@link jakarta.ws.rs.ext.MessageBodyWriter} that is capable of writing the - * object type specified here using the default {@link MediaType} or the - * {@link MediaType} specified in the {@link #mediaType(MediaType)} or - * {@link #mediaType(String)} methods and using any headers specified via the - * {@link #header(String, String...)} or {@link #headers(MultivaluedMap)} - * methods. - *

      - * - * @param content the object to be used as the content - * @param type the generic type of this object which will be used when - * selecting the appropriate - * {@link jakarta.ws.rs.ext.MessageBodyWriter} - * @param the entity type - * @return the updated builder. - * @throws IllegalArgumentException if {@code content} is {@code null} - */ - Builder content(T content, GenericType type) throws IllegalArgumentException; - - /** - * Builds a new EntityPart instance using the provided property values. - * - * @return {@link EntityPart} instance built from the provided property values. - * @throws IllegalStateException if the content was not specified or no - * matching - * {@link jakarta.ws.rs.ext.MessageBodyWriter} - * was found. - * @throws IOException if the underlying - * {@link jakarta.ws.rs.ext.MessageBodyWriter} - * throws an {@code IOException} - * @throws WebApplicationException if the underlying - * {@link jakarta.ws.rs.ext.MessageBodyWriter} - * throws a {@code WebApplicationException} - */ - EntityPart build() throws IllegalStateException, IOException, WebApplicationException; - } -} diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/GenericEntity.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/GenericEntity.java index 3d904b395..6cf0913b0 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/GenericEntity.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/GenericEntity.java @@ -23,7 +23,6 @@ import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; -import java.util.Objects; /** * Represents a message entity of a generic type {@code T}. @@ -180,7 +179,7 @@ public boolean equals(final Object obj) { @Override public int hashCode() { - return Objects.hash(entity, type); + return entity.hashCode() + type.hashCode() * 37 + 5; } @Override diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/HttpHeaders.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/HttpHeaders.java index 84cdd4c18..d49afa34b 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/HttpHeaders.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/HttpHeaders.java @@ -20,7 +20,8 @@ import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.function.Predicate; + +import jakarta.ws.rs.Entity; /** * An injectable interface that provides access to HTTP header information. All methods throw @@ -28,7 +29,7 @@ * * @author Paul Sandoz * @author Marc Hadley - * @see Context + * @see Entity * @since 1.0 */ public interface HttpHeaders { @@ -48,7 +49,7 @@ public interface HttpHeaders { *

      * Get a HTTP header as a single string value. *

      - * Each single non-string header value is converted to String using a {@link jakarta.ws.rs.ext.RuntimeDelegate.HeaderDelegate} if one + * Each single header value is converted to String using a {@link jakarta.ws.rs.ext.RuntimeDelegate.HeaderDelegate} if one * is available via {@link jakarta.ws.rs.ext.RuntimeDelegate#createHeaderDelegate(java.lang.Class)} for the header value * class or using its {@code toString} method if a header delegate is not available. * @@ -61,55 +62,6 @@ public interface HttpHeaders { */ public String getHeaderString(String name); - /** - * Checks whether a header with a specific name and value (or item of the token-separated value list) exists. - * - * Each single non-string header value is converted to String using a {@link jakarta.ws.rs.ext.RuntimeDelegate.HeaderDelegate} if one - * is available via {@link jakarta.ws.rs.ext.RuntimeDelegate#createHeaderDelegate(java.lang.Class)} for the header value - * class or using its {@code toString} method if a header delegate is not available. - * - *

      - * For example: {@code containsHeaderString("cache-control", ",", "no-store"::equalsIgnoreCase)} will return {@code true} if - * a {@code Cache-Control} header exists that has the value {@code no-store}, the value {@code No-Store} or the value - * {@code Max-Age, NO-STORE, no-transform}, but {@code false} when it has the value {@code no-store;no-transform} - * (missing comma), or the value {@code no - store} (whitespace within value). - * - * @param name the message header. - * @param valueSeparatorRegex Separates the header value into single values. {@code null} does not split. - * @param valuePredicate value must fulfil this predicate. - * @return {@code true} if and only if a header with the given name exists, having either a whitespace-trimmed value - * matching the predicate, or having at least one whitespace-trimmed single value in a token-separated list of single values. - * @see #getRequestHeaders() - * @see #getHeaderString(String) - * @since 4.0 - */ - public boolean containsHeaderString(String name, String valueSeparatorRegex, Predicate valuePredicate); - - /** - * Checks whether a header with a specific name and value (or item of the comma-separated value list) exists. - * - * Each single non-string header value is converted to String using a {@link jakarta.ws.rs.ext.RuntimeDelegate.HeaderDelegate} if one - * is available via {@link jakarta.ws.rs.ext.RuntimeDelegate#createHeaderDelegate(java.lang.Class)} for the header value - * class or using its {@code toString} method if a header delegate is not available. - * - *

      - * For example: {@code containsHeaderString("cache-control", "no-store"::equalsIgnoreCase)} will return {@code true} if - * a {@code Cache-Control} header exists that has the value {@code no-store}, the value {@code No-Store} or the value - * {@code Max-Age, NO-STORE, no-transform}, but {@code false} when it has the value {@code no-store;no-transform} - * (missing comma), or the value {@code no - store} (whitespace within value). - * - * @param name the message header. - * @param valuePredicate value must fulfil this predicate. - * @return {@code true} if and only if a header with the given name exists, having either a whitespace-trimmed value - * matching the predicate, or having at least one whitespace-trimmed single value in a comma-separated list of single values. - * @see #getRequestHeaders() - * @see #getHeaderString(String) - * @since 4.0 - */ - public default boolean containsHeaderString(String name, Predicate valuePredicate) { - return containsHeaderString(name, ",", valuePredicate); - } - /** * Get the values of HTTP request headers. The returned Map is case-insensitive wrt. keys and is read-only. The method * never returns {@code null}. diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Link.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Link.java index 6f03b86a9..046616cf0 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Link.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Link.java @@ -16,18 +16,11 @@ package jakarta.ws.rs.core; -import javax.xml.namespace.QName; import java.net.URI; -import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; -import java.util.Map.Entry; import jakarta.ws.rs.ext.RuntimeDelegate; -import jakarta.xml.bind.annotation.XmlAnyAttribute; -import jakarta.xml.bind.annotation.XmlAttribute; -import jakarta.xml.bind.annotation.adapters.XmlAdapter; /** *

      @@ -402,187 +395,4 @@ public interface Builder { */ public Link buildRelativized(URI uri, Object... values); } - - /** - * Value type for {@link jakarta.ws.rs.core.Link} that can be marshalled and - * unmarshalled by JAXB. - * - * 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. - * - * @see jakarta.ws.rs.core.Link.JaxbAdapter - * @since 2.0 - * @deprecated - */ - @Deprecated - public static class JaxbLink { - - private URI uri; - private Map 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 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 getParams() { - if (params == null) { - params = new HashMap(); - } - 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 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); - } - - } - - /** - * An implementation of JAXB {@link jakarta.xml.bind.annotation.adapters.XmlAdapter} that maps the JAX-RS - * {@link jakarta.ws.rs.core.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: - * - *

      -     * @XmlRootElement
      -     * public class MyModel {
      -     *
      -     *   private Link link;
      -     *
      -     *   @XmlElement(name="link")
      -     *   @XmlJavaTypeAdapter(JaxbAdapter.class)
      -     *   public Link getLink() {
      -     *     return link;
      -     *   }
      -     *   ...
      -     * }
      -     * 
      - * - * 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. - * - * @see jakarta.ws.rs.core.Link.JaxbLink - * @since 2.0 - * @deprecated - */ - @Deprecated - public static class JaxbAdapter extends XmlAdapter { - - /** - * 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 (Entry 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 (Entry e : v.getParams().entrySet()) { - final String name = e.getKey(); - jl.getParams().put(new QName("", name), e.getValue()); - } - return jl; - } - } } diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/MediaType.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/MediaType.java index 6dba6da88..72fedad98 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/MediaType.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/MediaType.java @@ -82,15 +82,11 @@ public class MediaType { public static final MediaType APPLICATION_XHTML_XML_TYPE = new MediaType("application", "xhtml+xml"); /** * A {@code String} constant representing {@value #APPLICATION_SVG_XML} media type. - * @deprecated since 4.0, use a custom string instead. Will be removed in a future release of this API. */ - @Deprecated(forRemoval = true) public static final String APPLICATION_SVG_XML = "application/svg+xml"; /** * A {@link MediaType} constant representing {@value #APPLICATION_SVG_XML} media type. - * @deprecated since 4.0, use a custom {@code MediaType} instead. Will be removed in a future release of this API. */ - @Deprecated(forRemoval = true) public static final MediaType APPLICATION_SVG_XML_TYPE = new MediaType("application", "svg+xml"); /** * A {@code String} constant representing {@value #APPLICATION_JSON} media type. diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/MultivaluedMap.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/MultivaluedMap.java index 33017c1e9..a500a0d6d 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/MultivaluedMap.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/MultivaluedMap.java @@ -65,6 +65,7 @@ public interface MultivaluedMap extends Map> { * @throws NullPointerException if the supplied array of new values is {@code null}. * @since 2.0 */ + @SuppressWarnings("unchecked") void addAll(K key, V... newValues); /** @@ -77,6 +78,7 @@ public interface MultivaluedMap extends Map> { * @throws NullPointerException if the supplied value list is {@code null}. * @since 2.0 */ + @SuppressWarnings("unchecked") void addAll(K key, List valueList); /** diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/NewCookie.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/NewCookie.java index 832edf551..4e880fb00 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/NewCookie.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/NewCookie.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2020 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 @@ -17,7 +17,6 @@ package jakarta.ws.rs.core; import java.util.Date; -import java.util.Objects; import jakarta.ws.rs.ext.RuntimeDelegate; import jakarta.ws.rs.ext.RuntimeDelegate.HeaderDelegate; @@ -56,9 +55,7 @@ public class NewCookie extends Cookie { * @param name the name of the cookie. * @param value the value of the cookie. * @throws IllegalArgumentException if name is {@code null}. - * @deprecated This constructor will be removed in a future version. Please use {@link NewCookie.Builder} instead. */ - @Deprecated public NewCookie(final String name, final String value) { this(name, value, null, null, DEFAULT_VERSION, null, DEFAULT_MAX_AGE, null, false, false, null); } @@ -74,9 +71,7 @@ public NewCookie(final String name, final String value) { * @param maxAge the maximum age of the cookie in seconds. * @param secure specifies whether the cookie will only be sent over a secure connection. * @throws IllegalArgumentException if name is {@code null}. - * @deprecated This constructor will be removed in a future version. Please use {@link NewCookie.Builder} instead. */ - @Deprecated public NewCookie(final String name, final String value, final String path, @@ -100,9 +95,7 @@ public NewCookie(final String name, * @param httpOnly if {@code true} make the cookie HTTP only, i.e. only visible as part of an HTTP request. * @throws IllegalArgumentException if name is {@code null}. * @since 2.0 - * @deprecated This constructor will be removed in a future version. Please use {@link NewCookie.Builder} instead. */ - @Deprecated public NewCookie(final String name, final String value, final String path, @@ -126,9 +119,7 @@ public NewCookie(final String name, * @param maxAge the maximum age of the cookie in seconds * @param secure specifies whether the cookie will only be sent over a secure connection * @throws IllegalArgumentException if name is {@code null}. - * @deprecated This constructor will be removed in a future version. Please use {@link NewCookie.Builder} instead. */ - @Deprecated public NewCookie(final String name, final String value, final String path, @@ -155,9 +146,7 @@ public NewCookie(final String name, * @param httpOnly if {@code true} make the cookie HTTP only, i.e. only visible as part of an HTTP request. * @throws IllegalArgumentException if name is {@code null}. * @since 2.0 - * @deprecated This constructor will be removed in a future version. Please use {@link NewCookie.Builder} instead. */ - @Deprecated public NewCookie(final String name, final String value, final String path, @@ -187,9 +176,7 @@ public NewCookie(final String name, * @param sameSite specifies the value of the {@code SameSite} cookie attribute * @throws IllegalArgumentException if name is {@code null}. * @since 3.1 - * @deprecated This constructor will be removed in a future version. Please use {@link NewCookie.Builder} instead. */ - @Deprecated public NewCookie(final String name, final String value, final String path, @@ -215,9 +202,7 @@ public NewCookie(final String name, * * @param cookie the cookie to clone. * @throws IllegalArgumentException if cookie is {@code null}. - * @deprecated This constructor will be removed in a future version. Please use {@link NewCookie.Builder} instead. */ - @Deprecated public NewCookie(final Cookie cookie) { this(cookie, null, DEFAULT_MAX_AGE, null, false, false, null); } @@ -230,9 +215,7 @@ public NewCookie(final Cookie cookie) { * @param maxAge the maximum age of the cookie in seconds. * @param secure specifies whether the cookie will only be sent over a secure connection. * @throws IllegalArgumentException if cookie is {@code null}. - * @deprecated This constructor will be removed in a future version. Please use {@link NewCookie.Builder} instead. */ - @Deprecated public NewCookie(final Cookie cookie, final String comment, final int maxAge, final boolean secure) { this(cookie, comment, maxAge, null, secure, false, null); } @@ -248,9 +231,7 @@ public NewCookie(final Cookie cookie, final String comment, final int maxAge, fi * @param httpOnly if {@code true} make the cookie HTTP only, i.e. only visible as part of an HTTP request. * @throws IllegalArgumentException if cookie is {@code null}. * @since 2.0 - * @deprecated This constructor will be removed in a future version. Please use {@link NewCookie.Builder} instead. */ - @Deprecated public NewCookie(final Cookie cookie, final String comment, final int maxAge, final Date expiry, final boolean secure, final boolean httpOnly) { this(cookie, comment, maxAge, expiry, secure, httpOnly, null); } @@ -268,9 +249,7 @@ public NewCookie(final Cookie cookie, final String comment, final int maxAge, fi * @param sameSite specifies the value of the {@code SameSite} cookie attribute * @throws IllegalArgumentException if cookie is {@code null}. * @since 3.1 - * @deprecated This constructor will be removed in a future version. Please use {@link NewCookie.Builder} instead. */ - @Deprecated public NewCookie(final Cookie cookie, final String comment, final int maxAge, final Date expiry, final boolean secure, final boolean httpOnly, final SameSite sameSite) { super(cookie == null ? null : cookie.getName(), @@ -286,23 +265,6 @@ public NewCookie(final Cookie cookie, final String comment, final int maxAge, fi this.sameSite = sameSite; } - /** - * Create a new instance from the supplied {@link AbstractNewCookieBuilder} instance. - * - * @param builder the builder. - * @throws IllegalArgumentException if {@code builder.name} is {@code null}. - * @since 3.1 - */ - protected NewCookie(AbstractNewCookieBuilder builder) { - super(builder); - this.comment = builder.comment; - this.maxAge = builder.maxAge; - this.expiry = builder.expiry; - this.secure = builder.secure; - this.httpOnly = builder.httpOnly; - this.sameSite = builder.sameSite; - } - /** * Creates a new instance of NewCookie by parsing the supplied string. * @@ -424,8 +386,14 @@ public String toString() { */ @Override public int hashCode() { - return Objects.hash(getName(), getValue(), getVersion(), getPath(), getDomain(), - comment, maxAge, expiry, secure, httpOnly, sameSite); + int hash = super.hashCode(); + hash = 59 * hash + (this.comment != null ? this.comment.hashCode() : 0); + hash = 59 * hash + this.maxAge; + hash = 59 + hash + (this.expiry != null ? this.expiry.hashCode() : 0); + hash = 59 * hash + (this.secure ? 1 : 0); + hash = 59 * hash + (this.httpOnly ? 1 : 0); + hash = 59 * hash + this.sameSite.ordinal(); + return hash; } /** @@ -445,29 +413,29 @@ public boolean equals(final Object obj) { return false; } final NewCookie other = (NewCookie) obj; - if (!Objects.equals(this.getName(), other.getName())) { + if (this.getName() != other.getName() && (this.getName() == null || !this.getName().equals(other.getName()))) { return false; } - if (!Objects.equals(this.getValue(), other.getValue())) { + if (this.getValue() != other.getValue() && (this.getValue() == null || !this.getValue().equals(other.getValue()))) { return false; } if (this.getVersion() != other.getVersion()) { return false; } - if (!Objects.equals(this.getPath(), other.getPath())) { + if (this.getPath() != other.getPath() && (this.getPath() == null || !this.getPath().equals(other.getPath()))) { return false; } - if (!Objects.equals(this.getDomain(), other.getDomain())) { + if (this.getDomain() != other.getDomain() && (this.getDomain() == null || !this.getDomain().equals(other.getDomain()))) { return false; } - if (!Objects.equals(this.comment, other.comment)) { + if (this.comment != other.comment && (this.comment == null || !this.comment.equals(other.comment))) { return false; } if (this.maxAge != other.maxAge) { return false; } - if (!Objects.equals(this.expiry, other.expiry)) { + if (this.expiry != other.expiry && (this.expiry == null || !this.expiry.equals(other.expiry))) { return false; } @@ -507,182 +475,4 @@ public enum SameSite { } - /** - * JAX-RS {@link NewCookie} builder class. - *

      - * New Cookie builder provides methods that let you conveniently configure and subsequently build a new - * {@code NewCookie} instance. - *

      - * For example: - * - *
      -     * NewCookie cookie = new NewCookie.Builder("name")
      -     *         .path("/")
      -     *         .domain("domain.com")
      -     *         .sameSite(SameSite.LAX)
      -     *         .build();
      -     * 
      - * - * @since 3.1 - */ - public static class Builder extends AbstractNewCookieBuilder { - - /** - * Create a new instance. - * - * @param name the name of the cookie. - */ - public Builder(String name) { - super(name); - } - - /** - * Create a new instance supplementing the information in the supplied cookie. - * - * @param cookie the cookie to clone. - */ - public Builder(Cookie cookie) { - super(cookie); - } - - @Override - public NewCookie build() { - return new NewCookie(this); - } - - } - - /** - * JAX-RS abstract {@link NewCookie} builder class. - * - * @param the current AbstractNewCookieBuilder type. - * - * @since 3.1 - */ - public abstract static class AbstractNewCookieBuilder> extends AbstractCookieBuilder> { - - private String comment; - private int maxAge = DEFAULT_MAX_AGE; - private Date expiry; - private boolean secure; - private boolean httpOnly; - private SameSite sameSite; - - /** - * Create a new instance. - * - * @param name the name of the cookie. - */ - public AbstractNewCookieBuilder(String name) { - super(name); - } - - /** - * Create a new instance supplementing the information in the supplied cookie. - * - * @param cookie the cookie to clone. - */ - public AbstractNewCookieBuilder(Cookie cookie) { - super(cookie == null ? null : cookie.getName()); - if (cookie != null) { - value(cookie.getValue()); - path(cookie.getPath()); - domain(cookie.getDomain()); - version(cookie.getVersion()); - } - } - - /** - * Set the comment associated with the cookie. - * - * @param comment the comment. - * @return the updated builder instance. - */ - public T comment(String comment) { - this.comment = comment; - return self(); - } - - /** - * Set the maximum age of the the cookie in seconds. Cookies older than the maximum age are discarded. A cookie can be - * unset by sending a new cookie with maximum age of 0 since it will overwrite any existing cookie and then be - * immediately discarded. The default value of {@code -1} indicates that the cookie will be discarded at the end of the - * browser/application session. - * - * @param maxAge the maximum age in seconds. - * @return the updated builder instance. - * @see #expiry(Date) - */ - public T maxAge(int maxAge) { - this.maxAge = maxAge; - return self(); - } - - /** - * Set the cookie expiry date. Cookies whose expiry date has passed are discarded. A cookie can be unset by setting a - * new cookie with an expiry date in the past, typically the lowest possible date that can be set. - *

      - * Note that it is recommended to use {@link #maxAge(int) Max-Age} to control cookie expiration, however some browsers - * do not understand {@code Max-Age}, in which case setting {@code Expires} parameter may be necessary. - *

      - * - * @param expiry the cookie expiry date - * @return the updated builder instance. - * @see #maxAge(int) - */ - public T expiry(Date expiry) { - this.expiry = expiry; - return self(); - } - - /** - * Whether the cookie will only be sent over a secure connection. Defaults to {@code false}. - * - * @param secure specifies whether the cookie will only be sent over a secure connection. - * @return the updated builder instance. - */ - public T secure(boolean secure) { - this.secure = secure; - return self(); - } - - /** - * Whether the cookie will only be visible as part of an HTTP request. Defaults to {@code false}. - * - * @param httpOnly if {@code true} make the cookie HTTP only, i.e. only visible as part of an HTTP request. - * @return the updated builder instance. - */ - public T httpOnly(boolean httpOnly) { - this.httpOnly = httpOnly; - return self(); - } - - /** - * Set the attribute that controls whether the cookie is sent with cross-origin requests, providing protection against - * cross-site request forgery. - * - * @param sameSite specifies the value of the {@code SameSite} cookie attribute. - * @return the updated builder instance. - */ - public T sameSite(SameSite sameSite) { - this.sameSite = sameSite; - return self(); - } - - @SuppressWarnings("unchecked") - private T self() { - return (T) this; - } - - /** - * Build a new {@link NewCookie} instance using all the configuration previously specified in this builder. - * - * @return a new {@link NewCookie} instance. - * @throws IllegalArgumentException if name is {@code null}. - */ - @Override - public abstract NewCookie build(); - - } - } diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/PathSegment.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/PathSegment.java index 375e13a54..effc6bdbe 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/PathSegment.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/PathSegment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2019 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 @@ -32,6 +32,7 @@ public interface PathSegment { /** * Get the path segment. + *

      * * @return the path segment */ diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Response.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Response.java index 39c44e104..82e85d704 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Response.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Response.java @@ -463,22 +463,6 @@ public MultivaluedMap getHeaders() { */ public abstract String getHeaderString(String name); - /** - * Check if the response is closed. The method returns {@code true} if the response is closed, - * returns {@code false} otherwise. - * - * @return {@code true} if the response has been {@link #close() closed}, {@code false} otherwise. - * @since 3.1 - */ - public boolean isClosed() { - try { - hasEntity(); - return false; - } catch (IllegalStateException ignored) { - return true; - } - } - /** * Create a new ResponseBuilder by performing a shallow copy of an existing Response. *

      @@ -1189,13 +1173,6 @@ public enum Status implements StatusType { * @since 2.0 */ PARTIAL_CONTENT(206, "Partial Content"), - /** - * 300 Multiple Choices, see HTTP/1.1: - * Semantics and Content. - * - * @since 3.1 - */ - MULTIPLE_CHOICES(300, "Multiple Choices"), /** * 301 Moved Permanently, see HTTP/1.1 * documentation. @@ -1229,13 +1206,6 @@ public enum Status implements StatusType { * documentation. */ TEMPORARY_REDIRECT(307, "Temporary Redirect"), - /** - * 308 Permanent Redirect, see RFC 7538: - * The Hypertext Transfer Protocol Status Code 308 (Permanent Redirect). - * - * @since 3.1 - */ - PERMANENT_REDIRECT(308, "Permanent Redirect"), /** * 400 Bad Request, see HTTP/1.1 * documentation. @@ -1364,13 +1334,6 @@ public enum Status implements StatusType { * @since 2.1 */ REQUEST_HEADER_FIELDS_TOO_LARGE(431, "Request Header Fields Too Large"), - /** - * 451 Unavailable For Legal Reasons, see RFC 7725: - * An HTTP Status Code to Report Legal Obstacles. - * - * @since 3.1 - */ - UNAVAILABLE_FOR_LEGAL_REASONS(451, "Unavailable For Legal Reasons"), /** * 500 Internal Server Error, see HTTP/1.1 * documentation. diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/SecurityContext.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/SecurityContext.java index aeabef68e..07f0f4824 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/SecurityContext.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/SecurityContext.java @@ -18,12 +18,14 @@ import java.security.Principal; +import jakarta.ws.rs.Entity; + /** * An injectable interface that provides access to security related information. * * @author Paul Sandoz * @author Marc Hadley - * @see Context + * @see Entity * @since 1.0 */ public interface SecurityContext { diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/UriInfo.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/UriInfo.java index 26a0a9f3a..8a2a0c9f0 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/UriInfo.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/UriInfo.java @@ -19,6 +19,8 @@ import java.net.URI; import java.util.List; +import jakarta.ws.rs.Entity; + /** * An injectable interface that provides access to application and request URI information. Relative URIs are relative * to the base URI of the application, see {@link #getBaseUri}. @@ -30,7 +32,7 @@ * * @author Paul Sandoz * @author Marc Hadley - * @see Context + * @see Entity * @since 1.0 */ public interface UriInfo { diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Variant.java b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Variant.java index b48bc6b10..d7b98c39d 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/core/Variant.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/core/Variant.java @@ -19,7 +19,6 @@ import java.io.StringWriter; import java.util.List; import java.util.Locale; -import java.util.Objects; import jakarta.ws.rs.ext.RuntimeDelegate; @@ -199,7 +198,11 @@ public static VariantListBuilder encodings(final String... encodings) { */ @Override public int hashCode() { - return Objects.hash(this.language, this.mediaType, this.encoding); + int hash = 7; + hash = 29 * hash + (this.language != null ? this.language.hashCode() : 0); + hash = 29 * hash + (this.mediaType != null ? this.mediaType.hashCode() : 0); + hash = 29 * hash + (this.encoding != null ? this.encoding.hashCode() : 0); + return hash; } /** @@ -217,13 +220,14 @@ public boolean equals(final Object obj) { return false; } final Variant other = (Variant) obj; - if (!Objects.equals(this.language, other.language)) { + if (this.language != other.language && (this.language == null || !this.language.equals(other.language))) { return false; } - if (!Objects.equals(this.mediaType, other.mediaType)) { + if (this.mediaType != other.mediaType && (this.mediaType == null || !this.mediaType.equals(other.mediaType))) { return false; } - return Objects.equals(this.encoding, other.encoding); + // noinspection StringEquality + return this.encoding == other.encoding || (this.encoding != null && this.encoding.equals(other.encoding)); } @Override diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/ext/ContextResolver.java b/jaxrs-api/src/main/java/jakarta/ws/rs/ext/ContextResolver.java index 368d680cc..094255f58 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/ext/ContextResolver.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/ext/ContextResolver.java @@ -16,6 +16,8 @@ package jakarta.ws.rs.ext; +import jakarta.ws.rs.Entity; + /** * Contract for a provider that supplies context information to resource classes and other providers. * @@ -30,7 +32,7 @@ * @param type of the context * @author Paul Sandoz * @author Marc Hadley - * @see jakarta.ws.rs.core.Context + * @see Entity * @see Providers#getContextResolver(Class, jakarta.ws.rs.core.MediaType) * @see Provider * @see jakarta.ws.rs.Produces diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/ext/FactoryFinder.java b/jaxrs-api/src/main/java/jakarta/ws/rs/ext/FactoryFinder.java index bbd5afd96..d3a91c8f6 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/ext/FactoryFinder.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/ext/FactoryFinder.java @@ -21,7 +21,9 @@ import java.io.IOException; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.Iterator; import java.util.Properties; +import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import java.util.logging.Level; import java.util.logging.Logger; @@ -43,11 +45,6 @@ private FactoryFinder() { } private static ClassLoader getContextClassLoader() { - // For performance reasons, check if a security manager is installed. If not there is no need to use a - // privileged action. - if (System.getSecurityManager() == null) { - return Thread.currentThread().getContextClassLoader(); - } return AccessController.doPrivileged((PrivilegedAction) () -> { ClassLoader cl = null; try { @@ -110,16 +107,24 @@ private static Object newInstance(final String className, final ClassLoader clas static Object find(final String factoryId, final Class service) throws ClassNotFoundException { ClassLoader classLoader = getContextClassLoader(); - // First try the TCCL - Object result = findFirstService(factoryId, classLoader, service); - if (result != null) { - return result; + try { + Iterator iterator = ServiceLoader.load(service, FactoryFinder.getContextClassLoader()).iterator(); + + if (iterator.hasNext()) { + return iterator.next(); + } + } catch (Exception | ServiceConfigurationError ex) { + LOGGER.log(Level.FINER, "Failed to load service " + factoryId + ".", ex); } - // Next try the class loader from the FactoryFinder - result = findFirstService(factoryId, getClassLoader(), service); - if (result != null) { - return result; + try { + Iterator iterator = ServiceLoader.load(service, FactoryFinder.class.getClassLoader()).iterator(); + + if (iterator.hasNext()) { + return iterator.next(); + } + } catch (Exception | ServiceConfigurationError ex) { + LOGGER.log(Level.FINER, "Failed to load service " + factoryId + ".", ex); } // try to read from $java.home/lib/jaxrs.properties @@ -163,29 +168,4 @@ static Object find(final String factoryId, final Class service) throws Cl throw new ClassNotFoundException( "Provider for " + factoryId + " cannot be found", null); } - - private static ClassLoader getClassLoader() { - if (System.getSecurityManager() == null) { - return FactoryFinder.class.getClassLoader(); - } - return AccessController.doPrivileged((PrivilegedAction) FactoryFinder.class::getClassLoader); - } - - private static T findFirstService(final String factoryId, final ClassLoader cl, final Class service) { - final PrivilegedAction action = () -> { - try { - final ServiceLoader loader = ServiceLoader.load(service, cl); - if (loader.iterator().hasNext()) { - return loader.iterator().next(); - } - } catch (Exception e) { - LOGGER.log(Level.FINER, "Failed to load service " + factoryId + ".", e); - } - return null; - }; - if (System.getSecurityManager() == null) { - return action.run(); - } - return AccessController.doPrivileged(action); - } } diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/ext/Providers.java b/jaxrs-api/src/main/java/jakarta/ws/rs/ext/Providers.java index ff518b590..d436ce5e3 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/ext/Providers.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/ext/Providers.java @@ -19,6 +19,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Type; +import jakarta.ws.rs.Entity; import jakarta.ws.rs.core.MediaType; /** @@ -26,7 +27,7 @@ * * @author Paul Sandoz * @author Marc Hadley - * @see jakarta.ws.rs.core.Context + * @see Entity * @see MessageBodyReader * @see MessageBodyWriter * @see ContextResolver diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/ext/RuntimeDelegate.java b/jaxrs-api/src/main/java/jakarta/ws/rs/ext/RuntimeDelegate.java index 3570e5164..05c65b41f 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/ext/RuntimeDelegate.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/ext/RuntimeDelegate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2019 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 @@ -23,10 +23,9 @@ import jakarta.ws.rs.SeBootstrap; import jakarta.ws.rs.SeBootstrap.Instance; import jakarta.ws.rs.core.Application; -import jakarta.ws.rs.core.EntityPart; import jakarta.ws.rs.core.Link; -import jakarta.ws.rs.core.UriBuilder; import jakarta.ws.rs.core.Response.ResponseBuilder; +import jakarta.ws.rs.core.UriBuilder; import jakarta.ws.rs.core.Variant.VariantListBuilder; /** @@ -240,8 +239,8 @@ public static interface HeaderDelegate { /** * Perform startup of the application in Java SE environments. *

      - * This method is not intended to be invoked by applications. Call {@link SeBootstrap#start(Application, - * SeBootstrap.Configuration)} instead. + * This method is not intended to be invoked by applications. Call {@link SeBootstrap#start(Application, Configuration)} + * instead. *

      * * @param application The application to start up. @@ -250,31 +249,4 @@ public static interface HeaderDelegate { * instance}. */ public abstract CompletionStage bootstrap(Application application, SeBootstrap.Configuration configuration); - - /** - * Perform startup of the application in Java SE environments. - *

      - * This method is not intended to be invoked by applications. Call {@link SeBootstrap#start(Class, - * SeBootstrap.Configuration)} instead. - *

      - * - * @param clazz The application class to instantiate and start. - * @param configuration The bootstrap configuration. - * @return {@code CompletionStage} asynchronously producing handle of the running application {@link SeBootstrap.Instance - * instance}. - */ - public abstract CompletionStage bootstrap(Class clazz, SeBootstrap.Configuration configuration); - - /** - * Create a new instance of a {@link jakarta.ws.rs.core.EntityPart.Builder}. - *

      - * This method is not intended to be invoked by applications. Call {@link EntityPart#withName(String)} instead. - *

      - * - * @param partName name for this part within the multipart body. - * @return new {@code EntityPart.Builder} instance with specified part name - * @throws java.lang.IllegalArgumentException if {@code partName} is {@code null}. - * @since 3.1 - */ - public abstract EntityPart.Builder createEntityPartBuilder(String partName) throws IllegalArgumentException; } diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/sse/FactoryFinder.java b/jaxrs-api/src/main/java/jakarta/ws/rs/sse/FactoryFinder.java index 40440ae87..fa614afab 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/sse/FactoryFinder.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/sse/FactoryFinder.java @@ -21,7 +21,9 @@ import java.io.IOException; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.Iterator; import java.util.Properties; +import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import java.util.logging.Level; import java.util.logging.Logger; @@ -43,11 +45,6 @@ private FactoryFinder() { } private static ClassLoader getContextClassLoader() { - // For performance reasons, check if a security manager is installed. If not there is no need to use a - // privileged action. - if (System.getSecurityManager() == null) { - return Thread.currentThread().getContextClassLoader(); - } return AccessController.doPrivileged((PrivilegedAction) () -> { ClassLoader cl = null; try { @@ -110,16 +107,24 @@ private static Object newInstance(final String className, final ClassLoader clas static Object find(final String factoryId, final Class service) throws ClassNotFoundException { ClassLoader classLoader = getContextClassLoader(); - // First try the TCCL - Object result = findFirstService(factoryId, classLoader, service); - if (result != null) { - return result; + try { + Iterator iterator = ServiceLoader.load(service, FactoryFinder.getContextClassLoader()).iterator(); + + if (iterator.hasNext()) { + return iterator.next(); + } + } catch (Exception | ServiceConfigurationError ex) { + LOGGER.log(Level.FINER, "Failed to load service " + factoryId + ".", ex); } - // Next try the class loader from the FactoryFinder - result = findFirstService(factoryId, getClassLoader(), service); - if (result != null) { - return result; + try { + Iterator iterator = ServiceLoader.load(service, FactoryFinder.class.getClassLoader()).iterator(); + + if (iterator.hasNext()) { + return iterator.next(); + } + } catch (Exception | ServiceConfigurationError ex) { + LOGGER.log(Level.FINER, "Failed to load service " + factoryId + ".", ex); } // try to read from $java.home/lib/jaxrs.properties @@ -163,29 +168,4 @@ static Object find(final String factoryId, final Class service) throws Cl throw new ClassNotFoundException( "Provider for " + factoryId + " cannot be found", null); } - - private static ClassLoader getClassLoader() { - if (System.getSecurityManager() == null) { - return FactoryFinder.class.getClassLoader(); - } - return AccessController.doPrivileged((PrivilegedAction) FactoryFinder.class::getClassLoader); - } - - private static T findFirstService(final String factoryId, final ClassLoader cl, final Class service) { - final PrivilegedAction action = () -> { - try { - final ServiceLoader loader = ServiceLoader.load(service, cl); - if (loader.iterator().hasNext()) { - return loader.iterator().next(); - } - } catch (Exception e) { - LOGGER.log(Level.FINER, "Failed to load service " + factoryId + ".", e); - } - return null; - }; - if (System.getSecurityManager() == null) { - return action.run(); - } - return AccessController.doPrivileged(action); - } } diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/sse/SseEventSink.java b/jaxrs-api/src/main/java/jakarta/ws/rs/sse/SseEventSink.java index b24543530..bf37ce372 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/sse/SseEventSink.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/sse/SseEventSink.java @@ -16,7 +16,6 @@ package jakarta.ws.rs.sse; -import java.io.IOException; import java.util.concurrent.CompletionStage; /** @@ -72,8 +71,7 @@ public interface SseEventSink extends AutoCloseable { *

      * Subsequent calls have no effect and are ignored. Once the {@link SseEventSink} is closed, invoking any method other * than this one and {@link #isClosed()} would result in an {@link IllegalStateException} being thrown. - * @throws IOException if an I/O error occurs. */ @Override - void close() throws IOException; + void close(); } diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/sse/SseEventSource.java b/jaxrs-api/src/main/java/jakarta/ws/rs/sse/SseEventSource.java index 7df3f1fc5..bc5f06d54 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/sse/SseEventSource.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/sse/SseEventSource.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2020 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,11 +72,6 @@ *

      * In the case of an error condition response, the Throwable passed to the onError consumer * should be a WebApplicationException containing the invalid Response object. - *

      - * Note that if, for any of the registered event consumers, an invocation of {@link Consumer#accept(Object) - * Consumer<InboundSseEvent>#accept(InboundSseEvent)} method throws an exception, this is not an error condition. - * Thus onError is not invoked and event processing is not stopped. - * Users are encouraged to handle exceptions on their own as part of the event processing logic. * * @author Marek Potociar * @since 2.1 @@ -141,13 +136,6 @@ static Builder newBuilder() { } } - /** - * Set the SSE streaming endpoint. - * - * @param endpoint SSE streaming endpoint. Must not be {@code null}. - * @return updated event source builder instance. - * @throws NullPointerException in case the supplied web target is {@code null}. - */ protected abstract Builder target(WebTarget endpoint); /** diff --git a/jaxrs-api/src/main/java/module-info.java b/jaxrs-api/src/main/java/module-info.java index aa24390e0..cc23fce91 100644 --- a/jaxrs-api/src/main/java/module-info.java +++ b/jaxrs-api/src/main/java/module-info.java @@ -14,14 +14,11 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 */ -/** - * Defines the Jakarta RESTful Web Services API - */ module jakarta.ws.rs { - requires static jakarta.xml.bind; - requires java.logging; + requires jakarta.inject; + requires jakarta.cdi; exports jakarta.ws.rs; exports jakarta.ws.rs.client; @@ -34,5 +31,4 @@ uses jakarta.ws.rs.ext.RuntimeDelegate; uses jakarta.ws.rs.sse.SseEventSource.Builder; - opens jakarta.ws.rs.core to jakarta.xml.bind; } diff --git a/jaxrs-api/src/test/java/jakarta/ws/rs/SeBootstrapTest.java b/jaxrs-api/src/test/java/jakarta/ws/rs/SeBootstrapTest.java index bc09f2e97..ba3c14132 100644 --- a/jaxrs-api/src/test/java/jakarta/ws/rs/SeBootstrapTest.java +++ b/jaxrs-api/src/test/java/jakarta/ws/rs/SeBootstrapTest.java @@ -1,30 +1,26 @@ package jakarta.ws.rs; +import javax.net.ssl.SSLContext; +import java.util.concurrent.CompletionStage; + +import jakarta.ws.rs.SeBootstrap; +import jakarta.ws.rs.SeBootstrap.Configuration; +import jakarta.ws.rs.SeBootstrap.Configuration.SSLClientAuthentication; +import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.ext.RuntimeDelegate; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; -import java.net.URI; -import java.util.concurrent.CompletionStage; - -import javax.net.ssl.SSLContext; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import jakarta.ws.rs.core.UriBuilder; -import jakarta.ws.rs.SeBootstrap.Configuration; -import jakarta.ws.rs.SeBootstrap.Configuration.SSLClientAuthentication; -import jakarta.ws.rs.core.Application; -import jakarta.ws.rs.ext.RuntimeDelegate; - /** * Unit tests for {@link SeBootstrap} * @@ -38,7 +34,7 @@ public final class SeBootstrapTest { * installed RuntimeDelegate. */ @BeforeEach - public void setUp() { + public final void setUp() { RuntimeDelegate.setInstance(mock(RuntimeDelegate.class)); } @@ -47,7 +43,7 @@ public void setUp() { * use a possibly cluttered instance. */ @AfterEach - public void tearDown() { + public final void tearDown() { RuntimeDelegate.setInstance(null); } @@ -58,7 +54,7 @@ public void tearDown() { * @since 3.1 */ @Test - public void shouldDelegateApplicationStartupToRuntimeDelegate() { + public final void shouldDelegateApplicationStartupToRuntimeDelegate() { // given final Application application = mock(Application.class); final Configuration configuration = mock(Configuration.class); @@ -73,30 +69,6 @@ public void shouldDelegateApplicationStartupToRuntimeDelegate() { assertThat(actualCompletionStage, is(sameInstance(nativeCompletionStage))); } - /** - * Assert that {@link SeBootstrap#start(Class, Configuration)} will delegate to - * {@link RuntimeDelegate#bootstrap(Class, Configuration)}. - * - * @since 3.1 - */ - @Test - public void shouldDelegateClassApplicationStartupToRuntimeDelegate() { - // given - final Application application = mock(Application.class); - final Class clazz = application.getClass(); - final Configuration configuration = mock(Configuration.class); - @SuppressWarnings("unchecked") - final CompletionStage nativeCompletionStage = mock(CompletionStage.class); - given(RuntimeDelegate.getInstance().bootstrap(clazz, configuration)) - .willReturn(nativeCompletionStage); - - // when - final CompletionStage actualCompletionStage = SeBootstrap.start(clazz, configuration); - - // then - assertThat(actualCompletionStage, is(sameInstance(nativeCompletionStage))); - } - /** * Assert that {@link SeBootstrap.Configuration#builder()} will delegate to * {@link RuntimeDelegate#createConfigurationBuilder()}. @@ -104,7 +76,7 @@ public void shouldDelegateClassApplicationStartupToRuntimeDelegate() { * @since 3.1 */ @Test - public void shouldDelegateConfigurationBuilderCreationToRuntimeDelegate() { + public final void shouldDelegateConfigurationBuilderCreationToRuntimeDelegate() { // given final SeBootstrap.Configuration.Builder nativeConfigurationBuilder = mock(SeBootstrap.Configuration.Builder.class); given(RuntimeDelegate.getInstance().createConfigurationBuilder()).willReturn(nativeConfigurationBuilder); @@ -123,7 +95,7 @@ public void shouldDelegateConfigurationBuilderCreationToRuntimeDelegate() { * @since 3.1 */ @Test - public void shouldReturnSameConfigurationBuilderInstanceWhenLoadingExternalConfiguration() { + public final void shouldReturnSameConfigurationBuilderInstanceWhenLoadingExternalConfiguration() { // given final SeBootstrap.Configuration.Builder previousConfigurationBuilder = spy(SeBootstrap.Configuration.Builder.class); final Object someExternalConfiguration = mock(Object.class); @@ -145,7 +117,7 @@ public void shouldReturnSameConfigurationBuilderInstanceWhenLoadingExternalConfi * @since 3.1 */ @Test - public void shouldPushCorrespondingPropertiesIntoConfigurationBuilder() { + public final void shouldPushCorrespondingPropertiesIntoConfigurationBuilder() { // given final String someProtocolValue = mockString(); final String someHostValue = mockString(); @@ -180,7 +152,7 @@ public void shouldPushCorrespondingPropertiesIntoConfigurationBuilder() { * @since 3.1 */ @Test - public void shouldPullCorrespondingPropertiesFromConfiguration() { + public final void shouldPullCorrespondingPropertiesFromConfiguration() { // given final String someProtocolValue = mockString(); final String someHostValue = mockString(); @@ -214,53 +186,6 @@ public void shouldPullCorrespondingPropertiesFromConfiguration() { assertThat(actualSSLClientAuthenticationValue, is(sameInstance(someSSLClientAuthenticationValue))); } - /** - * Assert that a default {@code Configuration} is used when not passed to the - * {@code SeBootstrap.start} method. - * - * @since 3.1 - */ - @Test - public void shouldUseDefaultConfigurationIfOmitted() { - // given - final Application application = mock(Application.class); - final Configuration configuration = mock(Configuration.class); - SeBootstrap.Configuration.Builder builder = mock(SeBootstrap.Configuration.Builder.class); - given(SeBootstrap.Configuration.builder()).willReturn(builder); - given(builder.build()).willReturn(configuration); - - // when - SeBootstrap.start(application); - - // then - verify(RuntimeDelegate.getInstance()).bootstrap(application, configuration); - } - - /** - * Assert that calling {@code Configuration.baseUri} returns the correct URI as set - * by the mocked classes. - * - * @since 3.1 - */ - @Test - public void shouldReturnSameUri() { - // given - final URI uri = URI.create("http://localhost:8080/foo"); - final UriBuilder uriBuilder = mock(UriBuilder.class); - given(uriBuilder.build()).willReturn(uri); - final Configuration configuration = mock(Configuration.class); - given(configuration.baseUri()).willCallRealMethod(); - given(configuration.baseUriBuilder()).willReturn(uriBuilder); - final SeBootstrap.Instance instance = mock(SeBootstrap.Instance.class); - given(instance.configuration()).willReturn(configuration); - - // when - URI returnedUri = instance.configuration().baseUri(); - - // then - assertThat(uri, is(returnedUri)); - } - private static String mockString() { return Integer.toString(mockInt()); } diff --git a/jaxrs-api/src/test/java/jakarta/ws/rs/SerializationTest.java b/jaxrs-api/src/test/java/jakarta/ws/rs/SerializationTest.java index ff64f6e22..1048504af 100644 --- a/jaxrs-api/src/test/java/jakarta/ws/rs/SerializationTest.java +++ b/jaxrs-api/src/test/java/jakarta/ws/rs/SerializationTest.java @@ -1,12 +1,5 @@ package jakarta.ws.rs; -import jakarta.ws.rs.core.EntityTag; -import jakarta.ws.rs.core.GenericType; -import jakarta.ws.rs.core.Link; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.MultivaluedMap; -import jakarta.ws.rs.core.NewCookie; -import jakarta.ws.rs.core.Response; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; @@ -16,6 +9,14 @@ import java.util.Locale; import java.util.Map; import java.util.Set; + +import jakarta.ws.rs.core.EntityTag; +import jakarta.ws.rs.core.GenericType; +import jakarta.ws.rs.core.Link; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.core.NewCookie; +import jakarta.ws.rs.core.Response; import org.junit.jupiter.api.Test; public class SerializationTest { diff --git a/jaxrs-api/src/test/java/jakarta/ws/rs/core/CookieTest.java b/jaxrs-api/src/test/java/jakarta/ws/rs/core/CookieTest.java index ab5720a90..afa6ff7d9 100644 --- a/jaxrs-api/src/test/java/jakarta/ws/rs/core/CookieTest.java +++ b/jaxrs-api/src/test/java/jakarta/ws/rs/core/CookieTest.java @@ -20,84 +20,27 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; public class CookieTest extends BaseDelegateTest { + /** + * Test of equals method, of class Cookie and NewCookie. + */ @Test - public final void shouldReturnFalseWhenComparingCookieToNullObject() { - Cookie cookie = new Cookie("name", "value"); - assertFalse(cookie.equals(null)); - - cookie = new Cookie.Builder("name").value("value").build(); - assertFalse(cookie.equals(null)); - } - - @Test - public final void shouldReturnFalseWhenComparingCookieToNewCookie() { + public void testEquals() { + Object nullObj = null; Cookie cookie = new Cookie("name", "value"); + Cookie cookie1 = new Cookie("name", "value"); + Cookie cookie2 = new Cookie("name", "value2"); NewCookie newCookie = new NewCookie("name", "value"); + NewCookie newCookie1 = new NewCookie("name", "value"); + NewCookie newCookie2 = new NewCookie("name", "value2"); + assertFalse(cookie.equals(nullObj)); assertFalse(cookie.equals(newCookie)); - - Cookie thisCookie = new Cookie.Builder("name").value("value").build(); - NewCookie thatNewCookie = new NewCookie.Builder("name").value("value").build(); - assertFalse(thisCookie.equals(thatNewCookie)); - } - - @Test - public final void shouldReturnFalseWhenComparingCookiesThatHaveDifferentValues() { - Cookie cookie = new Cookie("name", "value"); - Cookie cookie2 = new Cookie("name", "value2"); assertFalse(cookie.equals(cookie2)); - - Cookie thisCookie = new Cookie.Builder("name").value("value").build(); - Cookie thatCookie = new Cookie.Builder("name").value("value2").build(); - assertFalse(thisCookie.equals(thatCookie)); - } - - @Test - public final void shouldReturnTrueWhenComparingCookiesThatHaveSameValues() { - - Cookie cookie = new Cookie("name", "value"); - Cookie cookie1 = new Cookie("name", "value"); - NewCookie newCookie = new NewCookie("name", "value"); assertTrue(cookie.equals(cookie1)); assertTrue(cookie.equals(newCookie.toCookie())); - - Cookie thisCookie = new Cookie.Builder("name").value("value").build(); - Cookie thatCookie = new Cookie.Builder("name").value("value").build(); - assertTrue(thisCookie.equals(thatCookie)); - - thatCookie = new NewCookie.Builder("name").value("value").build().toCookie(); - assertTrue(thisCookie.equals(thatCookie)); + assertTrue(newCookie.equals(newCookie1)); + assertFalse(newCookie.equals(newCookie2)); } - - @Test - public final void shouldThrowAnIllegalArgumentExceptionWhenBuildingCookieWithNullName() { - - try { - new Cookie(null, "value"); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - } - - try { - new Cookie(null, "value", "path", "domain"); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - } - - try { - new Cookie(null, "value", "path", "domain", Cookie.DEFAULT_VERSION); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - } - - try { - new Cookie.Builder(null).build(); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - } - } - } diff --git a/jaxrs-api/src/test/java/jakarta/ws/rs/core/GenericEntityTest.java b/jaxrs-api/src/test/java/jakarta/ws/rs/core/GenericEntityTest.java index 387332ac5..619c9aa1d 100644 --- a/jaxrs-api/src/test/java/jakarta/ws/rs/core/GenericEntityTest.java +++ b/jaxrs-api/src/test/java/jakarta/ws/rs/core/GenericEntityTest.java @@ -16,10 +16,6 @@ package jakarta.ws.rs.core; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - import java.lang.reflect.GenericArrayType; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; @@ -33,6 +29,10 @@ import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + public class GenericEntityTest { @Test diff --git a/jaxrs-api/src/test/java/jakarta/ws/rs/core/GenericTypeTest.java b/jaxrs-api/src/test/java/jakarta/ws/rs/core/GenericTypeTest.java index 8459a77f1..0111211f5 100644 --- a/jaxrs-api/src/test/java/jakarta/ws/rs/core/GenericTypeTest.java +++ b/jaxrs-api/src/test/java/jakarta/ws/rs/core/GenericTypeTest.java @@ -16,9 +16,6 @@ package jakarta.ws.rs.core; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; @@ -27,6 +24,9 @@ import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + /** * Type literal construction unit tests. * diff --git a/jaxrs-api/src/test/java/jakarta/ws/rs/core/JaxbLinkTest.java b/jaxrs-api/src/test/java/jakarta/ws/rs/core/JaxbLinkTest.java deleted file mode 100644 index 99af1e7ca..000000000 --- a/jaxrs-api/src/test/java/jakarta/ws/rs/core/JaxbLinkTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2014, 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 jakarta.ws.rs.core; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.StringReader; -import java.io.StringWriter; -import java.net.URI; -import java.util.HashMap; -import java.util.Map; - -import javax.xml.namespace.QName; -import javax.xml.transform.stream.StreamSource; - -import org.junit.jupiter.api.Test; - -import jakarta.xml.bind.JAXBContext; -import jakarta.xml.bind.JAXBElement; -import jakarta.xml.bind.Marshaller; -import jakarta.xml.bind.Unmarshaller; - -/** - * Unit test for JAX-RS Link marshalling and unmarshalling via JAXB. - * - * @author Marek Potociar (marek.potociar at oracle.com) - */ -public class JaxbLinkTest { - - @Test - public void testSerializationOfJaxbLink() throws Exception { - JAXBContext jaxbContext = JAXBContext.newInstance(Link.JaxbLink.class); - final Marshaller marshaller = jaxbContext.createMarshaller(); - final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); - - Map expectedParams = new HashMap(); - final QName qName = new QName("http://example.ns", "foo"); - expectedParams.put(qName, "test"); - final URI expectedUri = URI.create("/foo/bar"); - Link.JaxbLink expected = new Link.JaxbLink(expectedUri, expectedParams); - - final StringWriter writer = new StringWriter(); - - JAXBElement jaxbLinkJAXBElement = new JAXBElement(new QName("", "link"), Link.JaxbLink.class, expected); - marshaller.marshal(jaxbLinkJAXBElement, writer); - - final Link.JaxbLink actual = unmarshaller.unmarshal(new StreamSource( - new StringReader(writer.toString())), Link.JaxbLink.class).getValue(); - - assertEquals(expected, actual, "Unmarshalled JaxbLink instance not equal to the marshalled one."); - assertEquals(expectedUri, actual.getUri(), "Unmarshalled JaxbLink instance URI not equal to original."); - assertEquals(expectedParams, actual.getParams(), "Unmarshalled JaxbLink instance params not equal to original."); - } - - @Test - public void testEqualsHashCode() throws Exception { - Link.JaxbLink first = new Link.JaxbLink(); - Link.JaxbLink second = new Link.JaxbLink(); - - // trigger lazy initialization on first - first.getParams(); - - assertThat(first, equalTo(second)); - assertThat(second, equalTo(first)); - assertThat(first.hashCode(), equalTo(second.hashCode())); - } -} diff --git a/jaxrs-api/src/test/java/jakarta/ws/rs/core/MediaTypeTest.java b/jaxrs-api/src/test/java/jakarta/ws/rs/core/MediaTypeTest.java index b042cae2f..2c3f3a32a 100644 --- a/jaxrs-api/src/test/java/jakarta/ws/rs/core/MediaTypeTest.java +++ b/jaxrs-api/src/test/java/jakarta/ws/rs/core/MediaTypeTest.java @@ -16,16 +16,16 @@ package jakarta.ws.rs.core; -import static org.hamcrest.CoreMatchers.not; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; +import java.util.Map; import org.hamcrest.Description; import org.hamcrest.DiagnosingMatcher; import org.hamcrest.Matcher; import org.junit.jupiter.api.Test; -import java.util.Map; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; /** * {@link MediaType} unit test. diff --git a/jaxrs-api/src/test/java/jakarta/ws/rs/core/NewCookieBuilderTest.java b/jaxrs-api/src/test/java/jakarta/ws/rs/core/NewCookieBuilderTest.java deleted file mode 100644 index 3a629f5dc..000000000 --- a/jaxrs-api/src/test/java/jakarta/ws/rs/core/NewCookieBuilderTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2010, 2020 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 jakarta.ws.rs.core; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.fail; - -/** - * Unit tests for {@link NewCookie.Builder} - * - * @author Nicolas NESMON - * @since 3.1 - */ -public final class NewCookieBuilderTest extends BaseDelegateTest { - - @Test - public final void shouldReturnSuppliedCookieInformationWhenSuppliedCookieIsNotNull() { - - String expectedName = "name"; - String expectedValue = "value"; - int expectedVersion = 2; - String expectedPath = "/"; - String expectedDomain = "localhost"; - - Cookie cookie = new Cookie.Builder(expectedName) - .value(expectedValue) - .version(expectedVersion) - .path(expectedPath) - .domain(expectedDomain) - .build(); - NewCookie newCookie = new NewCookie.Builder(cookie).build(); - - assertEquals(expectedName, newCookie.getName()); - assertEquals(expectedValue, newCookie.getValue()); - assertEquals(expectedVersion, newCookie.getVersion()); - assertEquals(expectedPath, newCookie.getPath()); - assertEquals(expectedDomain, newCookie.getDomain()); - } - - @Test - public final void shouldThrowAnIllegalArgumentExceptionWhenSuppliedCookieIsNull() { - - try { - new NewCookie.Builder((Cookie) null).build(); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - } - - try { - new NewCookie.Builder((Cookie) null).comment("comment").maxAge(120).secure(true).build(); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - } - } - - @Test - public final void shouldReturnNullWhenSameSiteIsNotSet() { - NewCookie newCookie = new NewCookie.Builder("name").build(); - assertNull(newCookie.getSameSite()); - } - - @Test - public final void shouldReturnNullWhenSameSiteIsSetToNull() { - NewCookie newCookie = new NewCookie.Builder("name").sameSite(null).build(); - assertNull(newCookie.getSameSite()); - } - - @Test - public final void shouldReturnSuppliedValueWhenSameSiteIsSetToNonNullValue() { - - NewCookie.Builder newCookieBuilder = new NewCookie.Builder("name"); - - NewCookie newCookie = newCookieBuilder.sameSite(NewCookie.SameSite.NONE).build(); - assertEquals(NewCookie.SameSite.NONE, newCookie.getSameSite()); - - newCookie = newCookieBuilder.sameSite(NewCookie.SameSite.LAX).build(); - assertEquals(NewCookie.SameSite.LAX, newCookie.getSameSite()); - - newCookie = newCookieBuilder.sameSite(NewCookie.SameSite.STRICT).build(); - assertEquals(NewCookie.SameSite.STRICT, newCookie.getSameSite()); - } - -} diff --git a/jaxrs-api/src/test/java/jakarta/ws/rs/core/NewCookieTest.java b/jaxrs-api/src/test/java/jakarta/ws/rs/core/NewCookieTest.java index 7cffb2a94..4b2c88e71 100644 --- a/jaxrs-api/src/test/java/jakarta/ws/rs/core/NewCookieTest.java +++ b/jaxrs-api/src/test/java/jakarta/ws/rs/core/NewCookieTest.java @@ -16,189 +16,54 @@ package jakarta.ws.rs.core; -import jakarta.ws.rs.core.NewCookie.SameSite; -import java.util.Date; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; public class NewCookieTest extends BaseDelegateTest { + /** + * Test of valueOf method, of class NewCookie. + */ @Test - public void testSameSite() { - - NewCookie sameSiteOmit = new NewCookie("name", "value", "/", "localhost", 1, null, 0, null, false, false); - assertNull(sameSiteOmit.getSameSite()); - sameSiteOmit = new NewCookie.Builder("name").build(); - assertNull(sameSiteOmit.getSameSite()); - - NewCookie sameSiteNull = new NewCookie("name", "value", "/", "localhost", 1, null, 0, null, false, false, null); - assertNull(sameSiteNull.getSameSite()); - sameSiteNull = new NewCookie.Builder("name").sameSite(null).build(); - assertNull(sameSiteNull.getSameSite()); - - NewCookie sameSiteNone = new NewCookie("name", "value", "/", "localhost", 1, null, 0, null, false, false, NewCookie.SameSite.NONE); - assertEquals(NewCookie.SameSite.NONE, sameSiteNone.getSameSite()); - sameSiteNone = new NewCookie.Builder("name").sameSite(NewCookie.SameSite.NONE).build(); - assertEquals(NewCookie.SameSite.NONE, sameSiteNone.getSameSite()); - - NewCookie sameSiteLax = new NewCookie("name", "value", "/", "localhost", 1, null, 0, null, false, false, NewCookie.SameSite.LAX); - assertEquals(NewCookie.SameSite.LAX, sameSiteLax.getSameSite()); - sameSiteLax = new NewCookie.Builder("name").sameSite(NewCookie.SameSite.LAX).build(); - assertEquals(NewCookie.SameSite.LAX, sameSiteLax.getSameSite()); - - NewCookie sameSiteStrict = new NewCookie("name", "value", "/", "localhost", 1, null, 0, null, false, false, NewCookie.SameSite.STRICT); - assertEquals(NewCookie.SameSite.STRICT, sameSiteStrict.getSameSite()); - sameSiteStrict = new NewCookie.Builder("name").sameSite(NewCookie.SameSite.STRICT).build(); - assertEquals(NewCookie.SameSite.STRICT, sameSiteStrict.getSameSite()); - - } - - @Test - public final void shouldReturnFalseWhenComparingNewCookieToNullObject() { - NewCookie newCookie = new NewCookie("name", "value"); - assertFalse(newCookie.equals(null)); - - newCookie = new NewCookie.Builder("name").value("value").build(); - assertFalse(newCookie.equals(null)); - } - - @Test - public final void shouldReturnFalseWhenComparingNewCookieToCookie() { - Cookie cookie = new Cookie("name", "value"); - NewCookie newCookie = new NewCookie("name", "value"); - assertFalse(newCookie.equals(cookie)); - - NewCookie thisNewCookie = new NewCookie.Builder("name").value("value").build(); - Cookie thatCookie = new Cookie.Builder("name").value("value").build(); - assertFalse(thisNewCookie.equals(thatCookie)); - } - - @Test - public final void shouldReturnFalseWhenComparingNewCookiesThatHaveDifferentValues() { - NewCookie newCookie = new NewCookie("name", "value"); - NewCookie newCookie2 = new NewCookie("name", "value2"); - assertFalse(newCookie.equals(newCookie2)); - - NewCookie thisNewCookie = new NewCookie.Builder("name").value("value").build(); - NewCookie thatNewCookie = new NewCookie.Builder("name").value("value2").build(); - assertFalse(thisNewCookie.equals(thatNewCookie)); - } - - @Test - public final void shouldReturnTrueWhenComparingNewCookiesThatHaveSameValues() { - NewCookie newCookie = new NewCookie("name", "value"); - NewCookie newCookie1 = new NewCookie("name", "value"); - assertTrue(newCookie.equals(newCookie1)); - - NewCookie thisNewCookie = new NewCookie.Builder("name").value("value").build(); - NewCookie thatNewCookie = new NewCookie.Builder("name").value("value").build(); - assertTrue(thisNewCookie.equals(thatNewCookie)); - } - - @Test - public final void shouldReturnSuppliedCookiePropertiesWhenBuildingNewCookiesFromCookie() { - Cookie cookie = new Cookie("name", "value", "path", "domain", Cookie.DEFAULT_VERSION); - NewCookie newCookie = new NewCookie(cookie); - assertEquals(newCookie.getName(), cookie.getName()); - assertEquals(newCookie.getPath(), cookie.getPath()); - assertEquals(newCookie.getDomain(), cookie.getDomain()); - assertEquals(newCookie.getVersion(), cookie.getVersion()); - - cookie = new Cookie.Builder("name") - .value("value") - .path("path") - .domain("domain") - .version(Cookie.DEFAULT_VERSION) - .build(); - newCookie = new NewCookie.Builder(cookie).build(); - assertEquals(newCookie.getName(), cookie.getName()); - assertEquals(newCookie.getPath(), cookie.getPath()); - assertEquals(newCookie.getDomain(), cookie.getDomain()); - assertEquals(newCookie.getVersion(), cookie.getVersion()); - } - - @Test - public final void shouldThrowAnIllegalArgumentExceptionWhenBuildingNewCookieWithNullName() { - - try { - new NewCookie(null, null); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - } - - try { - new NewCookie(null, "value", "path", "domain", "comment", NewCookie.DEFAULT_MAX_AGE, false); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - } - - try { - new NewCookie(null, "value", "path", "domain", "comment", NewCookie.DEFAULT_MAX_AGE, false, false); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - } - - try { - new NewCookie(null, "value", "path", "domain", Cookie.DEFAULT_VERSION, "comment", NewCookie.DEFAULT_MAX_AGE, false); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - } - - try { - new NewCookie(null, "value", "path", "domain", Cookie.DEFAULT_VERSION, "comment", NewCookie.DEFAULT_MAX_AGE, new Date(), false, false); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - } - + public void testCtor() { + Cookie c = new Cookie("name", "value"); + NewCookie nc = new NewCookie(c); + assertEquals(nc.getName(), c.getName()); try { - new NewCookie(null, "value", "path", "domain", Cookie.DEFAULT_VERSION, "comment", NewCookie.DEFAULT_MAX_AGE, new Date(), false, false, SameSite.LAX); + nc = new NewCookie(null); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { } - try { - new NewCookie.Builder((String) null).build(); + nc = new NewCookie(null, "comment", 120, true); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { } } @Test - public final void shouldThrowAnIllegalArgumentExceptionWhenBuildingNewCookieFromNullCookie() { - - try { - new NewCookie((Cookie)null); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - } + public void testSameSite() { + NewCookie sameSiteOmit = new NewCookie("name", "value", "/", "localhost", 1, + null, 0, null, false, false); + assertNull(sameSiteOmit.getSameSite()); - try { - new NewCookie(null, "comment", NewCookie.DEFAULT_MAX_AGE, false); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - } + NewCookie sameSiteNull = new NewCookie("name", "value", "/", "localhost", 1, + null, 0, null, false, false, null); + assertNull(sameSiteNull.getSameSite()); - try { - new NewCookie(null, "comment", NewCookie.DEFAULT_MAX_AGE, new Date(), false, false); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - } + NewCookie sameSiteNone = new NewCookie("name", "value", "/", "localhost", 1, + null, 0, null, false, false, NewCookie.SameSite.NONE); + assertEquals(NewCookie.SameSite.NONE, sameSiteNone.getSameSite()); - try { - new NewCookie(null, "comment", NewCookie.DEFAULT_MAX_AGE, new Date(), false, false, SameSite.LAX); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - } + NewCookie sameSiteLax = new NewCookie("name", "value", "/", "localhost", 1, + null, 0, null, false, false, NewCookie.SameSite.LAX); + assertEquals(NewCookie.SameSite.LAX, sameSiteLax.getSameSite()); - try { - new NewCookie.Builder((Cookie) null).build(); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - } + NewCookie sameSiteStrict = new NewCookie("name", "value", "/", "localhost", 1, + null, 0, null, false, false, NewCookie.SameSite.STRICT); + assertEquals(NewCookie.SameSite.STRICT, sameSiteStrict.getSameSite()); } } diff --git a/jaxrs-api/src/test/java/jakarta/ws/rs/core/VariantTest.java b/jaxrs-api/src/test/java/jakarta/ws/rs/core/VariantTest.java index d1434cf98..19d0e7c6d 100644 --- a/jaxrs-api/src/test/java/jakarta/ws/rs/core/VariantTest.java +++ b/jaxrs-api/src/test/java/jakarta/ws/rs/core/VariantTest.java @@ -16,10 +16,10 @@ package jakarta.ws.rs.core; -import static org.junit.jupiter.api.Assertions.assertNull; - import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertNull; + /** * Variant regression unit tests. * diff --git a/jaxrs-api/src/test/java/jakarta/ws/rs/ext/RuntimeDelegateTest.java b/jaxrs-api/src/test/java/jakarta/ws/rs/ext/RuntimeDelegateTest.java index 381141add..fd61ddc3c 100644 --- a/jaxrs-api/src/test/java/jakarta/ws/rs/ext/RuntimeDelegateTest.java +++ b/jaxrs-api/src/test/java/jakarta/ws/rs/ext/RuntimeDelegateTest.java @@ -1,10 +1,10 @@ package jakarta.ws.rs.ext; +import org.junit.jupiter.api.Test; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; -import org.junit.jupiter.api.Test; - /** * {@link jakarta.ws.rs.ext.RuntimeDelegate} unit tests. * diff --git a/jaxrs-spec/pom.xml b/jaxrs-spec/pom.xml index 050d7ebc6..5f506b876 100644 --- a/jaxrs-spec/pom.xml +++ b/jaxrs-spec/pom.xml @@ -27,7 +27,7 @@ jakarta.ws.rs all - 3.1.0 + 4.0.0-SNAPSHOT diff --git a/jaxrs-tck/pom.xml b/jaxrs-tck/pom.xml index 776cc461c..422305760 100644 --- a/jaxrs-tck/pom.xml +++ b/jaxrs-tck/pom.xml @@ -31,7 +31,7 @@ jakarta.ws.rs all - 3.1.0 + 4.0.0-SNAPSHOT diff --git a/jersey-tck/pom.xml b/jersey-tck/pom.xml index 5ab7e8b9b..f6d3e0c47 100644 --- a/jersey-tck/pom.xml +++ b/jersey-tck/pom.xml @@ -28,7 +28,7 @@ jakarta.ws.rs all - 3.1.0 + 4.0.0-SNAPSHOT Jakarta RESTful WS Compliance diff --git a/pom.xml b/pom.xml index e8bf7661f..b3fb77f26 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ jakarta.ws.rs all - 3.1.0 + 4.0.0-SNAPSHOT pom Jakarta RESTful WS Project @@ -57,7 +57,7 @@ jaxrs-api - jaxrs-tck + examples