From ae90c4c18254a591b45adb23340d80985856b191 Mon Sep 17 00:00:00 2001 From: NakulSabharwal Date: Wed, 13 Mar 2019 13:13:16 +0530 Subject: [PATCH 01/16] Updated wiki links --- readme.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/readme.md b/readme.md index e29c95a24..8188e4736 100644 --- a/readme.md +++ b/readme.md @@ -5,6 +5,10 @@ Get started with the Microsoft Graph Core SDK for Java by integrating the [Micro ## Important Note about the Microsoft Graph Core Java Preview During the preview we may make changes to the API, and other mechanisms of this library, which you will be required to take along with bug fixes or feature improvements. This may impact your application. An API change may require you to update your code. When we provide the General Availability release we will require you to update to the General Availability version within six months, as applications written using a preview version of library may no longer work. +## Samples and usage guide +[Middleware usage](https://github.com/microsoftgraph/msgraph-sdk-java-core/wiki)
+[Batching](https://github.com/microsoftgraph/msgraph-sdk-java-core/wiki/Batching) + ## 1. Installation ### 1.1 Install via Gradle From 22085cff4ec6cef8ccb5d2bf061e722993a65fc3 Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Wed, 13 Mar 2019 16:47:44 +0530 Subject: [PATCH 02/16] Added CONTRIBUTING.md --- CONTRIBUTING.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..f7681bdfe --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,41 @@ +# Contributing to the Microsoft Graph Core SDK for Java + +The Microsoft Graph Core SDK for Java is available for all manner of contribution. There are a couple of different recommended paths to get contributions into the released version of this SDK. + +__NOTE__ A signed a contribution license agreement is required for all contributions, and is checked automatically on new pull requests. Please read and sign the agreement https://cla.microsoft.com/ before starting any work for this repository. + +## File issues + +The best way to get started with a contribution is to start a dialog with the owners of this repository. Sometimes features will be under development or out of scope for this SDK and it's best to check before starting work on contribution. + +## Submit pull requests for trivial changes + +If you are making a change that does not affect the interface components and does not affect other downstream callers, feel free to make a pull request against the __dev__ branch. The dev branch will be updated frequently. + +Revisions of this nature will result in a 0.0.X change of the version number. + +## Submit pull requests for features + +If major functionality is being added, or there will need to be gestation time for a change, it should be submitted against the __feature__ branch. + +Revisions of this nature will result in a 0.X.X change of the version number. + +## Add yourself as a contributor + +This project follows the [all contributors](https://github.com/kentcdodds/all-contributors) specification. When making a contribution, please add yourself to the table of contributors: + + 1. In section 5. of the [README.md](https://github.com/microsoftgraph/msgraph-sdk-java-core/blob/dev/readme.md), after the last "|", copy and paste a new blank contributor element + ```html + [
+ Your Name](your website or github page)
+ [emoji](link "alt-text") | + ``` + + You can get your GitHub UID by inspecting your GitHub avatar image. + +2. For each contribution type (see [emoji key](https://github.com/kentcdodds/all-contributors#emoji-key) for a list of contribution types), add an emoji and a relevant link and alt-text. + + For example, if you write a blogpost on how to use the SDK, you would include: + + ```html + [??]("https://myblog.com/using-the-java-sdk" "Blog Post") \ No newline at end of file From eb2abcde22ab11701e39bc954fd462d35f1967db Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Wed, 13 Mar 2019 16:50:18 +0530 Subject: [PATCH 03/16] Added THIRD PARTY NOTICES --- THIRD PARTY NOTICES | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 THIRD PARTY NOTICES diff --git a/THIRD PARTY NOTICES b/THIRD PARTY NOTICES new file mode 100644 index 000000000..4c6ff0a5a --- /dev/null +++ b/THIRD PARTY NOTICES @@ -0,0 +1,26 @@ +This file is based on or incorporates material from the projects listed below +(Third Party IP). The original copyright notice and the license under which +Microsoft received such Third Party IP, are set forth below. Such licenses and +notices are provided for informational purposes only. Microsoft licenses the +Third Party IP to you under the licensing terms for the Microsoft product. +Microsoft reserves all other rights not expressly granted under this agreement, +whether by implication, estoppel or otherwise. + +Gson +Copyright 2008-2011 Google Inc. + +Provided for Informational Purposes Only + +Apache 2.0 License + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. \ No newline at end of file From 06721c1c0c3bfc0d4033e00a1fcbb4f7ae6e6e79 Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Wed, 3 Apr 2019 12:06:37 +0530 Subject: [PATCH 04/16] Added gradle-wrapper.jar --- gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54783 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 gradle/wrapper/gradle-wrapper.jar diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..e28513376b335211c611d1b3448e8c7a5b560f66 GIT binary patch literal 54783 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 F{{hRk_xS(- literal 0 HcmV?d00001 From 2a9dc737946743a5103ff295e7c23ac4df70cc2e Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Tue, 16 Apr 2019 00:37:06 +0530 Subject: [PATCH 05/16] Telemetry handler and its tests --- .../graph/httpcore/AuthenticationHandler.java | 6 ++ .../microsoft/graph/httpcore/HttpClients.java | 17 ++++++ .../graph/httpcore/RedirectHandler.java | 6 ++ .../graph/httpcore/RetryHandler.java | 6 ++ .../graph/httpcore/TelemetryHandler.java | 38 ++++++++++++ .../middlewareoption/TelemetryOptions.java | 38 ++++++++++++ .../graph/httpcore/HttpClientsTest.java | 14 +++++ .../graph/httpcore/TelemetryHandlerTest.java | 59 +++++++++++++++++++ .../graph/httpcore/TelemetryOptionsTest.java | 53 +++++++++++++++++ 9 files changed, 237 insertions(+) create mode 100644 src/main/java/com/microsoft/graph/httpcore/TelemetryHandler.java create mode 100644 src/main/java/com/microsoft/graph/httpcore/middlewareoption/TelemetryOptions.java create mode 100644 src/test/java/com/microsoft/graph/httpcore/TelemetryHandlerTest.java create mode 100644 src/test/java/com/microsoft/graph/httpcore/TelemetryOptionsTest.java diff --git a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java index 42e9fe304..b48b8b337 100644 --- a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java @@ -3,6 +3,7 @@ import java.io.IOException; import com.microsoft.graph.httpcore.middlewareoption.MiddlewareType; +import com.microsoft.graph.httpcore.middlewareoption.TelemetryOptions; import okhttp3.Interceptor; import okhttp3.Request; @@ -21,6 +22,11 @@ public AuthenticationHandler(ICoreAuthenticationProvider authProvider) { @Override public Response intercept(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); + Request authenticatedRequest = authProvider.authenticateRequest(originalRequest); return chain.proceed(authenticatedRequest); } diff --git a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java index 4084ae91d..144173609 100644 --- a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java +++ b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java @@ -1,5 +1,6 @@ package com.microsoft.graph.httpcore; +import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.OkHttpClient.Builder; @@ -30,6 +31,22 @@ public static OkHttpClient createDefault(ICoreAuthenticationProvider auth) { .followRedirects(false) .addInterceptor(new RetryHandler()) .addInterceptor(new RedirectHandler()) + .addInterceptor(new TelemetryHandler()) .build(); } + + /** + * Creates {@link OkHttpClient} instance with interceptors + * + * @param interceptors Use interceptors provided while constructing http client + * @return OkHttpClient build with interceptors provided + */ + public static OkHttpClient createFromInterceptors(Interceptor[] interceptors) { + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + for(Interceptor interceptor : interceptors) { + builder.addInterceptor(interceptor); + } + builder.addInterceptor(new TelemetryHandler()); + return builder.build(); + } } diff --git a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java index dbc866990..78c3aa787 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java @@ -11,6 +11,7 @@ import com.microsoft.graph.httpcore.middlewareoption.MiddlewareType; import com.microsoft.graph.httpcore.middlewareoption.RedirectOptions; +import com.microsoft.graph.httpcore.middlewareoption.TelemetryOptions; import okhttp3.HttpUrl; import okhttp3.Interceptor; @@ -100,6 +101,11 @@ Request getRedirect( @Override public Response intercept(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); + 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 5d8b18fc8..a8f542398 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java @@ -5,6 +5,7 @@ import com.microsoft.graph.httpcore.middlewareoption.IShouldRetry; import com.microsoft.graph.httpcore.middlewareoption.MiddlewareType; import com.microsoft.graph.httpcore.middlewareoption.RetryOptions; +import com.microsoft.graph.httpcore.middlewareoption.TelemetryOptions; import okhttp3.Interceptor; import okhttp3.Request; @@ -124,6 +125,11 @@ boolean isBuffered(Response response, Request request) { @Override public Response intercept(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); + Response response = chain.proceed(request); // Use should retry pass along with this request diff --git a/src/main/java/com/microsoft/graph/httpcore/TelemetryHandler.java b/src/main/java/com/microsoft/graph/httpcore/TelemetryHandler.java new file mode 100644 index 000000000..9bcd75d3f --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/TelemetryHandler.java @@ -0,0 +1,38 @@ +package com.microsoft.graph.httpcore; + +import java.io.IOException; + +import com.microsoft.graph.httpcore.middlewareoption.TelemetryOptions; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +public class TelemetryHandler implements Interceptor{ + + public static final String SDK_VERSION = "SdkVersion"; + public static final String VERSION = "v0.1.0-SNAPSHOT"; + public static final String GRAPH_VERSION_PREFIX = "graph-java-core"; + public static final String CLIENT_REQUEST_ID = "client-request-id"; + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + Request.Builder telemetryAddedBuilder = request.newBuilder(); + + TelemetryOptions telemetryOptions = request.tag(TelemetryOptions.class); + + if(telemetryOptions != null) { + String featureUsage = "(featureUsage=" + telemetryOptions.getFeatureUsage() + ")"; + String sdkversion_value = GRAPH_VERSION_PREFIX + "/" + VERSION + " " + featureUsage; + telemetryAddedBuilder.addHeader(SDK_VERSION, sdkversion_value); + + if(request.header(CLIENT_REQUEST_ID) == null) { + telemetryAddedBuilder.addHeader(CLIENT_REQUEST_ID, telemetryOptions.getClientRequestId()); + } + } + + return chain.proceed(telemetryAddedBuilder.build()); + } + +} diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/TelemetryOptions.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/TelemetryOptions.java new file mode 100644 index 000000000..0e7848323 --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/TelemetryOptions.java @@ -0,0 +1,38 @@ +package com.microsoft.graph.httpcore.middlewareoption; + +import java.math.BigInteger; +import java.util.UUID; + +public class TelemetryOptions { + + public static final String NONE_FLAG = "0x00000000"; + public static final String REDIRECT_HANDLER_ENABLED_FLAG = "0x00000001"; + public static final String RETRY_HANDLER_ENABLED_FLAG = "0x00000002"; + public static final String AUTH_HANDLER_ENABLED_FLAG = "0x00000004"; + public static final String DEFAULT_HTTPROVIDER_ENABLED_FLAG = "0x00000008"; + public static final String LOGGING_HANDLER_ENABLED_FLAG = "0x00000010"; + + private static final int RADIX = 16; + private BigInteger featureUsage = new BigInteger(NONE_FLAG.substring(2), RADIX); + private String clientRequestId; + + public void setFeatureUsage(String flag) { + featureUsage = featureUsage.or(new BigInteger(flag.substring(2), RADIX)); + } + + public String getFeatureUsage() { + return featureUsage.toString(RADIX); + } + + public void setClientRequestId(String clientRequestId) { + this.clientRequestId = clientRequestId; + } + + public String getClientRequestId() { + if(clientRequestId == null) { + clientRequestId = UUID.randomUUID().toString(); + } + return clientRequestId; + } + +} diff --git a/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java b/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java index 85bb76fd5..6043c432d 100644 --- a/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java @@ -4,6 +4,7 @@ import org.junit.Test; +import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -21,5 +22,18 @@ public Request authenticateRequest(Request request) { OkHttpClient httpclient = HttpClients.createDefault(authprovider); assertTrue(httpclient != null); } + + @Test + public void arrayInterceptorsTest() { + AuthenticationHandler authenticationHandler = new AuthenticationHandler(new ICoreAuthenticationProvider() { + @Override + public Request authenticateRequest(Request request) { + return request; + } + }); + Interceptor[] interceptors = {new RetryHandler(), new RedirectHandler(), authenticationHandler}; + OkHttpClient client = HttpClients.createFromInterceptors(interceptors); + assertTrue(client.interceptors().size()==4); + } } diff --git a/src/test/java/com/microsoft/graph/httpcore/TelemetryHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/TelemetryHandlerTest.java new file mode 100644 index 000000000..8f49b8126 --- /dev/null +++ b/src/test/java/com/microsoft/graph/httpcore/TelemetryHandlerTest.java @@ -0,0 +1,59 @@ +package com.microsoft.graph.httpcore; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; + +import org.junit.Ignore; +import org.junit.Test; + +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +@Ignore +public class TelemetryHandlerTest { + @Test + public void telemetryInitTest() { + TelemetryHandler telemetryHandler = new TelemetryHandler(); + assertNotNull(telemetryHandler); + } + + @Test + public void interceptTest() throws IOException { + String expectedHeader = TelemetryHandler.SDK_VERSION + TelemetryHandler.GRAPH_VERSION_PREFIX +"/" + +TelemetryHandler.VERSION; + OkHttpClient client = HttpClients.createDefault(new ICoreAuthenticationProvider() { + @Override + public Request authenticateRequest(Request request) { + return request; + } + }); + Request request = new Request.Builder().url("https://graph.microsoft.com/v1.0/users/").build(); + Response response = client.newCall(request).execute(); + assertNotNull(response); + assertTrue(response.request().header("SdkVersion").contains(expectedHeader)); + } + + @Test + public void arrayInterceptorsTest() throws IOException { + + AuthenticationHandler authenticationHandler = new AuthenticationHandler(new ICoreAuthenticationProvider() { + + @Override + public Request authenticateRequest(Request request) { + return request; + } + }); + Interceptor[] interceptors = {new RetryHandler(), new RedirectHandler(), authenticationHandler}; + OkHttpClient client = HttpClients.createFromInterceptors(interceptors); + String expectedHeader = TelemetryHandler.SDK_VERSION + TelemetryHandler.GRAPH_VERSION_PREFIX +"/" + +TelemetryHandler.VERSION; + Request request = new Request.Builder().url("https://graph.microsoft.com/v1.0/users/").build(); + Response response = client.newCall(request).execute(); + assertNotNull(response); + assertTrue(response.request().header("SdkVersion").contains(expectedHeader)); + } +} diff --git a/src/test/java/com/microsoft/graph/httpcore/TelemetryOptionsTest.java b/src/test/java/com/microsoft/graph/httpcore/TelemetryOptionsTest.java new file mode 100644 index 000000000..dece2ef55 --- /dev/null +++ b/src/test/java/com/microsoft/graph/httpcore/TelemetryOptionsTest.java @@ -0,0 +1,53 @@ +package com.microsoft.graph.httpcore; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.microsoft.graph.httpcore.middlewareoption.TelemetryOptions; + +public class TelemetryOptionsTest { + + @Test + public void createTelemetryOptionsTest() { + TelemetryOptions telemetryOptions = new TelemetryOptions(); + assertNotNull(telemetryOptions); + assertNotNull(telemetryOptions.getClientRequestId()); + } + + @Test + public void setFeatureUsageTest() { + TelemetryOptions telemetryOptions = new TelemetryOptions(); + telemetryOptions.setFeatureUsage(TelemetryOptions.AUTH_HANDLER_ENABLED_FLAG); + telemetryOptions.setFeatureUsage(TelemetryOptions.REDIRECT_HANDLER_ENABLED_FLAG); + assertTrue(telemetryOptions.getFeatureUsage().compareTo("5")==0); + } + + @Test + public void getFeatureUsageTest() { + TelemetryOptions telemetryOptions = new TelemetryOptions(); + telemetryOptions.setFeatureUsage(TelemetryOptions.AUTH_HANDLER_ENABLED_FLAG); + telemetryOptions.setFeatureUsage(TelemetryOptions.REDIRECT_HANDLER_ENABLED_FLAG); + telemetryOptions.setFeatureUsage(TelemetryOptions.RETRY_HANDLER_ENABLED_FLAG); + assertTrue(telemetryOptions.getFeatureUsage().compareTo("7")==0); + } + + @Test + public void setClientRequestIdTest() { + TelemetryOptions telemetryOptions = new TelemetryOptions(); + telemetryOptions.setClientRequestId("test id"); + assertTrue(telemetryOptions.getClientRequestId().compareTo("test id")==0); + } + + @Test + public void getClientRequestIdTest() { + TelemetryOptions telemetryOptions = new TelemetryOptions(); + assertNotNull(telemetryOptions.getClientRequestId()); + telemetryOptions.setClientRequestId("test id 1"); + assertTrue(telemetryOptions.getClientRequestId().compareTo("test id 1")==0); + telemetryOptions.setClientRequestId("test id 2"); + assertTrue(telemetryOptions.getClientRequestId().compareTo("test id 2")==0); + } + +} From c42ccb996faab7c0b3b264b970ab14468e73bbbb Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Wed, 17 Apr 2019 12:14:59 +0530 Subject: [PATCH 06/16] Changed flags from String to int --- .../middlewareoption/TelemetryOptions.java | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/TelemetryOptions.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/TelemetryOptions.java index 0e7848323..60def57d8 100644 --- a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/TelemetryOptions.java +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/TelemetryOptions.java @@ -1,27 +1,25 @@ package com.microsoft.graph.httpcore.middlewareoption; -import java.math.BigInteger; import java.util.UUID; public class TelemetryOptions { - public static final String NONE_FLAG = "0x00000000"; - public static final String REDIRECT_HANDLER_ENABLED_FLAG = "0x00000001"; - public static final String RETRY_HANDLER_ENABLED_FLAG = "0x00000002"; - public static final String AUTH_HANDLER_ENABLED_FLAG = "0x00000004"; - public static final String DEFAULT_HTTPROVIDER_ENABLED_FLAG = "0x00000008"; - public static final String LOGGING_HANDLER_ENABLED_FLAG = "0x00000010"; + public static final int NONE_FLAG = 0; + public static final int REDIRECT_HANDLER_ENABLED_FLAG = 1; + public static final int RETRY_HANDLER_ENABLED_FLAG = 2; + public static final int AUTH_HANDLER_ENABLED_FLAG = 4; + public static final int DEFAULT_HTTPROVIDER_ENABLED_FLAG = 8; + public static final int LOGGING_HANDLER_ENABLED_FLAG = 16; - private static final int RADIX = 16; - private BigInteger featureUsage = new BigInteger(NONE_FLAG.substring(2), RADIX); + private int featureUsage = NONE_FLAG; private String clientRequestId; - public void setFeatureUsage(String flag) { - featureUsage = featureUsage.or(new BigInteger(flag.substring(2), RADIX)); + public void setFeatureUsage(int flag) { + featureUsage = featureUsage | flag; } public String getFeatureUsage() { - return featureUsage.toString(RADIX); + return Integer.toHexString(featureUsage); } public void setClientRequestId(String clientRequestId) { From 0fdaef24af7e7e85762043272f893d905afb1321 Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Mon, 22 Apr 2019 18:15:15 +0530 Subject: [PATCH 07/16] Added null check for telemetry options --- .../com/microsoft/graph/httpcore/HttpClients.java | 8 +++++--- .../microsoft/graph/httpcore/TelemetryHandler.java | 14 +++++++------- .../graph/httpcore/TelemetryHandlerTest.java | 13 +++++++++++++ 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java index 144173609..ea0cfa359 100644 --- a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java +++ b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java @@ -43,9 +43,11 @@ public static OkHttpClient createDefault(ICoreAuthenticationProvider auth) { */ public static OkHttpClient createFromInterceptors(Interceptor[] interceptors) { OkHttpClient.Builder builder = new OkHttpClient.Builder(); - for(Interceptor interceptor : interceptors) { - builder.addInterceptor(interceptor); - } + if(interceptors != null) + for(Interceptor interceptor : interceptors) { + if(interceptor != null) + builder.addInterceptor(interceptor); + } builder.addInterceptor(new TelemetryHandler()); return builder.build(); } diff --git a/src/main/java/com/microsoft/graph/httpcore/TelemetryHandler.java b/src/main/java/com/microsoft/graph/httpcore/TelemetryHandler.java index 9bcd75d3f..c6031fedd 100644 --- a/src/main/java/com/microsoft/graph/httpcore/TelemetryHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/TelemetryHandler.java @@ -21,15 +21,15 @@ public Response intercept(Chain chain) throws IOException { Request.Builder telemetryAddedBuilder = request.newBuilder(); TelemetryOptions telemetryOptions = request.tag(TelemetryOptions.class); + if(telemetryOptions == null) + telemetryOptions = new TelemetryOptions(); - if(telemetryOptions != null) { - String featureUsage = "(featureUsage=" + telemetryOptions.getFeatureUsage() + ")"; - String sdkversion_value = GRAPH_VERSION_PREFIX + "/" + VERSION + " " + featureUsage; - telemetryAddedBuilder.addHeader(SDK_VERSION, sdkversion_value); + String featureUsage = "(featureUsage=" + telemetryOptions.getFeatureUsage() + ")"; + String sdkversion_value = GRAPH_VERSION_PREFIX + "/" + VERSION + " " + featureUsage; + telemetryAddedBuilder.addHeader(SDK_VERSION, sdkversion_value); - if(request.header(CLIENT_REQUEST_ID) == null) { - telemetryAddedBuilder.addHeader(CLIENT_REQUEST_ID, telemetryOptions.getClientRequestId()); - } + if(request.header(CLIENT_REQUEST_ID) == null) { + telemetryAddedBuilder.addHeader(CLIENT_REQUEST_ID, telemetryOptions.getClientRequestId()); } return chain.proceed(telemetryAddedBuilder.build()); diff --git a/src/test/java/com/microsoft/graph/httpcore/TelemetryHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/TelemetryHandlerTest.java index 8f49b8126..deab260a4 100644 --- a/src/test/java/com/microsoft/graph/httpcore/TelemetryHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/TelemetryHandlerTest.java @@ -56,4 +56,17 @@ public Request authenticateRequest(Request request) { assertNotNull(response); assertTrue(response.request().header("SdkVersion").contains(expectedHeader)); } + + @Test + public void arrayInterceptorEmptyTest() throws IOException { + Interceptor[] interceptors = null; + OkHttpClient client = HttpClients.createFromInterceptors(interceptors); + String expectedHeader = TelemetryHandler.SDK_VERSION + TelemetryHandler.GRAPH_VERSION_PREFIX +"/" + +TelemetryHandler.VERSION; + Request request = new Request.Builder().url("https://graph.microsoft.com/v1.0/users/").build(); + Response response = client.newCall(request).execute(); + assertNotNull(response); + assertTrue(response.request().header("SdkVersion").contains(expectedHeader)); + } + } From d93a7f001e4f1b16fd305596bcedfa47cda89162 Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Tue, 23 Apr 2019 11:08:06 +0530 Subject: [PATCH 08/16] Added telemetry handler in custom builder --- src/main/java/com/microsoft/graph/httpcore/HttpClients.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java index ea0cfa359..a85acc7de 100644 --- a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java +++ b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java @@ -16,7 +16,7 @@ private HttpClients() { * @return OkHttpClient.Builder() custom builder for developer to add its own interceptors to it */ public static Builder custom() { - return new OkHttpClient.Builder(); + return new OkHttpClient.Builder().addInterceptor(new TelemetryHandler()); } /** From 9b5ea782e629c316cd79581556573b880b991a65 Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Tue, 23 Apr 2019 11:37:46 +0530 Subject: [PATCH 09/16] Added Iterator and map response over BatchResponse and update with BatchResponse. --- .../graph/content/MSBatchResponseContent.java | 98 +++++++++++++------ .../content/MSBatchResponseContentTest.java | 40 ++++++++ 2 files changed, 108 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java b/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java index ed10d1da1..b5c873d01 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java @@ -2,6 +2,7 @@ import java.io.IOException; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; import org.json.simple.JSONArray; @@ -18,33 +19,17 @@ public class MSBatchResponseContent { - private JSONObject batchResponseObj; private Response batchResponse; private Map batchRequestsHashMap; private JSONArray batchResponseArray; + private String nextLink; /* * @param batchResponse OkHttp batch response on execution of batch requests */ public MSBatchResponseContent(Response batchResponse) { - if(batchResponse == null) - throw new IllegalArgumentException("Batch Response cannot be null"); - - this.batchRequestsHashMap = createBatchRequestsHashMap(batchResponse); this.batchResponse = batchResponse; - if(batchResponse.body() != null) { - try { - String batchResponseData = batchResponse.body().string(); - if(batchResponseData != null) { - batchResponseObj = stringToJSONObject(batchResponseData); - if(batchResponseObj != null) { - batchResponseArray = (JSONArray)batchResponseObj.get("responses"); - } - } - } catch (IOException e) { - e.printStackTrace(); - } - } + update(batchResponse); } /* @@ -54,12 +39,9 @@ public MSBatchResponseContent(Response batchResponse) { * @return OkHttp Response corresponding to requestId */ public Response getResponseById(String requestId) { - if(batchResponseObj == null) - return null; + if(batchResponseArray == null) return null; - JSONArray responses = (JSONArray)batchResponseObj.get("responses"); - if(responses == null) - return null; + JSONArray responses = batchResponseArray; for(Object response : responses) { JSONObject jsonresponse = (JSONObject)response; @@ -104,20 +86,76 @@ public Response getResponseById(String requestId) { return null; } - /* - * @return responses as a string + /** + * Get map of id and responses + * + * @return responses in Map of id and response */ - public String getResponses() { - return batchResponseArray != null ? batchResponseArray.toJSONString() : null; + public Map getResponses() { + if(batchResponseArray == null) + return null; + Map responsesMap = new HashMap<>(); + for(String id : batchRequestsHashMap.keySet()) { + responsesMap.put(id, getResponseById(id)); + } + return responsesMap; + } + + /** + * Get iterator over the responses + * + * @return iterator for responses + */ + public Iterator> getResponsesIterator() { + if(batchResponseArray == null) + return null; + Map responsesMap = new HashMap<>(); + for(String id : batchRequestsHashMap.keySet()) { + responsesMap.put(id, getResponseById(id)); + } + return responsesMap.entrySet().iterator(); + } + + public void update(Response batchResponse) { + if(batchResponse == null) + throw new IllegalArgumentException("Batch Response cannot be null"); + + Map requestMap = createBatchRequestsHashMap(batchResponse); + if(batchRequestsHashMap == null) + batchRequestsHashMap = new HashMap<>(); + if(requestMap != null) + batchRequestsHashMap.putAll(requestMap); + + if(batchResponse.body() != null) { + try { + String batchResponseData = batchResponse.body().string(); + if(batchResponseData != null) { + JSONObject batchResponseObj = stringToJSONObject(batchResponseData); + if(batchResponseObj != null) { + + JSONObject nextLinkObject = (JSONObject) batchResponseObj.get("nextLink"); + if(nextLinkObject!=null) + nextLink = nextLinkObject.toString(); + + if(batchResponseArray == null) + batchResponseArray = new JSONArray(); + + JSONArray responseArray = (JSONArray)batchResponseObj.get("responses"); + if(responseArray!=null) + batchResponseArray.addAll(responseArray); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } } /* * @return nextLink of batch response */ public String nextLink() { - if(batchResponseObj == null) return null; - Object nextLinkObject = batchResponseObj.get("nextLink"); - return nextLinkObject != null ? ((JSONObject)nextLinkObject).toString() : null; + return nextLink; } private Map createBatchRequestsHashMap(Response batchResponse) { diff --git a/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java b/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java index 87ac0ae7e..a7772aab9 100644 --- a/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java +++ b/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java @@ -4,6 +4,8 @@ import static org.junit.Assert.assertTrue; import java.io.IOException; +import java.util.Iterator; +import java.util.Map; import org.junit.Test; @@ -73,6 +75,44 @@ public void testGetMSBatchResponseContentByID() throws IOException { assertTrue(response != null); } + @Test + public void testGetMSBatchResponseContentIteratorOverResponse() throws IOException { + String responsebody = "{\"responses\": [{\"id\": \"1\",\"status\":200,\"headers\" : {\"Cache-Control\":\"no-cache\",\"OData-Version\":\"4.0\",\"Content-Type\":\"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\"},\"body\":{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users/$entity\",\"businessPhones\":[\"8006427676\"],\"displayName\":\"MOD Administrator\",\"givenName\":\"MOD\",\"jobTitle\":null,\"mail\":\"admin@M365x751487.OnMicrosoft.com\",\"mobilePhone\":\"425-882-1032\",\"officeLocation\":null,\"preferredLanguage\":\"en-US\",\"surname\":\"Administrator\",\"userPrincipalName\":\"admin@M365x751487.onmicrosoft.com\",\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\"}},{\"id\": \"2\",\"status\":200,\"headers\" : {\"Cache-Control\":\"no-store, no-cache\",\"OData-Version\":\"4.0\",\"Content-Type\":\"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\"},\"body\":{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#drives/$entity\",\"createdDateTime\":\"2019-01-12T09:05:38Z\",\"description\":\"\",\"id\":\"b!nlu9o5I9g0y8gsHXfUM_bPTZ0oM_wVNArHM5R4-VkHLlnxx5SpqHRJledwfICP9f\",\"lastModifiedDateTime\":\"2019-03-06T06:59:04Z\",\"name\":\"OneDrive\",\"webUrl\":\"https://m365x751487-my.sharepoint.com/personal/admin_m365x751487_onmicrosoft_com/Documents\",\"driveType\":\"business\",\"createdBy\":{\"user\":{\"displayName\":\"System Account\"}},\"lastModifiedBy\":{\"user\":{\"displayName\":\"System Account\"}},\"owner\":{\"user\":{\"email\":\"admin@M365x751487.OnMicrosoft.com\",\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\",\"displayName\":\"MOD Administrator\"}},\"quota\":{\"deleted\":0,\"remaining\":1099509670098,\"state\":\"normal\",\"total\":1099511627776,\"used\":30324}}},{\"id\": \"3\",\"status\":201,\"headers\" : {\"Location\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0\",\"Preference-Applied\":\"odata.include-annotations=*\",\"Cache-Control\":\"no-cache\",\"OData-Version\":\"4.0\",\"Content-Type\":\"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\"},\"body\":{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users('6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c')/onenote/notebooks/$entity\",\"id\":\"1-94e4376a-a1c1-441a-8b41-af5c86ee39d0\",\"self\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0\",\"createdDateTime\":\"2019-03-06T08:08:09Z\",\"displayName\":\"My Notebook -442293399\",\"lastModifiedDateTime\":\"2019-03-06T08:08:09Z\",\"isDefault\":false,\"userRole\":\"Owner\",\"isShared\":false,\"sectionsUrl\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0/sections\",\"sectionGroupsUrl\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0/sectionGroups\",\"createdBy\":{\"user\":{\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\",\"displayName\":\"MOD Administrator\"}},\"lastModifiedBy\":{\"user\":{\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\",\"displayName\":\"MOD Administrator\"}},\"links\":{\"oneNoteClientUrl\":{\"href\":\"onenote:https://m365x751487-my.sharepoint.com/personal/admin_m365x751487_onmicrosoft_com/Documents/Notebooks/My%20Notebook%20-442293399\"},\"oneNoteWebUrl\":{\"href\":\"https://m365x751487-my.sharepoint.com/personal/admin_m365x751487_onmicrosoft_com/Documents/Notebooks/My%20Notebook%20-442293399\"}}}}]}"; + String requestbody = "{\"requests\":[{\"method\":\"GET\",\"dependsOn\":[],\"id\":\"1\",\"url\":\"me\"},{\"method\":\"GET\",\"dependsOn\":[],\"id\":\"2\",\"url\":\"me\\/drive\"},{\"headers\":{\"content-type\":\"application\\/json\"},\"method\":\"POST\",\"dependsOn\":[],\"id\":\"3\",\"body\":{\"displayName\":\"My Notebook -1263732088\"},\"url\":\"me\\/onenote\\/notebooks\"}]}"; + Response responsedata = TestResponse(responsebody,requestbody); + MSBatchResponseContent batchresponse = new MSBatchResponseContent(responsedata); + Iterator> it = batchresponse.getResponsesIterator(); + while(it.hasNext()) { + Map.Entry entry = it.next(); + assertTrue(entry.getKey()!=null && entry.getValue()!=null); + } + } + + @Test + public void testGetMSBatchResponseContentMapResponse() throws IOException { + String responsebody = "{\"responses\": [{\"id\": \"1\",\"status\":200,\"headers\" : {\"Cache-Control\":\"no-cache\",\"OData-Version\":\"4.0\",\"Content-Type\":\"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\"},\"body\":{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users/$entity\",\"businessPhones\":[\"8006427676\"],\"displayName\":\"MOD Administrator\",\"givenName\":\"MOD\",\"jobTitle\":null,\"mail\":\"admin@M365x751487.OnMicrosoft.com\",\"mobilePhone\":\"425-882-1032\",\"officeLocation\":null,\"preferredLanguage\":\"en-US\",\"surname\":\"Administrator\",\"userPrincipalName\":\"admin@M365x751487.onmicrosoft.com\",\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\"}},{\"id\": \"2\",\"status\":200,\"headers\" : {\"Cache-Control\":\"no-store, no-cache\",\"OData-Version\":\"4.0\",\"Content-Type\":\"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\"},\"body\":{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#drives/$entity\",\"createdDateTime\":\"2019-01-12T09:05:38Z\",\"description\":\"\",\"id\":\"b!nlu9o5I9g0y8gsHXfUM_bPTZ0oM_wVNArHM5R4-VkHLlnxx5SpqHRJledwfICP9f\",\"lastModifiedDateTime\":\"2019-03-06T06:59:04Z\",\"name\":\"OneDrive\",\"webUrl\":\"https://m365x751487-my.sharepoint.com/personal/admin_m365x751487_onmicrosoft_com/Documents\",\"driveType\":\"business\",\"createdBy\":{\"user\":{\"displayName\":\"System Account\"}},\"lastModifiedBy\":{\"user\":{\"displayName\":\"System Account\"}},\"owner\":{\"user\":{\"email\":\"admin@M365x751487.OnMicrosoft.com\",\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\",\"displayName\":\"MOD Administrator\"}},\"quota\":{\"deleted\":0,\"remaining\":1099509670098,\"state\":\"normal\",\"total\":1099511627776,\"used\":30324}}},{\"id\": \"3\",\"status\":201,\"headers\" : {\"Location\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0\",\"Preference-Applied\":\"odata.include-annotations=*\",\"Cache-Control\":\"no-cache\",\"OData-Version\":\"4.0\",\"Content-Type\":\"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\"},\"body\":{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users('6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c')/onenote/notebooks/$entity\",\"id\":\"1-94e4376a-a1c1-441a-8b41-af5c86ee39d0\",\"self\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0\",\"createdDateTime\":\"2019-03-06T08:08:09Z\",\"displayName\":\"My Notebook -442293399\",\"lastModifiedDateTime\":\"2019-03-06T08:08:09Z\",\"isDefault\":false,\"userRole\":\"Owner\",\"isShared\":false,\"sectionsUrl\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0/sections\",\"sectionGroupsUrl\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0/sectionGroups\",\"createdBy\":{\"user\":{\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\",\"displayName\":\"MOD Administrator\"}},\"lastModifiedBy\":{\"user\":{\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\",\"displayName\":\"MOD Administrator\"}},\"links\":{\"oneNoteClientUrl\":{\"href\":\"onenote:https://m365x751487-my.sharepoint.com/personal/admin_m365x751487_onmicrosoft_com/Documents/Notebooks/My%20Notebook%20-442293399\"},\"oneNoteWebUrl\":{\"href\":\"https://m365x751487-my.sharepoint.com/personal/admin_m365x751487_onmicrosoft_com/Documents/Notebooks/My%20Notebook%20-442293399\"}}}}]}"; + String requestbody = "{\"requests\":[{\"method\":\"GET\",\"dependsOn\":[],\"id\":\"1\",\"url\":\"me\"},{\"method\":\"GET\",\"dependsOn\":[],\"id\":\"2\",\"url\":\"me\\/drive\"},{\"headers\":{\"content-type\":\"application\\/json\"},\"method\":\"POST\",\"dependsOn\":[],\"id\":\"3\",\"body\":{\"displayName\":\"My Notebook -1263732088\"},\"url\":\"me\\/onenote\\/notebooks\"}]}"; + Response responsedata = TestResponse(responsebody,requestbody); + MSBatchResponseContent batchresponse = new MSBatchResponseContent(responsedata); + for(Map.Entry entry: batchresponse.getResponses().entrySet()) { + assertTrue(entry.getKey() != null && entry.getValue() != null); + } + } + + @Test + public void testGetMSBatchResponseContentUpdate() throws IOException { + String responsebody = "{\"responses\": [{\"id\": \"1\",\"status\":200,\"headers\" : {\"Cache-Control\":\"no-cache\",\"OData-Version\":\"4.0\",\"Content-Type\":\"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\"},\"body\":{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users/$entity\",\"businessPhones\":[\"8006427676\"],\"displayName\":\"MOD Administrator\",\"givenName\":\"MOD\",\"jobTitle\":null,\"mail\":\"admin@M365x751487.OnMicrosoft.com\",\"mobilePhone\":\"425-882-1032\",\"officeLocation\":null,\"preferredLanguage\":\"en-US\",\"surname\":\"Administrator\",\"userPrincipalName\":\"admin@M365x751487.onmicrosoft.com\",\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\"}},{\"id\": \"2\",\"status\":200,\"headers\" : {\"Cache-Control\":\"no-store, no-cache\",\"OData-Version\":\"4.0\",\"Content-Type\":\"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\"},\"body\":{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#drives/$entity\",\"createdDateTime\":\"2019-01-12T09:05:38Z\",\"description\":\"\",\"id\":\"b!nlu9o5I9g0y8gsHXfUM_bPTZ0oM_wVNArHM5R4-VkHLlnxx5SpqHRJledwfICP9f\",\"lastModifiedDateTime\":\"2019-03-06T06:59:04Z\",\"name\":\"OneDrive\",\"webUrl\":\"https://m365x751487-my.sharepoint.com/personal/admin_m365x751487_onmicrosoft_com/Documents\",\"driveType\":\"business\",\"createdBy\":{\"user\":{\"displayName\":\"System Account\"}},\"lastModifiedBy\":{\"user\":{\"displayName\":\"System Account\"}},\"owner\":{\"user\":{\"email\":\"admin@M365x751487.OnMicrosoft.com\",\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\",\"displayName\":\"MOD Administrator\"}},\"quota\":{\"deleted\":0,\"remaining\":1099509670098,\"state\":\"normal\",\"total\":1099511627776,\"used\":30324}}},{\"id\": \"3\",\"status\":201,\"headers\" : {\"Location\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0\",\"Preference-Applied\":\"odata.include-annotations=*\",\"Cache-Control\":\"no-cache\",\"OData-Version\":\"4.0\",\"Content-Type\":\"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\"},\"body\":{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users('6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c')/onenote/notebooks/$entity\",\"id\":\"1-94e4376a-a1c1-441a-8b41-af5c86ee39d0\",\"self\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0\",\"createdDateTime\":\"2019-03-06T08:08:09Z\",\"displayName\":\"My Notebook -442293399\",\"lastModifiedDateTime\":\"2019-03-06T08:08:09Z\",\"isDefault\":false,\"userRole\":\"Owner\",\"isShared\":false,\"sectionsUrl\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0/sections\",\"sectionGroupsUrl\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0/sectionGroups\",\"createdBy\":{\"user\":{\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\",\"displayName\":\"MOD Administrator\"}},\"lastModifiedBy\":{\"user\":{\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\",\"displayName\":\"MOD Administrator\"}},\"links\":{\"oneNoteClientUrl\":{\"href\":\"onenote:https://m365x751487-my.sharepoint.com/personal/admin_m365x751487_onmicrosoft_com/Documents/Notebooks/My%20Notebook%20-442293399\"},\"oneNoteWebUrl\":{\"href\":\"https://m365x751487-my.sharepoint.com/personal/admin_m365x751487_onmicrosoft_com/Documents/Notebooks/My%20Notebook%20-442293399\"}}}}]}"; + String requestbody = "{\"requests\":[{\"method\":\"GET\",\"dependsOn\":[],\"id\":\"1\",\"url\":\"me\"},{\"method\":\"GET\",\"dependsOn\":[],\"id\":\"2\",\"url\":\"me\\/drive\"},{\"headers\":{\"content-type\":\"application\\/json\"},\"method\":\"POST\",\"dependsOn\":[],\"id\":\"3\",\"body\":{\"displayName\":\"My Notebook -1263732088\"},\"url\":\"me\\/onenote\\/notebooks\"}]}"; + Response responsedata = TestResponse(responsebody,requestbody); + MSBatchResponseContent batchresponse = new MSBatchResponseContent(responsedata); + assertTrue(batchresponse.getResponses().size() == 3); + String responsebody2 = "{\"responses\": [{\"id\": \"4\",\"status\":200,\"headers\" : {\"Cache-Control\":\"no-cache\",\"OData-Version\":\"4.0\",\"Content-Type\":\"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\"},\"body\":{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users/$entity\",\"businessPhones\":[\"8006427676\"],\"displayName\":\"MOD Administrator\",\"givenName\":\"MOD\",\"jobTitle\":null,\"mail\":\"admin@M365x751487.OnMicrosoft.com\",\"mobilePhone\":\"425-882-1032\",\"officeLocation\":null,\"preferredLanguage\":\"en-US\",\"surname\":\"Administrator\",\"userPrincipalName\":\"admin@M365x751487.onmicrosoft.com\",\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\"}},{\"id\": \"5\",\"status\":200,\"headers\" : {\"Cache-Control\":\"no-store, no-cache\",\"OData-Version\":\"4.0\",\"Content-Type\":\"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\"},\"body\":{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#drives/$entity\",\"createdDateTime\":\"2019-01-12T09:05:38Z\",\"description\":\"\",\"id\":\"b!nlu9o5I9g0y8gsHXfUM_bPTZ0oM_wVNArHM5R4-VkHLlnxx5SpqHRJledwfICP9f\",\"lastModifiedDateTime\":\"2019-03-06T06:59:04Z\",\"name\":\"OneDrive\",\"webUrl\":\"https://m365x751487-my.sharepoint.com/personal/admin_m365x751487_onmicrosoft_com/Documents\",\"driveType\":\"business\",\"createdBy\":{\"user\":{\"displayName\":\"System Account\"}},\"lastModifiedBy\":{\"user\":{\"displayName\":\"System Account\"}},\"owner\":{\"user\":{\"email\":\"admin@M365x751487.OnMicrosoft.com\",\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\",\"displayName\":\"MOD Administrator\"}},\"quota\":{\"deleted\":0,\"remaining\":1099509670098,\"state\":\"normal\",\"total\":1099511627776,\"used\":30324}}},{\"id\": \"6\",\"status\":201,\"headers\" : {\"Location\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0\",\"Preference-Applied\":\"odata.include-annotations=*\",\"Cache-Control\":\"no-cache\",\"OData-Version\":\"4.0\",\"Content-Type\":\"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\"},\"body\":{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users('6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c')/onenote/notebooks/$entity\",\"id\":\"1-94e4376a-a1c1-441a-8b41-af5c86ee39d0\",\"self\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0\",\"createdDateTime\":\"2019-03-06T08:08:09Z\",\"displayName\":\"My Notebook -442293399\",\"lastModifiedDateTime\":\"2019-03-06T08:08:09Z\",\"isDefault\":false,\"userRole\":\"Owner\",\"isShared\":false,\"sectionsUrl\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0/sections\",\"sectionGroupsUrl\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0/sectionGroups\",\"createdBy\":{\"user\":{\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\",\"displayName\":\"MOD Administrator\"}},\"lastModifiedBy\":{\"user\":{\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\",\"displayName\":\"MOD Administrator\"}},\"links\":{\"oneNoteClientUrl\":{\"href\":\"onenote:https://m365x751487-my.sharepoint.com/personal/admin_m365x751487_onmicrosoft_com/Documents/Notebooks/My%20Notebook%20-442293399\"},\"oneNoteWebUrl\":{\"href\":\"https://m365x751487-my.sharepoint.com/personal/admin_m365x751487_onmicrosoft_com/Documents/Notebooks/My%20Notebook%20-442293399\"}}}}]}"; + String requestbody2 = "{\"requests\":[{\"method\":\"GET\",\"dependsOn\":[],\"id\":\"4\",\"url\":\"me\"},{\"method\":\"GET\",\"dependsOn\":[],\"id\":\"5\",\"url\":\"me\\/drive\"},{\"headers\":{\"content-type\":\"application\\/json\"},\"method\":\"POST\",\"dependsOn\":[],\"id\":\"6\",\"body\":{\"displayName\":\"My Notebook -1263732088\"},\"url\":\"me\\/onenote\\/notebooks\"}]}"; + Response responsedata2 = TestResponse(responsebody2,requestbody2); + batchresponse.update(responsedata2); + assertTrue(batchresponse.getResponses().size() == 6); + } + private Response TestResponse(String responsebody, String requestbody) { Response.Builder builder = new Response.Builder(); builder.body(ResponseBody.create(MediaType.parse("application/json"), responsebody)); From 71c1f937eeec721c834a772824947dc42aa65603 Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Tue, 23 Apr 2019 12:12:39 +0530 Subject: [PATCH 10/16] edited nextLink updation --- .../com/microsoft/graph/content/MSBatchResponseContent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java b/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java index b5c873d01..04bf3fe5b 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java @@ -133,7 +133,7 @@ public void update(Response batchResponse) { JSONObject batchResponseObj = stringToJSONObject(batchResponseData); if(batchResponseObj != null) { - JSONObject nextLinkObject = (JSONObject) batchResponseObj.get("nextLink"); + JSONObject nextLinkObject = (JSONObject) batchResponseObj.get("@odata.nextLink"); if(nextLinkObject!=null) nextLink = nextLinkObject.toString(); From 78d94c906649e517f3b6c4a596b6ae0bb3c60e92 Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Wed, 24 Apr 2019 12:46:33 +0530 Subject: [PATCH 11/16] Edited responses iterator --- .../microsoft/graph/content/MSBatchResponseContent.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java b/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java index 04bf3fe5b..f640880f4 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java @@ -107,13 +107,8 @@ public Map getResponses() { * @return iterator for responses */ public Iterator> getResponsesIterator() { - if(batchResponseArray == null) - return null; - Map responsesMap = new HashMap<>(); - for(String id : batchRequestsHashMap.keySet()) { - responsesMap.put(id, getResponseById(id)); - } - return responsesMap.entrySet().iterator(); + Map responsesMap = getResponses(); + return responsesMap != null ? responsesMap.entrySet().iterator() : null; } public void update(Response batchResponse) { From de336ea7a6975defe945cec3ba856c54abcb57f2 Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Thu, 25 Apr 2019 13:36:52 +0530 Subject: [PATCH 12/16] edited retry after calculation, check for requestid is not empty --- .../graph/content/MSBatchRequestStep.java | 2 ++ .../graph/httpcore/RetryHandler.java | 17 +++++++--- .../graph/httpcore/RetryHandlerTest.java | 33 +++++++++++++++++++ 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/microsoft/graph/content/MSBatchRequestStep.java b/src/main/java/com/microsoft/graph/content/MSBatchRequestStep.java index 7386decf8..ac13bb0ab 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchRequestStep.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchRequestStep.java @@ -12,6 +12,8 @@ public class MSBatchRequestStep { public MSBatchRequestStep(String requestId, Request request, List arrayOfDependsOnIds) { if(requestId == null) throw new IllegalArgumentException("Request Id cannot be null."); + if(requestId.length() == 0) + throw new IllegalArgumentException("Request Id cannot be empty."); if(request == null) new IllegalArgumentException("Request cannot be null."); diff --git a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java index a8f542398..987f7bf7b 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java @@ -81,17 +81,24 @@ && checkStatus(statusCode) && isBuffered(response, request) return shouldRetry; } + /** + * Get retry after in milliseconds + * @param response Response + * @param delay Delay in seconds + * @param executionCount Execution count of retries + * @return Retry interval in milliseconds + */ long getRetryAfter(Response response, long delay, int executionCount) { String retryAfterHeader = response.header(RETRY_AFTER); - long retryDelay = RetryOptions.DEFAULT_DELAY; + double retryDelay = RetryOptions.DEFAULT_DELAY * DELAY_MILLISECONDS; if(retryAfterHeader != null) { - retryDelay = Long.parseLong(retryAfterHeader); + retryDelay = Long.parseLong(retryAfterHeader) * DELAY_MILLISECONDS; } else { - retryDelay = (long)((Math.pow(2.0, (double)executionCount)-1)*0.5); - retryDelay = executionCount < 2 ? retryDelay : retryDelay + delay + (long)Math.random(); + retryDelay = (double)((Math.pow(2.0, (double)executionCount)-1)*0.5); + retryDelay = (executionCount < 2 ? delay : retryDelay + delay) + (double)Math.random(); retryDelay *= DELAY_MILLISECONDS; } - return Math.min(retryDelay, RetryOptions.MAX_DELAY); + return (long)Math.min(retryDelay, RetryOptions.MAX_DELAY * DELAY_MILLISECONDS); } boolean checkStatus(int statusCode) { diff --git a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java index 1411eb94a..d5ddc3915 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java @@ -122,4 +122,37 @@ public void testRetryRequestWithExponentialBackOff() { assertTrue(retryhandler.retryRequest(response, 1, httppost, new RetryOptions())); } + + @Test + public void testGetRetryAfterWithHeader() { + RetryHandler retryHandler = new RetryHandler(); + long delay = retryHandler.getRetryAfter(TestResponse().newBuilder().addHeader("Retry-After", "60").build(), 1, 1); + assertTrue(delay == 60000); + delay = retryHandler.getRetryAfter(TestResponse().newBuilder().addHeader("Retry-After", "1").build(), 2, 3); + assertTrue(delay == 1000); + } + + @Test + public void testGetRetryAfterOnFirstExecution() { + RetryHandler retryHandler = new RetryHandler(); + long delay = retryHandler.getRetryAfter(TestResponse(), 3, 1); + assertTrue(delay > 3000); + delay = retryHandler.getRetryAfter(TestResponse(), 3, 2); + assertTrue(delay > 3100); + } + + @Test + public void testGetRetryAfterMaxExceed() { + RetryHandler retryHandler = new RetryHandler(); + long delay = retryHandler.getRetryAfter(TestResponse(), 190, 1); + assertTrue(delay == 180000); + } + + Response TestResponse() { + return new Response.Builder() + .code(429) + .message("message") + .request(new Request.Builder().url("https://localhost").build()) + .protocol(Protocol.HTTP_1_0).build(); + } } From 1d53c73a5d6326295dc47e33ec7406918e5d593f Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Thu, 25 Apr 2019 15:28:51 +0530 Subject: [PATCH 13/16] added Relative reference in location url --- .../graph/httpcore/RedirectHandler.java | 10 ++++-- .../graph/httpcore/RedirectHandlerTest.java | 36 ++++++++++++++++++- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java index 78c3aa787..b04d774c7 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java @@ -66,9 +66,15 @@ Request getRedirect( final Request request, final Response userResponse) throws ProtocolException { String location = userResponse.header("Location"); - if (location == null) return null; + if (location == null || location.length() == 0) return null; - // TODO: If Location header is relative reference then final URL should be relative to original target URL. + // For relative URL in location header, the new url to redirect is relative to original request + if(location.startsWith("/")) { + if(request.url().toString().endsWith("/")) { + location = location.substring(1); + } + location = request.url() + location; + } HttpUrl requestUrl = userResponse.request().url(); diff --git a/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java index 3182b850f..6eed2b7ad 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java @@ -21,7 +21,7 @@ public class RedirectHandlerTest { String testmeurl = "https://graph.microsoft.com/v1.0/me/"; - String testurl = "https://graph.microsoft.com/v1.0/"; + String testurl = "https://graph.microsoft.com/v1.0"; String differenthosturl = "https://graph.abc.com/v1.0/"; @Test @@ -228,5 +228,39 @@ public void testGetRedirectForPostMethodWithStatusCodeSeeOther() { fail("Redirect handler testGetRedirectForPostMethod1 failure"); } } + + @Test + public void testGetRedirectForRelativeURL() throws ProtocolException { + RedirectHandler redirectHandler = new RedirectHandler(); + Request httppost = new Request.Builder().url(testurl).build(); + + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_SEE_OTHER) + .message("See Other") + .addHeader("location", "/testrelativeurl") + .request(httppost) + .build(); + + Request request = redirectHandler.getRedirect(httppost, response); + assertTrue(request.url().toString().compareTo(testurl+"/testrelativeurl") == 0); + } + + @Test + public void testGetRedirectRelativeLocationRequestURLwithSlash() throws ProtocolException { + RedirectHandler redirectHandler = new RedirectHandler(); + Request httppost = new Request.Builder().url(testmeurl).build(); + + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_SEE_OTHER) + .message("See Other") + .addHeader("location", "/testrelativeurl") + .request(httppost) + .build(); + Request request = redirectHandler.getRedirect(httppost, response); + String expected = "https://graph.microsoft.com/v1.0/me/testrelativeurl"; + assertTrue(request.url().toString().compareTo(expected) == 0); + } } From b6d28e13f00169a86aaed0a82ecd86792ca188d8 Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Thu, 25 Apr 2019 17:28:21 +0530 Subject: [PATCH 14/16] version update to 1.0.0 and bintray url update --- gradle.properties | 6 +++--- .../java/com/microsoft/graph/httpcore/TelemetryHandler.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index eb7f41cfc..77dfc55e9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,12 +21,12 @@ ## linux requires 10G, OSX requires 11G org.gradle.jvmargs=-XX:MaxPermSize=512m -Xmx2g -mavenRepoUrl = https://api.bintray.com/content/microsoftgraph/Maven/microsoft-graph +mavenRepoUrl = https://api.bintray.com/content/microsoftgraph/Maven/microsoft-graph-core mavenBintraySnapshotUrl = http://oss.jfrog.org/artifactory/oss-snapshot-local mavenGroupId = com.microsoft.graph mavenArtifactId = microsoft-graph-core -mavenMajorVersion = 0 -mavenMinorVersion = 1 +mavenMajorVersion = 1 +mavenMinorVersion = 0 mavenPatchVersion = 0 mavenArtifactSuffix = nightliesUrl = http://dl.bintray.com/MicrosoftGraph/Maven diff --git a/src/main/java/com/microsoft/graph/httpcore/TelemetryHandler.java b/src/main/java/com/microsoft/graph/httpcore/TelemetryHandler.java index c6031fedd..3e0b8ec06 100644 --- a/src/main/java/com/microsoft/graph/httpcore/TelemetryHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/TelemetryHandler.java @@ -11,7 +11,7 @@ public class TelemetryHandler implements Interceptor{ public static final String SDK_VERSION = "SdkVersion"; - public static final String VERSION = "v0.1.0-SNAPSHOT"; + public static final String VERSION = "v1.0.0"; public static final String GRAPH_VERSION_PREFIX = "graph-java-core"; public static final String CLIENT_REQUEST_ID = "client-request-id"; From ef82d2ed18211b2a32d213add2e9e0020642338a Mon Sep 17 00:00:00 2001 From: NakulSabharwal Date: Fri, 26 Apr 2019 10:40:16 +0530 Subject: [PATCH 15/16] Updated readme with GA --- readme.md | 42 ++++++++---------------------------------- 1 file changed, 8 insertions(+), 34 deletions(-) diff --git a/readme.md b/readme.md index 8188e4736..d3eeb81bd 100644 --- a/readme.md +++ b/readme.md @@ -1,9 +1,6 @@ # Microsoft Graph Core Preview SDK for Java -Get started with the Microsoft Graph Core SDK for Java by integrating the [Microsoft Graph API](https://graph.microsoft.io/en-us/getting-started) into your Java application! - -## Important Note about the Microsoft Graph Core Java Preview -During the preview we may make changes to the API, and other mechanisms of this library, which you will be required to take along with bug fixes or feature improvements. This may impact your application. An API change may require you to update your code. When we provide the General Availability release we will require you to update to the General Availability version within six months, as applications written using a preview version of library may no longer work. +Get started with the Microsoft Graph Core SDK for Java by integrating the [Microsoft Graph API](https://graph.microsoft.io/en-us/getting-started) into your Java and Android application! ## Samples and usage guide [Middleware usage](https://github.com/microsoftgraph/msgraph-sdk-java-core/wiki)
@@ -18,14 +15,11 @@ Add the repository and a compile dependency for `microsoft-graph-core` to your p ```gradle repository { jcenter() - jcenter{ - url 'http://oss.jfrog.org/artifactory/oss-snapshot-local' - } } dependency { // Include the sdk as a dependency - compile('com.microsoft.graph:microsoft-graph-core:0.1.0-SNAPSHOT') + compile('com.microsoft.graph:microsoft-graph-core:1.0.0') } ``` @@ -35,34 +29,10 @@ Add the dependency in `dependencies` in pom.xml com.microsoft.graph microsoft-graph-core - 0.1.0-SNAPSHOT + 1.0.0 ``` -Add `profiles` in `project` to download Snapshot release binary: -``` - - - allow-snapshots - - true - - - - snapshots-repo - https://oss.sonatype.org/content/repositories/snapshots - - false - - - true - - - - - -``` - ### 1.3 Enable ProGuard (Android) The nature of the Graph API is such that the SDK needs quite a large set of classes to describe its functionality. You need to ensure that [ProGuard](https://developer.android.com/studio/build/shrink-code.html) is enabled on your project. Otherwise, you will incur long build times for functionality that is not necessarily relevant to your particular application. If you are still hitting the 64K method limit, you can also enable [multidexing](https://developer.android.com/studio/build/multidex.html). @@ -74,7 +44,11 @@ Register your application by following the steps at [Register your app with the ### 2.2 Create an IAuthenticationProvider object -An instance of the **HttpClients** class handles building client. To create a new instance of this class, you need to provide an instance of `ICoreAuthenticationProvider`, which can authenticate requests to Microsoft Graph. +An instance of the **HttpClients** class handles building client. To create a new instance of this class, you need to provide an instance of `ICoreAuthenticationProvider`, which can authenticate requests to Microsoft Graph. +### To get instance of HttpClients +Auth in Java app [here](https://github.com/microsoftgraph/msgraph-sdk-java-auth) + +Auth in Android app [here](https://github.com/microsoftgraph/msgraph-sdk-android-auth) ### 2.3 Get a HttpClients object You must get a **HttpClients** object to make requests against the service. From 02f463a6a0b882c48014d2e7417d7e0e522bdf45 Mon Sep 17 00:00:00 2001 From: NakulSabharwal Date: Fri, 26 Apr 2019 14:33:24 +0530 Subject: [PATCH 16/16] Updated title in readme --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index d3eeb81bd..eaf78529e 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -# Microsoft Graph Core Preview SDK for Java +# Microsoft Graph Core SDK for Java Get started with the Microsoft Graph Core SDK for Java by integrating the [Microsoft Graph API](https://graph.microsoft.io/en-us/getting-started) into your Java and Android application!