Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions components/abstractions/spotBugsExcludeFilter.xml
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,10 @@ xsi:schemaLocation="https://github.com/spotbugs/filter/3.0.0 https://raw.githubu
<Class name="com.microsoft.kiota.serialization.SerializationWriterProxyFactory" />
</Or>
</Match>
<!-- These calls deliberately violate nullability to verify argument validation. -->
<Match>
<Bug pattern="NP_NONNULL_PARAM_VIOLATION" />
<Class name="com.microsoft.kiota.serialization.FactoryRegistryExceptionTest" />
<Method name="~lambda\$invalidArgumentsKeepTheirValidationExceptions\$.*" />
</Match>
</FindBugsFilter>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.microsoft.kiota;

import jakarta.annotation.Nonnull;

/** An error in client-side request or response processing, rather than an API error response. */
public class ClientException extends RuntimeException {
private static final long serialVersionUID = 1L;

/** {@inheritDoc} */
public ClientException() {
super();
}

/** {@inheritDoc} */
public ClientException(@Nonnull final String message) {
super(message);
}

/** {@inheritDoc} */
public ClientException(@Nonnull final String message, @Nonnull final Throwable cause) {
super(message, cause);
}

/** {@inheritDoc} */
public ClientException(@Nonnull final Throwable cause) {
super(cause);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.microsoft.kiota.serialization;

import com.microsoft.kiota.ClientException;

import jakarta.annotation.Nonnull;

import java.io.InputStream;
Expand Down Expand Up @@ -32,6 +34,9 @@ public ParseNodeFactoryRegistry() {
private static final Pattern contentTypeVendorCleanupPattern =
Pattern.compile("[^/]+\\+", Pattern.CASE_INSENSITIVE);

/** {@inheritDoc}
* @throws ClientException when no factory is registered for the content type
*/
@Override
@Nonnull public ParseNode getParseNode(
@Nonnull final String contentType, @Nonnull final InputStream rawResponse) {
Expand All @@ -53,7 +58,7 @@ public ParseNodeFactoryRegistry() {
.get(cleanedContentType)
.getParseNode(cleanedContentType, rawResponse);
}
throw new RuntimeException(
throw new ClientException(
"Content type " + cleanedContentType + " does not have a factory to be parsed");
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.microsoft.kiota.serialization;

import com.microsoft.kiota.ClientException;
import com.microsoft.kiota.store.BackingStoreSerializationWriterProxyFactory;

import jakarta.annotation.Nonnull;
Expand Down Expand Up @@ -43,7 +44,7 @@ public SerializationWriterFactoryRegistry() {
* @param contentType
* @param serializeOnlyChangedValues control backing store functionality
* @return the serialization writer
* @throws RuntimeException when no factory is found for content type
* @throws ClientException when no factory is found for content type
*/
@Nonnull public SerializationWriter getSerializationWriter(
@Nonnull final String contentType, final boolean serializeOnlyChangedValues) {
Expand All @@ -59,7 +60,7 @@ public SerializationWriterFactoryRegistry() {
getSerializationWriterFactory(
getCleanedVendorSpecificContentType(cleanedContentType));
if (factory == null) {
throw new RuntimeException(
throw new ClientException(
"Content type "
+ contentType
+ " does not have a factory to be serialized");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.microsoft.kiota.serialization;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

import com.microsoft.kiota.ClientException;
import com.microsoft.kiota.Compatibility;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;

class FactoryRegistryExceptionTest {
@Test
void unsupportedResponseContentTypeThrowsClientException() {
var registry = new ParseNodeFactoryRegistry();
var response =
new ByteArrayInputStream(
"<html>Unavailable</html>".getBytes(StandardCharsets.UTF_8));
var error =
assertThrows(
ClientException.class,
() -> registry.getParseNode("text/html; charset=utf-8", response));
assertEquals(
"Content type text/html does not have a factory to be parsed", error.getMessage());
}

@ParameterizedTest
@ValueSource(booleans = {true, false})
void unsupportedRequestContentTypeThrowsClientException(boolean changedValuesOnly) {
var registry = new SerializationWriterFactoryRegistry();
var error =
assertThrows(
ClientException.class,
() -> registry.getSerializationWriter("text/html", changedValuesOnly));
assertEquals(
"Content type text/html does not have a factory to be serialized",
error.getMessage());
}

@Test
void invalidArgumentsKeepTheirValidationExceptions() {
var parser = new ParseNodeFactoryRegistry();
var writer = new SerializationWriterFactoryRegistry();
assertThrows(
NullPointerException.class,
() -> parser.getParseNode(null, new ByteArrayInputStream(new byte[0])));
assertThrows(
NullPointerException.class,
() -> parser.getParseNode("", new ByteArrayInputStream(new byte[0])));
assertThrows(NullPointerException.class, () -> parser.getParseNode("text/html", null));
assertThrows(NullPointerException.class, () -> writer.getSerializationWriter(null));
assertThrows(NullPointerException.class, () -> writer.getSerializationWriter(""));
}

@Test
void registeredVendorContentTypesStillWork() throws Exception {
var parser = new ParseNodeFactoryRegistry();
parser.contentTypeAssociatedFactories.put("application/json", new JsonParseNodeFactory());
var response = new ByteArrayInputStream("42".getBytes(StandardCharsets.UTF_8));
assertEquals(
42,
parser.getParseNode("application/vnd.example+json; charset=utf-8", response)
.getIntegerValue());
var writers = new SerializationWriterFactoryRegistry();
writers.contentTypeAssociatedFactories.put(
"application/json", new JsonSerializationWriterFactory());
try (var writer = writers.getSerializationWriter("application/vnd.example+json")) {
writer.writeIntegerValue(null, 42);
assertEquals(
"42",
new String(
Compatibility.readAllBytes(writer.getSerializedContent()),
StandardCharsets.UTF_8));
}
}
}
Loading