diff --git a/integration/base/src/main/java/com/inrupt/client/integration/base/AccessGrantScenarios.java b/integration/base/src/main/java/com/inrupt/client/integration/base/AccessGrantScenarios.java index 0b7c4b84992..4f580f62da3 100644 --- a/integration/base/src/main/java/com/inrupt/client/integration/base/AccessGrantScenarios.java +++ b/integration/base/src/main/java/com/inrupt/client/integration/base/AccessGrantScenarios.java @@ -36,10 +36,7 @@ import com.inrupt.client.auth.Session; import com.inrupt.client.openid.OpenIdException; import com.inrupt.client.openid.OpenIdSession; -import com.inrupt.client.solid.SolidClientException; -import com.inrupt.client.solid.SolidNonRDFSource; -import com.inrupt.client.solid.SolidRDFSource; -import com.inrupt.client.solid.SolidSyncClient; +import com.inrupt.client.solid.*; import com.inrupt.client.spi.RDFFactory; import com.inrupt.client.util.URIBuilder; import com.inrupt.client.vocabulary.ACL; @@ -240,7 +237,7 @@ void accessGrantIssuanceLifecycleTest(final Session session) { //unauthorized request test final SolidSyncClient client = SolidSyncClient.getClientBuilder().build(); - final SolidClientException err = assertThrows(SolidClientException.class, + final var err = assertThrows(UnauthorizedException.class, () -> client.read(sharedTextFileURI, SolidNonRDFSource.class)); assertEquals(Utils.UNAUTHORIZED, err.getStatusCode()); final Request reqRead = diff --git a/integration/base/src/main/java/com/inrupt/client/integration/base/AuthenticationScenarios.java b/integration/base/src/main/java/com/inrupt/client/integration/base/AuthenticationScenarios.java index 96b3d6bf34d..b6c15fc7a66 100644 --- a/integration/base/src/main/java/com/inrupt/client/integration/base/AuthenticationScenarios.java +++ b/integration/base/src/main/java/com/inrupt/client/integration/base/AuthenticationScenarios.java @@ -33,6 +33,7 @@ import com.inrupt.client.solid.SolidClientException; import com.inrupt.client.solid.SolidRDFSource; import com.inrupt.client.solid.SolidSyncClient; +import com.inrupt.client.solid.UnauthorizedException; import com.inrupt.client.util.URIBuilder; import com.inrupt.client.webid.WebIdProfile; @@ -190,7 +191,7 @@ void fetchPrivateResourceUnauthenticatedTest(final Session session) { assertDoesNotThrow(() -> authClient.create(testResource)); final SolidSyncClient client = SolidSyncClient.getClient(); - final SolidClientException err = assertThrows(SolidClientException.class, + final var err = assertThrows(UnauthorizedException.class, () -> client.read(privateResourceURL, SolidRDFSource.class)); assertEquals(Utils.UNAUTHORIZED, err.getStatusCode()); @@ -242,7 +243,7 @@ void fetchPrivateResourceUnauthAuthTest(final Session session) { assertDoesNotThrow(() -> authClient.create(testResource)); final SolidSyncClient client = SolidSyncClient.getClient(); - final SolidClientException err = assertThrows(SolidClientException.class, + final var err = assertThrows(UnauthorizedException.class, () -> client.read(privateResourceURL, SolidRDFSource.class)); assertEquals(Utils.UNAUTHORIZED, err.getStatusCode()); @@ -278,7 +279,7 @@ void multiSessionTest(final Session session) { assertDoesNotThrow(() -> authClient2.read(privateResourceURL, SolidRDFSource.class)); final SolidSyncClient client = SolidSyncClient.getClient(); - final SolidClientException err = assertThrows(SolidClientException.class, + final var err = assertThrows(UnauthorizedException.class, () -> client.read(privateResourceURL, SolidRDFSource.class)); assertEquals(Utils.UNAUTHORIZED, err.getStatusCode()); diff --git a/integration/base/src/main/java/com/inrupt/client/integration/base/DomainModulesResource.java b/integration/base/src/main/java/com/inrupt/client/integration/base/DomainModulesResource.java index 2606409dbf1..fc7854c4ab1 100644 --- a/integration/base/src/main/java/com/inrupt/client/integration/base/DomainModulesResource.java +++ b/integration/base/src/main/java/com/inrupt/client/integration/base/DomainModulesResource.java @@ -26,11 +26,7 @@ import com.inrupt.client.Request; import com.inrupt.client.Response; import com.inrupt.client.auth.Session; -import com.inrupt.client.solid.SolidClientException; -import com.inrupt.client.solid.SolidContainer; -import com.inrupt.client.solid.SolidRDFSource; -import com.inrupt.client.solid.SolidResourceHandlers; -import com.inrupt.client.solid.SolidSyncClient; +import com.inrupt.client.solid.*; import com.inrupt.client.spi.RDFFactory; import com.inrupt.client.util.URIBuilder; import com.inrupt.client.vocabulary.PIM; @@ -261,7 +257,7 @@ void findStorageTest() { } final var missingWebId = URIBuilder.newBuilder(URI.create(webidUrl)).path(UUID.randomUUID().toString()).build(); - final var err = assertThrows(SolidClientException.class, () -> client.read(missingWebId, WebIdProfile.class)); + final var err = assertThrows(NotFoundException.class, () -> client.read(missingWebId, WebIdProfile.class)); assertEquals(404, err.getStatusCode()); assertEquals(missingWebId, err.getUri()); } diff --git a/solid/src/main/java/com/inrupt/client/solid/BadRequestException.java b/solid/src/main/java/com/inrupt/client/solid/BadRequestException.java new file mode 100644 index 00000000000..4b11347dbb7 --- /dev/null +++ b/solid/src/main/java/com/inrupt/client/solid/BadRequestException.java @@ -0,0 +1,52 @@ +/* + * Copyright 2023 Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.client.solid; + +import com.inrupt.client.Headers; + +import java.net.URI; + +/** + * A runtime exception that represents an HTTP bad request (400) response. + * + * @see RFC 9110 (15.5.1.) 400 Bad Request + */ +public class BadRequestException extends SolidClientException { + private static final long serialVersionUID = -3379457428921025570L; + + public static final int STATUS_CODE = 400; + + /** + * Create a BadRequestException exception. + * + * @param message the message + * @param uri the uri + * @param headers the response headers + * @param body the body + */ + public BadRequestException( + final String message, + final URI uri, + final Headers headers, + final String body) { + super(message, uri, STATUS_CODE, headers, body); + } +} diff --git a/solid/src/main/java/com/inrupt/client/solid/ConflictException.java b/solid/src/main/java/com/inrupt/client/solid/ConflictException.java new file mode 100644 index 00000000000..2cf1b689789 --- /dev/null +++ b/solid/src/main/java/com/inrupt/client/solid/ConflictException.java @@ -0,0 +1,52 @@ +/* + * Copyright 2023 Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.client.solid; + +import com.inrupt.client.Headers; + +import java.net.URI; + +/** + * A runtime exception that represents an HTTP conflict (409) response.. + * + * @see RFC 9110 (15.5.10.) 409 Conflict + */ +public class ConflictException extends SolidClientException { + private static final long serialVersionUID = -203198307847520748L; + + public static final int STATUS_CODE = 409; + + /** + * Create a ConflictException exception. + * + * @param message the message + * @param uri the uri + * @param headers the response headers + * @param body the body + */ + public ConflictException( + final String message, + final URI uri, + final Headers headers, + final String body) { + super(message, uri, STATUS_CODE, headers, body); + } +} diff --git a/solid/src/main/java/com/inrupt/client/solid/ForbiddenException.java b/solid/src/main/java/com/inrupt/client/solid/ForbiddenException.java new file mode 100644 index 00000000000..bc3e787c3f6 --- /dev/null +++ b/solid/src/main/java/com/inrupt/client/solid/ForbiddenException.java @@ -0,0 +1,52 @@ +/* + * Copyright 2023 Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.client.solid; + +import com.inrupt.client.Headers; + +import java.net.URI; + +/** + * A runtime exception that represents an HTTP forbidden (403) response. + * + * @see RFC 9110 (15.5.4.) 403 Forbidden + */ +public class ForbiddenException extends SolidClientException { + private static final long serialVersionUID = 3299286274724874244L; + + public static final int STATUS_CODE = 403; + + /** + * Create a ForbiddenException exception. + * + * @param message the message + * @param uri the uri + * @param headers the response headers + * @param body the body + */ + public ForbiddenException( + final String message, + final URI uri, + final Headers headers, + final String body) { + super(message, uri, STATUS_CODE, headers, body); + } +} diff --git a/solid/src/main/java/com/inrupt/client/solid/GoneException.java b/solid/src/main/java/com/inrupt/client/solid/GoneException.java new file mode 100644 index 00000000000..a2a7b75f682 --- /dev/null +++ b/solid/src/main/java/com/inrupt/client/solid/GoneException.java @@ -0,0 +1,52 @@ +/* + * Copyright 2023 Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.client.solid; + +import com.inrupt.client.Headers; + +import java.net.URI; + +/** + * A runtime exception that represents an HTTP gone (410) response. + * + * @see RFC 9110 (15.5.11.) 410 Gone + */ +public class GoneException extends SolidClientException { + private static final long serialVersionUID = -6892345582498100242L; + + public static final int STATUS_CODE = 410; + + /** + * Create a GoneException exception. + * + * @param message the message + * @param uri the uri + * @param headers the response headers + * @param body the body + */ + public GoneException( + final String message, + final URI uri, + final Headers headers, + final String body) { + super(message, uri, STATUS_CODE, headers, body); + } +} diff --git a/solid/src/main/java/com/inrupt/client/solid/InternalServerErrorException.java b/solid/src/main/java/com/inrupt/client/solid/InternalServerErrorException.java new file mode 100644 index 00000000000..55805b0af2a --- /dev/null +++ b/solid/src/main/java/com/inrupt/client/solid/InternalServerErrorException.java @@ -0,0 +1,52 @@ +/* + * Copyright 2023 Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.client.solid; + +import com.inrupt.client.Headers; + +import java.net.URI; + +/** + * A runtime exception that represents an HTTP internal server error (500) response. + * + * @see RFC 9110 (15.6.1.) 500 Internal Server Error + */ +public class InternalServerErrorException extends SolidClientException { + private static final long serialVersionUID = -6672490715281719330L; + + public static final int STATUS_CODE = 500; + + /** + * Create an InternalServerErrorException exception. + * + * @param message the message + * @param uri the uri + * @param headers the response headers + * @param body the body + */ + public InternalServerErrorException( + final String message, + final URI uri, + final Headers headers, + final String body) { + super(message, uri, STATUS_CODE, headers, body); + } +} diff --git a/solid/src/main/java/com/inrupt/client/solid/MethodNotAllowedException.java b/solid/src/main/java/com/inrupt/client/solid/MethodNotAllowedException.java new file mode 100644 index 00000000000..de8e6d1abd6 --- /dev/null +++ b/solid/src/main/java/com/inrupt/client/solid/MethodNotAllowedException.java @@ -0,0 +1,52 @@ +/* + * Copyright 2023 Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.client.solid; + +import com.inrupt.client.Headers; + +import java.net.URI; + +/** + * A runtime exception that represents an HTTP method not allowed (405) response. + * + * @see RFC 9110 (15.5.6.) 405 Method Not Allowed + */ +public class MethodNotAllowedException extends SolidClientException { + private static final long serialVersionUID = -9125437562813923030L; + + public static final int STATUS_CODE = 405; + + /** + * Create a MethodNotAllowedException exception. + * + * @param message the message + * @param uri the uri + * @param headers the response headers + * @param body the body + */ + public MethodNotAllowedException( + final String message, + final URI uri, + final Headers headers, + final String body) { + super(message, uri, STATUS_CODE, headers, body); + } +} diff --git a/solid/src/main/java/com/inrupt/client/solid/NotAcceptableException.java b/solid/src/main/java/com/inrupt/client/solid/NotAcceptableException.java new file mode 100644 index 00000000000..afba65762fc --- /dev/null +++ b/solid/src/main/java/com/inrupt/client/solid/NotAcceptableException.java @@ -0,0 +1,52 @@ +/* + * Copyright 2023 Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.client.solid; + +import com.inrupt.client.Headers; + +import java.net.URI; + +/** + * A runtime exception that represents an HTTP not acceptable (406) response. + * + * @see RFC 9110 (15.5.7.) 406 Not Acceptable + */ +public class NotAcceptableException extends SolidClientException { + private static final long serialVersionUID = 6594993822477388733L; + + public static final int STATUS_CODE = 406; + + /** + * Create a NotAcceptableException exception. + * + * @param message the message + * @param uri the uri + * @param headers the response headers + * @param body the body + */ + public NotAcceptableException( + final String message, + final URI uri, + final Headers headers, + final String body) { + super(message, uri, STATUS_CODE, headers, body); + } +} diff --git a/solid/src/main/java/com/inrupt/client/solid/NotFoundException.java b/solid/src/main/java/com/inrupt/client/solid/NotFoundException.java new file mode 100644 index 00000000000..8ad955e226d --- /dev/null +++ b/solid/src/main/java/com/inrupt/client/solid/NotFoundException.java @@ -0,0 +1,52 @@ +/* + * Copyright 2023 Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.client.solid; + +import com.inrupt.client.Headers; + +import java.net.URI; + +/** + * A runtime exception that represents an HTTP not found (404) response. + * + * @see RFC 9110 (15.5.5.) 404 Not Found + */ +public class NotFoundException extends SolidClientException { + private static final long serialVersionUID = -2256628528500739683L; + + public static final int STATUS_CODE = 404; + + /** + * Create a NotFoundException exception. + * + * @param message the message + * @param uri the uri + * @param headers the response headers + * @param body the body + */ + public NotFoundException( + final String message, + final URI uri, + final Headers headers, + final String body) { + super(message, uri, STATUS_CODE, headers, body); + } +} diff --git a/solid/src/main/java/com/inrupt/client/solid/PreconditionFailedException.java b/solid/src/main/java/com/inrupt/client/solid/PreconditionFailedException.java new file mode 100644 index 00000000000..96650853456 --- /dev/null +++ b/solid/src/main/java/com/inrupt/client/solid/PreconditionFailedException.java @@ -0,0 +1,52 @@ +/* + * Copyright 2023 Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.client.solid; + +import com.inrupt.client.Headers; + +import java.net.URI; + +/** + * A runtime exception that represents an HTTP precondition failed (412) response. + * + * @see RFC 9110 (15.5.13.) 412 Precondition Failed + */ +public class PreconditionFailedException extends SolidClientException { + private static final long serialVersionUID = 4205761003697773528L; + + public static final int STATUS_CODE = 412; + + /** + * Create a PreconditionFailedException exception. + * + * @param message the message + * @param uri the uri + * @param headers the response headers + * @param body the body + */ + public PreconditionFailedException( + final String message, + final URI uri, + final Headers headers, + final String body) { + super(message, uri, STATUS_CODE, headers, body); + } +} diff --git a/solid/src/main/java/com/inrupt/client/solid/SolidClient.java b/solid/src/main/java/com/inrupt/client/solid/SolidClient.java index 97eda0906bf..88ce28493f0 100644 --- a/solid/src/main/java/com/inrupt/client/solid/SolidClient.java +++ b/solid/src/main/java/com/inrupt/client/solid/SolidClient.java @@ -133,7 +133,7 @@ public CompletionStage read(final URI identifier, final return client.send(builder.build(), Response.BodyHandlers.ofByteArray()) .thenApply(response -> { if (response.statusCode() >= ERROR_STATUS) { - throw new SolidClientException("Unable to read resource at " + identifier, identifier, + throw SolidClientException.handle("Unable to read resource at " + identifier, identifier, response.statusCode(), response.headers(), new String(response.body())); } else { final String contentType = response.headers().firstValue(CONTENT_TYPE) @@ -285,7 +285,7 @@ public CompletionStage delete(final T resource, final if (isSuccess(res.statusCode())) { return null; } else { - throw new SolidClientException("Unable to delete resource", resource.getIdentifier(), + throw SolidClientException.handle("Unable to delete resource", resource.getIdentifier(), res.statusCode(), res.headers(), new String(res.body(), UTF_8)); } }); @@ -369,7 +369,7 @@ Function, CompletionStage> handleRespon final Headers headers, final String message) { return res -> { if (!isSuccess(res.statusCode())) { - throw new SolidClientException(message, resource.getIdentifier(), + throw SolidClientException.handle(message, resource.getIdentifier(), res.statusCode(), res.headers(), new String(res.body(), UTF_8)); } 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 31e91925e29..a3887e6759e 100644 --- a/solid/src/main/java/com/inrupt/client/solid/SolidClientException.java +++ b/solid/src/main/java/com/inrupt/client/solid/SolidClientException.java @@ -90,5 +90,41 @@ public Headers getHeaders() { public String getBody() { return body; } + + public static SolidClientException handle( + final String message, + final URI uri, + final int statusCode, + final Headers headers, + final String body) { + switch (statusCode) { + case BadRequestException.STATUS_CODE: + return new BadRequestException(message, uri, headers, body); + case UnauthorizedException.STATUS_CODE: + return new UnauthorizedException(message, uri, headers, body); + case ForbiddenException.STATUS_CODE: + return new ForbiddenException(message, uri, headers, body); + case NotFoundException.STATUS_CODE: + return new NotFoundException(message, uri, headers, body); + case MethodNotAllowedException.STATUS_CODE: + return new MethodNotAllowedException(message, uri, headers, body); + case NotAcceptableException.STATUS_CODE: + return new NotAcceptableException(message, uri, headers, body); + case ConflictException.STATUS_CODE: + return new ConflictException(message, uri, headers, body); + case GoneException.STATUS_CODE: + return new GoneException(message, uri, headers, body); + case PreconditionFailedException.STATUS_CODE: + return new PreconditionFailedException(message, uri, headers, body); + case UnsupportedMediaTypeException.STATUS_CODE: + return new UnsupportedMediaTypeException(message, uri, headers, body); + case TooManyRequestsException.STATUS_CODE: + return new TooManyRequestsException(message, uri, headers, body); + case InternalServerErrorException.STATUS_CODE: + return new InternalServerErrorException(message, uri, headers, body); + default: + return new SolidClientException(message, uri, statusCode, headers, body); + } + } } diff --git a/solid/src/main/java/com/inrupt/client/solid/TooManyRequestsException.java b/solid/src/main/java/com/inrupt/client/solid/TooManyRequestsException.java new file mode 100644 index 00000000000..de1e5c07215 --- /dev/null +++ b/solid/src/main/java/com/inrupt/client/solid/TooManyRequestsException.java @@ -0,0 +1,52 @@ +/* + * Copyright 2023 Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.client.solid; + +import com.inrupt.client.Headers; + +import java.net.URI; + +/** + * A runtime exception that represents an HTTP too many requests (429) response. + * + * @see RFC 6585 (4.) 429 Too Many Requests + */ +public class TooManyRequestsException extends SolidClientException { + private static final long serialVersionUID = -1798491190232642824L; + + public static final int STATUS_CODE = 429; + + /** + * Create a TooManyRequestsException exception. + * + * @param message the message + * @param uri the uri + * @param headers the response headers + * @param body the body + */ + public TooManyRequestsException( + final String message, + final URI uri, + final Headers headers, + final String body) { + super(message, uri, STATUS_CODE, headers, body); + } +} diff --git a/solid/src/main/java/com/inrupt/client/solid/UnauthorizedException.java b/solid/src/main/java/com/inrupt/client/solid/UnauthorizedException.java new file mode 100644 index 00000000000..338df0f0386 --- /dev/null +++ b/solid/src/main/java/com/inrupt/client/solid/UnauthorizedException.java @@ -0,0 +1,52 @@ +/* + * Copyright 2023 Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.client.solid; + +import com.inrupt.client.Headers; + +import java.net.URI; + +/** + * A runtime exception that represents an HTTP unauthorized (401) response. + * + * @see RFC 9110 (15.5.2.) 401 Unauthorized + */ +public class UnauthorizedException extends SolidClientException { + private static final long serialVersionUID = -3219668517323678497L; + + public static final int STATUS_CODE = 401; + + /** + * Create an UnauthorizedException exception. + * + * @param message the message + * @param uri the uri + * @param headers the response headers + * @param body the body + */ + public UnauthorizedException( + final String message, + final URI uri, + final Headers headers, + final String body) { + super(message, uri, STATUS_CODE, headers, body); + } +} diff --git a/solid/src/main/java/com/inrupt/client/solid/UnsupportedMediaTypeException.java b/solid/src/main/java/com/inrupt/client/solid/UnsupportedMediaTypeException.java new file mode 100644 index 00000000000..6500c9fcea9 --- /dev/null +++ b/solid/src/main/java/com/inrupt/client/solid/UnsupportedMediaTypeException.java @@ -0,0 +1,52 @@ +/* + * Copyright 2023 Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.client.solid; + +import com.inrupt.client.Headers; + +import java.net.URI; + +/** + * A runtime exception that represents an HTTP unsupported media type (415) response. + * + * @see RFC 9110 (15.5.16.) 415 Unsupported Media Type + */ +public class UnsupportedMediaTypeException extends SolidClientException { + private static final long serialVersionUID = 1312856145838280673L; + + public static final int STATUS_CODE = 415; + + /** + * Create an UnsupportedMediaTypeException exception. + * + * @param message the message + * @param uri the uri + * @param headers the response headers + * @param body the body + */ + public UnsupportedMediaTypeException( + final String message, + final URI uri, + final Headers headers, + final String body) { + super(message, uri, STATUS_CODE, headers, body); + } +} 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 e1a5dd8ccdc..09aad4b244a 100644 --- a/solid/src/test/java/com/inrupt/client/solid/SolidClientTest.java +++ b/solid/src/test/java/com/inrupt/client/solid/SolidClientTest.java @@ -22,17 +22,15 @@ import static org.junit.jupiter.api.Assertions.*; +import com.inrupt.client.ClientProvider; import com.inrupt.client.Headers; +import com.inrupt.client.Response; import com.inrupt.client.auth.Session; import com.inrupt.client.spi.RDFFactory; import java.io.IOException; import java.net.URI; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.stream.Stream; @@ -243,7 +241,10 @@ void testGetRecipeType() { @ParameterizedTest @MethodSource - void testExceptionalResources(final URI uri, final int expectedStatusCode) { + void testExceptionalResources( + final URI uri, + final int expectedStatusCode, + final Class clazz) { final CompletableFuture future = client.read(uri, Recipe.class) @@ -251,6 +252,7 @@ void testExceptionalResources(final URI uri, final int expectedStatusCode) { final CompletionException err = assertThrows(CompletionException.class, () -> future.join()); assertTrue(err.getCause() instanceof SolidClientException); + assertInstanceOf(clazz, err.getCause()); final SolidClientException ex = (SolidClientException) err.getCause(); assertEquals(expectedStatusCode, ex.getStatusCode()); assertEquals(uri, ex.getUri()); @@ -261,10 +263,69 @@ void testExceptionalResources(final URI uri, final int expectedStatusCode) { private static Stream testExceptionalResources() { return Stream.of( Arguments.of( - URI.create(config.get("solid_resource_uri") + "/unauthorized"), 401), + URI.create(config.get("solid_resource_uri") + "/unauthorized"), 401, + UnauthorizedException.class), Arguments.of( - URI.create(config.get("solid_resource_uri") + "/forbidden"), 403), + URI.create(config.get("solid_resource_uri") + "/forbidden"), 403, + ForbiddenException.class), Arguments.of( - URI.create(config.get("solid_resource_uri") + "/missing"), 404)); + URI.create(config.get("solid_resource_uri") + "/missing"), 404, + NotFoundException.class)); + } + + @ParameterizedTest + @MethodSource + void testSpecialisedExceptions( + final Class clazz, + final int statusCode + ) { + final Headers headers = Headers.of(Collections.singletonMap("x-key", Arrays.asList("value"))); + final SolidClient solidClient = new SolidClient(ClientProvider.getClient(), headers, false); + final SolidContainer resource = new SolidContainer(URI.create("http://example.com"), null, null); + + final SolidClientException exception = assertThrows( + clazz, + () -> solidClient.handleResponse(resource, headers, "message") + .apply(new Response() { + @Override + public byte[] body() { + return new byte[0]; + } + + @Override + public Headers headers() { + return null; + } + + @Override + public URI uri() { + return null; + } + + @Override + public int statusCode() { + return statusCode; + } + }) + ); + assertEquals(statusCode, exception.getStatusCode()); + } + + private static Stream testSpecialisedExceptions() { + return Stream.of( + Arguments.of(BadRequestException.class, 400), + Arguments.of(UnauthorizedException.class, 401), + Arguments.of(ForbiddenException.class, 403), + Arguments.of(NotFoundException.class, 404), + Arguments.of(MethodNotAllowedException.class, 405), + Arguments.of(NotAcceptableException.class, 406), + Arguments.of(ConflictException.class, 409), + Arguments.of(GoneException.class, 410), + Arguments.of(PreconditionFailedException.class, 412), + Arguments.of(UnsupportedMediaTypeException.class, 415), + Arguments.of(TooManyRequestsException.class, 429), + Arguments.of(InternalServerErrorException.class, 500), + Arguments.of(SolidClientException.class, 418) + ); } } diff --git a/solid/src/test/java/com/inrupt/client/solid/SolidSyncClientTest.java b/solid/src/test/java/com/inrupt/client/solid/SolidSyncClientTest.java index a5e2dfd350a..53c2aeba1a9 100644 --- a/solid/src/test/java/com/inrupt/client/solid/SolidSyncClientTest.java +++ b/solid/src/test/java/com/inrupt/client/solid/SolidSyncClientTest.java @@ -179,8 +179,11 @@ void testGetRecipeType() { @ParameterizedTest @MethodSource - void testExceptionalResources(final URI uri, final int expectedStatusCode) { - final SolidClientException err = assertThrows(SolidClientException.class, () -> client.read(uri, Recipe.class)); + void testExceptionalResources( + final URI uri, + final int expectedStatusCode, + final Class clazz) { + final SolidClientException err = assertThrows(clazz, () -> client.read(uri, Recipe.class)); assertEquals(expectedStatusCode, err.getStatusCode()); assertEquals(uri, err.getUri()); @@ -191,10 +194,13 @@ void testExceptionalResources(final URI uri, final int expectedStatusCode) { private static Stream testExceptionalResources() { return Stream.of( Arguments.of( - URI.create(config.get("solid_resource_uri") + "/unauthorized"), 401), + URI.create(config.get("solid_resource_uri") + "/unauthorized"), 401, + UnauthorizedException.class), Arguments.of( - URI.create(config.get("solid_resource_uri") + "/forbidden"), 403), + URI.create(config.get("solid_resource_uri") + "/forbidden"), 403, + ForbiddenException.class), Arguments.of( - URI.create(config.get("solid_resource_uri") + "/missing"), 404)); + URI.create(config.get("solid_resource_uri") + "/missing"), 404, + NotFoundException.class)); } }