diff --git a/access-grant/pom.xml b/access-grant/pom.xml index e08c5f14434..76910cd80f8 100644 --- a/access-grant/pom.xml +++ b/access-grant/pom.xml @@ -14,8 +14,7 @@ - 1.8 - 1.8 + 8 diff --git a/api/pom.xml b/api/pom.xml index a5e2b0dece9..0371802bbd5 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -14,8 +14,7 @@ - 1.8 - 1.8 + 8 diff --git a/api/src/main/java/com/inrupt/client/ProblemDetails.java b/api/src/main/java/com/inrupt/client/ProblemDetails.java index 5cf6dde4c37..cab99569e63 100644 --- a/api/src/main/java/com/inrupt/client/ProblemDetails.java +++ b/api/src/main/java/com/inrupt/client/ProblemDetails.java @@ -37,7 +37,7 @@ public interface ProblemDetails { /** * The RFC9457 default problem type. */ - String DEFAULT_TYPE = "about:blank"; + URI DEFAULT_TYPE = URI.create("about:blank"); /** * The problem type. @@ -52,10 +52,10 @@ public interface ProblemDetails { String getTitle(); /** - * The problem details. - * @return the details + * The problem detail. + * @return the detail */ - String getDetails(); + String getDetail(); /** * The problem status code. diff --git a/core/pom.xml b/core/pom.xml index 58bb19c1b12..3beac12833d 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -14,8 +14,7 @@ - 1.8 - 1.8 + 8 diff --git a/examples/cli/pom.xml b/examples/cli/pom.xml index 22e86768a94..8a6f3dcda54 100644 --- a/examples/cli/pom.xml +++ b/examples/cli/pom.xml @@ -16,8 +16,7 @@ - 17 - 17 + 17 3.12.0 diff --git a/examples/spring-web/pom.xml b/examples/spring-web/pom.xml index d096a7e3b11..c4f7c71b60a 100644 --- a/examples/spring-web/pom.xml +++ b/examples/spring-web/pom.xml @@ -16,8 +16,7 @@ - 17 - 17 + 17 3.3.1 diff --git a/examples/springboot/pom.xml b/examples/springboot/pom.xml index a90d1ae67a7..85b735a3c10 100644 --- a/examples/springboot/pom.xml +++ b/examples/springboot/pom.xml @@ -16,8 +16,7 @@ - 17 - 17 + 17 3.3.1 diff --git a/examples/webapp/pom.xml b/examples/webapp/pom.xml index e86454e524b..b207a327b9e 100644 --- a/examples/webapp/pom.xml +++ b/examples/webapp/pom.xml @@ -16,8 +16,7 @@ - 17 - 17 + 17 3.12.0 diff --git a/okhttp/pom.xml b/okhttp/pom.xml index 9cbc265a454..5200707f159 100644 --- a/okhttp/pom.xml +++ b/okhttp/pom.xml @@ -14,8 +14,7 @@ - 1.8 - 1.8 + 8 diff --git a/openid/pom.xml b/openid/pom.xml index 89841e15834..0440b487f6f 100644 --- a/openid/pom.xml +++ b/openid/pom.xml @@ -14,8 +14,7 @@ - 1.8 - 1.8 + 8 diff --git a/parser/pom.xml b/parser/pom.xml index cd15afa28ef..0dc234e3fb3 100644 --- a/parser/pom.xml +++ b/parser/pom.xml @@ -14,8 +14,7 @@ - 1.8 - 1.8 + 8 diff --git a/pom.xml b/pom.xml index 296dfd7ece6..b0b4ad3b500 100644 --- a/pom.xml +++ b/pom.xml @@ -14,8 +14,7 @@ true - 11 - 11 + 11 UTF-8 UTF-8 diff --git a/quarkus/pom.xml b/quarkus/pom.xml index 82a2116391c..15a6dcc3652 100644 --- a/quarkus/pom.xml +++ b/quarkus/pom.xml @@ -13,11 +13,6 @@ Integration utilities for Quarkus support. - - 11 - 11 - - diff --git a/rdf-legacy/pom.xml b/rdf-legacy/pom.xml index 64b8fd02489..0bd84f3350d 100644 --- a/rdf-legacy/pom.xml +++ b/rdf-legacy/pom.xml @@ -14,8 +14,7 @@ - 1.8 - 1.8 + 8 1.12.0 diff --git a/rdf4j/pom.xml b/rdf4j/pom.xml index 218654c1078..fe5547dc039 100644 --- a/rdf4j/pom.xml +++ b/rdf4j/pom.xml @@ -14,8 +14,7 @@ - 1.8 - 1.8 + 8 5.0.0 diff --git a/solid/pom.xml b/solid/pom.xml index 3be4e20184b..1d8dbabcae1 100644 --- a/solid/pom.xml +++ b/solid/pom.xml @@ -14,8 +14,7 @@ - 1.8 - 1.8 + 8 @@ -29,6 +28,11 @@ inrupt-client-vocabulary ${project.version} + + org.slf4j + slf4j-api + ${slf4j.version} + @@ -85,12 +89,6 @@ ${project.version} test - - org.slf4j - slf4j-api - ${slf4j.version} - test - org.slf4j slf4j-simple diff --git a/solid/src/main/java/com/inrupt/client/solid/SolidClientException.java b/solid/src/main/java/com/inrupt/client/solid/SolidClientException.java index 8aa2a85697a..731280df350 100644 --- a/solid/src/main/java/com/inrupt/client/solid/SolidClientException.java +++ b/solid/src/main/java/com/inrupt/client/solid/SolidClientException.java @@ -97,7 +97,7 @@ public String getBody() { * @return the problem details object */ public ProblemDetails getProblemDetails() { - return SolidProblemDetails.fromErrorResponse(statusCode, headers, body.getBytes()); + return SolidProblemDetails.fromErrorResponse(uri, statusCode, headers, body.getBytes()); } /** diff --git a/solid/src/main/java/com/inrupt/client/solid/SolidProblemDetails.java b/solid/src/main/java/com/inrupt/client/solid/SolidProblemDetails.java index 91ae336fb24..9a393d403bd 100644 --- a/solid/src/main/java/com/inrupt/client/solid/SolidProblemDetails.java +++ b/solid/src/main/java/com/inrupt/client/solid/SolidProblemDetails.java @@ -27,16 +27,21 @@ import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.net.URI; import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class SolidProblemDetails implements ProblemDetails { + private static final Logger LOGGER = LoggerFactory.getLogger(SolidProblemDetails.class); private static final long serialVersionUID = -4597170432270957765L; private final URI type; private final String title; - private final String details; + private final String detail; private final int status; private final URI instance; private static JsonService jsonService; @@ -47,20 +52,20 @@ public class SolidProblemDetails implements ProblemDetails { * RFC9457. * @param type the problem type * @param title the problem title - * @param details the problem details + * @param detail the problem details * @param status the error response status code * @param instance the problem instance */ public SolidProblemDetails( final URI type, final String title, - final String details, + final String detail, final int status, final URI instance ) { this.type = type; this.title = title; - this.details = details; + this.detail = detail; this.status = status; this.instance = instance; } @@ -76,8 +81,8 @@ public String getTitle() { } @Override - public String getDetails() { - return this.details; + public String getDetail() { + return this.detail; } @Override @@ -103,9 +108,9 @@ static class Data { */ public String title; /** - * The problem details. + * The problem detail. */ - public String details; + public String detail; /** * The problem status code. */ @@ -133,51 +138,30 @@ private static JsonService getJsonService() { /** * Builds a {@link ProblemDetails} instance from an HTTP error response. + * @param uri the original URI * @param statusCode the HTTP error response status code * @param headers the HTTP error response headers * @param body the HTTP error response body * @return a {@link ProblemDetails} instance */ - public static SolidProblemDetails fromErrorResponse( - final int statusCode, - final Headers headers, - final byte[] body - ) { + static SolidProblemDetails fromErrorResponse(final URI uri, final int statusCode, final Headers headers, + final byte[] body) { final JsonService jsonService = getJsonService(); - if (jsonService == null - || (headers != null && !headers.allValues("Content-Type").contains(ProblemDetails.MIME_TYPE))) { - return new SolidProblemDetails( - URI.create(ProblemDetails.DEFAULT_TYPE), - null, - null, - statusCode, - null - ); - } - try { - final Data pdData = jsonService.fromJson( - new ByteArrayInputStream(body), - Data.class - ); - final URI type = Optional.ofNullable(pdData.type) - .orElse(URI.create(ProblemDetails.DEFAULT_TYPE)); - // JSON mappers map invalid integers to 0, which is an invalid value in our case anyway. - final int status = Optional.of(pdData.status).filter(s -> s != 0).orElse(statusCode); - return new SolidProblemDetails( - type, - pdData.title, - pdData.details, - status, - pdData.instance - ); - } catch (IOException e) { - return new SolidProblemDetails( - URI.create(ProblemDetails.DEFAULT_TYPE), - null, - null, - statusCode, - null - ); + if (jsonService != null + && (headers != null && headers.allValues("Content-Type").contains(ProblemDetails.MIME_TYPE))) { + try (final InputStream input = new ByteArrayInputStream(body)) { + final Data pdData = jsonService.fromJson(input, Data.class); + final URI type = Optional.ofNullable(pdData.type) + .map(uri::resolve) + .orElse(ProblemDetails.DEFAULT_TYPE); + final URI instance = pdData.instance != null ? uri.resolve(pdData.instance) : null; + // JSON mappers map invalid integers to 0, which is an invalid value in our case anyway. + final int status = Optional.of(pdData.status).filter(s -> s != 0).orElse(statusCode); + return new SolidProblemDetails(type, pdData.title, pdData.detail, status, instance); + } catch (IOException e) { + LOGGER.debug("Unable to parse ProblemDetails response from server", e); + } } + return new SolidProblemDetails(ProblemDetails.DEFAULT_TYPE, null, null, statusCode, null); } } diff --git a/solid/src/test/java/com/inrupt/client/solid/SolidClientTest.java b/solid/src/test/java/com/inrupt/client/solid/SolidClientTest.java index 76c409d99f4..775a86d3253 100644 --- a/solid/src/test/java/com/inrupt/client/solid/SolidClientTest.java +++ b/solid/src/test/java/com/inrupt/client/solid/SolidClientTest.java @@ -412,10 +412,10 @@ public int statusCode() { assertEquals(statusCode, exception.getStatusCode()); // The following assertions check that in absence of an RFC9457 compliant response, we properly initialize the // default values for the attached Problem Details. - assertEquals(ProblemDetails.DEFAULT_TYPE, exception.getProblemDetails().getType().toString()); + assertEquals(ProblemDetails.DEFAULT_TYPE, exception.getProblemDetails().getType()); assertEquals(statusCode, exception.getProblemDetails().getStatus()); assertNull(exception.getProblemDetails().getTitle()); - assertNull(exception.getProblemDetails().getDetails()); + assertNull(exception.getProblemDetails().getDetail()); assertNull(exception.getProblemDetails().getInstance()); } @@ -487,7 +487,7 @@ public int statusCode() { assertEquals(problemDetails.getType(), exception.getProblemDetails().getType()); assertEquals(problemDetails.getTitle(), exception.getProblemDetails().getTitle()); assertEquals(problemDetails.getStatus(), exception.getProblemDetails().getStatus()); - assertEquals(problemDetails.getDetails(), exception.getProblemDetails().getDetails()); + assertEquals(problemDetails.getDetail(), exception.getProblemDetails().getDetail()); assertEquals(problemDetails.getInstance(), exception.getProblemDetails().getInstance()); } @@ -606,10 +606,10 @@ public int statusCode() { ); assertEquals(statusCode, exception.getStatusCode()); // On malformed response, the ProblemDetails should fall back to defaults. - assertEquals(ProblemDetails.DEFAULT_TYPE, exception.getProblemDetails().getType().toString()); + assertEquals(ProblemDetails.DEFAULT_TYPE, exception.getProblemDetails().getType()); assertNull(exception.getProblemDetails().getTitle()); assertEquals(statusCode, exception.getProblemDetails().getStatus()); - assertNull(exception.getProblemDetails().getDetails()); + assertNull(exception.getProblemDetails().getDetail()); assertNull(exception.getProblemDetails().getInstance()); } @@ -653,10 +653,10 @@ public int statusCode() { ); assertEquals(statusCode, exception.getStatusCode()); // On malformed response, the ProblemDetails should fall back to defaults. - assertEquals(ProblemDetails.DEFAULT_TYPE, exception.getProblemDetails().getType().toString()); + assertEquals(ProblemDetails.DEFAULT_TYPE, exception.getProblemDetails().getType()); assertNull(exception.getProblemDetails().getTitle()); assertEquals(statusCode, exception.getProblemDetails().getStatus()); - assertNull(exception.getProblemDetails().getDetails()); + assertNull(exception.getProblemDetails().getDetail()); assertNull(exception.getProblemDetails().getInstance()); } } diff --git a/solid/src/test/java/com/inrupt/client/solid/SolidProblemDetailsTest.java b/solid/src/test/java/com/inrupt/client/solid/SolidProblemDetailsTest.java index 6baaaf2ac2d..9502088b2f7 100644 --- a/solid/src/test/java/com/inrupt/client/solid/SolidProblemDetailsTest.java +++ b/solid/src/test/java/com/inrupt/client/solid/SolidProblemDetailsTest.java @@ -26,10 +26,12 @@ import com.inrupt.client.Headers; import com.inrupt.client.ProblemDetails; +import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -37,6 +39,8 @@ // Ideally, this class should be in the api module, but it creates // a circular dependency with the JSON module implementation. class SolidProblemDetailsTest { + private static final URI POD = URI.create("https://storage.test/pod/"); + Headers mockProblemDetailsHeader() { final List headerValues = new ArrayList<>(); headerValues.add("application/problem+json"); @@ -49,47 +53,75 @@ Headers mockProblemDetailsHeader() { void testEmptyProblemDetails() { final int statusCode = 400; final ProblemDetails pd = SolidProblemDetails.fromErrorResponse( + POD, statusCode, mockProblemDetailsHeader(), "{}".getBytes() ); - assertEquals(ProblemDetails.DEFAULT_TYPE, pd.getType().toString()); + assertEquals(ProblemDetails.DEFAULT_TYPE, pd.getType()); assertEquals(statusCode, pd.getStatus()); assertNull(pd.getTitle()); - assertNull(pd.getDetails()); + assertNull(pd.getDetail()); assertNull(pd.getInstance()); } + + @Test + void testRelativeUriProblemDetails() { + final int statusCode = 400; + final UUID instance = UUID.randomUUID(); + final ProblemDetails pd = SolidProblemDetails.fromErrorResponse( + POD, + statusCode, + mockProblemDetailsHeader(), + ("{" + + "\"title\":\"Some title\"," + + "\"status\":400," + + "\"detail\":\"Some details\"," + + "\"instance\":\"Instance" + instance + "\"," + + "\"type\":\"SomeType\"" + + "}").getBytes() + ); + assertEquals(URI.create("https://storage.test/pod/SomeType"), pd.getType()); + assertEquals(statusCode, pd.getStatus()); + Assertions.assertEquals("Some title", pd.getTitle()); + assertEquals("Some details", pd.getDetail()); + assertEquals("https://storage.test/pod/Instance" + instance, pd.getInstance().toString()); + } + @Test void testCompleteProblemDetails() { final int statusCode = 400; + final UUID instance = UUID.randomUUID(); final ProblemDetails pd = SolidProblemDetails.fromErrorResponse( + POD, statusCode, mockProblemDetailsHeader(), ("{" + "\"title\":\"Some title\"," + "\"status\":400," + - "\"details\":\"Some details\"," + - "\"instance\":\"https://example.org/instance\"," + + "\"detail\":\"Some details\"," + + "\"instance\":\"urn:uuid:" + instance + "\"," + "\"type\":\"https://example.org/type\"" + "}").getBytes() ); assertEquals("https://example.org/type", pd.getType().toString()); assertEquals(statusCode, pd.getStatus()); Assertions.assertEquals("Some title", pd.getTitle()); - assertEquals("Some details", pd.getDetails()); - assertEquals("https://example.org/instance", pd.getInstance().toString()); + assertEquals("Some details", pd.getDetail()); + assertEquals("urn:uuid:" + instance, pd.getInstance().toString()); } @Test void testIgnoreUnknownProblemDetails() { final int statusCode = 400; final ProblemDetails pd = SolidProblemDetails.fromErrorResponse( + POD, statusCode, mockProblemDetailsHeader(), ("{" + "\"title\":\"Some title\"," + "\"status\":400," + - "\"details\":\"Some details\"," + + "\"detail\":\"Some details\"," + "\"instance\":\"https://example.org/instance\"," + "\"type\":\"https://example.org/type\"," + "\"unknown\":\"Some unknown property\"" + @@ -98,7 +130,7 @@ void testIgnoreUnknownProblemDetails() { assertEquals("https://example.org/type", pd.getType().toString()); assertEquals(statusCode, pd.getStatus()); Assertions.assertEquals("Some title", pd.getTitle()); - assertEquals("Some details", pd.getDetails()); + assertEquals("Some details", pd.getDetail()); assertEquals("https://example.org/instance", pd.getInstance().toString()); } @@ -106,6 +138,7 @@ void testIgnoreUnknownProblemDetails() { void testInvalidStatusProblemDetails() { final int statusCode = 400; final ProblemDetails pd = SolidProblemDetails.fromErrorResponse( + POD, statusCode, mockProblemDetailsHeader(), ("{" + @@ -119,6 +152,7 @@ void testInvalidStatusProblemDetails() { void testMismatchingStatusProblemDetails() { final int statusCode = 400; final ProblemDetails pd = SolidProblemDetails.fromErrorResponse( + POD, statusCode, mockProblemDetailsHeader(), ("{" + @@ -131,18 +165,20 @@ void testMismatchingStatusProblemDetails() { @Test void testInvalidTypeProblemDetails() { final ProblemDetails pd = SolidProblemDetails.fromErrorResponse( + POD, 400, mockProblemDetailsHeader(), ("{" + "\"type\":\"Some invalid type\"" + "}").getBytes() ); - assertEquals(ProblemDetails.DEFAULT_TYPE, pd.getType().toString()); + assertEquals(ProblemDetails.DEFAULT_TYPE, pd.getType()); } @Test void testInvalidInstanceProblemDetails() { final ProblemDetails pd = SolidProblemDetails.fromErrorResponse( + POD, 400, mockProblemDetailsHeader(), ("{" + @@ -156,14 +192,15 @@ void testInvalidInstanceProblemDetails() { void testInvalidProblemDetails() { final int statusCode = 400; final ProblemDetails pd = SolidProblemDetails.fromErrorResponse( + POD, statusCode, mockProblemDetailsHeader(), "Not valid application/problem+json".getBytes() ); - assertEquals(ProblemDetails.DEFAULT_TYPE, pd.getType().toString()); + assertEquals(ProblemDetails.DEFAULT_TYPE, pd.getType()); assertEquals(statusCode, pd.getStatus()); assertNull(pd.getTitle()); - assertNull(pd.getDetails()); + assertNull(pd.getDetail()); assertNull(pd.getInstance()); } } diff --git a/spring/pom.xml b/spring/pom.xml index 270343c7904..8957a915542 100644 --- a/spring/pom.xml +++ b/spring/pom.xml @@ -13,11 +13,6 @@ Integration utilities for Spring support. - - 11 - 11 - - diff --git a/uma/pom.xml b/uma/pom.xml index e4092b069f9..f532ef2955d 100644 --- a/uma/pom.xml +++ b/uma/pom.xml @@ -14,8 +14,7 @@ - 1.8 - 1.8 + 8