From 6aba30d683c1e7ab009975cbdab6d5b79b6dd8b4 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 9 Feb 2021 10:30:25 -0500 Subject: [PATCH 01/13] - adds spotbugs base configuration --- build.gradle | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/build.gradle b/build.gradle index 5e4db62f4..b434b4018 100644 --- a/build.gradle +++ b/build.gradle @@ -14,6 +14,7 @@ plugins { id 'maven-publish' id 'signing' id 'jacoco' + id 'com.github.spotbugs' version '4.6.0' } java { @@ -32,6 +33,16 @@ jacoco { toolVersion = "0.8.7-SNAPSHOT" //https://github.com/gradle/gradle/issues/15038 } +spotbugsMain { + reports { + html { + enabled = true + destination = file("$buildDir/reports/spotbugs/main/spotbugs.html") + stylesheet = 'fancy-hist.xsl' + } + } +} + jacocoTestReport { reports { xml.enabled true From 61d5640a884d4ab6a8cfab3f9d1224b70054ed63 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 12 Feb 2021 11:28:36 -0500 Subject: [PATCH 02/13] - fixes static analysis errors as example --- .../serializer/CollectionResponseSerializer.java | 11 ++++++++--- .../microsoft/graph/serializer/DefaultSerializer.java | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/microsoft/graph/serializer/CollectionResponseSerializer.java b/src/main/java/com/microsoft/graph/serializer/CollectionResponseSerializer.java index 997148cb9..c48374fe1 100644 --- a/src/main/java/com/microsoft/graph/serializer/CollectionResponseSerializer.java +++ b/src/main/java/com/microsoft/graph/serializer/CollectionResponseSerializer.java @@ -56,7 +56,7 @@ private CollectionResponseSerializer() {} @SuppressWarnings("unchecked") @Nullable public static BaseCollectionResponse deserialize(@Nonnull final JsonElement json, @Nonnull final Type typeOfT, @Nonnull final ILogger logger) throws JsonParseException { - if (json == null || !json.isJsonObject()| !typeOfT.getClass().equals(Class.class)) { + if (json == null || !json.isJsonObject() || !typeOfT.getClass().equals(Class.class)) { return null; } serializer = new DefaultSerializer(logger); @@ -86,8 +86,13 @@ public static BaseCollectionResponse deserialize(@Nonnull final JsonEle if(sourceElement.isJsonObject()) { final JsonObject sourceObject = sourceElement.getAsJsonObject(); Class entityClass = serializer.getDerivedClass(sourceObject, baseEntityClass); - if(entityClass == null && baseEntityClass != null) - entityClass = baseEntityClass; // it is possible the odata type is absent or we can't find the derived type (not in SDK yet) + if(entityClass == null) { + if(baseEntityClass == null) { + logger.logError("Could not find target class for object " + sourceObject.toString(), null); + continue; + } else + entityClass = baseEntityClass; // it is possible the odata type is absent or we can't find the derived type (not in SDK yet) + } final T1 targetObject = (T1)serializer.deserializeObject(sourceObject, entityClass); ((IJsonBackedObject)targetObject).setRawObject(serializer, sourceObject); list.add(targetObject); diff --git a/src/main/java/com/microsoft/graph/serializer/DefaultSerializer.java b/src/main/java/com/microsoft/graph/serializer/DefaultSerializer.java index 63e6e4bfb..5ab663775 100644 --- a/src/main/java/com/microsoft/graph/serializer/DefaultSerializer.java +++ b/src/main/java/com/microsoft/graph/serializer/DefaultSerializer.java @@ -352,7 +352,7 @@ private void addAdditionalDataFromManagerToJson(AdditionalDataManager additional * @return the derived class if found, or null if not applicable */ @Nullable - public Class getDerivedClass(@Nonnull final JsonObject jsonObject, @Nonnull final Class parentClass) { + public Class getDerivedClass(@Nonnull final JsonObject jsonObject, @Nullable final Class parentClass) { //Identify the odata.type information if provided if (jsonObject.get(ODATA_TYPE_KEY) != null) { /** #microsoft.graph.user or #microsoft.graph.callrecords.callrecord */ From da944a54b71fad4baec2c4158eff5527a209593d Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 12 Feb 2021 15:40:36 -0500 Subject: [PATCH 03/13] - fixes a first set of linting issues --- .../graph/content/BatchRequestBuilder.java | 2 +- .../com/microsoft/graph/core/BaseClient.java | 3 +- .../com/microsoft/graph/core/Multipart.java | 88 +++++++++---------- .../graph/http/BaseCollectionPage.java | 2 +- .../com/microsoft/graph/http/BaseRequest.java | 8 +- .../http/GraphFatalServiceException.java | 2 +- .../graph/http/GraphServiceException.java | 43 +++++---- .../microsoft/graph/http/IHttpRequest.java | 4 +- .../graph/options/FunctionOption.java | 3 +- .../microsoft/graph/options/HeaderOption.java | 2 +- .../com/microsoft/graph/options/Option.java | 5 +- .../microsoft/graph/options/QueryOption.java | 11 +-- .../http/GraphServiceExceptionTests.java | 23 ++--- 13 files changed, 98 insertions(+), 98 deletions(-) diff --git a/src/main/java/com/microsoft/graph/content/BatchRequestBuilder.java b/src/main/java/com/microsoft/graph/content/BatchRequestBuilder.java index 731dfd9aa..c6ceda75d 100644 --- a/src/main/java/com/microsoft/graph/content/BatchRequestBuilder.java +++ b/src/main/java/com/microsoft/graph/content/BatchRequestBuilder.java @@ -39,7 +39,7 @@ public class BatchRequestBuilder extends BaseRequestBuilder options) { + public BatchRequestBuilder(@Nonnull final String requestUrl, @Nonnull final IBaseClient client, @Nonnull final List options) { super(requestUrl, client, options); } /** diff --git a/src/main/java/com/microsoft/graph/core/BaseClient.java b/src/main/java/com/microsoft/graph/core/BaseClient.java index a97f6c030..6a94a3c66 100644 --- a/src/main/java/com/microsoft/graph/core/BaseClient.java +++ b/src/main/java/com/microsoft/graph/core/BaseClient.java @@ -35,6 +35,7 @@ import javax.annotation.Nullable; +import java.util.Collections; import java.util.Objects; import javax.annotation.Nonnull; @@ -110,7 +111,7 @@ public CustomRequestBuilder customRequest(@Nonnull final String url */ @Nonnull public BatchRequestBuilder batch() { - return new BatchRequestBuilder(getServiceRoot() + "/$batch", this, null); + return new BatchRequestBuilder(getServiceRoot() + "/$batch", this, Collections.emptyList()); } /** diff --git a/src/main/java/com/microsoft/graph/core/Multipart.java b/src/main/java/com/microsoft/graph/core/Multipart.java index 9b83ce480..365be77e9 100644 --- a/src/main/java/com/microsoft/graph/core/Multipart.java +++ b/src/main/java/com/microsoft/graph/core/Multipart.java @@ -16,8 +16,8 @@ /** * Helper for submitting multipart data - * - * This follows the Network Working Group's RFC + * + * This follows the Network Working Group's RFC * on multipart/form-data posting format: * https://www.ietf.org/rfc/rfc2388.txt */ @@ -28,7 +28,7 @@ public class Multipart { /** Default encoding for multi-part requests */ public static final String MULTIPART_ENCODING = "US-ASCII"; private String contentType = "multipart/form-data"; - + /** * Create a new multipart object */ @@ -36,7 +36,7 @@ public Multipart() { out = new ByteArrayOutputStream(); boundary = "part_" + new BigInteger(130, new SecureRandom()).toString(); } - + /** * Get the multipart boundary for use in the request header * @return the multipart boundary @@ -45,7 +45,7 @@ public Multipart() { public String getBoundary() { return boundary; } - + /** * Set the multipart boundary for use in the request header * @param boundary The multipart boundary @@ -53,7 +53,7 @@ public String getBoundary() { public void setBoundary(@Nonnull final String boundary) { this.boundary = boundary; } - + /** * Get the contentType for use in the request header * @return the multipart Content-Type @@ -62,7 +62,7 @@ public void setBoundary(@Nonnull final String boundary) { public String getContentType() { return contentType; } - + /** * Set the contentType for use in the request header * @param contentType The multipart Content-Type @@ -70,7 +70,7 @@ public String getContentType() { public void setContentType(@Nonnull final String contentType) { this.contentType = contentType; } - + /** * Get the Content-Type header to send the multipart request * @return the multipart header option @@ -79,72 +79,71 @@ public void setContentType(@Nonnull final String contentType) { public HeaderOption header() { return new HeaderOption("Content-Type", contentType + "; boundary=\"" + boundary + "\""); } - + private void writePartData(String partContent, byte[] byteArray) throws IOException{ out.write(partContent.getBytes(MULTIPART_ENCODING)); out.write(byteArray); String returnContent = RETURN + RETURN; out.write(returnContent.getBytes(MULTIPART_ENCODING)); } - + /** * Create content headers value and parameter * @param name The content header name * @param contentType The content header Content-Type - * @param filename The content header filename - * @return content header value and parameter string + * @param filename The content header filename + * @return content header value and parameter string */ @VisibleForTesting String createPartHeader(String name, String contentType, String filename) { StringBuilder partContent = new StringBuilder(addBoundary()); partContent.append("Content-Disposition: form-data"); if(filename != null) { - if(name != null) + if(name != null) partContent.append("; name=\"").append(name).append("\"; filename=\"").append(filename).append("\""); - else + else partContent.append("; filename=\"").append(filename).append("\""); } - else if(name != null) + else if(name != null) partContent.append("; name=\"").append(name).append("\""); if(contentType != null) partContent.append(RETURN).append("Content-Type: ").append(contentType); partContent.append(RETURN).append(RETURN); return partContent.toString(); } - + /** * Create content headers value and parameter * @param contentValue The content header value - * @param contentDispParameter Map containing content paramter's key and value pair - * @return content header value and parameter string + * @param contentDispParameter Map containing content paramter's key and value pair + * @return content header value and parameter string */ @Nonnull public static String createContentHeaderValue(@Nonnull final String contentValue, @Nullable final Map contentDispParameter) { - String contentHeaderValue = contentValue; + final StringBuilder builder = new StringBuilder(contentValue); if(contentDispParameter != null) { for(Map.Entry entry : contentDispParameter.entrySet()) - contentHeaderValue += ";" + entry.getKey() + "=\"" + entry.getValue() + "\""; + builder.append(";" + entry.getKey() + "=\"" + entry.getValue() + "\""); } - return contentHeaderValue; + return builder.toString(); } - + /** * Create content headers header-name, value and parameter string * @param headers Map containing Header-name and header-value pair */ private String createPartHeader(Map headers) { - String partContent = addBoundary(); - String defaultPartContent = "Content-Disposition: form-data;" + RETURN + "Content-Type: " + contentType + RETURN + RETURN; - - if(headers != null) { - for(Map.Entry entry : headers.entrySet()) - partContent += entry.getKey() +": "+entry.getValue() + RETURN; - partContent += RETURN; - } - else - partContent += defaultPartContent; - return partContent; + final StringBuilder builder = new StringBuilder(addBoundary()); + final String defaultPartContent = "Content-Disposition: form-data;" + RETURN + "Content-Type: " + contentType + RETURN + RETURN; + + if(headers != null) { + for(Map.Entry entry : headers.entrySet()) + builder.append(entry.getKey() +": "+entry.getValue() + RETURN); + builder.append(RETURN); + } else + builder.append(defaultPartContent); + return builder.toString(); } /** @@ -170,7 +169,7 @@ private void addData(String name, String contentType, String filename, byte[] by public void addFormData(@Nonnull final String name, @Nonnull final String contentType, @Nonnull final byte[] byteArray) throws IOException { addData(name, contentType, null, byteArray); } - + /** * Add a part to the multipart body * @param contentType The MIME type (text/html, video/mp4, etc.) @@ -180,7 +179,7 @@ public void addFormData(@Nonnull final String name, @Nonnull final String conten public void addPart(@Nonnull final String contentType, @Nonnull final byte[] byteArray) throws IOException { addData(null, contentType, null, byteArray); } - + /** * Add a part to the multipart body * @param headers Map containing Header's header-name(eg: Content-Disposition, Content-Type, etc..) and header's value-parameter string @@ -191,7 +190,7 @@ public void addPart(@Nonnull final Map headers, @Nonnull final b final String partContent = createPartHeader(headers); writePartData(partContent, content); } - + /** * Add an HTML part to the multipart body * @param name The name of the part @@ -201,7 +200,7 @@ public void addPart(@Nonnull final Map headers, @Nonnull final b public void addHtmlPart(@Nonnull final String name, @Nonnull final byte[] content) throws IOException { addFormData(name, "text/html", content); } - + /** * Add a file part to the multipart body * @param name The name of the part @@ -210,11 +209,12 @@ public void addHtmlPart(@Nonnull final String name, @Nonnull final byte[] conten * @throws IOException Throws an exception if the output stream cannot be written to */ public void addFilePart(@Nonnull final String name, @Nonnull final String contentType, @Nonnull final java.io.File file) throws IOException { - final InputStream fileStream = new FileInputStream(file); - final byte[] fileBytes = getByteArray(fileStream); - addData(name, contentType, file.getName(), fileBytes); + try(final InputStream fileStream = new FileInputStream(file)) { + final byte[] fileBytes = getByteArray(fileStream); + addData(name, contentType, file.getName(), fileBytes); + } } - + /** * Adds a boundary at the beginning of a new part * @return The boundary @@ -222,7 +222,7 @@ public void addFilePart(@Nonnull final String name, @Nonnull final String conten private String addBoundary() { return "--" + boundary + RETURN; } - + /** * Adds a boundary at the end of the multipart body * @return The boundary @@ -230,7 +230,7 @@ private String addBoundary() { private String addEnding() { return "--" + boundary + "--"; } - + /** * Returns a full multipart body byte array * @return The byte[] representation of the multipart object @@ -242,7 +242,7 @@ public byte[] content() throws IOException { finalStream.write(addEnding().getBytes(MULTIPART_ENCODING)); return finalStream.toByteArray(); } - + /** * Helper method to convert an InputStream to a byte[] * @param in The input stream to convert diff --git a/src/main/java/com/microsoft/graph/http/BaseCollectionPage.java b/src/main/java/com/microsoft/graph/http/BaseCollectionPage.java index 0411eab2d..fce85908a 100644 --- a/src/main/java/com/microsoft/graph/http/BaseCollectionPage.java +++ b/src/main/java/com/microsoft/graph/http/BaseCollectionPage.java @@ -83,7 +83,7 @@ public BaseCollectionPage(@Nonnull final List pageContents, @Nullable final T * @param nextRequestBuilder the request builder for the next page * @param responseAdditionalData the additional data returned by the response */ - public BaseCollectionPage(@Nonnull final List pageContents, @Nonnull final T2 nextRequestBuilder, @Nonnull final AdditionalDataManager responseAdditionalData) { + public BaseCollectionPage(@Nonnull final List pageContents, @Nullable final T2 nextRequestBuilder, @Nonnull final AdditionalDataManager responseAdditionalData) { this(pageContents, nextRequestBuilder); this.additionalDataManager().putAll(responseAdditionalData); } diff --git a/src/main/java/com/microsoft/graph/http/BaseRequest.java b/src/main/java/com/microsoft/graph/http/BaseRequest.java index a73776532..c0d76746d 100644 --- a/src/main/java/com/microsoft/graph/http/BaseRequest.java +++ b/src/main/java/com/microsoft/graph/http/BaseRequest.java @@ -177,8 +177,12 @@ public BaseRequest(@Nonnull final String requestUrl, @Override @Nullable public URL getRequestUrl() { - String requestUrl = addFunctionParameters(); - final Builder uriBuilder = HttpUrl.parse(requestUrl).newBuilder(); + final String requestUrl = addFunctionParameters(); + final HttpUrl parsedUrl = HttpUrl.parse(requestUrl); + if (parsedUrl == null) { + throw new ClientException("Invalid URL " + requestUrl, null); + } + final Builder uriBuilder = parsedUrl.newBuilder(); for (final QueryOption option : queryOptions) { uriBuilder.addQueryParameter(option.getName(), option.getValue().toString()); diff --git a/src/main/java/com/microsoft/graph/http/GraphFatalServiceException.java b/src/main/java/com/microsoft/graph/http/GraphFatalServiceException.java index ed3fdacb7..c12eea883 100644 --- a/src/main/java/com/microsoft/graph/http/GraphFatalServiceException.java +++ b/src/main/java/com/microsoft/graph/http/GraphFatalServiceException.java @@ -52,7 +52,7 @@ protected GraphFatalServiceException(@Nonnull final String method, @Nonnull final List requestHeaders, @Nullable final String requestBody, final int responseCode, - @Nullable final String responseMessage, + @Nonnull final String responseMessage, @Nonnull final List responseHeaders, @Nullable final GraphErrorResponse error, final boolean verbose) { diff --git a/src/main/java/com/microsoft/graph/http/GraphServiceException.java b/src/main/java/com/microsoft/graph/http/GraphServiceException.java index d5b6516dc..7ef12cd26 100644 --- a/src/main/java/com/microsoft/graph/http/GraphServiceException.java +++ b/src/main/java/com/microsoft/graph/http/GraphServiceException.java @@ -35,18 +35,22 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.TreeMap; +import java.util.Map.Entry; import javax.annotation.Nonnull; import javax.annotation.Nullable; import okhttp3.Headers; import okhttp3.Response; +import okhttp3.ResponseBody; import static java.nio.charset.StandardCharsets.UTF_8; @@ -144,7 +148,7 @@ protected GraphServiceException(@Nonnull final String method, @Nonnull final List requestHeaders, @Nullable final String requestBody, final int responseCode, - @Nullable final String responseMessage, + @Nonnull final String responseMessage, @Nonnull final List responseHeaders, @Nullable final GraphErrorResponse error, final boolean verbose) { @@ -333,9 +337,10 @@ public GraphError getServiceError() { public static GraphServiceException createFromResponse(@Nonnull final IHttpRequest request, @Nullable final T serializable, @Nonnull final ISerializer serializer, - @Nullable final Response response, + @Nonnull final Response response, @Nonnull final ILogger logger) throws IOException { + Objects.requireNonNull(response, "reponse parameter cannot be null"); final String method = response.request().method(); final String url = request.getRequestUrl().toString(); final List requestHeaders = new LinkedList<>(); @@ -351,7 +356,7 @@ public static GraphServiceException createFromResponse(@Nonnull final IHttpR sb.append(" {"); if (isVerbose) { - sb.append(bytes); + sb.append(Arrays.toString(bytes)); } else { for (int i = 0; i < MAX_BYTE_COUNT_BEFORE_TRUNCATION && i < bytes.length; i++) { sb.append(bytes[i]).append(", "); @@ -394,21 +399,14 @@ public static GraphServiceException createFromResponse(@Nullable final String ur @Nonnull final Map headers, @Nonnull final String responseMessage, final int responseCode, @Nonnull final GraphErrorResponse error, final boolean isVerbose) { final List responseHeaders = new LinkedList<>(); - for (final String key : headers.keySet()) { - final String fieldPrefix; - if (key == null) { - fieldPrefix = ""; - } else { - fieldPrefix = key + " : "; - } - responseHeaders.add(fieldPrefix + headers.get(key)); + for (final Entry entry : headers.entrySet()) { + responseHeaders.add(entry.getKey() + (entry.getKey() == null ? "" : " : " ) + entry.getValue()); } - if (responseCode >= INTERNAL_SERVER_ERROR) { - return new GraphFatalServiceException(method, - url, + return new GraphFatalServiceException(method == null ? "" : method, + url == null ? "" : url, requestHeaders, requestBody, responseCode, @@ -418,8 +416,8 @@ public static GraphServiceException createFromResponse(@Nullable final String ur isVerbose); } - return new GraphServiceException(method, - url, + return new GraphServiceException(method == null ? "" : method, + url == null ? "" : url, requestHeaders, requestBody, responseCode, @@ -432,10 +430,17 @@ public static GraphServiceException createFromResponse(@Nullable final String ur private static GraphErrorResponse parseErrorResponse(@Nonnull ISerializer serializer, @Nonnull Response response) throws IOException { - + Objects.requireNonNull(serializer, "serializer is required."); + Objects.requireNonNull(response, "response is required."); byte[] responseBytes; - try(final InputStream is = response.body().byteStream()) { - responseBytes = ByteStreams.toByteArray(is); + try(final ResponseBody body = response.body()) { + if(body == null) { + responseBytes = new byte[]{}; + } else { + try(final InputStream is = body.byteStream()) { + responseBytes = ByteStreams.toByteArray(is); + } + } } GraphErrorResponse error; try { diff --git a/src/main/java/com/microsoft/graph/http/IHttpRequest.java b/src/main/java/com/microsoft/graph/http/IHttpRequest.java index 76f674e17..c032d4096 100644 --- a/src/main/java/com/microsoft/graph/http/IHttpRequest.java +++ b/src/main/java/com/microsoft/graph/http/IHttpRequest.java @@ -181,7 +181,7 @@ public interface IHttpRequest { */ @Nullable default nativeRequestType getHttpRequest() throws ClientException { - return getHttpRequest(null); //TODO do something for the nonnull annotation + return getHttpRequest(null); } /** @@ -193,6 +193,6 @@ default nativeRequestType getHttpRequest() throws ClientExce * @return the Request object to be executed */ @Nullable - nativeRequestType getHttpRequest(@Nonnull final requestBodyType serializedObject) throws ClientException; + nativeRequestType getHttpRequest(@Nullable final requestBodyType serializedObject) throws ClientException; } diff --git a/src/main/java/com/microsoft/graph/options/FunctionOption.java b/src/main/java/com/microsoft/graph/options/FunctionOption.java index 95c7de873..7ca46895b 100644 --- a/src/main/java/com/microsoft/graph/options/FunctionOption.java +++ b/src/main/java/com/microsoft/graph/options/FunctionOption.java @@ -23,6 +23,7 @@ package com.microsoft.graph.options; import javax.annotation.Nonnull; +import javax.annotation.Nullable; /** Represents an option to use with OData methods */ public class FunctionOption extends Option { @@ -33,7 +34,7 @@ public class FunctionOption extends Option { * @param name the name of the option * @param value the value of the option */ - public FunctionOption(@Nonnull final String name, @Nonnull final Object value) { + public FunctionOption(@Nonnull final String name, @Nullable final Object value) { super(name, value); } } diff --git a/src/main/java/com/microsoft/graph/options/HeaderOption.java b/src/main/java/com/microsoft/graph/options/HeaderOption.java index ff336254f..cf09dff9b 100644 --- a/src/main/java/com/microsoft/graph/options/HeaderOption.java +++ b/src/main/java/com/microsoft/graph/options/HeaderOption.java @@ -36,7 +36,7 @@ public class HeaderOption extends Option { * @param name the name of the header * @param value the value of the header */ - public HeaderOption(@Nonnull final String name, @Nonnull final String value) { + public HeaderOption(@Nonnull final String name, @Nullable final String value) { super(name, value); } } diff --git a/src/main/java/com/microsoft/graph/options/Option.java b/src/main/java/com/microsoft/graph/options/Option.java index 5def6285f..ef67b39c4 100644 --- a/src/main/java/com/microsoft/graph/options/Option.java +++ b/src/main/java/com/microsoft/graph/options/Option.java @@ -25,6 +25,7 @@ import java.util.Objects; import javax.annotation.Nonnull; +import javax.annotation.Nullable; /** * An option that is settable for a request @@ -47,7 +48,7 @@ public class Option { * @param name the name of the option * @param value the value of the option */ - protected Option(@Nonnull final String name, @Nonnull final Object value) { + protected Option(@Nonnull final String name, @Nullable final Object value) { Objects.requireNonNull(name, "name should not be null"); if(name.isEmpty()) { throw new IllegalArgumentException("name should not empty"); @@ -71,7 +72,7 @@ public String getName() { * * @return the value of the option */ - @Nonnull + @Nullable public Object getValue() { return value; } diff --git a/src/main/java/com/microsoft/graph/options/QueryOption.java b/src/main/java/com/microsoft/graph/options/QueryOption.java index ed34eb2b8..59c8f6e36 100644 --- a/src/main/java/com/microsoft/graph/options/QueryOption.java +++ b/src/main/java/com/microsoft/graph/options/QueryOption.java @@ -1,16 +1,16 @@ // ------------------------------------------------------------------------------ // Copyright (c) 2017 Microsoft Corporation -// +// // 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, sub-license, 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 @@ -23,6 +23,7 @@ package com.microsoft.graph.options; import javax.annotation.Nonnull; +import javax.annotation.Nullable; /** * A query parameter */ @@ -30,11 +31,11 @@ public class QueryOption extends Option { /** * Create a query parameter option object - * + * * @param name the name of the query parameter * @param value the value of the query parameter */ - public QueryOption(@Nonnull final String name, @Nonnull final Object value) { + public QueryOption(@Nonnull final String name, @Nullable final Object value) { super(name, value); } } diff --git a/src/test/java/com/microsoft/graph/http/GraphServiceExceptionTests.java b/src/test/java/com/microsoft/graph/http/GraphServiceExceptionTests.java index f0942a7bf..d092010b6 100644 --- a/src/test/java/com/microsoft/graph/http/GraphServiceExceptionTests.java +++ b/src/test/java/com/microsoft/graph/http/GraphServiceExceptionTests.java @@ -4,13 +4,9 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.InputStream; import java.net.URL; import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -25,6 +21,7 @@ import com.microsoft.graph.core.GraphErrorCodes; import com.microsoft.graph.logger.DefaultLogger; +import com.microsoft.graph.serializer.ISerializer; public class GraphServiceExceptionTests { @@ -57,11 +54,9 @@ public void testVerboseError() { } @Test - public void testcreateFromResponse() { + public void testcreateFromResponse() throws IOException { DefaultLogger logger = new DefaultLogger(); GraphServiceException exception = null; - Boolean success = false; - Boolean failure = false; final Response response = new Response.Builder() .request(new Request.Builder().url("https://a.b.c").build()) .protocol(Protocol.HTTP_1_1) @@ -71,20 +66,12 @@ public void testcreateFromResponse() { MediaType.parse("application/json") )) .build(); - try{ - IHttpRequest mRequest = mock(IHttpRequest.class); - when(mRequest.getRequestUrl()).thenReturn(new URL("http://localhost")); - exception = GraphServiceException.createFromResponse(mRequest ,null,null,response,logger); - success = true; - }catch (IOException ex){ - failure = true; - } - assertTrue(success); - assertFalse(failure); + IHttpRequest mRequest = mock(IHttpRequest.class); + when(mRequest.getRequestUrl()).thenReturn(new URL("http://localhost")); + exception = GraphServiceException.createFromResponse(mRequest ,null, mock(ISerializer.class),response,logger); String message = exception.getMessage(); - assertTrue(message.indexOf("Error code: Unable to parse error response message") == 0); assertTrue(message.indexOf("http://localhost") > 0); } } From 99ca9e676d40afae41f5012005d188e6e7d5f2a8 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 15 Feb 2021 09:18:47 -0500 Subject: [PATCH 04/13] - lints serializer package --- .../com/microsoft/graph/serializer/DefaultSerializer.java | 4 ++-- .../java/com/microsoft/graph/serializer/GsonFactory.java | 3 ++- .../java/com/microsoft/graph/serializer/ISerializer.java | 8 ++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/microsoft/graph/serializer/DefaultSerializer.java b/src/main/java/com/microsoft/graph/serializer/DefaultSerializer.java index 5ab663775..51075262c 100644 --- a/src/main/java/com/microsoft/graph/serializer/DefaultSerializer.java +++ b/src/main/java/com/microsoft/graph/serializer/DefaultSerializer.java @@ -82,7 +82,7 @@ public T deserializeObject(@Nonnull final String inputString, @Nonnull final @Nullable public T deserializeObject(@Nonnull final InputStream inputStream, @Nonnull final Class clazz, @Nonnull final Map> responseHeaders) { T result = null; - try (final InputStreamReader streamReader = new InputStreamReader(inputStream)) { + try (final InputStreamReader streamReader = new InputStreamReader(inputStream, "UTF-8")) { final JsonElement rawElement = gson.fromJson(streamReader, JsonElement.class); result = deserializeObject(rawElement, clazz, responseHeaders); } catch (IOException ex) { @@ -276,7 +276,7 @@ private void getChildAdditionalData(final IJsonBackedObject serializableObject, try { final Object fieldObject = field.get(serializableObject); final JsonElement fieldJsonElement = outJson.get(field.getName()); - if(fieldObject == null || field == null || fieldJsonElement == null) + if(fieldObject == null || fieldJsonElement == null) continue; // If the object is a HashMap, iterate through its children diff --git a/src/main/java/com/microsoft/graph/serializer/GsonFactory.java b/src/main/java/com/microsoft/graph/serializer/GsonFactory.java index d80a5b371..e51b998cf 100644 --- a/src/main/java/com/microsoft/graph/serializer/GsonFactory.java +++ b/src/main/java/com/microsoft/graph/serializer/GsonFactory.java @@ -40,6 +40,7 @@ import java.lang.reflect.Type; import java.text.ParseException; import java.time.OffsetDateTime; +import java.util.Arrays; import java.util.EnumSet; import java.util.GregorianCalendar; @@ -112,7 +113,7 @@ public JsonElement serialize(final byte[] src, try { return new JsonPrimitive(ByteArraySerializer.serialize(src)); } catch (final Exception e) { - logger.logError(PARSING_MESSAGE + src, e); + logger.logError(PARSING_MESSAGE + Arrays.toString(src), e); return null; } } diff --git a/src/main/java/com/microsoft/graph/serializer/ISerializer.java b/src/main/java/com/microsoft/graph/serializer/ISerializer.java index cf3efc973..7e64de2d6 100644 --- a/src/main/java/com/microsoft/graph/serializer/ISerializer.java +++ b/src/main/java/com/microsoft/graph/serializer/ISerializer.java @@ -59,7 +59,7 @@ default T deserializeObject(@Nonnull final String inputString, @Nonnull fina * @return the deserialized item from the input string */ @Nullable - T deserializeObject(@Nonnull final String inputString, @Nonnull final Class clazz, @Nonnull final Map> responseHeaders); + T deserializeObject(@Nonnull final String inputString, @Nonnull final Class clazz, @Nullable final Map> responseHeaders); /** * Deserialize an object from the input stream @@ -84,7 +84,7 @@ default T deserializeObject(@Nonnull final InputStream inputStream, @Nonnull * @return the deserialized item from the input string */ @Nullable - T deserializeObject(@Nonnull final InputStream inputStream, @Nonnull final Class clazz, @Nonnull final Map> responseHeaders); + T deserializeObject(@Nonnull final InputStream inputStream, @Nonnull final Class clazz, @Nullable final Map> responseHeaders); /** * Deserialize an object from the input JsonElement @@ -95,7 +95,7 @@ default T deserializeObject(@Nonnull final InputStream inputStream, @Nonnull * @return the deserialized item from the input string */ @Nullable - default T deserializeObject(@Nonnull JsonElement jsonElement, @Nonnull Class clazz) { + default T deserializeObject(@Nonnull final JsonElement jsonElement, @Nonnull final Class clazz) { return deserializeObject(jsonElement, clazz, null); } @@ -109,7 +109,7 @@ default T deserializeObject(@Nonnull JsonElement jsonElement, @Nonnull Class * @return the deserialized item from the input string */ @Nullable - T deserializeObject(@Nonnull JsonElement jsonElement, @Nonnull Class clazz, @Nonnull Map> responseHeaders); + T deserializeObject(@Nonnull final JsonElement jsonElement, @Nonnull final Class clazz, @Nullable final Map> responseHeaders); /** * Serializes an object into a string From e408ea0d8f10143f22883eb3dde69cc41a1bf844 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 15 Feb 2021 09:52:06 -0500 Subject: [PATCH 05/13] - lints httpcore package --- .../graph/httpcore/AuthenticationHandler.java | 14 +++--- .../graph/httpcore/ChaosHttpHandler.java | 19 ++++---- .../graph/httpcore/RedirectHandler.java | 11 +++-- .../graph/httpcore/RetryHandler.java | 45 +++++++++++-------- .../graph/httpcore/TelemetryHandler.java | 14 +++--- 5 files changed, 60 insertions(+), 43 deletions(-) diff --git a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java index 306e35e7b..daf8fc44c 100644 --- a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java @@ -6,7 +6,6 @@ import com.microsoft.graph.authentication.IAuthenticationProvider; -import javax.annotation.Nullable; import javax.annotation.Nonnull; import com.microsoft.graph.httpcore.middlewareoption.MiddlewareType; @@ -40,18 +39,19 @@ public AuthenticationHandler(@Nonnull final IAuthenticationProvider authProvider } @Override - @Nullable + @Nonnull public Response intercept(@Nonnull final Chain chain) throws IOException { Request originalRequest = chain.request(); - if(originalRequest.tag(TelemetryOptions.class) == null) - originalRequest = originalRequest.newBuilder().tag(TelemetryOptions.class, new TelemetryOptions()).build(); - originalRequest.tag(TelemetryOptions.class).setFeatureUsage(TelemetryOptions.AUTH_HANDLER_ENABLED_FLAG); + TelemetryOptions telemetryOptions = originalRequest.tag(TelemetryOptions.class); + if(telemetryOptions == null) { + telemetryOptions = new TelemetryOptions(); + originalRequest = originalRequest.newBuilder().tag(TelemetryOptions.class, telemetryOptions).build(); + } + telemetryOptions.setFeatureUsage(TelemetryOptions.AUTH_HANDLER_ENABLED_FLAG); try { final CompletableFuture future = authProvider.getAuthorizationTokenAsync(originalRequest.url().url()); - if(future == null) - return chain.proceed(originalRequest); final String accessToken = future.get(); if(accessToken == null) return chain.proceed(originalRequest); diff --git a/src/main/java/com/microsoft/graph/httpcore/ChaosHttpHandler.java b/src/main/java/com/microsoft/graph/httpcore/ChaosHttpHandler.java index 37970397a..e4eec8304 100644 --- a/src/main/java/com/microsoft/graph/httpcore/ChaosHttpHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/ChaosHttpHandler.java @@ -28,32 +28,35 @@ public class ChaosHttpHandler implements Interceptor { /** * constant string being used */ - private final String RETRY_AFTER = "Retry-After"; + private static final String RETRY_AFTER = "Retry-After"; /** * Denominator for the failure rate (i.e. 1/X) */ - private final int failureRate = 3; + private static final int failureRate = 3; /** * default value to return on retry after */ - private final String retryAfterValue = "10"; + private static final String retryAfterValue = "10"; /** * body to respond on failed requests */ - private final String responseBody = "{\"error\": {\"code\": \"TooManyRequests\",\"innerError\": {\"code\": \"429\",\"date\": \"2020-08-18T12:51:51\",\"message\": \"Please retry after\",\"request-id\": \"94fb3b52-452a-4535-a601-69e0a90e3aa2\",\"status\": \"429\"},\"message\": \"Please retry again later.\"}}"; + private static final String responseBody = "{\"error\": {\"code\": \"TooManyRequests\",\"innerError\": {\"code\": \"429\",\"date\": \"2020-08-18T12:51:51\",\"message\": \"Please retry after\",\"request-id\": \"94fb3b52-452a-4535-a601-69e0a90e3aa2\",\"status\": \"429\"},\"message\": \"Please retry again later.\"}}"; /** * Too many requests status code */ public static final int MSClientErrorCodeTooManyRequests = 429; @Override - @Nullable + @Nonnull public Response intercept(@Nonnull final Chain chain) throws IOException { Request request = chain.request(); - if(request.tag(TelemetryOptions.class) == null) - request = request.newBuilder().tag(TelemetryOptions.class, new TelemetryOptions()).build(); - request.tag(TelemetryOptions.class).setFeatureUsage(TelemetryOptions.RETRY_HANDLER_ENABLED_FLAG); + TelemetryOptions telemetryOptions = request.tag(TelemetryOptions.class); + if(telemetryOptions == null) { + telemetryOptions = new TelemetryOptions(); + request = request.newBuilder().tag(TelemetryOptions.class, telemetryOptions).build(); + } + telemetryOptions.setFeatureUsage(TelemetryOptions.RETRY_HANDLER_ENABLED_FLAG); final int dice = ThreadLocalRandom.current().nextInt(1, Integer.MAX_VALUE); diff --git a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java index 34b52b2d7..d66a36fbd 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java @@ -115,13 +115,16 @@ Request getRedirect( // Intercept request and response made to network @Override - @Nullable + @Nonnull public Response intercept(@Nonnull final Chain chain) throws IOException { Request request = chain.request(); - if(request.tag(TelemetryOptions.class) == null) - request = request.newBuilder().tag(TelemetryOptions.class, new TelemetryOptions()).build(); - request.tag(TelemetryOptions.class).setFeatureUsage(TelemetryOptions.REDIRECT_HANDLER_ENABLED_FLAG); + TelemetryOptions telemetryOptions = request.tag(TelemetryOptions.class); + if(telemetryOptions == null) { + telemetryOptions = new TelemetryOptions(); + request = request.newBuilder().tag(TelemetryOptions.class, telemetryOptions).build(); + } + telemetryOptions.setFeatureUsage(TelemetryOptions.REDIRECT_HANDLER_ENABLED_FLAG); Response response = null; int requestsCount = 1; diff --git a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java index 2881ed68f..67bc9804c 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java @@ -16,6 +16,7 @@ import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; +import okhttp3.ResponseBody; /** * The middleware responsible for retrying requests when they fail because of transient issues @@ -32,27 +33,27 @@ public class RetryHandler implements Interceptor{ /** * Header name to track the retry attempt number */ - private final String RETRY_ATTEMPT_HEADER = "Retry-Attempt"; + private static final String RETRY_ATTEMPT_HEADER = "Retry-Attempt"; /** * Header name for the retry after information */ - private final String RETRY_AFTER = "Retry-After"; + private static final String RETRY_AFTER = "Retry-After"; /** * Header name for the transfer information */ - private final String TRANSFER_ENCODING = "Transfer-Encoding"; + private static final String TRANSFER_ENCODING = "Transfer-Encoding"; /** * Chunked encoding header value */ - private final String TRANSFER_ENCODING_CHUNKED = "chunked"; + private static final String TRANSFER_ENCODING_CHUNKED = "chunked"; /** * Binary content type header value */ - private final String APPLICATION_OCTET_STREAM = "application/octet-stream"; + private static final String APPLICATION_OCTET_STREAM = "application/octet-stream"; /** * Header name for the content type */ - private final String CONTENT_TYPE = "Content-Type"; + private static final String CONTENT_TYPE = "Content-Type"; /** * Too many requests status code @@ -70,7 +71,7 @@ public class RetryHandler implements Interceptor{ /** * One second as milliseconds */ - private final long DELAY_MILLISECONDS = 1000; + private static final long DELAY_MILLISECONDS = 1000; private final ILogger logger; @@ -114,7 +115,8 @@ boolean retryRequest(Response response, int executionCount, Request request, Ret // Payloads with forward only streams will be have the responses returned // without any retry attempt. shouldRetry = - (executionCount <= retryOptions.maxRetries()) + retryOptions != null + && executionCount <= retryOptions.maxRetries() && checkStatus(statusCode) && isBuffered(response, request) && shouldRetryCallback != null && shouldRetryCallback.shouldRetry(retryOptions.delay(), executionCount, request, response); @@ -155,7 +157,7 @@ boolean checkStatus(int statusCode) { || statusCode == MSClientErrorCodeGatewayTimeout); } - boolean isBuffered(Response response, Request request) { + boolean isBuffered(final Response response, final Request request) { String methodName = request.method(); if(methodName.equalsIgnoreCase("GET") || methodName.equalsIgnoreCase("DELETE") || methodName.equalsIgnoreCase("HEAD") || methodName.equalsIgnoreCase("OPTIONS")) return true; @@ -164,11 +166,12 @@ boolean isBuffered(Response response, Request request) { methodName.equalsIgnoreCase("PUT") || methodName.equalsIgnoreCase("PATCH"); - if(isHTTPMethodPutPatchOrPost) { - boolean isStream = response.header(CONTENT_TYPE)!=null && response.header(CONTENT_TYPE).equalsIgnoreCase(APPLICATION_OCTET_STREAM); + if(isHTTPMethodPutPatchOrPost && response != null) { + final String contentTypeHeaderValue = response.header(CONTENT_TYPE); + final boolean isStream = contentTypeHeaderValue!=null && contentTypeHeaderValue.equalsIgnoreCase(APPLICATION_OCTET_STREAM); if(!isStream) { - String transferEncoding = response.header(TRANSFER_ENCODING); - boolean isTransferEncodingChunked = (transferEncoding != null) && + final String transferEncoding = response.header(TRANSFER_ENCODING); + final boolean isTransferEncodingChunked = (transferEncoding != null) && transferEncoding.equalsIgnoreCase(TRANSFER_ENCODING_CHUNKED); if(request.body() != null && isTransferEncodingChunked) @@ -179,13 +182,16 @@ boolean isBuffered(Response response, Request request) { } @Override - @Nullable + @Nonnull public Response intercept(@Nonnull final Chain chain) throws IOException { Request request = chain.request(); - if(request.tag(TelemetryOptions.class) == null) - request = request.newBuilder().tag(TelemetryOptions.class, new TelemetryOptions()).build(); - request.tag(TelemetryOptions.class).setFeatureUsage(TelemetryOptions.RETRY_HANDLER_ENABLED_FLAG); + TelemetryOptions telemetryOptions = request.tag(TelemetryOptions.class); + if(telemetryOptions == null) { + telemetryOptions = new TelemetryOptions(); + request = request.newBuilder().tag(TelemetryOptions.class, telemetryOptions).build(); + } + telemetryOptions.setFeatureUsage(TelemetryOptions.RETRY_HANDLER_ENABLED_FLAG); Response response = chain.proceed(request); @@ -198,8 +204,9 @@ public Response intercept(@Nonnull final Chain chain) throws IOException { request = request.newBuilder().addHeader(RETRY_ATTEMPT_HEADER, String.valueOf(executionCount)).build(); executionCount++; if(response != null) { - if(response.body() != null) - response.body().close(); + final ResponseBody body = response.body(); + if(body != null) + body.close(); response.close(); } response = chain.proceed(request); diff --git a/src/main/java/com/microsoft/graph/httpcore/TelemetryHandler.java b/src/main/java/com/microsoft/graph/httpcore/TelemetryHandler.java index a3c6de666..fdf1f53ec 100644 --- a/src/main/java/com/microsoft/graph/httpcore/TelemetryHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/TelemetryHandler.java @@ -45,7 +45,7 @@ public class TelemetryHandler implements Interceptor{ private static final String DEFAULT_VERSION_VALUE = "0"; @Override - @Nullable + @Nonnull public Response intercept(@Nonnull final Chain chain) throws IOException { final Request request = chain.request(); final Request.Builder telemetryAddedBuilder = request.newBuilder(); @@ -87,10 +87,14 @@ private String getAndroidAPILevelInternal() { break; } } - final Field sdkVersionField = versionClass.getField("SDK_INT"); - final Object value = sdkVersionField.get(null); - final String valueStr = String.valueOf(value); - return valueStr == null || valueStr == "" ? DEFAULT_VERSION_VALUE : valueStr; + if(versionClass == null) + return DEFAULT_VERSION_VALUE; + else { + final Field sdkVersionField = versionClass.getField("SDK_INT"); + final Object value = sdkVersionField.get(null); + final String valueStr = String.valueOf(value); + return valueStr == null || valueStr.equals("") ? DEFAULT_VERSION_VALUE : valueStr; + } } catch (IllegalAccessException | ClassNotFoundException | NoSuchFieldException ex) { // we're not on android and return "0" to align with java version which returns "0" when running on android return DEFAULT_VERSION_VALUE; From b225b775cde22379f6202ddc56a1fe496408cfbf Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 15 Feb 2021 09:58:50 -0500 Subject: [PATCH 06/13] - lints content package --- .../java/com/microsoft/graph/content/BatchRequestContent.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/microsoft/graph/content/BatchRequestContent.java b/src/main/java/com/microsoft/graph/content/BatchRequestContent.java index 8a6f7d163..935f24c1c 100644 --- a/src/main/java/com/microsoft/graph/content/BatchRequestContent.java +++ b/src/main/java/com/microsoft/graph/content/BatchRequestContent.java @@ -138,10 +138,10 @@ public void removeBatchRequestStepWithId(@Nonnull final String ...stepIds) { for(final String stepId : stepIds) { Objects.requireNonNull(stepId, "parameter stepIds cannot contain null values"); - requests.removeIf(x -> x.id == stepId); + requests.removeIf(x -> stepId.equals(x.id)); for(final BatchRequestStep step : requests) { if(step.dependsOn != null) { - step.dependsOn.removeIf(x -> x == stepId); + step.dependsOn.removeIf(x -> stepId.equals(x)); if(step.dependsOn.isEmpty()) step.dependsOn = null; // so we don't send dependsOn: [] over the wire } From a017c5d815e08fda7f5a0160e7b23d53f2f50329 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 15 Feb 2021 10:03:37 -0500 Subject: [PATCH 07/13] - fixes mocks after linting --- .../graph/httpcore/TelemetryHandlerTest.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/microsoft/graph/httpcore/TelemetryHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/TelemetryHandlerTest.java index e86be6903..795a88091 100644 --- a/src/test/java/com/microsoft/graph/httpcore/TelemetryHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/TelemetryHandlerTest.java @@ -2,9 +2,13 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import java.io.IOException; +import java.net.URL; +import java.util.concurrent.CompletableFuture; import com.microsoft.graph.authentication.IAuthenticationProvider; import org.junit.jupiter.api.Test; @@ -22,11 +26,12 @@ public void telemetryInitTest() { } @Test - @SuppressWarnings("unchecked") public void interceptTest() throws IOException { final String expectedHeader = TelemetryHandler.GRAPH_VERSION_PREFIX +"/" +TelemetryHandler.VERSION; - final OkHttpClient client = HttpClients.createDefault(mock(IAuthenticationProvider.class)); + final IAuthenticationProvider authProvider = mock(IAuthenticationProvider.class); + when(authProvider.getAuthorizationTokenAsync(any(URL.class))).thenReturn(CompletableFuture.completedFuture("")); + final OkHttpClient client = HttpClients.createDefault(authProvider); final Request request = new Request.Builder().url("https://graph.microsoft.com/v1.0/users/").build(); final Response response = client.newCall(request).execute(); assertNotNull(response); @@ -36,10 +41,10 @@ public void interceptTest() throws IOException { } @Test - @SuppressWarnings("unchecked") public void arrayInterceptorsTest() throws IOException { - - final AuthenticationHandler authenticationHandler = new AuthenticationHandler(mock(IAuthenticationProvider.class)); + final IAuthenticationProvider authProvider = mock(IAuthenticationProvider.class); + when(authProvider.getAuthorizationTokenAsync(any(URL.class))).thenReturn(CompletableFuture.completedFuture("")); + final AuthenticationHandler authenticationHandler = new AuthenticationHandler(authProvider); final Interceptor[] interceptors = {new RetryHandler(), new RedirectHandler(), authenticationHandler}; final OkHttpClient client = HttpClients.createFromInterceptors(interceptors); final String expectedHeader = TelemetryHandler.GRAPH_VERSION_PREFIX +"/" From c9b5b43d1e9574bef6f6a11c3230b67325094e8c Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 15 Feb 2021 10:20:47 -0500 Subject: [PATCH 08/13] - lints concurrency package --- .../microsoft/graph/concurrency/ChunkedUploadRequest.java | 2 +- .../graph/concurrency/ChunkedUploadResponseHandler.java | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadRequest.java b/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadRequest.java index badb00375..3d4a99d23 100644 --- a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadRequest.java +++ b/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadRequest.java @@ -63,7 +63,7 @@ protected ChunkedUploadRequest(@Nonnull final String requestUrl, final long totalLength) { this.data = new byte[chunkSize]; System.arraycopy(chunk, 0, this.data, 0, chunkSize); - this.baseRequest = new BaseRequest>(requestUrl, client, options, (Class>)(new ChunkedUploadResult((UploadType)null)).getClass()) { + this.baseRequest = new BaseRequest>(requestUrl, client, options, (Class>)(new ChunkedUploadResult<>((UploadType)null)).getClass()) { }; this.baseRequest.setHttpMethod(HttpMethod.PUT); this.baseRequest.addHeader(CONTENT_RANGE_HEADER_NAME, diff --git a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResponseHandler.java b/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResponseHandler.java index ba7efc8ab..272d341da 100644 --- a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResponseHandler.java +++ b/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResponseHandler.java @@ -39,6 +39,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import okhttp3.MediaType; import okhttp3.Response; import okhttp3.ResponseBody; @@ -105,7 +106,9 @@ public ChunkedUploadResult generateResult( && response.code() < HttpResponseCode.HTTP_MULTIPLE_CHOICES) { try(final ResponseBody body = response.body()) { final String location = response.headers().get("Location"); - if (body.contentType() != null && body.contentType().subtype().contains("json")) { + final MediaType contentType = body.contentType(); + final String subType = contentType == null ? null : contentType.subtype(); + if (subType != null && subType.contains("json")) { return parseJsonUploadResult(body, serializer, logger); } else if (location != null) { logger.logDebug("Upload session is completed (Outlook), uploaded item returned."); From 328245674ce9a3575296ebec543a570d82f6b2be Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 15 Feb 2021 10:40:05 -0500 Subject: [PATCH 09/13] - lints http package --- .../graph/http/CoreHttpProvider.java | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/microsoft/graph/http/CoreHttpProvider.java b/src/main/java/com/microsoft/graph/http/CoreHttpProvider.java index 17cf3c5ff..4f8dbf059 100644 --- a/src/main/java/com/microsoft/graph/http/CoreHttpProvider.java +++ b/src/main/java/com/microsoft/graph/http/CoreHttpProvider.java @@ -43,6 +43,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Scanner; import javax.annotation.Nonnull; @@ -100,18 +101,13 @@ public class CoreHttpProvider implements IHttpProvider { */ public CoreHttpProvider(@Nonnull final ISerializer serializer, @Nonnull final ILogger logger, - @Nullable final OkHttpClient httpClient) { - if (httpClient == null) { - throw new NullPointerException("httpClient"); - } else if(serializer == null) { - throw new NullPointerException("serializer"); - } else if(logger == null) { - throw new NullPointerException("logger"); - } else { - this.serializer = serializer; - this.logger = logger; - this.corehttpClient = httpClient; - } + @Nonnull final OkHttpClient httpClient) { + Objects.requireNonNull(logger, "parameter logger cannot be null"); + Objects.requireNonNull(serializer, "parameter serializer cannot be null"); + Objects.requireNonNull(httpClient, "parameter httpClient cannot be null"); + this.serializer = serializer; + this.logger = logger; + this.corehttpClient = httpClient; } /** @@ -135,7 +131,7 @@ public ISerializer getSerializer() { * @return a future with the result */ @Override - @Nullable + @Nonnull public java.util.concurrent.CompletableFuture sendAsync(@Nonnull final IHttpRequest request, @Nonnull final Class resultClass, @Nullable final Body serializable) { @@ -157,13 +153,13 @@ public java.util.concurrent.CompletableFuture sendAsync(@ * @return a future with the result * @throws ClientException this exception occurs if the request was unable to complete for any reason */ - @Nullable + @Nonnull public java.util.concurrent.CompletableFuture sendAsync(@Nonnull final IHttpRequest request, @Nonnull final Class resultClass, @Nullable final BodyType serializable, - @Nonnull final IStatefulResponseHandler handler) + @Nullable final IStatefulResponseHandler handler) throws ClientException { - return sendFutureRequestInternal(request, + return sendRequestAsyncInternal(request, resultClass, serializable, handler); @@ -206,7 +202,7 @@ public Result send(@Nonnull final IHttpRequest request, public Result send(@Nonnull final IHttpRequest request, @Nonnull final Class resultClass, @Nullable final Body serializable, - @Nonnull final IStatefulResponseHandler handler) throws ClientException { + @Nullable final IStatefulResponseHandler handler) throws ClientException { return sendRequestInternal(request, resultClass, serializable, handler); } /** @@ -344,8 +340,8 @@ public MediaType contentType() { * @return the result from the request * @throws ClientException an exception occurs if the request was unable to complete for any reason */ - @Nullable - private java.util.concurrent.CompletableFuture sendFutureRequestInternal(@Nonnull final IHttpRequest request, + @Nonnull + private java.util.concurrent.CompletableFuture sendRequestAsyncInternal(@Nonnull final IHttpRequest request, @Nonnull final Class resultClass, @Nullable final Body serializable, @Nullable final IStatefulResponseHandler handler) @@ -389,6 +385,7 @@ private Result processResponse(final Response re final Class resultClass, final Body serializable, final IStatefulResponseHandler handler) { + if (response == null) return null; final ResponseBody body = response.body(); try { InputStream in = null; @@ -412,7 +409,7 @@ private Result processResponse(final Response re request, response, this.serializer, this.logger); } - if (response.code() >= HttpResponseCode.HTTP_CLIENT_ERROR) { + if (response.code() >= HttpResponseCode.HTTP_CLIENT_ERROR && body != null) { logger.logDebug("Handling error response"); in = body.byteStream(); handleErrorResponse(request, serializable, response); @@ -431,12 +428,13 @@ private Result processResponse(final Response re return handleEmptyResponse(responseHeaders, resultClass); } - in = new BufferedInputStream(body.byteStream()); - if (body == null || body.contentLength() == 0) return null; - if (body.contentType() != null && body.contentType().subtype().contains("json") + in = new BufferedInputStream(body.byteStream()); + + final MediaType contentType = body.contentType(); + if (contentType != null && contentType.subtype().contains("json") && resultClass != InputStream.class) { logger.logDebug("Response json"); return handleJsonResponse(in, responseHeaders, resultClass); @@ -444,9 +442,9 @@ private Result processResponse(final Response re logger.logDebug("Response binary"); isBinaryStreamInput = true; return (Result) handleBinaryStream(in); - } else if (body.contentType() != null && resultClass != InputStream.class && - body.contentType().type().contains("text") && - body.contentType().subtype().contains("plain")) { + } else if (contentType != null && resultClass != InputStream.class && + contentType.type().contains("text") && + contentType.subtype().contains("plain")) { return handleRawResponse(in, resultClass); } else { return null; @@ -459,7 +457,7 @@ private Result processResponse(final Response re }catch(IOException e) { logger.logError(e.getMessage(), e); } - if (response != null) response.close(); + response.close(); } } } catch (final GraphServiceException ex) { From 27aec578b21a41d3022fb2e36a7d7c738ee6886c Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 15 Feb 2021 10:48:32 -0500 Subject: [PATCH 10/13] - enables html report for tests spotbugs --- build.gradle | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/build.gradle b/build.gradle index b434b4018..e5853d161 100644 --- a/build.gradle +++ b/build.gradle @@ -43,6 +43,16 @@ spotbugsMain { } } +spotbugsTest { + reports { + html { + enabled = true + destination = file("$buildDir/reports/spotbugs/test/spotbugs.html") + stylesheet = 'fancy-hist.xsl' + } + } +} + jacocoTestReport { reports { xml.enabled true From b8c42363227c8a48e01d4b80f9a40996f4346490 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 15 Feb 2021 14:26:47 -0500 Subject: [PATCH 11/13] - lints unit tests --- .../TokenCredentialAuthProviderTest.java | 2 +- .../content/BatchResponseContentTest.java | 40 +++++++++---------- .../microsoft/graph/core/BaseClientTests.java | 15 ++++--- .../graph/core/GraphServiceClientTest.java | 5 ++- .../graph/http/BaseCollectionPageTests.java | 2 +- .../http/BaseCollectionRequestTests.java | 4 +- .../graph/http/BaseRequestBuilderTests.java | 7 ++-- .../graph/http/BaseRequestTests.java | 12 +++--- .../graph/http/BaseStreamRequestTests.java | 2 +- .../http/GraphFatalServiceExceptionTests.java | 4 +- .../http/GraphServiceExceptionTests.java | 4 +- .../graph/http/ReferenceRequestBodyTests.java | 2 +- .../graph/httpcore/RetryHandlerTest.java | 6 +-- 13 files changed, 53 insertions(+), 52 deletions(-) diff --git a/src/test/java/com/microsoft/graph/authentication/TokenCredentialAuthProviderTest.java b/src/test/java/com/microsoft/graph/authentication/TokenCredentialAuthProviderTest.java index 339cf4ee5..6868eb01c 100644 --- a/src/test/java/com/microsoft/graph/authentication/TokenCredentialAuthProviderTest.java +++ b/src/test/java/com/microsoft/graph/authentication/TokenCredentialAuthProviderTest.java @@ -15,7 +15,7 @@ public class TokenCredentialAuthProviderTest { - public final String testToken = "CredentialTestToken"; + private static final String testToken = "CredentialTestToken"; @Test public void providerAddsTokenOnValidHostName() throws MalformedURLException, InterruptedException, diff --git a/src/test/java/com/microsoft/graph/content/BatchResponseContentTest.java b/src/test/java/com/microsoft/graph/content/BatchResponseContentTest.java index 27ae876e5..6414b7252 100644 --- a/src/test/java/com/microsoft/graph/content/BatchResponseContentTest.java +++ b/src/test/java/com/microsoft/graph/content/BatchResponseContentTest.java @@ -2,6 +2,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -9,7 +10,6 @@ import java.io.IOException; import java.util.Iterator; -import java.util.Map; import com.google.gson.JsonElement; import com.microsoft.graph.http.GraphErrorResponse; @@ -20,13 +20,6 @@ import org.junit.jupiter.api.Test; -import okhttp3.MediaType; -import okhttp3.Protocol; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; -import okhttp3.ResponseBody; - public class BatchResponseContentTest { @Test public void testValidBatchResponseContent() { @@ -102,20 +95,23 @@ public void deserializesErrorsProperly() { String responsebody = "{\"responses\":[{\"id\":\"1\",\"status\":400,\"headers\":{\"Cache-Control\":\"no-cache\",\"x-ms-resource-unit\":\"1\",\"Content-Type\":\"application/json\"},\"body\":{\"error\":{\"code\":\"Request_BadRequest\",\"message\":\"Avalueisrequiredforproperty'displayName'ofresource'User'.\",\"innerError\":{\"date\":\"2021-02-02T19:19:38\",\"request-id\":\"408b8e64-4047-4c97-95b6-46e9f212ab48\",\"client-request-id\":\"102910da-260c-3028-0fb3-7d6903a02622\"}}}}]}"; ISerializer serializer = new DefaultSerializer(mock(ILogger.class)); BatchResponseContent batchresponse = serializer.deserializeObject(responsebody, BatchResponseContent.class); - if(batchresponse != null && batchresponse.responses != null) // this is done by the batch request in the fluent API - for(final BatchResponseStep step : batchresponse.responses) { - step.serializer = serializer; + if(batchresponse != null) { + if(batchresponse.responses != null) // this is done by the batch request in the fluent API + for(final BatchResponseStep step : batchresponse.responses) { + step.serializer = serializer; + } + assertThrows(GraphServiceException.class, () -> { + batchresponse.getResponseById("1").getDeserializedBody(BatchRequestContent.class); + }); + try { + batchresponse.getResponseById("1").getDeserializedBody(BatchRequestContent.class); + } catch(GraphServiceException ex) { + final GraphErrorResponse response = ex.getError(); + assertNotNull(response); + assertNotNull(response.error); + assertNotNull(response.error.message); } - assertThrows(GraphServiceException.class, () -> { - final Object body = batchresponse.getResponseById("1").getDeserializedBody(BatchRequestContent.class); - }); - try { - final Object body = batchresponse.getResponseById("1").getDeserializedBody(BatchRequestContent.class); - } catch(GraphServiceException ex) { - final GraphErrorResponse response = ex.getError(); - assertNotNull(response); - assertNotNull(response.error); - assertNotNull(response.error.message); - } + } else + fail("batch response was null"); } } diff --git a/src/test/java/com/microsoft/graph/core/BaseClientTests.java b/src/test/java/com/microsoft/graph/core/BaseClientTests.java index a3fbfb52b..3d853e493 100644 --- a/src/test/java/com/microsoft/graph/core/BaseClientTests.java +++ b/src/test/java/com/microsoft/graph/core/BaseClientTests.java @@ -14,6 +14,7 @@ import okhttp3.OkHttpClient; import okhttp3.Request; +import okhttp3.RequestBody; import okio.BufferedSink; import okio.Okio; @@ -97,11 +98,15 @@ public void testCustomRequest() { } private String getStringFromRequestBody(Request request) { try { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - final BufferedSink buffer = Okio.buffer(Okio.sink(out)); - request.body().writeTo(buffer); - ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); - return CoreHttpProvider.streamToString(in); + try(final ByteArrayOutputStream out = new ByteArrayOutputStream()) { + final BufferedSink buffer = Okio.buffer(Okio.sink(out)); + final RequestBody body = request.body(); + if(body != null) + body.writeTo(buffer); + try(final ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray())) { + return CoreHttpProvider.streamToString(in); + } + } } catch (Exception ex) { ex.printStackTrace(); return ""; diff --git a/src/test/java/com/microsoft/graph/core/GraphServiceClientTest.java b/src/test/java/com/microsoft/graph/core/GraphServiceClientTest.java index c9a018374..14c211583 100644 --- a/src/test/java/com/microsoft/graph/core/GraphServiceClientTest.java +++ b/src/test/java/com/microsoft/graph/core/GraphServiceClientTest.java @@ -10,6 +10,7 @@ import java.io.InputStream; import java.util.List; import java.util.Map; +import java.util.concurrent.CompletableFuture; import org.junit.jupiter.api.Test; @@ -119,12 +120,12 @@ public ISerializer getSerializer() { @Override public java.util.concurrent.CompletableFuture sendAsync(IHttpRequest request, Class resultClass, BodyType serializable) { - return null; + return CompletableFuture.completedFuture(null); } @Override public java.util.concurrent.CompletableFuture sendAsync(IHttpRequest request, Class resultClass, BodyType serializable, final IStatefulResponseHandler handler) { - return null; + return CompletableFuture.completedFuture(null); } @Override diff --git a/src/test/java/com/microsoft/graph/http/BaseCollectionPageTests.java b/src/test/java/com/microsoft/graph/http/BaseCollectionPageTests.java index 91693e427..d677327a6 100644 --- a/src/test/java/com/microsoft/graph/http/BaseCollectionPageTests.java +++ b/src/test/java/com/microsoft/graph/http/BaseCollectionPageTests.java @@ -23,7 +23,7 @@ public class BaseCollectionPageTests { private BaseRequestBuilder mRequestBuilder; - private static ArrayList list; + private ArrayList list; private BaseCollectionPage> baseCollectionPage; private String requestUrl = "https://a.b.c/"; diff --git a/src/test/java/com/microsoft/graph/http/BaseCollectionRequestTests.java b/src/test/java/com/microsoft/graph/http/BaseCollectionRequestTests.java index 7f01e21b4..7865618a9 100644 --- a/src/test/java/com/microsoft/graph/http/BaseCollectionRequestTests.java +++ b/src/test/java/com/microsoft/graph/http/BaseCollectionRequestTests.java @@ -93,7 +93,7 @@ public void testSend() { @Test public void testPost() { - final ICollectionResponse result = mRequest.post(null); + final ICollectionResponse result = mRequest.post(new JsonObject()); assertNotNull(result); assertEquals("zzz", result.values().get(0).get("id").getAsString()); } @@ -156,7 +156,7 @@ public void testGetMethod() { @Test public void testPostMethod() { assertNull(mRequest.getHttpMethod()); - mRequest.post(null); + mRequest.post(new JsonObject()); assertEquals(HttpMethod.POST, mRequest.getHttpMethod()); } diff --git a/src/test/java/com/microsoft/graph/http/BaseRequestBuilderTests.java b/src/test/java/com/microsoft/graph/http/BaseRequestBuilderTests.java index ea1ff68bf..c61caf5f2 100644 --- a/src/test/java/com/microsoft/graph/http/BaseRequestBuilderTests.java +++ b/src/test/java/com/microsoft/graph/http/BaseRequestBuilderTests.java @@ -2,12 +2,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.mock; + +import com.microsoft.graph.core.IBaseClient; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import okhttp3.Request; - /** * Test cases for {@see BaseRequestBuilder} */ @@ -18,7 +19,7 @@ public class BaseRequestBuilderTests { @BeforeEach public void setUp() throws Exception { - baseRequestBuilder = new BaseRequestBuilder<>(expectedRequestUrl,null,null){}; + baseRequestBuilder = new BaseRequestBuilder<>(expectedRequestUrl, mock(IBaseClient.class), null){}; } @Test diff --git a/src/test/java/com/microsoft/graph/http/BaseRequestTests.java b/src/test/java/com/microsoft/graph/http/BaseRequestTests.java index f1a25ba62..27c8d95c3 100644 --- a/src/test/java/com/microsoft/graph/http/BaseRequestTests.java +++ b/src/test/java/com/microsoft/graph/http/BaseRequestTests.java @@ -75,7 +75,7 @@ public void testSendWithCallback() throws InterruptedException, ExecutionExcepti public void testFunctionParameters() { final Option fo1 = new FunctionOption("1", "one"); final Option fo2 = new FunctionOption("2", null); - final BaseRequest request = new BaseRequest("https://a.b.c/", mock(IBaseClient.class), Arrays.asList(fo1, fo2), null){}; + final BaseRequest request = new BaseRequest("https://a.b.c/", mock(IBaseClient.class), Arrays.asList(fo1, fo2), Void.class){}; assertEquals("https://a.b.c/(1='one',2=null)", request.getRequestUrl().toString()); request.addFunctionOption(new FunctionOption("3","two"));; assertEquals("https://a.b.c/(1='one',2=null,3='two')", request.getRequestUrl().toString()); @@ -86,7 +86,7 @@ public void testFunctionParameters() { public void testQueryParameters() { final Option q1 = new QueryOption("q1","option1 "); final Option q2 = new QueryOption("q2","option2"); - final BaseRequest request = new BaseRequest("https://a.b.c/", mock(IBaseClient.class), Arrays.asList(q1, q2), null){}; + final BaseRequest request = new BaseRequest("https://a.b.c/", mock(IBaseClient.class), Arrays.asList(q1, q2), Void.class){}; assertEquals("https://a.b.c/?q1=option1%20&q2=option2", request.getRequestUrl().toString()); request.addQueryOption(new QueryOption("q3","option3")); assertEquals("https://a.b.c/?q1=option1%20&q2=option2&q3=option3", request.getRequestUrl().toString()); @@ -99,14 +99,14 @@ public void testFunctionAndQueryParameters() { final Option f2 = new FunctionOption("f2", null); final Option q1 = new QueryOption("q1","option1 "); final Option q2 = new QueryOption("q2","option2"); - final BaseRequest request = new BaseRequest("https://a.b.c/", mock(IBaseClient.class), Arrays.asList(f1, f2, q1, q2), null){}; + final BaseRequest request = new BaseRequest("https://a.b.c/", mock(IBaseClient.class), Arrays.asList(f1, f2, q1, q2), Void.class){}; assertEquals("https://a.b.c/(f1='fun1',f2=null)?q1=option1%20&q2=option2", request.getRequestUrl().toString()); assertEquals(4, request.getOptions().size()); } @Test public void testHttpMethod() { - final BaseRequest request = new BaseRequest("https://a.b.c/", mock(IBaseClient.class), null, null){}; + final BaseRequest request = new BaseRequest("https://a.b.c/", mock(IBaseClient.class), null, Void.class){}; assertNull(request.getHttpMethod()); request.setHttpMethod(HttpMethod.GET); assertEquals(HttpMethod.GET, request.getHttpMethod()); @@ -116,7 +116,7 @@ public void testHttpMethod() { public void testHeader() { final String expectedHeader = "header key"; final String expectedValue = "header value"; - final BaseRequest request = new BaseRequest("https://a.b.c/", mock(IBaseClient.class), null, null){}; + final BaseRequest request = new BaseRequest("https://a.b.c/", mock(IBaseClient.class), null, Void.class){}; assertEquals(0, request.getHeaders().size()); request.addHeader(expectedHeader,expectedValue); assertEquals(1,request.getHeaders().size()); @@ -128,7 +128,7 @@ public void testProtectedProperties() { assertEquals(0, mRequest.queryOptions.size()); final Option q1 = new QueryOption("q1","option1 "); final Option f1 = new FunctionOption("f1","option2"); - final BaseRequest request = new BaseRequest("https://a.b.c/", mock(IBaseClient.class), Arrays.asList(q1,f1), null){}; + final BaseRequest request = new BaseRequest("https://a.b.c/", mock(IBaseClient.class), Arrays.asList(q1,f1), Void.class){}; assertEquals(1, request.functionOptions.size()); assertEquals(1, request.queryOptions.size()); assertEquals("q1", request.queryOptions.get(0).getName()); diff --git a/src/test/java/com/microsoft/graph/http/BaseStreamRequestTests.java b/src/test/java/com/microsoft/graph/http/BaseStreamRequestTests.java index dbf528afd..bbbfd8f2c 100644 --- a/src/test/java/com/microsoft/graph/http/BaseStreamRequestTests.java +++ b/src/test/java/com/microsoft/graph/http/BaseStreamRequestTests.java @@ -60,7 +60,7 @@ public void testSend() throws IOException { mock(ILogger.class), mockClient); when(mBaseClient.getHttpProvider()).thenReturn(mProvider); - final BaseStreamRequest request = new BaseStreamRequest<>("https://a.b.c/", mBaseClient,null, null){}; + final BaseStreamRequest request = new BaseStreamRequest<>("https://a.b.c/", mBaseClient,null, String.class){}; request.send(); } diff --git a/src/test/java/com/microsoft/graph/http/GraphFatalServiceExceptionTests.java b/src/test/java/com/microsoft/graph/http/GraphFatalServiceExceptionTests.java index 998f45569..682027503 100644 --- a/src/test/java/com/microsoft/graph/http/GraphFatalServiceExceptionTests.java +++ b/src/test/java/com/microsoft/graph/http/GraphFatalServiceExceptionTests.java @@ -10,9 +10,9 @@ public class GraphFatalServiceExceptionTests { @Test public void testGraphFatalServiceException() { - GraphFatalServiceException exception = new GraphFatalServiceException(null,null,new ArrayList(),null,401,"Unauthenticated",new ArrayList(),null, false); + GraphFatalServiceException exception = new GraphFatalServiceException("GET", "https://graph.microsoft.com/v1.0/me",new ArrayList(),null,401,"Unauthenticated",new ArrayList(),null, false); String expectedMessage = "Unexpected exception returned from the service." + - "null null\n" + + "GET https://graph.microsoft.com/v1.0/me\n" + "\n" + "\n" + "401 : Unauthenticated\n" + diff --git a/src/test/java/com/microsoft/graph/http/GraphServiceExceptionTests.java b/src/test/java/com/microsoft/graph/http/GraphServiceExceptionTests.java index d092010b6..b2f577843 100644 --- a/src/test/java/com/microsoft/graph/http/GraphServiceExceptionTests.java +++ b/src/test/java/com/microsoft/graph/http/GraphServiceExceptionTests.java @@ -31,7 +31,7 @@ public void testError() { GraphError error = new GraphError(); error.code = GraphErrorCodes.UNAUTHENTICATED.toString(); errorResponse.error = error; - GraphServiceException exception = new GraphServiceException(null,null,new ArrayList(),null,401,"Unauthorized",new ArrayList(),errorResponse, false); + GraphServiceException exception = new GraphServiceException("GET","https://graph.microsoft.com/v1.0/me",new ArrayList(),null,401,"Unauthorized",new ArrayList(),errorResponse, false); String message = exception.getMessage(); assertTrue(message.indexOf("Error code: UNAUTHENTICATED") == 0); assertTrue(message.indexOf("401 : Unauthorized") > 0); @@ -45,7 +45,7 @@ public void testVerboseError() { GraphError error = new GraphError(); error.code = GraphErrorCodes.UNAUTHENTICATED.toString(); errorResponse.error = error; - GraphServiceException exception = new GraphServiceException(null,null,new ArrayList(),null,401,"Unauthorized",new ArrayList(),errorResponse, true); + GraphServiceException exception = new GraphServiceException("GET","https://graph.microsoft.com/v1.0/me",new ArrayList(),null,401,"Unauthorized",new ArrayList(),errorResponse, true); String message = exception.getMessage(); assertTrue(message.indexOf("Error code: UNAUTHENTICATED") == 0); assertTrue(message.indexOf("401 : Unauthorized") > 0); diff --git a/src/test/java/com/microsoft/graph/http/ReferenceRequestBodyTests.java b/src/test/java/com/microsoft/graph/http/ReferenceRequestBodyTests.java index 124b3e209..cfd1ada8f 100644 --- a/src/test/java/com/microsoft/graph/http/ReferenceRequestBodyTests.java +++ b/src/test/java/com/microsoft/graph/http/ReferenceRequestBodyTests.java @@ -11,7 +11,7 @@ public class ReferenceRequestBodyTests { @Test public void testRawObject() { - ReferenceRequestBody body = new ReferenceRequestBody(null); + ReferenceRequestBody body = new ReferenceRequestBody(""); ISerializer serializer = mock(ISerializer.class); JsonObject jsonObject = new JsonObject(); body.setRawObject(serializer,jsonObject); diff --git a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java index 688d4812e..466d2572c 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java @@ -21,10 +21,8 @@ public class RetryHandlerTest { - int maxRetries = 2; - int retryInterval = 1000; - String testmeurl = "https://graph.microsoft.com/v1.0/me"; - private final int HTTP_SERVER_ERROR = 500; + private static final String testmeurl = "https://graph.microsoft.com/v1.0/me"; + private static final int HTTP_SERVER_ERROR = 500; @Test public void testRetryHandlerCreation() { From 752e808dfcb31e72114fd6fa217f556efcb08481 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 15 Feb 2021 14:40:51 -0500 Subject: [PATCH 12/13] - adds spotbugs exclusions --- build.gradle | 2 ++ spotBugsExcludeFilter.xml | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 spotBugsExcludeFilter.xml diff --git a/build.gradle b/build.gradle index e5853d161..923ea3704 100644 --- a/build.gradle +++ b/build.gradle @@ -34,6 +34,7 @@ jacoco { } spotbugsMain { + excludeFilter = file("spotBugsExcludeFilter.xml") reports { html { enabled = true @@ -44,6 +45,7 @@ spotbugsMain { } spotbugsTest { + excludeFilter = file("spotBugsExcludeFilter.xml") reports { html { enabled = true diff --git a/spotBugsExcludeFilter.xml b/spotBugsExcludeFilter.xml new file mode 100644 index 000000000..31e4a5f86 --- /dev/null +++ b/spotBugsExcludeFilter.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file From ab2ff3093be70001cb355048839fbc863ffc8f7f Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 15 Feb 2021 16:09:11 -0500 Subject: [PATCH 13/13] - adds missing defensive programming for nonnull annotations --- .../concurrency/ChunkedUploadProvider.java | 17 ++------- .../concurrency/ChunkedUploadRequest.java | 5 +++ .../ChunkedUploadResponseHandler.java | 9 ++++- .../concurrency/ChunkedUploadResult.java | 8 +++- .../microsoft/graph/content/BatchRequest.java | 6 +-- .../com/microsoft/graph/core/BaseClient.java | 37 +++++++------------ .../graph/core/CustomRequestBuilder.java | 3 +- .../com/microsoft/graph/core/DateOnly.java | 2 + .../com/microsoft/graph/core/Multipart.java | 5 ++- .../com/microsoft/graph/core/TimeOfDay.java | 2 + .../graph/http/BaseCollectionRequest.java | 29 +++++++++++---- .../http/BaseCollectionRequestBuilder.java | 6 ++- .../graph/http/BaseCollectionResponse.java | 5 +++ ...ollectionWithReferencesRequestBuilder.java | 3 +- .../http/BaseDeltaCollectionRequest.java | 12 +++--- .../http/BaseEntityCollectionRequest.java | 2 +- .../http/BaseReferenceRequestBuilder.java | 3 +- .../com/microsoft/graph/http/BaseRequest.java | 32 +++++++++++----- .../graph/http/BaseRequestBuilder.java | 7 +++- .../graph/http/BaseStreamRequest.java | 11 +++++- .../graph/http/BaseWithReferenceRequest.java | 9 ++++- .../http/BaseWithReferenceRequestBuilder.java | 5 ++- .../graph/http/CoreHttpProvider.java | 11 ++++++ .../microsoft/graph/http/CustomRequest.java | 10 +++++ .../com/microsoft/graph/http/GraphError.java | 5 +++ .../graph/http/GraphErrorResponse.java | 7 +++- .../graph/http/GraphServiceException.java | 16 +++++--- .../graph/http/PrimitiveRequestBuilder.java | 5 ++- .../graph/http/ReferenceRequestBody.java | 5 ++- .../microsoft/graph/httpcore/HttpClients.java | 2 + .../middlewareoption/TelemetryOptions.java | 3 +- .../microsoft/graph/logger/DefaultLogger.java | 24 +++++++----- .../graph/serializer/ByteArraySerializer.java | 11 ++++-- .../serializer/CollectionPageSerializer.java | 2 + .../graph/serializer/DefaultSerializer.java | 17 ++++++--- .../graph/serializer/EnumSetSerializer.java | 11 ++++-- .../FallbackTypeAdapterFactory.java | 25 +++++++------ .../serializer/OffsetDateTimeSerializer.java | 3 ++ .../graph/http/GraphErrorResponseTests.java | 4 +- 39 files changed, 253 insertions(+), 126 deletions(-) diff --git a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadProvider.java b/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadProvider.java index 8e9ce8f33..ce0c61989 100644 --- a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadProvider.java +++ b/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadProvider.java @@ -30,6 +30,7 @@ import java.io.InputStream; import java.security.InvalidParameterException; import java.util.List; +import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -103,25 +104,15 @@ public ChunkedUploadProvider(@Nonnull final IUploadSession uploadSession, @Nonnull final InputStream inputStream, final long streamSize, @Nonnull final Class uploadTypeClass) { - if (uploadSession == null) { - throw new InvalidParameterException("Upload session is null."); - } - - if (client == null) { - throw new InvalidParameterException("OneDrive client is null."); - } - - if (inputStream == null) { - throw new InvalidParameterException("Input stream is null."); - } + Objects.requireNonNull(uploadSession, "Upload session is null."); if (streamSize <= 0) { throw new InvalidParameterException("Stream size should larger than 0."); } - this.client = client; + this.client = Objects.requireNonNull(client, "Graph client is null."); this.readSoFar = 0; - this.inputStream = inputStream; + this.inputStream = Objects.requireNonNull(inputStream, "Input stream is null."); this.streamSize = streamSize; this.uploadUrl = uploadSession.getUploadUrl(); this.responseHandler = new ChunkedUploadResponseHandler(uploadTypeClass, uploadSession.getClass()); diff --git a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadRequest.java b/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadRequest.java index 3d4a99d23..1ac59126c 100644 --- a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadRequest.java +++ b/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadRequest.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Locale; +import java.util.Objects; import javax.annotation.Nullable; import javax.annotation.Nonnull; @@ -61,6 +62,9 @@ protected ChunkedUploadRequest(@Nonnull final String requestUrl, final int chunkSize, final long beginIndex, final long totalLength) { + Objects.requireNonNull(requestUrl, "parameter requestUrl cannot be null"); + Objects.requireNonNull(client, "parameter client cannot be null"); + Objects.requireNonNull(chunk, "parameter chunk cannot be null"); this.data = new byte[chunkSize]; System.arraycopy(chunk, 0, this.data, 0, chunkSize); this.baseRequest = new BaseRequest>(requestUrl, client, options, (Class>)(new ChunkedUploadResult<>((UploadType)null)).getClass()) { @@ -84,6 +88,7 @@ protected ChunkedUploadRequest(@Nonnull final String requestUrl, @Nonnull public ChunkedUploadResult upload( @Nonnull final ChunkedUploadResponseHandler responseHandler) { + Objects.requireNonNull(responseHandler, "parameter responseHandler cannot be null"); ChunkedUploadResult result = null; try { diff --git a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResponseHandler.java b/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResponseHandler.java index 272d341da..c571407a0 100644 --- a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResponseHandler.java +++ b/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResponseHandler.java @@ -35,6 +35,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.Objects; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -65,8 +66,8 @@ public class ChunkedUploadResponseHandler * @param uploadSessionType the type of the upload session */ protected ChunkedUploadResponseHandler(@Nonnull final Class uploadType, @Nonnull final Class uploadSessionType) { - this.deserializeTypeClass = uploadType; - this.uploadSessionClass = uploadSessionType; + this.deserializeTypeClass = Objects.requireNonNull(uploadType, "parameter uploadType cannot be null"); + this.uploadSessionClass = Objects.requireNonNull(uploadSessionType, "parameter uploadSessionType cannot be null"); } /** @@ -96,6 +97,10 @@ public ChunkedUploadResult generateResult( @Nonnull final Response response, @Nonnull final ISerializer serializer, @Nonnull final ILogger logger) throws Exception { + Objects.requireNonNull(request, "parameter request cannot be null"); + Objects.requireNonNull(response, "parameter response cannot be null"); + Objects.requireNonNull(serializer, "parameter serializer cannot be null"); + Objects.requireNonNull(logger, "parameter logger cannot be null"); if (response.code() >= HttpResponseCode.HTTP_CLIENT_ERROR) { logger.logDebug("Receiving error during upload, see detail on result error"); diff --git a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResult.java b/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResult.java index 81a5e1c72..7894bb55c 100644 --- a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResult.java +++ b/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResult.java @@ -8,6 +8,9 @@ import com.microsoft.graph.http.GraphServiceException; import javax.annotation.Nullable; + +import java.util.Objects; + import javax.annotation.Nonnull; /** @@ -68,7 +71,10 @@ protected ChunkedUploadResult(@Nullable final ClientException error) { * @param exception The exception received from server. */ protected ChunkedUploadResult(@Nonnull final GraphServiceException exception) { - this(new ClientException(exception.getMessage(/* verbose */ true), exception)); + this(new ClientException(Objects + .requireNonNull(exception, "parameter exception cannot be null") + .getMessage(/* verbose */ true), + exception)); } /** diff --git a/src/main/java/com/microsoft/graph/content/BatchRequest.java b/src/main/java/com/microsoft/graph/content/BatchRequest.java index ce65cdb42..ae7b732c4 100644 --- a/src/main/java/com/microsoft/graph/content/BatchRequest.java +++ b/src/main/java/com/microsoft/graph/content/BatchRequest.java @@ -43,7 +43,7 @@ public class BatchRequest extends BaseRequest { * @param client the client to use to execute the request * @param options the options to apply to the request */ - public BatchRequest(@Nonnull final String requestUrl, @Nonnull final IBaseClient client, @Nonnull final List options) { + public BatchRequest(@Nonnull final String requestUrl, @Nonnull final IBaseClient client, @Nonnull final List options) { super(requestUrl, client, options, BatchResponseContent.class); } @@ -55,7 +55,7 @@ public BatchRequest(@Nonnull final String requestUrl, @Nonnull final IBaseClient * @throws ClientException an exception occurs if there was an error while the request was sent */ @Nullable - public BatchResponseContent post(@Nonnull final BatchRequestContent content) throws ClientException { + public BatchResponseContent post(@Nullable final BatchRequestContent content) throws ClientException { this.setHttpMethod(HttpMethod.POST); final BatchResponseContent response = this.getClient().getHttpProvider().send(this, BatchResponseContent.class, content); setSerializerOnSteps(response); @@ -69,7 +69,7 @@ public BatchResponseContent post(@Nonnull final BatchRequestContent content) thr * @throws ClientException an exception occurs if there was an error while the request was sent */ @Nullable - public java.util.concurrent.CompletableFuture postAsync(@Nonnull final BatchRequestContent content) throws ClientException { + public java.util.concurrent.CompletableFuture postAsync(@Nullable final BatchRequestContent content) throws ClientException { this.setHttpMethod(HttpMethod.POST); return this.getClient().getHttpProvider().sendAsync(this, BatchResponseContent.class, content).thenApply(response -> { setSerializerOnSteps(response); diff --git a/src/main/java/com/microsoft/graph/core/BaseClient.java b/src/main/java/com/microsoft/graph/core/BaseClient.java index 6a94a3c66..cc0a2e333 100644 --- a/src/main/java/com/microsoft/graph/core/BaseClient.java +++ b/src/main/java/com/microsoft/graph/core/BaseClient.java @@ -75,7 +75,7 @@ public String getServiceRoot() { @Override public void setServiceRoot(@Nonnull final String value) { - endpoint = value; + endpoint = Objects.requireNonNull(value, "value parameter cannot be null"); } /** @@ -89,7 +89,9 @@ public void setServiceRoot(@Nonnull final String value) { */ @Nonnull public CustomRequestBuilder customRequest(@Nonnull final String url, @Nonnull final Class responseType) { - return new CustomRequestBuilder<>(getServiceRoot() + url, this, null, responseType); + Objects.requireNonNull(url, "url parameter cannot be null"); + Objects.requireNonNull(responseType, "responseType parameter cannot be null"); + return new CustomRequestBuilder<>(getServiceRoot() + url, this, null, responseType); } /** @@ -101,8 +103,7 @@ public CustomRequestBuilder customRequest(@Nonnull final String url, @Non */ @Nonnull public CustomRequestBuilder customRequest(@Nonnull final String url) { - return new CustomRequestBuilder<>(getServiceRoot() + url, this, null, - JsonElement.class); + return this.customRequest(url, JsonElement.class); } /** @@ -197,7 +198,7 @@ private IHttpProvider getHttpProvider() { */ @Nonnull public Builder serializer(@Nonnull final ISerializer serializer) { - checkNotNull(serializer, "serializer"); + Objects.requireNonNull(serializer, "parameter serializer cannot be null"); this.serializer = serializer; return this; } @@ -211,7 +212,7 @@ public Builder serializer(@Nonnull final ISer */ @Nonnull public Builder httpProvider(@Nonnull final IHttpProvider httpProvider) { - checkNotNull(httpProvider, "httpProvider"); + Objects.requireNonNull(httpProvider, "parameter httpProvider cannot be null"); this.httpProvider = httpProvider; return this; } @@ -225,7 +226,7 @@ public Builder httpProvider(@Nonnull final IH */ @Nonnull public Builder logger(@Nonnull final ILogger logger) { - checkNotNull(logger, "logger"); + Objects.requireNonNull(logger, "parameter logger cannot be null"); this.logger = logger; return this; } @@ -239,7 +240,7 @@ public Builder logger(@Nonnull final ILogger */ @Nonnull public Builder httpClient(@Nonnull final httpClientType client) { - checkNotNull(client, "client"); + Objects.requireNonNull(client, "parameter client cannot be null"); this.httpClient = client; return this; } @@ -252,7 +253,7 @@ public Builder httpClient(@Nonnull final http */ @Nonnull public Builder authenticationProvider(@Nonnull final IAuthenticationProvider auth) { - checkNotNull(auth, "auth"); + Objects.requireNonNull(auth, "parameter auth cannot be null"); this.auth = auth; return this; } @@ -288,18 +289,6 @@ public IBaseClient buildClient() throws ClientException { } } - /** - * Checks whether the provided object is null or not and throws an exception if it is - * - * @param o object to check - * @param name name to use in the exception message - */ - protected static void checkNotNull(@Nullable final Object o, @Nonnull final String name) { - if (o==null) { - throw new NullPointerException(name + " cannot be null"); - } - } - /** * The HTTP provider instance */ @@ -353,7 +342,7 @@ public ISerializer getSerializer() { * @param logger The logger */ protected void setLogger(@Nonnull final ILogger logger) { - checkNotNull(logger, "logger"); + Objects.requireNonNull(logger, "parameter logger cannot be null"); this.logger = logger; } @@ -363,7 +352,7 @@ protected void setLogger(@Nonnull final ILogger logger) { * @param httpProvider The HTTP provider */ protected void setHttpProvider(@Nonnull final IHttpProvider httpProvider) { - checkNotNull(httpProvider, "httpProvider"); + Objects.requireNonNull(httpProvider, "parameter httpProvider cannot be null"); this.httpProvider = httpProvider; } @@ -373,7 +362,7 @@ protected void setHttpProvider(@Nonnull final IHttpProvider h * @param serializer The serializer */ public void setSerializer(@Nonnull final ISerializer serializer) { - checkNotNull(serializer, "serializer"); + Objects.requireNonNull(serializer, "parameter serializer cannot be null"); this.serializer = serializer; } diff --git a/src/main/java/com/microsoft/graph/core/CustomRequestBuilder.java b/src/main/java/com/microsoft/graph/core/CustomRequestBuilder.java index 6354965b6..5915eb32b 100644 --- a/src/main/java/com/microsoft/graph/core/CustomRequestBuilder.java +++ b/src/main/java/com/microsoft/graph/core/CustomRequestBuilder.java @@ -1,6 +1,7 @@ package com.microsoft.graph.core; import java.util.List; +import java.util.Objects; import javax.annotation.Nullable; import javax.annotation.Nonnull; @@ -28,7 +29,7 @@ public class CustomRequestBuilder extends BaseRequestBuilder { */ public CustomRequestBuilder(@Nonnull final String requestUrl, @Nonnull final IBaseClient client, @Nullable final List requestOptions, @Nonnull final Class responseType) { super(requestUrl, client, requestOptions); - this.responseType = responseType; + this.responseType = Objects.requireNonNull(responseType, "parameter responseType cannot be null"); } /** diff --git a/src/main/java/com/microsoft/graph/core/DateOnly.java b/src/main/java/com/microsoft/graph/core/DateOnly.java index 76ee7b722..e5a805092 100644 --- a/src/main/java/com/microsoft/graph/core/DateOnly.java +++ b/src/main/java/com/microsoft/graph/core/DateOnly.java @@ -3,6 +3,7 @@ import java.text.ParseException; import java.util.Locale; +import java.util.Objects; import javax.annotation.Nullable; import javax.annotation.Nonnull; @@ -36,6 +37,7 @@ public class DateOnly { */ @Nullable public static DateOnly parse(@Nonnull final String dateStr) throws ParseException { + Objects.requireNonNull(dateStr, "parameter dateStr cannot be null"); // break the date up into its constituent parts final String[] dateInfo = dateStr.split("-"); diff --git a/src/main/java/com/microsoft/graph/core/Multipart.java b/src/main/java/com/microsoft/graph/core/Multipart.java index 365be77e9..0600cac80 100644 --- a/src/main/java/com/microsoft/graph/core/Multipart.java +++ b/src/main/java/com/microsoft/graph/core/Multipart.java @@ -7,6 +7,7 @@ import java.math.BigInteger; import java.security.SecureRandom; import java.util.Map; +import java.util.Objects; import javax.annotation.Nullable; import javax.annotation.Nonnull; @@ -51,7 +52,7 @@ public String getBoundary() { * @param boundary The multipart boundary */ public void setBoundary(@Nonnull final String boundary) { - this.boundary = boundary; + this.boundary = Objects.requireNonNull(boundary, "parameter boundary cannot be null"); } /** @@ -68,7 +69,7 @@ public String getContentType() { * @param contentType The multipart Content-Type */ public void setContentType(@Nonnull final String contentType) { - this.contentType = contentType; + this.contentType = Objects.requireNonNull(contentType, "parameter contentType cannot be null"); } /** diff --git a/src/main/java/com/microsoft/graph/core/TimeOfDay.java b/src/main/java/com/microsoft/graph/core/TimeOfDay.java index a49cb71d5..bc87efe02 100644 --- a/src/main/java/com/microsoft/graph/core/TimeOfDay.java +++ b/src/main/java/com/microsoft/graph/core/TimeOfDay.java @@ -7,6 +7,7 @@ import java.math.BigDecimal; import java.text.ParseException; import java.util.Locale; +import java.util.Objects; /** * The time of day @@ -37,6 +38,7 @@ public class TimeOfDay { */ @Nullable public static TimeOfDay parse(@Nonnull final String timeStr) throws ParseException { + Objects.requireNonNull(timeStr, "parameter timeStr cannot be null"); // break the date up into its constituent parts final String[] timeInfo = timeStr.split(":"); diff --git a/src/main/java/com/microsoft/graph/http/BaseCollectionRequest.java b/src/main/java/com/microsoft/graph/http/BaseCollectionRequest.java index 944b3c436..c148ef198 100644 --- a/src/main/java/com/microsoft/graph/http/BaseCollectionRequest.java +++ b/src/main/java/com/microsoft/graph/http/BaseCollectionRequest.java @@ -26,6 +26,8 @@ import java.lang.reflect.InvocationTargetException; import java.util.Collections; import java.util.List; +import java.util.Objects; + import javax.annotation.Nullable; import javax.annotation.Nonnull; @@ -82,9 +84,9 @@ public BaseCollectionRequest(@Nonnull final String requestUrl, @Nonnull final Class responseCollectionClass, @Nonnull final Class collectionPageClass, @Nonnull final Class, T2, T3, ? extends BaseCollectionRequest>> collectionRequestBuilderClass) { - this.responseCollectionClass = responseCollectionClass; - this.collectionPageClass = collectionPageClass; - this.collRequestBuilderClass = collectionRequestBuilderClass; + this.responseCollectionClass = Objects.requireNonNull(responseCollectionClass, "parameter responseCollectionClass cannot be null"); + this.collectionPageClass = Objects.requireNonNull(collectionPageClass, "parameter collectionPageClass cannot be null"); + this.collRequestBuilderClass = Objects.requireNonNull(collectionRequestBuilderClass, "parameter collectionRequestBuilderClass cannot be null"); baseRequest = new BaseRequest(requestUrl, client, options, responseCollectionClass) {}; } @@ -119,6 +121,7 @@ protected java.util.concurrent.CompletableFuture sendAsync() throws ClientEx */ @Nullable public T3 buildFromResponse(@Nonnull final T2 response) { + Objects.requireNonNull(response, "parameter response cannot be null"); try { final Object builder = response.nextLink() == null ? null : this.collRequestBuilderClass .getConstructor(String.class, IBaseClient.class, java.util.List.class) @@ -170,7 +173,8 @@ public List getHeaders() { * @param value the value of the header */ @Override - public void addHeader(@Nonnull final String header, @Nonnull final String value) { + public void addHeader(@Nonnull final String header, @Nullable final String value) { + Objects.requireNonNull(header, "parameter header cannot be null"); baseRequest.addHeader(header, value); } @@ -210,6 +214,7 @@ public List