From f9acadc3a42eaded79d4fd396c70ca368cec02a2 Mon Sep 17 00:00:00 2001 From: "FAREAST\\deagrawa" Date: Thu, 25 Oct 2018 15:50:02 +0530 Subject: [PATCH 01/38] Setup gradle project --- .gitignore | 35 +++++ build.gradle | 32 +++++ gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 172 +++++++++++++++++++++++ gradlew.bat | 84 +++++++++++ settings.gradle | 18 +++ 6 files changed, 346 insertions(+) create mode 100644 .gitignore create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..f121de793 --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +/.gradle/ +/build/ +/bin/ + +#Eclipse +.project +.classpath +.settings + +# Maven +/target/ +/pom.xml +local.properties \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 000000000..0307d7bc2 --- /dev/null +++ b/build.gradle @@ -0,0 +1,32 @@ +/* + * This build file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Java Library project to get you started. + * For more details take a look at the Java Libraries chapter in the Gradle + * user guide available at https://docs.gradle.org/4.3/userguide/java_library_plugin.html + */ + +// Apply the java-library plugin to add support for Java Library +apply plugin: 'java-library' + +// In this section you declare where to find the dependencies of your project +repositories { + // Use jcenter for resolving your dependencies. + // You can declare any Maven/Ivy/file repository here. + jcenter() +} + +dependencies { + // This dependency is exported to consumers, that is to say found on their compile classpath. + api 'org.apache.commons:commons-math3:3.6.1' + + // This dependency is used internally, and not exposed to consumers on their own compile classpath. + implementation 'com.google.guava:guava:23.0' + + // Use JUnit test framework + testImplementation 'junit:junit:4.12' + + // Use Apache HttpClient + compile 'org.apache.httpcomponents:httpclient:4.5.6' +} + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..92165eede --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.3-bin.zip diff --git a/gradlew b/gradlew new file mode 100644 index 000000000..cccdd3d51 --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 000000000..f9553162f --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 000000000..2b04dfc4e --- /dev/null +++ b/settings.gradle @@ -0,0 +1,18 @@ +/* + * This settings file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * In a single project build this file can be empty or even removed. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user guide at https://docs.gradle.org/4.3/userguide/multi_project_builds.html + */ + +/* +// To declare projects as part of a multi-project build use the 'include' method +include 'shared' +include 'api' +include 'services:webservice' +*/ + +rootProject.name = 'msgraph-sdk-java-core' From 0e8c72dcabdd551615c97fe4ec847de8ea0c0a06 Mon Sep 17 00:00:00 2001 From: deagrawa Date: Wed, 21 Nov 2018 16:18:57 +0530 Subject: [PATCH 02/38] Adding HttpClient and middleware classes --- .../graph/httpcore/AuthenticationHandler.java | 24 +++++ .../microsoft/graph/httpcore/HttpClients.java | 44 ++++++++ .../httpcore/IAuthenticationProvider.java | 12 +++ .../graph/httpcore/RedirectHandler.java | 73 +++++++++++++ .../graph/httpcore/RetryHandler.java | 101 ++++++++++++++++++ 5 files changed, 254 insertions(+) create mode 100644 src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java create mode 100644 src/main/java/com/microsoft/graph/httpcore/HttpClients.java create mode 100644 src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java create mode 100644 src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java create mode 100644 src/main/java/com/microsoft/graph/httpcore/RetryHandler.java diff --git a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java new file mode 100644 index 000000000..82747d1ee --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java @@ -0,0 +1,24 @@ +package com.microsoft.graph.httpcore; + +import java.io.IOException; + +import org.apache.http.HttpException; +import org.apache.http.HttpRequest; +import org.apache.http.HttpRequestInterceptor; +import org.apache.http.protocol.HttpContext; + +public class AuthenticationHandler implements HttpRequestInterceptor { + + private IAuthenticationProvider authProvider; + + public AuthenticationHandler(IAuthenticationProvider authProvider) { + this.authProvider = authProvider; + } + + @Override + public void process(HttpRequest request, HttpContext context) throws HttpException, IOException { + // TODO Auto-generated method stub + authProvider.authenticateRequest(request); + } + +} diff --git a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java new file mode 100644 index 000000000..8eb239b05 --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java @@ -0,0 +1,44 @@ +package com.microsoft.graph.httpcore; + +import org.apache.http.client.config.RequestConfig; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; + +public class HttpClients { + private HttpClients() { + super(); + } + + /** + * Creates builder object for construction of custom + * {@link CloseableHttpClient} instances. + */ + public static HttpClientBuilder custom() { + return HttpClientBuilder.create(); + } + + /** + * Creates {@link CloseableHttpClient} instance with default + * configuration. + */ + public static CloseableHttpClient createDefault() { + //return HttpClientBuilder.create().build(); + + RequestConfig config = RequestConfig.custom().setMaxRedirects(5).build(); + + IAuthenticationProvider auth = null; + return HttpClientBuilder.create().addInterceptorFirst(new AuthenticationHandler(null)) + .setRedirectStrategy(new RedirectHandler()) + .setServiceUnavailableRetryStrategy(new RetryHandler()) + .setDefaultRequestConfig(config) + .build(); + } + + /** + * Creates {@link CloseableHttpClient} instance with default + * configuration based on system properties. + */ + public static CloseableHttpClient createSystem() { + return HttpClientBuilder.create().useSystemProperties().build(); + } +} diff --git a/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java b/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java new file mode 100644 index 000000000..c969cfe11 --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java @@ -0,0 +1,12 @@ +package com.microsoft.graph.httpcore; + +import org.apache.http.HttpRequest; + +public interface IAuthenticationProvider { + /** + * Authenticates the request + * + * @param request the request to authenticate + */ + void authenticateRequest(final HttpRequest request); +} diff --git a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java new file mode 100644 index 000000000..6e1e7bcfd --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java @@ -0,0 +1,73 @@ +package com.microsoft.graph.httpcore; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.http.Header; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.ProtocolException; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.impl.client.DefaultRedirectStrategy; +import org.apache.http.protocol.HttpContext; +import org.apache.http.util.Args; + +public class RedirectHandler extends DefaultRedirectStrategy{ + + public static final RedirectHandler INSTANCE = new RedirectHandler(); + + @Override + public boolean isRedirected( + final HttpRequest request, + final HttpResponse response, + final HttpContext context) throws ProtocolException { + Args.notNull(request, "HTTP request"); + Args.notNull(response, "HTTP response"); + + final int statusCode = response.getStatusLine().getStatusCode(); + final Header locationHeader = response.getFirstHeader("location"); + if(locationHeader == null) + return false; + + if(statusCode == HttpStatus.SC_MOVED_TEMPORARILY || + statusCode == HttpStatus.SC_MOVED_PERMANENTLY || + statusCode == HttpStatus.SC_TEMPORARY_REDIRECT || + statusCode == HttpStatus.SC_SEE_OTHER) + return true; + + return false; + } + + @Override + public HttpUriRequest getRedirect( + final HttpRequest request, + final HttpResponse response, + final HttpContext context) throws ProtocolException { + final URI uri = getLocationURI(request, response, context); + final String method = request.getRequestLine().getMethod(); + if (method.equalsIgnoreCase(HttpHead.METHOD_NAME)) { + return new HttpHead(uri); + } else if (method.equalsIgnoreCase(HttpGet.METHOD_NAME)) + return new HttpGet(uri); + else { + final int status = response.getStatusLine().getStatusCode(); + if(status != HttpStatus.SC_SEE_OTHER) { + try { + final URI requestURI = new URI(request.getRequestLine().getUri()); + if(!uri.getHost().equalsIgnoreCase(requestURI.getHost())) { + request.removeHeaders("Authorization"); + } + return RequestBuilder.copy(request).setUri(uri).build(); + } + catch (final URISyntaxException ex) { + throw new ProtocolException(ex.getMessage(), ex); + } + } + return new HttpGet(uri); + } + } +} diff --git a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java new file mode 100644 index 000000000..b49b26a8a --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java @@ -0,0 +1,101 @@ +package com.microsoft.graph.httpcore; + +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.client.ServiceUnavailableRetryStrategy; +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; +import org.apache.http.client.methods.HttpPatch; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.protocol.HttpContext; +import org.apache.http.protocol.HttpCoreContext; +import org.apache.http.util.Args; + +public class RetryHandler implements ServiceUnavailableRetryStrategy{ + + /** + * Maximum number of allowed retries if the server responds with a HTTP code + * in our retry code list. Default value is 1. + */ + private final int maxRetries; + + /** + * Retry interval between subsequent requests, in milliseconds. Default + * value is 1 second. + */ + private long retryInterval; + private final int DELAY_SECONDS = 10; + private final String RETRY_AFTER = "Retry-After"; + private final String TRANSFER_ENCODING = "Transfer-Encoding"; + + private final int MSClientErrorCodeTooManyRequests = 429; + private final int MSClientErrorCodeServiceUnavailable = 503; + private final int MSClientErrorCodeGatewayTimeout = 504; + + public RetryHandler(final int maxRetries, final int retryInterval) { + super(); + Args.positive(maxRetries, "Max retries"); + Args.positive(retryInterval, "Retry interval"); + this.maxRetries = maxRetries; + this.retryInterval = retryInterval; + } + + public RetryHandler() { + this(1, 1000); + } + + @Override + public boolean retryRequest(HttpResponse response, int executionCount, HttpContext context) { + boolean shouldRetry = false; + int statusCode = response.getStatusLine().getStatusCode(); + shouldRetry = (executionCount < maxRetries) && checkStatus(statusCode) && isBuffered(response, context); + + if(shouldRetry) { + Header header = response.getFirstHeader(RETRY_AFTER); + if(header != null) + retryInterval = Long.parseLong(header.getValue()); + else + retryInterval = (long)Math.pow(2.0, (double)executionCount) * DELAY_SECONDS; + } + return shouldRetry; + } + + @Override + public long getRetryInterval() { + // TODO Auto-generated method stub + return retryInterval; + } + + private boolean checkStatus(int statusCode) { + if (statusCode == MSClientErrorCodeTooManyRequests || statusCode == MSClientErrorCodeServiceUnavailable + || statusCode == MSClientErrorCodeGatewayTimeout) + return true; + return false; + } + + private boolean isBuffered(HttpResponse response, HttpContext context) { + HttpRequest request = (HttpRequest)context.getAttribute( HttpCoreContext.HTTP_REQUEST); + String methodName = request.getRequestLine().getMethod(); + + boolean isHTTPMethodPutPatchOrPost = methodName.equalsIgnoreCase(HttpPost.METHOD_NAME) || + methodName.equalsIgnoreCase(HttpPut.METHOD_NAME) || + methodName.equalsIgnoreCase(HttpPatch.METHOD_NAME); + + Header transferEncoding = response.getFirstHeader(TRANSFER_ENCODING); + boolean isTransferEncodingChunked = (transferEncoding != null) && + transferEncoding.getValue().equalsIgnoreCase("chunked"); + + HttpEntity entity = null; + if(request instanceof HttpEntityEnclosingRequestBase) { + HttpEntityEnclosingRequestBase httprequest = (HttpEntityEnclosingRequestBase)request; + entity = httprequest.getEntity(); + } + + if(entity != null && isHTTPMethodPutPatchOrPost && isTransferEncodingChunked) + return false; + return true; + } + +} From 00e75841a64cf9948b6a6f1a42f1cac9ef6aa4b8 Mon Sep 17 00:00:00 2001 From: deagrawa Date: Wed, 21 Nov 2018 16:31:57 +0530 Subject: [PATCH 03/38] Updating httpClient with default creation logic --- .../microsoft/graph/httpcore/HttpClients.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java index 8eb239b05..bf0a60f92 100644 --- a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java +++ b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java @@ -22,17 +22,27 @@ public static HttpClientBuilder custom() { * configuration. */ public static CloseableHttpClient createDefault() { - //return HttpClientBuilder.create().build(); - RequestConfig config = RequestConfig.custom().setMaxRedirects(5).build(); - - IAuthenticationProvider auth = null; return HttpClientBuilder.create().addInterceptorFirst(new AuthenticationHandler(null)) .setRedirectStrategy(new RedirectHandler()) .setServiceUnavailableRetryStrategy(new RetryHandler()) .setDefaultRequestConfig(config) .build(); } + + /** + * Creates {@link CloseableHttpClient} instance with default + * configuration and provided authProvider + */ + public static CloseableHttpClient createDefault(IAuthenticationProvider auth) { + RequestConfig config = RequestConfig.custom().setMaxRedirects(5).build(); + + return HttpClientBuilder.create().addInterceptorFirst(new AuthenticationHandler(auth)) + .setRedirectStrategy(new RedirectHandler()) + .setServiceUnavailableRetryStrategy(new RetryHandler()) + .setDefaultRequestConfig(config) + .build(); + } /** * Creates {@link CloseableHttpClient} instance with default From 7b9154e2724463618743dac10d04650e35a41781 Mon Sep 17 00:00:00 2001 From: deagrawa Date: Mon, 26 Nov 2018 18:03:53 +0530 Subject: [PATCH 04/38] Adding batch request content files --- .../graph/content/MSBatchRequestContent.java | 107 ++++++++++++++++++ .../graph/content/MSBatchRequestStep.java | 29 +++++ .../graph/content/MSBatchResponseContent.java | 31 +++++ 3 files changed, 167 insertions(+) create mode 100644 src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java create mode 100644 src/main/java/com/microsoft/graph/content/MSBatchRequestStep.java create mode 100644 src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java diff --git a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java new file mode 100644 index 000000000..d649cf70d --- /dev/null +++ b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java @@ -0,0 +1,107 @@ +package com.microsoft.graph.content; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpRequest; +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; +import org.apache.http.util.EntityUtils; +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; + +public class MSBatchRequestContent { + private List batchRequestStepsArray; + private final int maxNumberOfRequests = 20; + + public MSBatchRequestContent(List batchRequestStepsArray) { + batchRequestStepsArray = new ArrayList<>(); + if(batchRequestStepsArray.size() <= maxNumberOfRequests) { + for(MSBatchRequestStep requestStep: batchRequestStepsArray) + addBatchRequestStep(requestStep); + } + } + + public MSBatchRequestContent() { + batchRequestStepsArray = new ArrayList<>(); + } + + public void addBatchRequestStep(MSBatchRequestStep batchRequestStep) { + if(batchRequestStep.getRequestId().compareTo("") == 0) + return; + if(batchRequestStepsArray.size() == maxNumberOfRequests) + return; + for(MSBatchRequestStep requestStep: batchRequestStepsArray) { + if(batchRequestStep.getRequestId().compareTo(requestStep.getRequestId()) == 0) + return; + } + batchRequestStepsArray.add(batchRequestStep); + } + + public void removeBatchRequesStepWithId(String requestId) { + for (int i = batchRequestStepsArray.size()-1; i >= 0; i--) + { + MSBatchRequestStep requestStep = batchRequestStepsArray.get(i); + for (int j = requestStep.getArrayOfDependsOnIds().size() - 1; j >= 0; j--) + { + String dependsOnId = requestStep.getArrayOfDependsOnIds().get(j); + if(dependsOnId.compareTo(requestId) == 0) + { + requestStep.getArrayOfDependsOnIds().remove(j); + } + } + if(requestId.compareTo(requestStep.getRequestId()) == 0) + batchRequestStepsArray.remove(i); + } + } + + public String getBatchRequestContent() { + Map>> batchRequestContentMap = new HashMap(); + List> batchContentArray = new ArrayList(); + for(MSBatchRequestStep requestStep : batchRequestStepsArray) { + batchContentArray.add(getBatchRequestMapFromRequestStep(requestStep)); + } + batchRequestContentMap.put("requests", batchContentArray); + return JSONValue.toJSONString(batchRequestContentMap); + } + + private Map getBatchRequestMapFromRequestStep(MSBatchRequestStep batchRequestStep){ + Map contentmap = new HashMap(); + contentmap.put("id", batchRequestStep.getRequestId()); + contentmap.put("url", batchRequestStep.getRequest().getRequestLine().getUri()); + contentmap.put("method", batchRequestStep.getRequest().getRequestLine().getMethod()); + Header[] headers = batchRequestStep.getRequest().getAllHeaders(); + if(headers != null) { + JSONObject obj = new JSONObject(); + for(Header header: headers) { + obj.put(header.getName(), header.getValue()); + } + contentmap.put("headers", obj.toJSONString()); + } + HttpEntity entity = null; + HttpRequest request = batchRequestStep.getRequest(); + if(request instanceof HttpEntityEnclosingRequestBase) { + HttpEntityEnclosingRequestBase httprequest = (HttpEntityEnclosingRequestBase)request; + entity = httprequest.getEntity(); + } + if(entity != null) { + try { + String body = EntityUtils.toString(entity); + contentmap.put("body", body); + } + catch(Exception e) { + } + } + + List arrayOfDependsOnIds = batchRequestStep.getArrayOfDependsOnIds(); + if(arrayOfDependsOnIds != null) { + contentmap.put("dependsOn", JSONValue.toJSONString(arrayOfDependsOnIds)); + } + + return contentmap; + } + +} diff --git a/src/main/java/com/microsoft/graph/content/MSBatchRequestStep.java b/src/main/java/com/microsoft/graph/content/MSBatchRequestStep.java new file mode 100644 index 000000000..d87bf27da --- /dev/null +++ b/src/main/java/com/microsoft/graph/content/MSBatchRequestStep.java @@ -0,0 +1,29 @@ +package com.microsoft.graph.content; + +import java.util.List; + +import org.apache.http.HttpRequest; + +public class MSBatchRequestStep { + private String requestId; + private HttpRequest request; + private List arrayOfDependsOnIds; + + public MSBatchRequestStep(String requestId, HttpRequest request, List arrayOfDependsOnIds) { + this.requestId = requestId; + this.request = request; + this.arrayOfDependsOnIds = arrayOfDependsOnIds; + } + + public String getRequestId() { + return requestId; + } + + public HttpRequest getRequest() { + return request; + } + + public List getArrayOfDependsOnIds(){ + return arrayOfDependsOnIds; + } +} diff --git a/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java b/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java new file mode 100644 index 000000000..ac30ccb0e --- /dev/null +++ b/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java @@ -0,0 +1,31 @@ +package com.microsoft.graph.content; + +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +public class MSBatchResponseContent { + + private JSONObject batchResponseObj; + + public MSBatchResponseContent(String batchResponseData ) { + JSONParser parser = new JSONParser(); + try { + batchResponseObj = (JSONObject) parser.parse(batchResponseData); + } + catch(ParseException e) { + } + } + + public String getResponseById(String requestId) { + if(batchResponseObj.get(requestId) != null) + return batchResponseObj.get(requestId).toString(); + return null; + } + + public String getResponses() { + if(batchResponseObj != null) + return batchResponseObj.toJSONString(); + return null; + } +} From ed236bdaf652571ba41c05e8e0850f936f9fabb4 Mon Sep 17 00:00:00 2001 From: deagrawa Date: Mon, 26 Nov 2018 18:04:30 +0530 Subject: [PATCH 05/38] Taking dependency on json-simple library --- build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.gradle b/build.gradle index 0307d7bc2..53d3467ec 100644 --- a/build.gradle +++ b/build.gradle @@ -28,5 +28,9 @@ dependencies { // Use Apache HttpClient compile 'org.apache.httpcomponents:httpclient:4.5.6' + + // https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple + compile group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1' + } From fc3dfae889ef4100aeda5cd1738836711f46d5af Mon Sep 17 00:00:00 2001 From: deagrawa Date: Thu, 3 Jan 2019 11:56:30 +0530 Subject: [PATCH 06/38] Test files for middlewares classes --- .../graph/content/MSBatchRequestContent.java | 14 ++--- .../graph/content/MSBatchResponseContent.java | 48 +++++++++++++-- .../graph/httpcore/RedirectHandler.java | 4 +- .../content/MSBatchRequestContentTest.java | 60 +++++++++++++++++++ .../graph/content/MSBatchRequestStepTest.java | 25 ++++++++ .../content/MSBatchResponseContentTest.java | 40 +++++++++++++ 6 files changed, 176 insertions(+), 15 deletions(-) create mode 100644 src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java create mode 100644 src/test/java/com/microsoft/graph/content/MSBatchRequestStepTest.java create mode 100644 src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java diff --git a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java index d649cf70d..8174306aa 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java @@ -18,7 +18,7 @@ public class MSBatchRequestContent { private final int maxNumberOfRequests = 20; public MSBatchRequestContent(List batchRequestStepsArray) { - batchRequestStepsArray = new ArrayList<>(); + this.batchRequestStepsArray = new ArrayList<>(); if(batchRequestStepsArray.size() <= maxNumberOfRequests) { for(MSBatchRequestStep requestStep: batchRequestStepsArray) addBatchRequestStep(requestStep); @@ -29,16 +29,16 @@ public MSBatchRequestContent() { batchRequestStepsArray = new ArrayList<>(); } - public void addBatchRequestStep(MSBatchRequestStep batchRequestStep) { + public boolean addBatchRequestStep(MSBatchRequestStep batchRequestStep) { if(batchRequestStep.getRequestId().compareTo("") == 0) - return; + return false; if(batchRequestStepsArray.size() == maxNumberOfRequests) - return; + return false; for(MSBatchRequestStep requestStep: batchRequestStepsArray) { if(batchRequestStep.getRequestId().compareTo(requestStep.getRequestId()) == 0) - return; + return false; } - batchRequestStepsArray.add(batchRequestStep); + return batchRequestStepsArray.add(batchRequestStep); } public void removeBatchRequesStepWithId(String requestId) { @@ -74,7 +74,7 @@ private Map getBatchRequestMapFromRequestStep(MSBatchRequestStep contentmap.put("url", batchRequestStep.getRequest().getRequestLine().getUri()); contentmap.put("method", batchRequestStep.getRequest().getRequestLine().getMethod()); Header[] headers = batchRequestStep.getRequest().getAllHeaders(); - if(headers != null) { + if(headers != null && headers.length != 0) { JSONObject obj = new JSONObject(); for(Header header: headers) { obj.put(header.getName(), header.getValue()); diff --git a/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java b/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java index ac30ccb0e..cefea1fa7 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java @@ -1,5 +1,14 @@ package com.microsoft.graph.content; +import java.util.Set; + +import org.apache.http.Consts; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.message.BasicHttpResponse; +import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; @@ -11,21 +20,48 @@ public class MSBatchResponseContent { public MSBatchResponseContent(String batchResponseData ) { JSONParser parser = new JSONParser(); try { - batchResponseObj = (JSONObject) parser.parse(batchResponseData); + if(batchResponseData != null) + batchResponseObj = (JSONObject) parser.parse(batchResponseData); } catch(ParseException e) { } } - public String getResponseById(String requestId) { - if(batchResponseObj.get(requestId) != null) - return batchResponseObj.get(requestId).toString(); - return null; + public HttpResponse getResponseById(String requestId) { + if(batchResponseObj == null) + return null; + + JSONArray responses = (JSONArray)batchResponseObj.get("responses"); + if(responses == null) + return null; + + for(Object response: responses) { + JSONObject jsonresponse = (JSONObject)response; + String id = (String)jsonresponse.get("id"); + if(id.compareTo(requestId) == 0) { + HttpResponse httpresponse = new BasicHttpResponse(null, ((Long)jsonresponse.get("status")).intValue(), null); + if(jsonresponse.get("body") != null) { + HttpEntity entity = new StringEntity(jsonresponse.get("body").toString(), ContentType.APPLICATION_JSON); + httpresponse.setEntity(entity); + } + if(jsonresponse.get("headers") != null){ + JSONObject jsonheaders = (JSONObject)jsonresponse.get("headers"); + for(Object key: jsonheaders.keySet()) { + String strkey = (String)key; + String strvalue = (String)jsonheaders.get(strkey); + httpresponse.setHeader(strkey, strvalue); + } + } + return httpresponse; + + } + } + return null; } public String getResponses() { if(batchResponseObj != null) - return batchResponseObj.toJSONString(); + return ((JSONArray)batchResponseObj.get("responses")).toJSONString(); return null; } } diff --git a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java index 6e1e7bcfd..0935868e0 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java @@ -58,9 +58,9 @@ public HttpUriRequest getRedirect( if(status != HttpStatus.SC_SEE_OTHER) { try { final URI requestURI = new URI(request.getRequestLine().getUri()); - if(!uri.getHost().equalsIgnoreCase(requestURI.getHost())) { + if(!uri.getHost().equalsIgnoreCase(requestURI.getHost()) || + !uri.getScheme().equalsIgnoreCase(requestURI.getScheme())) request.removeHeaders("Authorization"); - } return RequestBuilder.copy(request).setUri(uri).build(); } catch (final URISyntaxException ex) { diff --git a/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java b/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java new file mode 100644 index 000000000..390bb52b3 --- /dev/null +++ b/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java @@ -0,0 +1,60 @@ +package com.microsoft.graph.content; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.http.HttpRequest; +import org.apache.http.client.methods.HttpGet; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class MSBatchRequestContentTest { + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + } + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testMSBatchRequestContentCreation() { + + List requestStepArray = new ArrayList<>(); + for(int i=0;i<5;i++) { + HttpRequest request = new HttpGet("http://graph.microsoft.com"); + List arrayOfDependsOnIds = new ArrayList(); + MSBatchRequestStep requestStep = new MSBatchRequestStep("" + i, request, arrayOfDependsOnIds); + requestStepArray.add(requestStep); + } + MSBatchRequestContent requestContent = new MSBatchRequestContent(requestStepArray); + assertTrue(requestContent.getBatchRequestContent() != null); + } + + @Test + public void testGetBatchRequestContent() { + HttpRequest request = new HttpGet("http://graph.microsoft.com"); + List arrayOfDependsOnIds = new ArrayList(); + MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); + MSBatchRequestContent requestContent = new MSBatchRequestContent(); + requestContent.addBatchRequestStep(requestStep); + String content = requestContent.getBatchRequestContent(); + String expectedContent = "{\"requests\":[{\"method\":\"GET\",\"dependsOn\":\"[]\",\"id\":\"1\",\"url\":\"http:\\/\\/graph.microsoft.com\"}]}"; + assertTrue(content.compareTo(expectedContent) == 0); + } + +} diff --git a/src/test/java/com/microsoft/graph/content/MSBatchRequestStepTest.java b/src/test/java/com/microsoft/graph/content/MSBatchRequestStepTest.java new file mode 100644 index 000000000..fa98ec302 --- /dev/null +++ b/src/test/java/com/microsoft/graph/content/MSBatchRequestStepTest.java @@ -0,0 +1,25 @@ +package com.microsoft.graph.content; + +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.http.HttpRequest; +import org.apache.http.client.methods.HttpGet; +import org.junit.Test; + +public class MSBatchRequestStepTest { + + @Test + public void testMSBatchRequestStepCreation() { + HttpRequest request = new HttpGet("http://graph.microsoft.com"); + List arrayOfDependsOnIds = new ArrayList(); + MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); + assertTrue("Test BatchRequestStep creation", requestStep != null); + assertTrue("Test Request id", requestStep.getRequestId().compareTo("1") == 0); + assertTrue("Test Request object", requestStep.getRequest() == request); + assertTrue("Test Array of depends on Ids", requestStep.getArrayOfDependsOnIds() != null); + } + +} diff --git a/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java b/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java new file mode 100644 index 000000000..5f4bbac74 --- /dev/null +++ b/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java @@ -0,0 +1,40 @@ +package com.microsoft.graph.content; + +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.Arrays; + +import org.apache.http.HttpResponse; +import org.apache.http.ParseException; +import org.apache.http.util.EntityUtils; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class MSBatchResponseContentTest { + + @Test + public void testNullMSBatchResponseContent() { + String responsedata = null; + MSBatchResponseContent batchresponse = new MSBatchResponseContent(responsedata); + assertTrue(batchresponse.getResponses() == null); + } + + @Test + public void testValidMSBatchResponseContent() { + String responsedata = "{\"responses\": [{ \"id\": \"1\", \"status\": 302, \"headers\": { \"location\": \"https://b0mpua-by3301.files.1drv.com/y23vmagahszhxzlcvhasdhasghasodfi\" } }, { \"id\": \"3\", \"status\": 401, \"body\": { \"error\": { \"code\": \"Forbidden\", \"message\": \"...\" } } }, { \"id\": \"2\", \"status\": 200, \"body\": { \"@odata.context\": \"https://graph.microsoft.com/v1.0/$metadata#Collection(microsoft.graph.plannerTask)\", \"value\": [] } }, { \"id\": \"4\", \"status\": 204, \"body\": null } ] }"; + MSBatchResponseContent batchresponse = new MSBatchResponseContent(responsedata); + assertTrue(batchresponse.getResponses() != null); + } + + @Test + public void testGetMSBatchResponseContentByID() { + String responsedata = "{\"responses\": [{ \"id\": \"1\", \"status\": 302, \"headers\": { \"location\": \"https://b0mpua-by3301.files.1drv.com/y23vmagahszhxzlcvhasdhasghasodfi\" } }, { \"id\": \"3\", \"status\": 401, \"body\": { \"error\": { \"code\": \"Forbidden\", \"message\": \"...\" } } }, { \"id\": \"2\", \"status\": 200, \"body\": { \"@odata.context\": \"https://graph.microsoft.com/v1.0/$metadata#Collection(microsoft.graph.plannerTask)\", \"value\": [] } }, { \"id\": \"4\", \"status\": 204, \"body\": null } ] }"; + MSBatchResponseContent batchresponse = new MSBatchResponseContent(responsedata); + HttpResponse response = batchresponse.getResponseById("1"); + assertTrue(response != null); + } +} From 23518672e36cf6cc605f49c1bb1fb13dcf91bd24 Mon Sep 17 00:00:00 2001 From: deagrawa Date: Wed, 16 Jan 2019 11:58:21 +0530 Subject: [PATCH 07/38] Add test files for Authentication handler and clean test file for batch request content --- .../content/MSBatchRequestContentTest.java | 16 ------- .../httpcore/AuthenticationHandlerTest.java | 47 +++++++++++++++++++ 2 files changed, 47 insertions(+), 16 deletions(-) create mode 100644 src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java diff --git a/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java b/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java index 390bb52b3..5013f0dae 100644 --- a/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java +++ b/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java @@ -15,22 +15,6 @@ public class MSBatchRequestContentTest { - @BeforeClass - public static void setUpBeforeClass() throws Exception { - } - - @AfterClass - public static void tearDownAfterClass() throws Exception { - } - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - @Test public void testMSBatchRequestContentCreation() { diff --git a/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java new file mode 100644 index 000000000..fe3a68ccf --- /dev/null +++ b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java @@ -0,0 +1,47 @@ +package com.microsoft.graph.httpcore; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; + +import org.apache.http.Header; +import org.apache.http.HttpException; +import org.apache.http.HttpRequest; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.protocol.HttpClientContext; +import org.junit.Test; + +public class AuthenticationHandlerTest { + + static String token = "TEST-TOKEN"; + + public static class AuthProvider implements IAuthenticationProvider{ + public static String getToken() { + return "Bearer " + token; + } + public void authenticateRequest(HttpRequest request) { + // TODO Auto-generated method stub + request.addHeader("Authorization", AuthProvider.getToken()); + } + } + + @Test + public void testAuthenticationHandler() { + AuthProvider authProvider = new AuthProvider(); + AuthenticationHandler authHandler = new AuthenticationHandler(authProvider); + HttpGet httpget = new HttpGet("https://graph.microsoft.com/v1.0/me/"); + HttpClientContext localContext = HttpClientContext.create(); + + try { + authHandler.process(httpget, localContext); + Header header = httpget.getFirstHeader("Authorization"); + assertTrue(header.getValue().equals("Bearer " + token)); + } catch (HttpException | IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + fail("Authentication handler failure"); + } + } + +} From bdc8a32e928a6de0ec00d2922bd56665465c7239 Mon Sep 17 00:00:00 2001 From: deagrawa Date: Wed, 16 Jan 2019 13:07:28 +0530 Subject: [PATCH 08/38] Add test file for Redirect Handler middleware --- .../graph/httpcore/RedirectHandlerTest.java | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java diff --git a/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java new file mode 100644 index 000000000..63c382a11 --- /dev/null +++ b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java @@ -0,0 +1,149 @@ +package com.microsoft.graph.httpcore; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.HttpVersion; +import org.apache.http.ProtocolException; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.message.BasicHttpResponse; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class RedirectHandlerTest { + + @Test + public void testIsRedirectedFailure() { + RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + HttpGet httpget = new HttpGet("https://graph.microsoft.com/v1.0/me/"); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); + HttpClientContext localContext = HttpClientContext.create(); + try { + boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); + assertTrue(!isRedirected); + } catch (ProtocolException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + fail("Redirect handler isRedirect failure"); + } + } + + @Test + public void testIsRedirectedFailure1() { + RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + HttpGet httpget = new HttpGet("https://graph.microsoft.com/v1.0/me/"); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_BAD_REQUEST, "Bad Request"); + HttpClientContext localContext = HttpClientContext.create(); + try { + boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); + assertTrue(!isRedirected); + } catch (ProtocolException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + fail("Redirect handler isRedirect failure"); + } + } + + @Test + public void testIsRedirectedSuccess() { + RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + HttpGet httpget = new HttpGet("https://graph.microsoft.com/v1.0/me/"); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); + response.setHeader("location", "https://graph.microsoft.com/v1.0/me/"); + HttpClientContext localContext = HttpClientContext.create(); + try { + boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); + assertTrue(isRedirected); + } catch (ProtocolException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + fail("Redirect handler isRedirect failure"); + } + } + + @Test + public void testGetRedirectForGetMethod() { + RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + HttpGet httpget = new HttpGet("https://graph.microsoft.com/v1.0/"); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); + response.setHeader("location", "https://graph.microsoft.com/v1.0/me/"); + HttpClientContext localContext = HttpClientContext.create(); + try { + HttpRequest request = redirectHandler.getRedirect(httpget, response, localContext); + assertTrue(request != null); + final String method = request.getRequestLine().getMethod(); + assertTrue(method.equalsIgnoreCase(HttpGet.METHOD_NAME)); + } catch (ProtocolException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + fail("Redirect handler isRedirect failure"); + } + } + + @Test + public void testGetRedirectForHeadMethod() { + RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + HttpHead httphead = new HttpHead("https://graph.microsoft.com/v1.0/"); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); + response.setHeader("location", "https://graph.microsoft.com/v1.0/me/"); + HttpClientContext localContext = HttpClientContext.create(); + try { + HttpRequest request = redirectHandler.getRedirect(httphead, response, localContext); + assertTrue(request != null); + final String method = request.getRequestLine().getMethod(); + assertTrue(method.equalsIgnoreCase(HttpHead.METHOD_NAME)); + } catch (ProtocolException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + fail("Redirect handler isRedirect failure"); + } + } + + @Test + public void testGetRedirectForPostMethod() { + RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + HttpPost httppost = new HttpPost("https://graph.microsoft.com/v1.0/"); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); + response.setHeader("location", "https://graph.microsoft.com/v1.0/me/"); + HttpClientContext localContext = HttpClientContext.create(); + try { + HttpRequest request = redirectHandler.getRedirect(httppost, response, localContext); + assertTrue(request != null); + final String method = request.getRequestLine().getMethod(); + assertTrue(method.equalsIgnoreCase(HttpPost.METHOD_NAME)); + } catch (ProtocolException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + fail("Redirect handler isRedirect failure"); + } + } + + @Test + public void testGetRedirectForPostMethod1() { + RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + HttpPost httppost = new HttpPost("https://graph.microsoft.com/v1.0/"); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other"); + response.setHeader("location", "https://graph.microsoft.com/v1.0/me/"); + HttpClientContext localContext = HttpClientContext.create(); + try { + HttpRequest request = redirectHandler.getRedirect(httppost, response, localContext); + assertTrue(request != null); + final String method = request.getRequestLine().getMethod(); + assertTrue(method.equalsIgnoreCase(HttpGet.METHOD_NAME)); + } catch (ProtocolException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + fail("Redirect handler isRedirect failure"); + } + } + +} From c86ca674d89869d010fbc8ec28e5cd8d411c9c07 Mon Sep 17 00:00:00 2001 From: deagrawa Date: Wed, 16 Jan 2019 18:54:12 +0530 Subject: [PATCH 09/38] Add test file for retry handler middleware --- .../graph/httpcore/RetryHandlerTest.java | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java diff --git a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java new file mode 100644 index 000000000..b35c8c464 --- /dev/null +++ b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java @@ -0,0 +1,105 @@ +package com.microsoft.graph.httpcore; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.UnsupportedEncodingException; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.HttpVersion; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.entity.StringEntity; +import org.apache.http.message.BasicHttpResponse; +import org.apache.http.protocol.HttpCoreContext; +import org.junit.Test; + +public class RetryHandlerTest { + + @Test + public void testRetryHandlerCreation() { + RetryHandler retryhandler = new RetryHandler(2, 2000); + assertTrue(retryhandler.getRetryInterval() == 2000); + } + + @Test + public void testRetryRequestWithMaxRetryAttempts() { + RetryHandler retryhandler = new RetryHandler(2, 2000); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); + HttpClientContext localContext = HttpClientContext.create(); + assertFalse(retryhandler.retryRequest(response, 3, localContext)); + } + + @Test + public void testRetryRequestForStatusCode() { + RetryHandler retryhandler = new RetryHandler(2, 2000); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_INTERNAL_SERVER_ERROR, "Internal Server Error"); + HttpClientContext localContext = HttpClientContext.create(); + assertFalse(retryhandler.retryRequest(response, 1, localContext)); + } + + @Test + public void testRetryRequestWithTransferEncoding() { + RetryHandler retryhandler = new RetryHandler(2, 2000); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); + response.setHeader("Transfer-Encoding", "chunked"); + HttpPost httppost = new HttpPost("https://graph.microsoft.com/v1.0/"); + + try { + HttpEntity entity = new StringEntity("TEST"); + httppost.setEntity(entity); + HttpClientContext localContext = HttpClientContext.create(); + localContext.setAttribute(HttpCoreContext.HTTP_REQUEST, httppost); + assertFalse(retryhandler.retryRequest(response, 1, localContext)); + + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + fail("Retry handler testRetryHandlerRetryRequest3 test failure"); + } + } + + @Test + public void testRetryRequestWithExponentialBackOff() { + RetryHandler retryhandler = new RetryHandler(2, 2000); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); + HttpPost httppost = new HttpPost("https://graph.microsoft.com/v1.0/"); + + try { + HttpEntity entity = new StringEntity("TEST"); + httppost.setEntity(entity); + HttpClientContext localContext = HttpClientContext.create(); + localContext.setAttribute(HttpCoreContext.HTTP_REQUEST, httppost); + assertTrue(retryhandler.retryRequest(response, 1, localContext)); + assertTrue(retryhandler.getRetryInterval() == 20); + + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + fail("Retry handler testRetryHandlerRetryRequest3 test failure"); + } + } + + @Test + public void testRetryHandlerRetryRequestWithRetryAfterHeader() { + RetryHandler retryhandler = new RetryHandler(2, 2000); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); + response.setHeader("Retry-After", "100"); + HttpPost httppost = new HttpPost("https://graph.microsoft.com/v1.0/"); + + try { + HttpEntity entity = new StringEntity("TEST"); + httppost.setEntity(entity); + HttpClientContext localContext = HttpClientContext.create(); + localContext.setAttribute(HttpCoreContext.HTTP_REQUEST, httppost); + assertTrue(retryhandler.retryRequest(response, 1, localContext)); + assertTrue(retryhandler.getRetryInterval() == 100); + + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + fail("Retry handler testRetryHandlerRetryRequestWithRetryAfterHeader test failure"); + } + } + +} From b38f97793267dd9e4a44e6ebd99591adff1172a6 Mon Sep 17 00:00:00 2001 From: deagrawa Date: Thu, 17 Jan 2019 18:07:11 +0530 Subject: [PATCH 10/38] Updating test files for middlewares and HttpClient --- .../microsoft/graph/httpcore/HttpClients.java | 13 ----------- .../httpcore/AuthenticationHandlerTest.java | 2 -- .../graph/httpcore/HttpClientsTest.java | 23 +++++++++++++++++++ .../graph/httpcore/RedirectHandlerTest.java | 10 -------- 4 files changed, 23 insertions(+), 25 deletions(-) create mode 100644 src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java diff --git a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java index bf0a60f92..e51eb5921 100644 --- a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java +++ b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java @@ -17,19 +17,6 @@ public static HttpClientBuilder custom() { return HttpClientBuilder.create(); } - /** - * Creates {@link CloseableHttpClient} instance with default - * configuration. - */ - public static CloseableHttpClient createDefault() { - RequestConfig config = RequestConfig.custom().setMaxRedirects(5).build(); - return HttpClientBuilder.create().addInterceptorFirst(new AuthenticationHandler(null)) - .setRedirectStrategy(new RedirectHandler()) - .setServiceUnavailableRetryStrategy(new RetryHandler()) - .setDefaultRequestConfig(config) - .build(); - } - /** * Creates {@link CloseableHttpClient} instance with default * configuration and provided authProvider diff --git a/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java index fe3a68ccf..1cfd6abe3 100644 --- a/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java @@ -21,7 +21,6 @@ public static String getToken() { return "Bearer " + token; } public void authenticateRequest(HttpRequest request) { - // TODO Auto-generated method stub request.addHeader("Authorization", AuthProvider.getToken()); } } @@ -38,7 +37,6 @@ public void testAuthenticationHandler() { Header header = httpget.getFirstHeader("Authorization"); assertTrue(header.getValue().equals("Bearer " + token)); } catch (HttpException | IOException e) { - // TODO Auto-generated catch block e.printStackTrace(); fail("Authentication handler failure"); } diff --git a/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java b/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java new file mode 100644 index 000000000..474ccfc15 --- /dev/null +++ b/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java @@ -0,0 +1,23 @@ +package com.microsoft.graph.httpcore; + +import static org.junit.Assert.assertTrue; + +import org.apache.http.HttpRequest; +import org.apache.http.impl.client.CloseableHttpClient; +import org.junit.Test; + +public class HttpClientsTest { + + @Test + public void testHttpClientCreation() { + IAuthenticationProvider authprovider = new IAuthenticationProvider() { + @Override + public void authenticateRequest(HttpRequest request) { + request.addHeader("Authorization", "TOKEN"); + } + }; + CloseableHttpClient httpclient = HttpClients.createDefault(authprovider); + assertTrue(httpclient != null); + } + +} diff --git a/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java index 63c382a11..fb433276e 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java @@ -13,10 +13,6 @@ import org.apache.http.client.methods.HttpPost; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.message.BasicHttpResponse; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; public class RedirectHandlerTest { @@ -31,7 +27,6 @@ public void testIsRedirectedFailure() { boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); assertTrue(!isRedirected); } catch (ProtocolException e) { - // TODO Auto-generated catch block e.printStackTrace(); fail("Redirect handler isRedirect failure"); } @@ -47,7 +42,6 @@ public void testIsRedirectedFailure1() { boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); assertTrue(!isRedirected); } catch (ProtocolException e) { - // TODO Auto-generated catch block e.printStackTrace(); fail("Redirect handler isRedirect failure"); } @@ -64,7 +58,6 @@ public void testIsRedirectedSuccess() { boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); assertTrue(isRedirected); } catch (ProtocolException e) { - // TODO Auto-generated catch block e.printStackTrace(); fail("Redirect handler isRedirect failure"); } @@ -83,7 +76,6 @@ public void testGetRedirectForGetMethod() { final String method = request.getRequestLine().getMethod(); assertTrue(method.equalsIgnoreCase(HttpGet.METHOD_NAME)); } catch (ProtocolException e) { - // TODO Auto-generated catch block e.printStackTrace(); fail("Redirect handler isRedirect failure"); } @@ -102,7 +94,6 @@ public void testGetRedirectForHeadMethod() { final String method = request.getRequestLine().getMethod(); assertTrue(method.equalsIgnoreCase(HttpHead.METHOD_NAME)); } catch (ProtocolException e) { - // TODO Auto-generated catch block e.printStackTrace(); fail("Redirect handler isRedirect failure"); } @@ -140,7 +131,6 @@ public void testGetRedirectForPostMethod1() { final String method = request.getRequestLine().getMethod(); assertTrue(method.equalsIgnoreCase(HttpGet.METHOD_NAME)); } catch (ProtocolException e) { - // TODO Auto-generated catch block e.printStackTrace(); fail("Redirect handler isRedirect failure"); } From 266331ea927d328cf6ef29e4af836ba1c299dc04 Mon Sep 17 00:00:00 2001 From: deagrawa Date: Thu, 17 Jan 2019 18:07:59 +0530 Subject: [PATCH 11/38] Updating build setting to include apache httpclient as an API dependency --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 53d3467ec..ab9da0ab6 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,7 @@ dependencies { testImplementation 'junit:junit:4.12' // Use Apache HttpClient - compile 'org.apache.httpcomponents:httpclient:4.5.6' + api 'org.apache.httpcomponents:httpclient:4.5.6' // https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple compile group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1' From 0ecb41c1bf0348fdcbc5b6e9032f6a2241e1ae8e Mon Sep 17 00:00:00 2001 From: deagrawa Date: Thu, 17 Jan 2019 18:40:52 +0530 Subject: [PATCH 12/38] Update variables used in Retry and Redirect handler tests. --- .../graph/httpcore/RedirectHandlerTest.java | 42 ++++++++++--------- .../graph/httpcore/RetryHandlerTest.java | 24 ++++++----- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java index fb433276e..8e6a3bfa5 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java @@ -16,11 +16,14 @@ import org.junit.Test; public class RedirectHandlerTest { + + String testmeurl = "https://graph.microsoft.com/v1.0/me/"; + String testurl = "https://graph.microsoft.com/v1.0/"; @Test public void testIsRedirectedFailure() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet("https://graph.microsoft.com/v1.0/me/"); + HttpGet httpget = new HttpGet(testmeurl); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); HttpClientContext localContext = HttpClientContext.create(); try { @@ -28,14 +31,14 @@ public void testIsRedirectedFailure() { assertTrue(!isRedirected); } catch (ProtocolException e) { e.printStackTrace(); - fail("Redirect handler isRedirect failure"); + fail("Redirect handler testIsRedirectedFailure failure"); } } @Test public void testIsRedirectedFailure1() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet("https://graph.microsoft.com/v1.0/me/"); + HttpGet httpget = new HttpGet(testmeurl); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_BAD_REQUEST, "Bad Request"); HttpClientContext localContext = HttpClientContext.create(); try { @@ -43,32 +46,32 @@ public void testIsRedirectedFailure1() { assertTrue(!isRedirected); } catch (ProtocolException e) { e.printStackTrace(); - fail("Redirect handler isRedirect failure"); + fail("Redirect handler testIsRedirectedFailure1 failure"); } } @Test public void testIsRedirectedSuccess() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet("https://graph.microsoft.com/v1.0/me/"); + HttpGet httpget = new HttpGet(testmeurl); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); - response.setHeader("location", "https://graph.microsoft.com/v1.0/me/"); + response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); assertTrue(isRedirected); } catch (ProtocolException e) { e.printStackTrace(); - fail("Redirect handler isRedirect failure"); + fail("Redirect handler testIsRedirectedSuccess failure"); } } @Test public void testGetRedirectForGetMethod() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet("https://graph.microsoft.com/v1.0/"); + HttpGet httpget = new HttpGet(testurl); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); - response.setHeader("location", "https://graph.microsoft.com/v1.0/me/"); + response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { HttpRequest request = redirectHandler.getRedirect(httpget, response, localContext); @@ -77,16 +80,16 @@ public void testGetRedirectForGetMethod() { assertTrue(method.equalsIgnoreCase(HttpGet.METHOD_NAME)); } catch (ProtocolException e) { e.printStackTrace(); - fail("Redirect handler isRedirect failure"); + fail("Redirect handler testGetRedirectForGetMethod failure"); } } @Test public void testGetRedirectForHeadMethod() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpHead httphead = new HttpHead("https://graph.microsoft.com/v1.0/"); + HttpHead httphead = new HttpHead(testurl); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); - response.setHeader("location", "https://graph.microsoft.com/v1.0/me/"); + response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { HttpRequest request = redirectHandler.getRedirect(httphead, response, localContext); @@ -95,16 +98,16 @@ public void testGetRedirectForHeadMethod() { assertTrue(method.equalsIgnoreCase(HttpHead.METHOD_NAME)); } catch (ProtocolException e) { e.printStackTrace(); - fail("Redirect handler isRedirect failure"); + fail("Redirect handler testGetRedirectForHeadMethod failure"); } } @Test public void testGetRedirectForPostMethod() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpPost httppost = new HttpPost("https://graph.microsoft.com/v1.0/"); + HttpPost httppost = new HttpPost(testurl); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); - response.setHeader("location", "https://graph.microsoft.com/v1.0/me/"); + response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { HttpRequest request = redirectHandler.getRedirect(httppost, response, localContext); @@ -112,18 +115,17 @@ public void testGetRedirectForPostMethod() { final String method = request.getRequestLine().getMethod(); assertTrue(method.equalsIgnoreCase(HttpPost.METHOD_NAME)); } catch (ProtocolException e) { - // TODO Auto-generated catch block e.printStackTrace(); - fail("Redirect handler isRedirect failure"); + fail("Redirect handler testGetRedirectForPostMethod failure"); } } @Test public void testGetRedirectForPostMethod1() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpPost httppost = new HttpPost("https://graph.microsoft.com/v1.0/"); + HttpPost httppost = new HttpPost(testurl); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other"); - response.setHeader("location", "https://graph.microsoft.com/v1.0/me/"); + response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { HttpRequest request = redirectHandler.getRedirect(httppost, response, localContext); @@ -132,7 +134,7 @@ public void testGetRedirectForPostMethod1() { assertTrue(method.equalsIgnoreCase(HttpGet.METHOD_NAME)); } catch (ProtocolException e) { e.printStackTrace(); - fail("Redirect handler isRedirect failure"); + fail("Redirect handler testGetRedirectForPostMethod1 failure"); } } diff --git a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java index b35c8c464..4768bcdc9 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java @@ -18,16 +18,20 @@ import org.junit.Test; public class RetryHandlerTest { + + int maxRetries = 2; + int retryInterval = 2000; + String testurl = "https://graph.microsoft.com/v1.0/"; @Test public void testRetryHandlerCreation() { - RetryHandler retryhandler = new RetryHandler(2, 2000); - assertTrue(retryhandler.getRetryInterval() == 2000); + RetryHandler retryhandler = new RetryHandler(maxRetries, retryInterval); + assertTrue(retryhandler.getRetryInterval() == retryInterval); } @Test public void testRetryRequestWithMaxRetryAttempts() { - RetryHandler retryhandler = new RetryHandler(2, 2000); + RetryHandler retryhandler = new RetryHandler(maxRetries, retryInterval); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); HttpClientContext localContext = HttpClientContext.create(); assertFalse(retryhandler.retryRequest(response, 3, localContext)); @@ -35,7 +39,7 @@ public void testRetryRequestWithMaxRetryAttempts() { @Test public void testRetryRequestForStatusCode() { - RetryHandler retryhandler = new RetryHandler(2, 2000); + RetryHandler retryhandler = new RetryHandler(maxRetries, retryInterval); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_INTERNAL_SERVER_ERROR, "Internal Server Error"); HttpClientContext localContext = HttpClientContext.create(); assertFalse(retryhandler.retryRequest(response, 1, localContext)); @@ -43,10 +47,10 @@ public void testRetryRequestForStatusCode() { @Test public void testRetryRequestWithTransferEncoding() { - RetryHandler retryhandler = new RetryHandler(2, 2000); + RetryHandler retryhandler = new RetryHandler(maxRetries, retryInterval); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); response.setHeader("Transfer-Encoding", "chunked"); - HttpPost httppost = new HttpPost("https://graph.microsoft.com/v1.0/"); + HttpPost httppost = new HttpPost(testurl); try { HttpEntity entity = new StringEntity("TEST"); @@ -63,9 +67,9 @@ public void testRetryRequestWithTransferEncoding() { @Test public void testRetryRequestWithExponentialBackOff() { - RetryHandler retryhandler = new RetryHandler(2, 2000); + RetryHandler retryhandler = new RetryHandler(maxRetries, retryInterval); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); - HttpPost httppost = new HttpPost("https://graph.microsoft.com/v1.0/"); + HttpPost httppost = new HttpPost(testurl); try { HttpEntity entity = new StringEntity("TEST"); @@ -83,10 +87,10 @@ public void testRetryRequestWithExponentialBackOff() { @Test public void testRetryHandlerRetryRequestWithRetryAfterHeader() { - RetryHandler retryhandler = new RetryHandler(2, 2000); + RetryHandler retryhandler = new RetryHandler(maxRetries, retryInterval); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); response.setHeader("Retry-After", "100"); - HttpPost httppost = new HttpPost("https://graph.microsoft.com/v1.0/"); + HttpPost httppost = new HttpPost(testurl); try { HttpEntity entity = new StringEntity("TEST"); From 9b38515579db638cbf832104d07d76e741b366ba Mon Sep 17 00:00:00 2001 From: deagrawa Date: Fri, 18 Jan 2019 12:47:25 +0530 Subject: [PATCH 13/38] Update getRedirect logic in RedirectHandler --- .../graph/httpcore/RedirectHandler.java | 43 ++++++++----------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java index 0935868e0..3b8110bf0 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java @@ -44,30 +44,23 @@ public boolean isRedirected( @Override public HttpUriRequest getRedirect( - final HttpRequest request, - final HttpResponse response, - final HttpContext context) throws ProtocolException { - final URI uri = getLocationURI(request, response, context); - final String method = request.getRequestLine().getMethod(); - if (method.equalsIgnoreCase(HttpHead.METHOD_NAME)) { - return new HttpHead(uri); - } else if (method.equalsIgnoreCase(HttpGet.METHOD_NAME)) - return new HttpGet(uri); - else { - final int status = response.getStatusLine().getStatusCode(); - if(status != HttpStatus.SC_SEE_OTHER) { - try { - final URI requestURI = new URI(request.getRequestLine().getUri()); - if(!uri.getHost().equalsIgnoreCase(requestURI.getHost()) || - !uri.getScheme().equalsIgnoreCase(requestURI.getScheme())) - request.removeHeaders("Authorization"); - return RequestBuilder.copy(request).setUri(uri).build(); - } - catch (final URISyntaxException ex) { - throw new ProtocolException(ex.getMessage(), ex); - } - } - return new HttpGet(uri); - } + final HttpRequest request, + final HttpResponse response, + final HttpContext context) throws ProtocolException { + final URI uri = getLocationURI(request, response, context); + try { + final URI requestURI = new URI(request.getRequestLine().getUri()); + if(!uri.getHost().equalsIgnoreCase(requestURI.getHost()) || + !uri.getScheme().equalsIgnoreCase(requestURI.getScheme())) + request.removeHeaders("Authorization"); + } + catch (final URISyntaxException ex) { + throw new ProtocolException(ex.getMessage(), ex); + } + + final int status = response.getStatusLine().getStatusCode(); + if(status == HttpStatus.SC_SEE_OTHER) + return new HttpGet(uri); + return RequestBuilder.copy(request).setUri(uri).build(); } } From f1c1de5c3081fdd2c3fcedfe7355166ea7b4dfdc Mon Sep 17 00:00:00 2001 From: deagrawa Date: Fri, 18 Jan 2019 12:56:33 +0530 Subject: [PATCH 14/38] Add support to redirect when status code received is 308 in RedirectHandler --- .../java/com/microsoft/graph/httpcore/RedirectHandler.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java index 3b8110bf0..1fe483272 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java @@ -36,7 +36,8 @@ public boolean isRedirected( if(statusCode == HttpStatus.SC_MOVED_TEMPORARILY || statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode == HttpStatus.SC_TEMPORARY_REDIRECT || - statusCode == HttpStatus.SC_SEE_OTHER) + statusCode == HttpStatus.SC_SEE_OTHER || + statusCode == 308) return true; return false; From 6ef44658fc981ef3aff5340bba83840b3161535a Mon Sep 17 00:00:00 2001 From: deagrawa Date: Fri, 18 Jan 2019 12:59:43 +0530 Subject: [PATCH 15/38] BatchResponseContent - remove unsed import statements BatchRequestContent - parametrize object creation of collection classes. --- .../com/microsoft/graph/content/MSBatchRequestContent.java | 6 +++--- .../com/microsoft/graph/content/MSBatchResponseContent.java | 3 --- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java index 8174306aa..2612cafb4 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java @@ -59,8 +59,8 @@ public void removeBatchRequesStepWithId(String requestId) { } public String getBatchRequestContent() { - Map>> batchRequestContentMap = new HashMap(); - List> batchContentArray = new ArrayList(); + Map>> batchRequestContentMap = new HashMap<>(); + List> batchContentArray = new ArrayList<>(); for(MSBatchRequestStep requestStep : batchRequestStepsArray) { batchContentArray.add(getBatchRequestMapFromRequestStep(requestStep)); } @@ -69,7 +69,7 @@ public String getBatchRequestContent() { } private Map getBatchRequestMapFromRequestStep(MSBatchRequestStep batchRequestStep){ - Map contentmap = new HashMap(); + Map contentmap = new HashMap<>(); contentmap.put("id", batchRequestStep.getRequestId()); contentmap.put("url", batchRequestStep.getRequest().getRequestLine().getUri()); contentmap.put("method", batchRequestStep.getRequest().getRequestLine().getMethod()); diff --git a/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java b/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java index cefea1fa7..06aef03fe 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java @@ -1,8 +1,5 @@ package com.microsoft.graph.content; -import java.util.Set; - -import org.apache.http.Consts; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.entity.ContentType; From 3df3bd3e37311002247c64c15e309e78d1e03c15 Mon Sep 17 00:00:00 2001 From: deagrawa Date: Fri, 18 Jan 2019 13:23:36 +0530 Subject: [PATCH 16/38] Update RetryHandler options like delay and retryInterval --- .../java/com/microsoft/graph/httpcore/RetryHandler.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java index b49b26a8a..d0a7f6901 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java @@ -26,7 +26,7 @@ public class RetryHandler implements ServiceUnavailableRetryStrategy{ * value is 1 second. */ private long retryInterval; - private final int DELAY_SECONDS = 10; + private final int DELAY_MILLISECONDS = 1000; private final String RETRY_AFTER = "Retry-After"; private final String TRANSFER_ENCODING = "Transfer-Encoding"; @@ -43,7 +43,7 @@ public RetryHandler(final int maxRetries, final int retryInterval) { } public RetryHandler() { - this(1, 1000); + this(2, 1000); } @Override @@ -57,14 +57,13 @@ public boolean retryRequest(HttpResponse response, int executionCount, HttpConte if(header != null) retryInterval = Long.parseLong(header.getValue()); else - retryInterval = (long)Math.pow(2.0, (double)executionCount) * DELAY_SECONDS; + retryInterval = (long)Math.pow(2.0, (double)executionCount) * DELAY_MILLISECONDS; } return shouldRetry; } @Override public long getRetryInterval() { - // TODO Auto-generated method stub return retryInterval; } From 84a405a0619e2cf56d8178688563a80d719a28c6 Mon Sep 17 00:00:00 2001 From: deagrawa Date: Mon, 21 Jan 2019 11:18:38 +0530 Subject: [PATCH 17/38] Fix review comments on PR: https://github.com/microsoftgraph/msgraph-sdk-java-core/pull/2 --- .../java/com/microsoft/graph/content/MSBatchRequestContent.java | 2 +- .../com/microsoft/graph/content/MSBatchResponseContent.java | 1 + .../com/microsoft/graph/httpcore/AuthenticationHandler.java | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java index 2612cafb4..b84c94521 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java @@ -93,9 +93,9 @@ private Map getBatchRequestMapFromRequestStep(MSBatchRequestStep contentmap.put("body", body); } catch(Exception e) { + e.printStackTrace(); } } - List arrayOfDependsOnIds = batchRequestStep.getArrayOfDependsOnIds(); if(arrayOfDependsOnIds != null) { contentmap.put("dependsOn", JSONValue.toJSONString(arrayOfDependsOnIds)); diff --git a/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java b/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java index 06aef03fe..42c0f44dc 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java @@ -21,6 +21,7 @@ public MSBatchResponseContent(String batchResponseData ) { batchResponseObj = (JSONObject) parser.parse(batchResponseData); } catch(ParseException e) { + e.printStackTrace(); } } diff --git a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java index 82747d1ee..1657df1d3 100644 --- a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java @@ -17,7 +17,6 @@ public AuthenticationHandler(IAuthenticationProvider authProvider) { @Override public void process(HttpRequest request, HttpContext context) throws HttpException, IOException { - // TODO Auto-generated method stub authProvider.authenticateRequest(request); } From 75355258e7447d8a18fe54bb19d2062c38e1bd1d Mon Sep 17 00:00:00 2001 From: deagrawa Date: Mon, 21 Jan 2019 11:51:49 +0530 Subject: [PATCH 18/38] Fixing review comments on PR : https://github.com/microsoftgraph/msgraph-sdk-java-core/pull/2 --- .../microsoft/graph/content/MSBatchRequestContent.java | 9 +++++++-- .../microsoft/graph/httpcore/AuthenticationHandler.java | 3 ++- .../graph/httpcore/IAuthenticationProvider.java | 6 +++--- .../graph/httpcore/AuthenticationHandlerTest.java | 7 ++----- .../com/microsoft/graph/httpcore/HttpClientsTest.java | 5 ++--- .../com/microsoft/graph/httpcore/RetryHandlerTest.java | 2 +- 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java index b84c94521..17040beea 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java @@ -41,7 +41,8 @@ public boolean addBatchRequestStep(MSBatchRequestStep batchRequestStep) { return batchRequestStepsArray.add(batchRequestStep); } - public void removeBatchRequesStepWithId(String requestId) { + public boolean removeBatchRequesStepWithId(String requestId) { + boolean ret = false; for (int i = batchRequestStepsArray.size()-1; i >= 0; i--) { MSBatchRequestStep requestStep = batchRequestStepsArray.get(i); @@ -51,11 +52,15 @@ public void removeBatchRequesStepWithId(String requestId) { if(dependsOnId.compareTo(requestId) == 0) { requestStep.getArrayOfDependsOnIds().remove(j); + ret = true; } } - if(requestId.compareTo(requestStep.getRequestId()) == 0) + if(requestId.compareTo(requestStep.getRequestId()) == 0) { batchRequestStepsArray.remove(i); + ret = true; + } } + return ret; } public String getBatchRequestContent() { diff --git a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java index 1657df1d3..de09aa8ff 100644 --- a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java @@ -17,7 +17,8 @@ public AuthenticationHandler(IAuthenticationProvider authProvider) { @Override public void process(HttpRequest request, HttpContext context) throws HttpException, IOException { - authProvider.authenticateRequest(request); + String token = authProvider.getAccessToken(); + request.addHeader("Authorization", "Bearer " + token); } } diff --git a/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java b/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java index c969cfe11..26e174155 100644 --- a/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java +++ b/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java @@ -4,9 +4,9 @@ public interface IAuthenticationProvider { /** - * Authenticates the request + * Get Access Token * - * @param request the request to authenticate */ - void authenticateRequest(final HttpRequest request); + + String getAccessToken(); } diff --git a/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java index 1cfd6abe3..6f3e44bf6 100644 --- a/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java @@ -17,11 +17,8 @@ public class AuthenticationHandlerTest { static String token = "TEST-TOKEN"; public static class AuthProvider implements IAuthenticationProvider{ - public static String getToken() { - return "Bearer " + token; - } - public void authenticateRequest(HttpRequest request) { - request.addHeader("Authorization", AuthProvider.getToken()); + public String getAccessToken() { + return token; } } diff --git a/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java b/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java index 474ccfc15..fa7ad43e4 100644 --- a/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java @@ -2,7 +2,6 @@ import static org.junit.Assert.assertTrue; -import org.apache.http.HttpRequest; import org.apache.http.impl.client.CloseableHttpClient; import org.junit.Test; @@ -12,8 +11,8 @@ public class HttpClientsTest { public void testHttpClientCreation() { IAuthenticationProvider authprovider = new IAuthenticationProvider() { @Override - public void authenticateRequest(HttpRequest request) { - request.addHeader("Authorization", "TOKEN"); + public String getAccessToken() { + return "TOKEN"; } }; CloseableHttpClient httpclient = HttpClients.createDefault(authprovider); diff --git a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java index 4768bcdc9..63240e40d 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java @@ -77,7 +77,7 @@ public void testRetryRequestWithExponentialBackOff() { HttpClientContext localContext = HttpClientContext.create(); localContext.setAttribute(HttpCoreContext.HTTP_REQUEST, httppost); assertTrue(retryhandler.retryRequest(response, 1, localContext)); - assertTrue(retryhandler.getRetryInterval() == 20); + assertTrue(retryhandler.getRetryInterval() == 2000); } catch (UnsupportedEncodingException e) { e.printStackTrace(); From 05ab9f4a0db680632b95cab10bf1fd824db87a58 Mon Sep 17 00:00:00 2001 From: deagrawa Date: Mon, 21 Jan 2019 16:05:09 +0530 Subject: [PATCH 19/38] Add more test cases for Content classes and Redirect Handler to increase code coverage to more than 90% --- build.gradle | 1 + .../content/MSBatchRequestContentTest.java | 58 +++++++++++++-- .../content/MSBatchResponseContentTest.java | 23 ++++++ .../graph/httpcore/RedirectHandlerTest.java | 72 +++++++++++++++++++ 4 files changed, 149 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index ab9da0ab6..faa8338ca 100644 --- a/build.gradle +++ b/build.gradle @@ -8,6 +8,7 @@ // Apply the java-library plugin to add support for Java Library apply plugin: 'java-library' +apply plugin: 'jacoco' // In this section you declare where to find the dependencies of your project repositories { diff --git a/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java b/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java index 5013f0dae..7f923c63d 100644 --- a/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java +++ b/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java @@ -15,13 +15,14 @@ public class MSBatchRequestContentTest { + String testurl = "http://graph.microsoft.com"; + @Test public void testMSBatchRequestContentCreation() { - List requestStepArray = new ArrayList<>(); for(int i=0;i<5;i++) { - HttpRequest request = new HttpGet("http://graph.microsoft.com"); - List arrayOfDependsOnIds = new ArrayList(); + HttpRequest request = new HttpGet(testurl); + List arrayOfDependsOnIds = new ArrayList<>(); MSBatchRequestStep requestStep = new MSBatchRequestStep("" + i, request, arrayOfDependsOnIds); requestStepArray.add(requestStep); } @@ -31,8 +32,8 @@ public void testMSBatchRequestContentCreation() { @Test public void testGetBatchRequestContent() { - HttpRequest request = new HttpGet("http://graph.microsoft.com"); - List arrayOfDependsOnIds = new ArrayList(); + HttpRequest request = new HttpGet(testurl); + List arrayOfDependsOnIds = new ArrayList<>(); MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); MSBatchRequestContent requestContent = new MSBatchRequestContent(); requestContent.addBatchRequestStep(requestStep); @@ -40,5 +41,52 @@ public void testGetBatchRequestContent() { String expectedContent = "{\"requests\":[{\"method\":\"GET\",\"dependsOn\":\"[]\",\"id\":\"1\",\"url\":\"http:\\/\\/graph.microsoft.com\"}]}"; assertTrue(content.compareTo(expectedContent) == 0); } + + @Test + public void testGetBatchRequestContentWithHeader() { + HttpRequest request = new HttpGet(testurl); + request.setHeader("testkey", "testvalue"); + List arrayOfDependsOnIds = new ArrayList<>(); + MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); + MSBatchRequestContent requestContent = new MSBatchRequestContent(); + requestContent.addBatchRequestStep(requestStep); + String content = requestContent.getBatchRequestContent(); + String expectedContent = "{\"requests\":[{\"headers\":\"{\\\"testkey\\\":\\\"testvalue\\\"}\",\"method\":\"GET\",\"dependsOn\":\"[]\",\"id\":\"1\",\"url\":\"http:\\/\\/graph.microsoft.com\"}]}"; + assertTrue(content.compareTo(expectedContent) == 0); + } + + @Test + public void testRemoveBatchRequesStepWithId() { + HttpRequest request = new HttpGet(testurl); + List arrayOfDependsOnIds = new ArrayList<>(); + MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); + MSBatchRequestContent requestContent = new MSBatchRequestContent(); + requestContent.addBatchRequestStep(requestStep); + requestContent.removeBatchRequesStepWithId("1"); + String content = requestContent.getBatchRequestContent(); + String expectedContent = "{\"requests\":[]}"; + assertTrue(content.compareTo(expectedContent) == 0); + } + + @Test + public void testRemoveBatchRequesStepWithId1() { + HttpRequest request = new HttpGet(testurl); + List arrayOfDependsOnIds = new ArrayList<>(); + MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); + + HttpRequest request1 = new HttpGet(testurl); + List arrayOfDependsOnIds1 = new ArrayList<>(); + arrayOfDependsOnIds1.add("1"); + MSBatchRequestStep requestStep1 = new MSBatchRequestStep("2", request1, arrayOfDependsOnIds1); + + MSBatchRequestContent requestContent = new MSBatchRequestContent(); + requestContent.addBatchRequestStep(requestStep); + requestContent.addBatchRequestStep(requestStep1); + + requestContent.removeBatchRequesStepWithId("1"); + String content = requestContent.getBatchRequestContent(); + String expectedContent = "{\"requests\":[{\"method\":\"GET\",\"dependsOn\":\"[]\",\"id\":\"2\",\"url\":\"http:\\/\\/graph.microsoft.com\"}]}"; + assertTrue(content.compareTo(expectedContent) == 0); + } } diff --git a/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java b/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java index 5f4bbac74..da393580f 100644 --- a/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java +++ b/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java @@ -30,6 +30,29 @@ public void testValidMSBatchResponseContent() { assertTrue(batchresponse.getResponses() != null); } + @Test + public void testInvalidMSBatchResponseContent() { + //passing empty responses + String responsedata = "{\"responses\": [] }"; + MSBatchResponseContent batchresponse = new MSBatchResponseContent(responsedata); + assertTrue(batchresponse.getResponseById("1") == null); + } + + @Test + public void testInvalidMSBatchResponseContent1() { + //passing null response json string + MSBatchResponseContent batchresponse = new MSBatchResponseContent(null); + assertTrue(batchresponse.getResponseById("1") == null); + } + + @Test + public void testInvalidMSBatchResponseContent2() { + //passing malformed json response + String invalidResponsedata = "{responses: [] }"; + MSBatchResponseContent batchresponse = new MSBatchResponseContent(invalidResponsedata); + assertTrue(batchresponse.getResponses() == null); + } + @Test public void testGetMSBatchResponseContentByID() { String responsedata = "{\"responses\": [{ \"id\": \"1\", \"status\": 302, \"headers\": { \"location\": \"https://b0mpua-by3301.files.1drv.com/y23vmagahszhxzlcvhasdhasghasodfi\" } }, { \"id\": \"3\", \"status\": 401, \"body\": { \"error\": { \"code\": \"Forbidden\", \"message\": \"...\" } } }, { \"id\": \"2\", \"status\": 200, \"body\": { \"@odata.context\": \"https://graph.microsoft.com/v1.0/$metadata#Collection(microsoft.graph.plannerTask)\", \"value\": [] } }, { \"id\": \"4\", \"status\": 204, \"body\": null } ] }"; diff --git a/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java index 8e6a3bfa5..5bee73cfb 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import org.apache.http.Header; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; @@ -19,6 +20,7 @@ public class RedirectHandlerTest { String testmeurl = "https://graph.microsoft.com/v1.0/me/"; String testurl = "https://graph.microsoft.com/v1.0/"; + String differenthosturl = "https://graph.abc.com/v1.0/"; @Test public void testIsRedirectedFailure() { @@ -40,6 +42,7 @@ public void testIsRedirectedFailure1() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; HttpGet httpget = new HttpGet(testmeurl); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_BAD_REQUEST, "Bad Request"); + response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); @@ -66,6 +69,54 @@ public void testIsRedirectedSuccess() { } } + @Test + public void testIsRedirectedSuccess1() { + RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + HttpGet httpget = new HttpGet(testmeurl); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_PERMANENTLY, "Moved Permanently"); + response.setHeader("location", testmeurl); + HttpClientContext localContext = HttpClientContext.create(); + try { + boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); + assertTrue(isRedirected); + } catch (ProtocolException e) { + e.printStackTrace(); + fail("Redirect handler testIsRedirectedSuccess1 failure"); + } + } + + @Test + public void testIsRedirectedSuccess2() { + RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + HttpGet httpget = new HttpGet(testmeurl); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_TEMPORARY_REDIRECT, "Temporary Redirect"); + response.setHeader("location", testmeurl); + HttpClientContext localContext = HttpClientContext.create(); + try { + boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); + assertTrue(isRedirected); + } catch (ProtocolException e) { + e.printStackTrace(); + fail("Redirect handler testIsRedirectedSuccess2 failure"); + } + } + + @Test + public void testIsRedirectedSuccess3() { + RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + HttpGet httpget = new HttpGet(testmeurl); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other"); + response.setHeader("location", testmeurl); + HttpClientContext localContext = HttpClientContext.create(); + try { + boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); + assertTrue(isRedirected); + } catch (ProtocolException e) { + e.printStackTrace(); + fail("Redirect handler testIsRedirectedSuccess3 failure"); + } + } + @Test public void testGetRedirectForGetMethod() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; @@ -83,6 +134,27 @@ public void testGetRedirectForGetMethod() { fail("Redirect handler testGetRedirectForGetMethod failure"); } } + + @Test + public void testGetRedirectForGetMethodForAuthHeader() { + RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + HttpGet httpget = new HttpGet(testurl); + httpget.addHeader("Authorization", "TOKEN"); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); + response.setHeader("location", differenthosturl); + HttpClientContext localContext = HttpClientContext.create(); + try { + HttpRequest request = redirectHandler.getRedirect(httpget, response, localContext); + assertTrue(request != null); + final String method = request.getRequestLine().getMethod(); + assertTrue(method.equalsIgnoreCase(HttpGet.METHOD_NAME)); + Header header = request.getFirstHeader("Authorization"); + assertTrue(header == null); + } catch (ProtocolException e) { + e.printStackTrace(); + fail("Redirect handler testGetRedirectForGetMethodForAuthHeader failure"); + } + } @Test public void testGetRedirectForHeadMethod() { From ae3ced17420b199840e446ad52311b13c2e1a82e Mon Sep 17 00:00:00 2001 From: deagrawa Date: Mon, 21 Jan 2019 17:01:20 +0530 Subject: [PATCH 20/38] Give meaningful names to test methods in test classes. --- .../graph/content/MSBatchRequestContentTest.java | 2 +- .../graph/content/MSBatchResponseContentTest.java | 9 +++------ .../graph/httpcore/RedirectHandlerTest.java | 14 +++++++------- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java b/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java index 7f923c63d..c15448051 100644 --- a/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java +++ b/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java @@ -69,7 +69,7 @@ public void testRemoveBatchRequesStepWithId() { } @Test - public void testRemoveBatchRequesStepWithId1() { + public void testRemoveBatchRequesStepWithIdByAddingMultipleBatchSteps() { HttpRequest request = new HttpGet(testurl); List arrayOfDependsOnIds = new ArrayList<>(); MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); diff --git a/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java b/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java index da393580f..bf9652aff 100644 --- a/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java +++ b/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java @@ -31,23 +31,20 @@ public void testValidMSBatchResponseContent() { } @Test - public void testInvalidMSBatchResponseContent() { - //passing empty responses + public void testInvalidMSBatchResponseContentWithEmptyResponse() { String responsedata = "{\"responses\": [] }"; MSBatchResponseContent batchresponse = new MSBatchResponseContent(responsedata); assertTrue(batchresponse.getResponseById("1") == null); } @Test - public void testInvalidMSBatchResponseContent1() { - //passing null response json string + public void testInvalidMSBatchResponseContentWithNullResponseString() { MSBatchResponseContent batchresponse = new MSBatchResponseContent(null); assertTrue(batchresponse.getResponseById("1") == null); } @Test - public void testInvalidMSBatchResponseContent2() { - //passing malformed json response + public void testInvalidMSBatchResponseContentWithMalformedResponse() { String invalidResponsedata = "{responses: [] }"; MSBatchResponseContent batchresponse = new MSBatchResponseContent(invalidResponsedata); assertTrue(batchresponse.getResponses() == null); diff --git a/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java index 5bee73cfb..1e998f761 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java @@ -23,7 +23,7 @@ public class RedirectHandlerTest { String differenthosturl = "https://graph.abc.com/v1.0/"; @Test - public void testIsRedirectedFailure() { + public void testIsRedirectedFailureByNoLocationHeader() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; HttpGet httpget = new HttpGet(testmeurl); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); @@ -38,7 +38,7 @@ public void testIsRedirectedFailure() { } @Test - public void testIsRedirectedFailure1() { + public void testIsRedirectedFailureByStatusCodeBadRequest() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; HttpGet httpget = new HttpGet(testmeurl); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_BAD_REQUEST, "Bad Request"); @@ -54,7 +54,7 @@ public void testIsRedirectedFailure1() { } @Test - public void testIsRedirectedSuccess() { + public void testIsRedirectedSuccessWithStatusCodeMovedTemporarily() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; HttpGet httpget = new HttpGet(testmeurl); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); @@ -70,7 +70,7 @@ public void testIsRedirectedSuccess() { } @Test - public void testIsRedirectedSuccess1() { + public void testIsRedirectedSuccessWithStatusCodeMovedPermanently() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; HttpGet httpget = new HttpGet(testmeurl); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_PERMANENTLY, "Moved Permanently"); @@ -86,7 +86,7 @@ public void testIsRedirectedSuccess1() { } @Test - public void testIsRedirectedSuccess2() { + public void testIsRedirectedSuccessWithStatusCodeTemporaryRedirect() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; HttpGet httpget = new HttpGet(testmeurl); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_TEMPORARY_REDIRECT, "Temporary Redirect"); @@ -102,7 +102,7 @@ public void testIsRedirectedSuccess2() { } @Test - public void testIsRedirectedSuccess3() { + public void testIsRedirectedSuccessWithStatusCodeSeeOther() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; HttpGet httpget = new HttpGet(testmeurl); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other"); @@ -193,7 +193,7 @@ public void testGetRedirectForPostMethod() { } @Test - public void testGetRedirectForPostMethod1() { + public void testGetRedirectForPostMethodWithStatusCodeSeeOther() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; HttpPost httppost = new HttpPost(testurl); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other"); From 00b01c71177f5fd5f3d6aa6efb15ec1e0045187e Mon Sep 17 00:00:00 2001 From: deagrawa Date: Wed, 23 Jan 2019 12:54:45 +0530 Subject: [PATCH 21/38] Add middleware options classes to enable middleware custom configurations --- .../graph/httpcore/RetryHandler.java | 26 ++++++++++----- .../middlewareoption/HttpContextBuilder.java | 33 +++++++++++++++++++ .../middlewareoption/IMiddlewareControl.java | 5 +++ .../middlewareoption/IShouldRetry.java | 8 +++++ .../middlewareoption/MiddlewareType.java | 16 +++++++++ .../middlewareoption/RetryOptions.java | 24 ++++++++++++++ 6 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/microsoft/graph/httpcore/middlewareoption/HttpContextBuilder.java create mode 100644 src/main/java/com/microsoft/graph/httpcore/middlewareoption/IMiddlewareControl.java create mode 100644 src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java create mode 100644 src/main/java/com/microsoft/graph/httpcore/middlewareoption/MiddlewareType.java create mode 100644 src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java diff --git a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java index d0a7f6901..77de83f11 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java @@ -13,19 +13,22 @@ import org.apache.http.protocol.HttpCoreContext; import org.apache.http.util.Args; +import com.microsoft.graph.httpcore.middlewareoption.MiddlewareType; +import com.microsoft.graph.httpcore.middlewareoption.RetryOptions; + public class RetryHandler implements ServiceUnavailableRetryStrategy{ /** * Maximum number of allowed retries if the server responds with a HTTP code * in our retry code list. Default value is 1. */ - private final int maxRetries; + private final int maxRetries = 2; /** * Retry interval between subsequent requests, in milliseconds. Default * value is 1 second. */ - private long retryInterval; + private long retryInterval = 1000; private final int DELAY_MILLISECONDS = 1000; private final String RETRY_AFTER = "Retry-After"; private final String TRANSFER_ENCODING = "Transfer-Encoding"; @@ -33,21 +36,28 @@ public class RetryHandler implements ServiceUnavailableRetryStrategy{ private final int MSClientErrorCodeTooManyRequests = 429; private final int MSClientErrorCodeServiceUnavailable = 503; private final int MSClientErrorCodeGatewayTimeout = 504; + private final RetryOptions mRetryOption; - public RetryHandler(final int maxRetries, final int retryInterval) { + public RetryHandler(RetryOptions option) { super(); - Args.positive(maxRetries, "Max retries"); - Args.positive(retryInterval, "Retry interval"); - this.maxRetries = maxRetries; - this.retryInterval = retryInterval; + this.mRetryOption = option; } public RetryHandler() { - this(2, 1000); + this(null); } @Override public boolean retryRequest(HttpResponse response, int executionCount, HttpContext context) { + + RetryOptions retryOption = (RetryOptions)context.getAttribute(MiddlewareType.RETRY.toString()); + if(retryOption != null) { + return retryOption.shouldRetry().shouldRetry(response, executionCount, context); + } + if(mRetryOption != null) { + return mRetryOption.shouldRetry().shouldRetry(response, executionCount, context); + } + boolean shouldRetry = false; int statusCode = response.getStatusLine().getStatusCode(); shouldRetry = (executionCount < maxRetries) && checkStatus(statusCode) && isBuffered(response, context); diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/HttpContextBuilder.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/HttpContextBuilder.java new file mode 100644 index 000000000..a068df89c --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/HttpContextBuilder.java @@ -0,0 +1,33 @@ +package com.microsoft.graph.httpcore.middlewareoption; + +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.protocol.HttpClientContext; + +public class HttpContextBuilder { + + private RetryOptions retryoptions; + private int maxRedirect = -1; + + public static HttpContextBuilder create() { + return new HttpContextBuilder(); + } + + public void setRetryOption(IShouldRetry shouldRetry) { + retryoptions = new RetryOptions(shouldRetry); + } + + public void setRedirectOption(int maxRedirect) { + this.maxRedirect = maxRedirect; + } + + public HttpClientContext build() { + HttpClientContext context = HttpClientContext.create(); + if(retryoptions != null) + context.setAttribute(MiddlewareType.RETRY.toString(), retryoptions); + if(maxRedirect != -1) { + RequestConfig config = RequestConfig.custom().setMaxRedirects(maxRedirect).build(); + context.setRequestConfig(config); + } + return context; + } +} diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IMiddlewareControl.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IMiddlewareControl.java new file mode 100644 index 000000000..699c8d152 --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IMiddlewareControl.java @@ -0,0 +1,5 @@ +package com.microsoft.graph.httpcore.middlewareoption; + +public interface IMiddlewareControl { + +} diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java new file mode 100644 index 000000000..cd208e0ca --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java @@ -0,0 +1,8 @@ +package com.microsoft.graph.httpcore.middlewareoption; + +import org.apache.http.HttpResponse; +import org.apache.http.protocol.HttpContext; + +public interface IShouldRetry { + boolean shouldRetry(HttpResponse response, int executionCount, HttpContext context); +} diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/MiddlewareType.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/MiddlewareType.java new file mode 100644 index 000000000..193ab9d1b --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/MiddlewareType.java @@ -0,0 +1,16 @@ +package com.microsoft.graph.httpcore.middlewareoption; + +public enum MiddlewareType { + + //Authentication Middleware + AUTHENTICATION, + + //Redirect Middleware + REDIRECT, + + //Retry Middleware + RETRY, + + //Not supported + NOT_SUPPORTED +} diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java new file mode 100644 index 000000000..867108389 --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java @@ -0,0 +1,24 @@ +package com.microsoft.graph.httpcore.middlewareoption; + +import org.apache.http.HttpResponse; +import org.apache.http.protocol.HttpContext; + +public class RetryOptions implements IMiddlewareControl { + private IShouldRetry shouldretry; + + public RetryOptions(){ + this(new IShouldRetry() { + public boolean shouldRetry(HttpResponse response, int executionCount, HttpContext context) { + return true; + } + }); + } + + public RetryOptions(IShouldRetry shouldretry){ + this.shouldretry = shouldretry; + } + + public IShouldRetry shouldRetry() { + return shouldretry; + } +} From ae5dfebc7beb17ca05a8096887070c338373d029 Mon Sep 17 00:00:00 2001 From: deagrawa Date: Wed, 23 Jan 2019 13:02:17 +0530 Subject: [PATCH 22/38] Add retry handler test with retry options --- .../graph/httpcore/RetryHandlerTest.java | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java index 63240e40d..36082894e 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java @@ -14,24 +14,50 @@ import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.entity.StringEntity; import org.apache.http.message.BasicHttpResponse; +import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpCoreContext; import org.junit.Test; +import com.microsoft.graph.httpcore.middlewareoption.IShouldRetry; +import com.microsoft.graph.httpcore.middlewareoption.RetryOptions; + public class RetryHandlerTest { int maxRetries = 2; - int retryInterval = 2000; + int retryInterval = 1000; String testurl = "https://graph.microsoft.com/v1.0/"; @Test public void testRetryHandlerCreation() { - RetryHandler retryhandler = new RetryHandler(maxRetries, retryInterval); + RetryHandler retryhandler = new RetryHandler(); assertTrue(retryhandler.getRetryInterval() == retryInterval); } + @Test + public void testRetryHandlerWithRetryOptions() { + RetryOptions option = new RetryOptions(); + RetryHandler retryhandler = new RetryHandler(option); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); + HttpClientContext localContext = HttpClientContext.create(); + assertTrue(retryhandler.retryRequest(response, 1, localContext)); + } + + @Test + public void testRetryHandlerWithCustomRetryOptions() { + RetryOptions option = new RetryOptions(new IShouldRetry() { + public boolean shouldRetry(HttpResponse response, int executionCount, HttpContext context) { + return false; + } + }); + RetryHandler retryhandler = new RetryHandler(option); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); + HttpClientContext localContext = HttpClientContext.create(); + assertTrue(!retryhandler.retryRequest(response, 1, localContext)); + } + @Test public void testRetryRequestWithMaxRetryAttempts() { - RetryHandler retryhandler = new RetryHandler(maxRetries, retryInterval); + RetryHandler retryhandler = new RetryHandler(); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); HttpClientContext localContext = HttpClientContext.create(); assertFalse(retryhandler.retryRequest(response, 3, localContext)); @@ -39,7 +65,7 @@ public void testRetryRequestWithMaxRetryAttempts() { @Test public void testRetryRequestForStatusCode() { - RetryHandler retryhandler = new RetryHandler(maxRetries, retryInterval); + RetryHandler retryhandler = new RetryHandler(); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_INTERNAL_SERVER_ERROR, "Internal Server Error"); HttpClientContext localContext = HttpClientContext.create(); assertFalse(retryhandler.retryRequest(response, 1, localContext)); @@ -47,7 +73,7 @@ public void testRetryRequestForStatusCode() { @Test public void testRetryRequestWithTransferEncoding() { - RetryHandler retryhandler = new RetryHandler(maxRetries, retryInterval); + RetryHandler retryhandler = new RetryHandler(); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); response.setHeader("Transfer-Encoding", "chunked"); HttpPost httppost = new HttpPost(testurl); @@ -67,7 +93,7 @@ public void testRetryRequestWithTransferEncoding() { @Test public void testRetryRequestWithExponentialBackOff() { - RetryHandler retryhandler = new RetryHandler(maxRetries, retryInterval); + RetryHandler retryhandler = new RetryHandler(); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); HttpPost httppost = new HttpPost(testurl); @@ -87,7 +113,7 @@ public void testRetryRequestWithExponentialBackOff() { @Test public void testRetryHandlerRetryRequestWithRetryAfterHeader() { - RetryHandler retryhandler = new RetryHandler(maxRetries, retryInterval); + RetryHandler retryhandler = new RetryHandler(); HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); response.setHeader("Retry-After", "100"); HttpPost httppost = new HttpPost(testurl); From eda6444475fa88e649c6f0926913c687936e1118 Mon Sep 17 00:00:00 2001 From: deagrawa Date: Fri, 25 Jan 2019 16:46:26 +0530 Subject: [PATCH 23/38] Update gradle script with code to publish --- build.gradle | 322 +++++++++++++++++++++++++++++++++++++++++++++- gradle.properties | 46 +++++++ 2 files changed, 363 insertions(+), 5 deletions(-) create mode 100644 gradle.properties diff --git a/build.gradle b/build.gradle index faa8338ca..c81d1d2ce 100644 --- a/build.gradle +++ b/build.gradle @@ -3,11 +3,16 @@ * * This generated file contains a sample Java Library project to get you started. * For more details take a look at the Java Libraries chapter in the Gradle - * user guide available at https://docs.gradle.org/4.3/userguide/java_library_plugin.html + * user guide available at https://docs.gradle.org/4.5/userguide/java_library_plugin.html */ // Apply the java-library plugin to add support for Java Library apply plugin: 'java-library' +apply plugin: 'java' +apply plugin: 'eclipse' +apply plugin: 'maven' +apply plugin: 'maven-publish' +apply plugin: 'signing' apply plugin: 'jacoco' // In this section you declare where to find the dependencies of your project @@ -15,6 +20,12 @@ repositories { // Use jcenter for resolving your dependencies. // You can declare any Maven/Ivy/file repository here. jcenter() + mavenCentral() +} + +def platformDependency = "org.apache.httpcomponents:httpclient:4.5.6" +if ( project.hasProperty("platform") && project.platform == "android" ) { + platformDependency = "org.apache.httpcomponents:httpclient-android:4.3.5" } dependencies { @@ -22,16 +33,317 @@ dependencies { api 'org.apache.commons:commons-math3:3.6.1' // This dependency is used internally, and not exposed to consumers on their own compile classpath. - implementation 'com.google.guava:guava:23.0' + implementation 'com.google.guava:guava:20.0' // Use JUnit test framework testImplementation 'junit:junit:4.12' - // Use Apache HttpClient - api 'org.apache.httpcomponents:httpclient:4.5.6' + api platformDependency // https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple compile group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1' - } +def pomConfig = { + licenses { + license([:]) { + name "MIT License" + url "http://opensource.org/licenses/MIT" + distribution "repo" + } + } +} + +//Publishing tasks- +//Maven Central Snapshot: publishSnapshotPublicationToMavenRepository +//Maven Central Release: publishMavenCentralReleasePublicationToMaven2Repository +//Bintray Snapshot: publishSnapshotPublicationToMaven3Repository +//Bintray Release: uploadArchives + +publishing { + + publications { + + maven(MavenPublication) { + + groupId 'com.microsoft.graph' + + artifactId 'microsoft-graph-core' + + version "${mavenMajorVersion}.${mavenMinorVersion}.${mavenPatchVersion}${mavenArtifactSuffix}" + + from components.java + + artifact sourceJar + pom.withXml { + def root = asNode() + root.appendNode('name', 'Microsoft Graph Core SDK for Java') + root.appendNode('url', 'https://github.com/microsoftgraph/msgraph-sdk-java-core') + root.children().last() + pomConfig + def pomFile = file("${project.buildDir}/libs/microsoft-graph-core.pom") + writeTo(pomFile) + } + + } + Snapshot(MavenPublication) { + customizePom(pom) + groupId 'com.microsoft.graph' + artifactId 'microsoft-graph-core' + version "${mavenMajorVersion}.${mavenMinorVersion}.${mavenPatchVersion}${mavenCentralSnapshotArtifactSuffix}" + from components.java + pom.withXml { + def pomFile = file("${project.buildDir}/generated-pom.xml") + writeTo(pomFile) + } + artifact(sourceJar) { + classifier = 'sources' + } + artifact(javadocJar) { + classifier = 'javadoc' + } + } + + mavenCentralRelease(MavenPublication) { + customizePom(pom) + groupId 'com.microsoft.graph' + artifactId 'microsoft-graph-core' + version "${mavenMajorVersion}.${mavenMinorVersion}.${mavenPatchVersion}" + from components.java + pom.withXml { + def pomFile = file("${project.buildDir}/generated-pom.xml") + writeTo(pomFile) + def pomAscFile = signing.sign(pomFile).signatureFiles[0] + artifact(pomAscFile) { + classifier = null + extension = 'pom.asc' + } + } + artifact(sourceJar) { + classifier = 'sources' + } + artifact(javadocJar) { + classifier = 'javadoc' + } + project.tasks.signArchives.signatureFiles.each { + artifact(it) { + def matcher = it.file =~ /-(sources|javadoc)\.jar\.asc$/ + if(matcher.find()){ + classifier = matcher.group(1) + } + else{ + classifier = null + } + extension = 'jar.asc' + } + } + } + } + repositories { + maven { + url = project.property('mavenCentralSnapshotUrl') + + credentials { + if (project.rootProject.file('local.properties').exists()) { + + Properties properties = new Properties() + + properties.load(project.rootProject.file('local.properties').newDataInputStream()) + + username = properties.getProperty('sonatypeUsername') + + password = properties.getProperty('sonatypePassword') + + } + } + } + + maven { + url = project.property('mavenCentralReleaseUrl') + + credentials { + if (project.rootProject.file('local.properties').exists()) { + + Properties properties = new Properties() + + properties.load(project.rootProject.file('local.properties').newDataInputStream()) + + username = properties.getProperty('sonatypeUsername') + + password = properties.getProperty('sonatypePassword') + + } + } + } + + maven { + url = project.property('mavenBintraySnapshotUrl') + + credentials { + if (project.rootProject.file('local.properties').exists()) { + + Properties properties = new Properties() + + properties.load(project.rootProject.file('local.properties').newDataInputStream()) + + username = (properties.containsKey('bintray.user')) ? properties.getProperty('bintray.user').toLowerCase() : "BINTRAY_USERNAME" + + password = properties.getProperty('bintray.apikey') + + } + } + } + } + +} + +task sourceJar(type: Jar) { + classifier = 'sources' + from sourceSets.main.allJava +} + +compileJava { + sourceCompatibility = 1.7 + targetCompatibility = 1.7 +} + +def getVersionCode() { + return mavenMajorVersion.toInteger() * 10000 + mavenMinorVersion.toInteger() * 100 + mavenPatchVersion.toInteger() +} + +def getVersionName() { + return "${mavenMajorVersion}.${mavenMinorVersion}.${mavenPatchVersion}${mavenArtifactSuffix}" +} + +uploadArchives { + + def bintrayUsername = "" + + def bintrayApikey = "" + + if (project.rootProject.file('local.properties').exists()) { + + Properties properties = new Properties() + + properties.load(project.rootProject.file('local.properties').newDataInputStream()) + + bintrayUsername = properties.getProperty('bintray.user') + + bintrayApikey = properties.getProperty('bintray.apikey') + + } + + configuration = configurations.archives + + repositories.mavenDeployer { + + pom { + + setGroupId project.mavenGroupId + + setArtifactId project.mavenArtifactId + + setVersion getVersionName() + + } + + repository (url: project.mavenRepoUrl) { + + url = url + "/" + getVersionName() + + authentication( + + // put these values in local file ~/.gradle/gradle.properties + + userName: project.hasProperty("bintrayUsername") ? project.bintrayUsername : bintrayUsername, + + password: project.hasProperty("bintrayApikey") ? project.bintrayApikey : bintrayApikey + + ) + + } + + } + +} + +task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from javadoc.destinationDir +} + +artifacts { + archives jar + archives sourceJar + archives javadocJar +} + +signing { + sign configurations.archives +} +tasks.withType(Sign)*.enabled = mavenCentralPublishingEnabled.toBoolean() + +def customizePom(pom) { + pom.withXml { + def root = asNode() + + root.dependencies.removeAll { dep -> + dep.scope == "test" + } + + root.children().last() + { + resolveStrategy = Closure.DELEGATE_FIRST + + description 'Microsoft Graph Core SDK' + name 'Microsoft Graph Java Core SDK' + url 'https://github.com/microsoftgraph/msgraph-sdk-java-core' + organization { + name 'Microsoft' + url 'https://github.com/microsoftgraph/msgraph-sdk-java-core' + } + issueManagement { + system 'GitHub' + url 'https://github.com/microsoftgraph/msgraph-sdk-java-core/issues' + } + licenses { + license { + name "MIT License" + url "http://opensource.org/licenses/MIT" + distribution "repo" + } + } + scm { + url 'https://github.com/microsoftgraph/msgraph-sdk-java-core' + connection 'scm:git:git://github.com/microsoftgraph/msgraph-sdk-java-core.git' + developerConnection 'scm:git:ssh://git@github.com:microsoftgraph/msgraph-sdk-java-core.git' + } + developers { + developer { + name 'Microsoft' + } + } + } + } +} + +gradle.taskGraph.whenReady { taskGraph -> + if (project.rootProject.file('local.properties').exists()) { + Properties properties = new Properties() + properties.load(project.rootProject.file('local.properties').newDataInputStream()) + tasks.withType(Sign)*.enabled = (properties.containsKey('enableSigning')) ? properties.getProperty('enableSigning').toBoolean() : false + allprojects { ext."signing.keyId" = properties.getProperty('signing.keyId') } + allprojects { ext."signing.secretKeyRingFile" = properties.getProperty('signing.secretKeyRingFile') } + allprojects { ext."signing.password" = properties.getProperty('signing.password') } + } +} + +model { + tasks.generatePomFileForMavenCentralReleasePublication { + destination = file("$buildDir/generated-pom.xml") + } + tasks.publishMavenCentralReleasePublicationToMavenLocal { + dependsOn project.tasks.signArchives + } + tasks.publishMavenCentralReleasePublicationToMaven2Repository { + dependsOn project.tasks.signArchives + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 000000000..eb7f41cfc --- /dev/null +++ b/gradle.properties @@ -0,0 +1,46 @@ +# Project-wide Gradle settings. + +# IDE users: +# Settings specified in this file will override any Gradle settings +# configured through the IDE. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx10248m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +# The size of the library demands a large amount of RAM to build. Increase as necessary if you get GC errors +## linux requires 10G, OSX requires 11G +org.gradle.jvmargs=-XX:MaxPermSize=512m -Xmx2g + +mavenRepoUrl = https://api.bintray.com/content/microsoftgraph/Maven/microsoft-graph +mavenBintraySnapshotUrl = http://oss.jfrog.org/artifactory/oss-snapshot-local +mavenGroupId = com.microsoft.graph +mavenArtifactId = microsoft-graph-core +mavenMajorVersion = 0 +mavenMinorVersion = 1 +mavenPatchVersion = 0 +mavenArtifactSuffix = +nightliesUrl = http://dl.bintray.com/MicrosoftGraph/Maven + +#These values are used to run functional tests +#If you wish to run the functional tests, edit the gradle.properties +#file in your user directory instead of adding them here. +#ex: C:\Users\username\.gradle\gradle.properties +ClientId="CLIENT_ID" +Username="USERNAME" +Password="PASSWORD" + +#enable mavenCentralPublishingEnabled to publish to maven central +mavenCentralSnapshotUrl=https://oss.sonatype.org/content/repositories/snapshots +mavenCentralReleaseUrl=https://oss.sonatype.org/service/local/staging/deploy/maven2 +mavenCentralSnapshotArtifactSuffix = -SNAPSHOT +mavenCentralPublishingEnabled=false From bbe81bf82e2b46b97c318e4024158b9add540c85 Mon Sep 17 00:00:00 2001 From: deagrawa Date: Mon, 11 Feb 2019 11:07:16 +0530 Subject: [PATCH 24/38] Update readme and add license file. --- LICENSE | 21 +++++++++ readme.md | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..11938c882 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Microsoft Graph + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/readme.md b/readme.md index cea3bfaf2..558235580 100644 --- a/readme.md +++ b/readme.md @@ -1 +1,123 @@ -# Microsoft Graph Core SDK for Java \ No newline at end of file +# Microsoft Graph Core SDK for Java + +[ ![Download](https://api.bintray.com/packages/microsoftgraph/Maven/microsoft-graph/images/download.svg) ](https://bintray.com/microsoftgraph/Maven/microsoft-graph/_latestVersion) + + +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! + +## 1. Installation + +### 1.1 Install via Gradle + +Add the repository and a compile dependency for `microsoft-graph` to your project's `build.gradle`: + +```gradle +repository { + jcenter() +} + +dependency { + // Include the sdk as a dependency + compile('com.microsoft.graph:microsoft-graph-core:0.1.0-SNAPSHOT') +} +``` + +### 1.2 Install via Maven +Add the dependency in `dependencies` in pom.xml +```dependency + + com.microsoft.graph + microsoft-graph-core + 0.1.0-SNAPSHOT + +``` + +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). + +## 2. Getting started + +### 2.1 Register your application + +Register your application by following the steps at [Register your app with the Azure AD v2.0 endpoint](https://developer.microsoft.com/en-us/graph/docs/concepts/auth_register_app_v2). + +### 2.2 Create an IAuthenticationProvider object + +An instance of the **GraphServiceClient** class handles building requests, sending them to the Microsoft Graph API, and processing the responses. To create a new instance of this class, you need to provide an instance of `IAuthenticationProvider`, which can authenticate requests to Microsoft Graph. + +For an example of authentication in a client application, see the [MSGraph SDK Android MSA Auth for Android Adapter](https://github.com/microsoftgraph/msgraph-sdk-android-msa-auth-for-android-adapter). + +### 2.3 Get a HttpClient object +You must get a **HttpClient** object to make requests against the service. + +```java +CloseableHttpClient httpClient = HttpClients.createDefault(authenticationProvider); +``` + +## 3. Make requests against the service + +After you have a HttpClient that is authenticated, you can begin making calls against the service. The requests against the service look like our [REST API](https://developer.microsoft.com/en-us/graph/docs/concepts/overview). + +### 3.1 Get the user's drive + +To retrieve the user's drive: + +```java +HttpGet httpget = new HttpGet("https://graph.microsoft.com/v1.0/me/"); +try{ + HttpResponse response = httpclient.execute(httpget); + //... +}catch(IOException e){ +//Handle exception +} +``` + +## 4. Issues + +For known issues, see [issues](https://github.com/MicrosoftGraph/msgraph-sdk-java-core/issues). + +## 5. Contributions + +The Microsoft Graph SDK is open for contribution. To contribute to this project, see [Contributing](https://github.com/microsoftgraph/msgraph-sdk-java/blob/master/CONTRIBUTING.md). + + + +[
Deepak Agrawal](https://github.com/deepak2016)
[💻](https://github.com/microsoftgraph/msgraph-sdk-java/commits?author=deepak2016 "Code") + + +This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind are welcome! + +## 6. Supported Java versions +The Microsoft Graph SDK for Java library is supported at runtime for Java 7+ and [Android API revision 15](http://source.android.com/source/build-numbers.html) and greater. + +## 7. License + +Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the [MIT license](LICENSE). + +## 8. Third-party notices + +[Third-party notices](THIRD%20PARTY%20NOTICES) From fbbb08ef8d1a59d42a18c618da0902b8c0a2c6c3 Mon Sep 17 00:00:00 2001 From: deagrawa Date: Mon, 11 Feb 2019 11:47:37 +0530 Subject: [PATCH 25/38] Add jcenter url in readme --- readme.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/readme.md b/readme.md index 558235580..22e38fc0a 100644 --- a/readme.md +++ b/readme.md @@ -14,6 +14,9 @@ Add the repository and a compile dependency for `microsoft-graph` to your projec ```gradle repository { jcenter() + jcenter{ + url 'http://oss.jfrog.org/artifactory/oss-snapshot-local' + } } dependency { From ac9d6501ac62ae1f4dab5c5777564ef31b8409e2 Mon Sep 17 00:00:00 2001 From: deagrawa Date: Mon, 11 Feb 2019 12:05:48 +0530 Subject: [PATCH 26/38] Changing iAuthenticationProvider interface to access http request. --- .../microsoft/graph/httpcore/AuthenticationHandler.java | 3 +-- .../microsoft/graph/httpcore/IAuthenticationProvider.java | 8 ++++---- .../graph/httpcore/AuthenticationHandlerTest.java | 6 +++--- .../com/microsoft/graph/httpcore/HttpClientsTest.java | 8 ++++---- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java index de09aa8ff..1657df1d3 100644 --- a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java @@ -17,8 +17,7 @@ public AuthenticationHandler(IAuthenticationProvider authProvider) { @Override public void process(HttpRequest request, HttpContext context) throws HttpException, IOException { - String token = authProvider.getAccessToken(); - request.addHeader("Authorization", "Bearer " + token); + authProvider.authenticateRequest(request); } } diff --git a/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java b/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java index 26e174155..f3312f588 100644 --- a/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java +++ b/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java @@ -3,10 +3,10 @@ import org.apache.http.HttpRequest; public interface IAuthenticationProvider { - /** - * Get Access Token + /** + * Authenticates the request * + * @param request the request to authenticate */ - - String getAccessToken(); + void authenticateRequest(HttpRequest request); } diff --git a/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java index 6f3e44bf6..dbd855760 100644 --- a/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java @@ -17,9 +17,9 @@ public class AuthenticationHandlerTest { static String token = "TEST-TOKEN"; public static class AuthProvider implements IAuthenticationProvider{ - public String getAccessToken() { - return token; - } + public void authenticateRequest(HttpRequest request) { + request.addHeader("Authorization", "Bearer " + token); + } } @Test diff --git a/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java b/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java index fa7ad43e4..c084f69fc 100644 --- a/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java @@ -2,6 +2,7 @@ import static org.junit.Assert.assertTrue; +import org.apache.http.HttpRequest; import org.apache.http.impl.client.CloseableHttpClient; import org.junit.Test; @@ -10,10 +11,9 @@ public class HttpClientsTest { @Test public void testHttpClientCreation() { IAuthenticationProvider authprovider = new IAuthenticationProvider() { - @Override - public String getAccessToken() { - return "TOKEN"; - } + public void authenticateRequest(HttpRequest request) { + request.addHeader("Authorization", "Bearer " + "TOKEN"); + } }; CloseableHttpClient httpclient = HttpClients.createDefault(authprovider); assertTrue(httpclient != null); From 1ec6286158cf63149b6095c23127106ef7789b6b Mon Sep 17 00:00:00 2001 From: deagrawa Date: Tue, 26 Feb 2019 12:18:37 +0530 Subject: [PATCH 27/38] Changes to move dependency from Apache HttpClient to OkHttp in httpcore module --- build.gradle | 7 +- .../graph/httpcore/AuthenticationHandler.java | 17 +-- .../microsoft/graph/httpcore/HttpClients.java | 31 ++-- .../httpcore/IAuthenticationProvider.java | 4 +- .../graph/httpcore/RedirectHandler.java | 134 +++++++++++------- .../graph/httpcore/RetryHandler.java | 77 +++++----- .../middlewareoption/IShouldRetry.java | 6 +- .../middlewareoption/RetryOptions.java | 6 +- 8 files changed, 149 insertions(+), 133 deletions(-) diff --git a/build.gradle b/build.gradle index c81d1d2ce..261f884bc 100644 --- a/build.gradle +++ b/build.gradle @@ -23,11 +23,6 @@ repositories { mavenCentral() } -def platformDependency = "org.apache.httpcomponents:httpclient:4.5.6" -if ( project.hasProperty("platform") && project.platform == "android" ) { - platformDependency = "org.apache.httpcomponents:httpclient-android:4.3.5" -} - dependencies { // This dependency is exported to consumers, that is to say found on their compile classpath. api 'org.apache.commons:commons-math3:3.6.1' @@ -38,7 +33,7 @@ dependencies { // Use JUnit test framework testImplementation 'junit:junit:4.12' - api platformDependency + api 'com.squareup.okhttp3:okhttp:3.12.1' // https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple compile group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1' diff --git a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java index 1657df1d3..b7eb1003c 100644 --- a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java @@ -2,22 +2,23 @@ import java.io.IOException; -import org.apache.http.HttpException; -import org.apache.http.HttpRequest; -import org.apache.http.HttpRequestInterceptor; -import org.apache.http.protocol.HttpContext; +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; -public class AuthenticationHandler implements HttpRequestInterceptor { +public class AuthenticationHandler implements Interceptor { private IAuthenticationProvider authProvider; public AuthenticationHandler(IAuthenticationProvider authProvider) { this.authProvider = authProvider; } - + @Override - public void process(HttpRequest request, HttpContext context) throws HttpException, IOException { - authProvider.authenticateRequest(request); + public Response intercept(Chain chain) throws IOException { + Request originalRequest = chain.request(); + 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 e51eb5921..65e53490b 100644 --- a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java +++ b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java @@ -1,8 +1,7 @@ package com.microsoft.graph.httpcore; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; +import okhttp3.OkHttpClient; +import okhttp3.OkHttpClient.Builder; public class HttpClients { private HttpClients() { @@ -11,31 +10,21 @@ private HttpClients() { /** * Creates builder object for construction of custom - * {@link CloseableHttpClient} instances. + * {@link OkHttpClient} instances. */ - public static HttpClientBuilder custom() { - return HttpClientBuilder.create(); + public static Builder custom() { + return new OkHttpClient.Builder(); } /** - * Creates {@link CloseableHttpClient} instance with default + * Creates {@link OkHttpClient} instance with default * configuration and provided authProvider */ - public static CloseableHttpClient createDefault(IAuthenticationProvider auth) { - RequestConfig config = RequestConfig.custom().setMaxRedirects(5).build(); + public static OkHttpClient createDefault(IAuthenticationProvider auth) { - return HttpClientBuilder.create().addInterceptorFirst(new AuthenticationHandler(auth)) - .setRedirectStrategy(new RedirectHandler()) - .setServiceUnavailableRetryStrategy(new RetryHandler()) - .setDefaultRequestConfig(config) + return new OkHttpClient.Builder().addInterceptor(new AuthenticationHandler(auth)) + .addInterceptor(new RetryHandler()) + .addInterceptor(new RedirectHandler()) .build(); } - - /** - * Creates {@link CloseableHttpClient} instance with default - * configuration based on system properties. - */ - public static CloseableHttpClient createSystem() { - return HttpClientBuilder.create().useSystemProperties().build(); - } } diff --git a/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java b/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java index f3312f588..10c64a6f7 100644 --- a/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java +++ b/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java @@ -1,6 +1,6 @@ package com.microsoft.graph.httpcore; -import org.apache.http.HttpRequest; +import okhttp3.Request; public interface IAuthenticationProvider { /** @@ -8,5 +8,5 @@ public interface IAuthenticationProvider { * * @param request the request to authenticate */ - void authenticateRequest(HttpRequest request); + Request authenticateRequest(Request request); } diff --git a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java index 1fe483272..cb1882829 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java @@ -1,67 +1,101 @@ package com.microsoft.graph.httpcore; -import java.net.URI; -import java.net.URISyntaxException; +import static java.net.HttpURLConnection.HTTP_MOVED_PERM; +import static java.net.HttpURLConnection.HTTP_MOVED_TEMP; +import static java.net.HttpURLConnection.HTTP_SEE_OTHER; +import static okhttp3.internal.http.StatusLine.HTTP_PERM_REDIRECT; +import static okhttp3.internal.http.StatusLine.HTTP_TEMP_REDIRECT; -import org.apache.http.Header; -import org.apache.http.HttpRequest; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.ProtocolException; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpHead; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.client.methods.RequestBuilder; -import org.apache.http.impl.client.DefaultRedirectStrategy; -import org.apache.http.protocol.HttpContext; -import org.apache.http.util.Args; +import java.io.IOException; +import java.net.ProtocolException; -public class RedirectHandler extends DefaultRedirectStrategy{ +import okhttp3.HttpUrl; +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.internal.http.HttpMethod; + +public class RedirectHandler implements Interceptor{ public static final RedirectHandler INSTANCE = new RedirectHandler(); + final int maxRedirect = 5; - @Override - public boolean isRedirected( - final HttpRequest request, - final HttpResponse response, - final HttpContext context) throws ProtocolException { - Args.notNull(request, "HTTP request"); - Args.notNull(response, "HTTP response"); - - final int statusCode = response.getStatusLine().getStatusCode(); - final Header locationHeader = response.getFirstHeader("location"); + public boolean isRedirected(Request request, Response response, int redirectCount) throws IOException { + + if(redirectCount > maxRedirect) return false; + + final String locationHeader = response.header("location"); if(locationHeader == null) return false; - if(statusCode == HttpStatus.SC_MOVED_TEMPORARILY || - statusCode == HttpStatus.SC_MOVED_PERMANENTLY || - statusCode == HttpStatus.SC_TEMPORARY_REDIRECT || - statusCode == HttpStatus.SC_SEE_OTHER || - statusCode == 308) + final int statusCode = response.code(); + if(statusCode == HTTP_PERM_REDIRECT || + statusCode == HTTP_MOVED_PERM || + statusCode == HTTP_TEMP_REDIRECT || + statusCode == HTTP_SEE_OTHER || + statusCode == HTTP_MOVED_TEMP) return true; return false; } - @Override - public HttpUriRequest getRedirect( - final HttpRequest request, - final HttpResponse response, - final HttpContext context) throws ProtocolException { - final URI uri = getLocationURI(request, response, context); - try { - final URI requestURI = new URI(request.getRequestLine().getUri()); - if(!uri.getHost().equalsIgnoreCase(requestURI.getHost()) || - !uri.getScheme().equalsIgnoreCase(requestURI.getScheme())) - request.removeHeaders("Authorization"); - } - catch (final URISyntaxException ex) { - throw new ProtocolException(ex.getMessage(), ex); - } - - final int status = response.getStatusLine().getStatusCode(); - if(status == HttpStatus.SC_SEE_OTHER) - return new HttpGet(uri); - return RequestBuilder.copy(request).setUri(uri).build(); + public Request getRedirect( + final Request request, + final Response userResponse) throws ProtocolException { + String location = userResponse.header("Location"); + if (location == null) return null; + HttpUrl url = userResponse.request().url().resolve(location); + // Don't follow redirects to unsupported protocols. + if (url == null) return null; + + // Most redirects don't include a request body. + Request.Builder requestBuilder = userResponse.request().newBuilder(); + final String method = userResponse.request().method(); + + if (HttpMethod.permitsRequestBody(method)) { + final boolean maintainBody = HttpMethod.redirectsWithBody(method); + if (HttpMethod.redirectsToGet(method)) { + requestBuilder.method("GET", null); + } else { + RequestBody requestBody = maintainBody ? userResponse.request().body() : null; + requestBuilder.method(method, requestBody); + } + if (!maintainBody) { + requestBuilder.removeHeader("Transfer-Encoding"); + requestBuilder.removeHeader("Content-Length"); + requestBuilder.removeHeader("Content-Type"); + } + } + + // When redirecting across hosts, drop all authentication headers. This + // is potentially annoying to the application layer since they have no + // way to retain them. + boolean sameScheme = url.scheme().equals(userResponse.request().url().scheme()); + boolean sameHost = url.host().equals(userResponse.request().url().host()); + if (!sameScheme || !sameHost) { + requestBuilder.removeHeader("Authorization"); + } + + return requestBuilder.url(url).build(); } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + Response response = null; + int redirectCount = 1; + while(true) { + response = chain.proceed(request); + boolean shouldRedirect = isRedirected(request, response, redirectCount); + if(!shouldRedirect) break; + + Request followup = getRedirect(request, response); + if(followup == null) break; + request = followup; + + redirectCount++; + } + return response; + } } diff --git a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java index 77de83f11..237dfed87 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java @@ -1,22 +1,14 @@ package com.microsoft.graph.httpcore; -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.HttpRequest; -import org.apache.http.HttpResponse; -import org.apache.http.client.ServiceUnavailableRetryStrategy; -import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; -import org.apache.http.client.methods.HttpPatch; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.protocol.HttpContext; -import org.apache.http.protocol.HttpCoreContext; -import org.apache.http.util.Args; +import java.io.IOException; -import com.microsoft.graph.httpcore.middlewareoption.MiddlewareType; import com.microsoft.graph.httpcore.middlewareoption.RetryOptions; -public class RetryHandler implements ServiceUnavailableRetryStrategy{ +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +public class RetryHandler implements Interceptor{ /** * Maximum number of allowed retries if the server responds with a HTTP code @@ -47,32 +39,30 @@ public RetryHandler() { this(null); } - @Override - public boolean retryRequest(HttpResponse response, int executionCount, HttpContext context) { + public boolean retryRequest(Response response, int executionCount, Request request) { - RetryOptions retryOption = (RetryOptions)context.getAttribute(MiddlewareType.RETRY.toString()); + RetryOptions retryOption = request.tag(RetryOptions.class); if(retryOption != null) { - return retryOption.shouldRetry().shouldRetry(response, executionCount, context); + return retryOption.shouldRetry().shouldRetry(response, executionCount, request); } if(mRetryOption != null) { - return mRetryOption.shouldRetry().shouldRetry(response, executionCount, context); + return mRetryOption.shouldRetry().shouldRetry(response, executionCount, request); } boolean shouldRetry = false; - int statusCode = response.getStatusLine().getStatusCode(); - shouldRetry = (executionCount < maxRetries) && checkStatus(statusCode) && isBuffered(response, context); + int statusCode = response.code(); + shouldRetry = (executionCount < maxRetries) && checkStatus(statusCode) && isBuffered(response, request); if(shouldRetry) { - Header header = response.getFirstHeader(RETRY_AFTER); - if(header != null) - retryInterval = Long.parseLong(header.getValue()); + String retryAfterHeader = response.header(RETRY_AFTER); + if(retryAfterHeader != null) + retryInterval = Long.parseLong(retryAfterHeader); else retryInterval = (long)Math.pow(2.0, (double)executionCount) * DELAY_MILLISECONDS; } return shouldRetry; } - @Override public long getRetryInterval() { return retryInterval; } @@ -84,27 +74,34 @@ private boolean checkStatus(int statusCode) { return false; } - private boolean isBuffered(HttpResponse response, HttpContext context) { - HttpRequest request = (HttpRequest)context.getAttribute( HttpCoreContext.HTTP_REQUEST); - String methodName = request.getRequestLine().getMethod(); + private boolean isBuffered(Response response, Request request) { + String methodName = request.method(); - boolean isHTTPMethodPutPatchOrPost = methodName.equalsIgnoreCase(HttpPost.METHOD_NAME) || - methodName.equalsIgnoreCase(HttpPut.METHOD_NAME) || - methodName.equalsIgnoreCase(HttpPatch.METHOD_NAME); + boolean isHTTPMethodPutPatchOrPost = methodName.equalsIgnoreCase("POST") || + methodName.equalsIgnoreCase("PUT") || + methodName.equalsIgnoreCase("PATCH"); - Header transferEncoding = response.getFirstHeader(TRANSFER_ENCODING); + //Header transferEncoding = response.getFirstHeader(TRANSFER_ENCODING); + String transferEncoding = response.header(TRANSFER_ENCODING); boolean isTransferEncodingChunked = (transferEncoding != null) && - transferEncoding.getValue().equalsIgnoreCase("chunked"); - - HttpEntity entity = null; - if(request instanceof HttpEntityEnclosingRequestBase) { - HttpEntityEnclosingRequestBase httprequest = (HttpEntityEnclosingRequestBase)request; - entity = httprequest.getEntity(); - } + transferEncoding.equalsIgnoreCase("chunked"); - if(entity != null && isHTTPMethodPutPatchOrPost && isTransferEncodingChunked) + if(request.body() != null && isHTTPMethodPutPatchOrPost && isTransferEncodingChunked) return false; return true; } + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + + Response response = chain.proceed(request); + int executionCount = 0; + while(retryRequest(response, executionCount, request)) { + executionCount++; + response = chain.proceed(request); + } + return response; + } + } diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java index cd208e0ca..366c310a6 100644 --- a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java @@ -1,8 +1,8 @@ package com.microsoft.graph.httpcore.middlewareoption; -import org.apache.http.HttpResponse; -import org.apache.http.protocol.HttpContext; +import okhttp3.Request; +import okhttp3.Response; public interface IShouldRetry { - boolean shouldRetry(HttpResponse response, int executionCount, HttpContext context); + boolean shouldRetry(Response response, int executionCount, Request request); } diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java index 867108389..57ccfbc29 100644 --- a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java @@ -1,14 +1,14 @@ package com.microsoft.graph.httpcore.middlewareoption; -import org.apache.http.HttpResponse; -import org.apache.http.protocol.HttpContext; +import okhttp3.Request; +import okhttp3.Response; public class RetryOptions implements IMiddlewareControl { private IShouldRetry shouldretry; public RetryOptions(){ this(new IShouldRetry() { - public boolean shouldRetry(HttpResponse response, int executionCount, HttpContext context) { + public boolean shouldRetry(Response response, int executionCount, Request request) { return true; } }); From d644fda2ab59662769a0cd147922454ede2eed96 Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Mon, 4 Mar 2019 18:38:45 +0530 Subject: [PATCH 28/38] Added okhttp to batch request, redirect --- .../graph/content/MSBatchRequestContent.java | 159 ++++++++++-------- .../graph/content/MSBatchRequestStep.java | 17 +- .../graph/content/MSBatchResponseContent.java | 33 ++-- .../microsoft/graph/httpcore/HttpClients.java | 1 - .../graph/httpcore/RedirectHandler.java | 39 ++--- .../content/MSBatchRequestContentTest.java | 27 ++- .../graph/content/MSBatchRequestStepTest.java | 8 +- .../content/MSBatchResponseContentTest.java | 14 +- .../httpcore/AuthenticationHandlerTest.java | 12 +- .../graph/httpcore/HttpClientsTest.java | 15 +- .../graph/httpcore/RedirectHandlerTest.java | 60 ++++--- .../graph/httpcore/RetryHandlerTest.java | 28 +-- 12 files changed, 215 insertions(+), 198 deletions(-) diff --git a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java index 17040beea..b944f9e32 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java @@ -1,112 +1,127 @@ package com.microsoft.graph.content; -import java.util.ArrayList; +import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.HttpRequest; -import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; -import org.apache.http.util.EntityUtils; +import org.json.simple.JSONArray; import org.json.simple.JSONObject; -import org.json.simple.JSONValue; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +import okhttp3.Headers; +import okhttp3.Request; +import okhttp3.RequestBody; +import okio.Buffer; public class MSBatchRequestContent { - private List batchRequestStepsArray; + private Map batchRequestStepsHashMap; private final int maxNumberOfRequests = 20; public MSBatchRequestContent(List batchRequestStepsArray) { - this.batchRequestStepsArray = new ArrayList<>(); - if(batchRequestStepsArray.size() <= maxNumberOfRequests) { - for(MSBatchRequestStep requestStep: batchRequestStepsArray) - addBatchRequestStep(requestStep); - } + if(batchRequestStepsArray.size() > maxNumberOfRequests) + throw new IllegalArgumentException("Number of batch request steps cannot exceed 20."); + + this.batchRequestStepsHashMap = new HashMap<>(); + for(MSBatchRequestStep requestStep: batchRequestStepsArray) + addBatchRequestStep(requestStep); } public MSBatchRequestContent() { - batchRequestStepsArray = new ArrayList<>(); + batchRequestStepsHashMap = new HashMap(); } public boolean addBatchRequestStep(MSBatchRequestStep batchRequestStep) { - if(batchRequestStep.getRequestId().compareTo("") == 0) - return false; - if(batchRequestStepsArray.size() == maxNumberOfRequests) + if(batchRequestStepsHashMap.containsKey(batchRequestStep.getRequestId())) return false; - for(MSBatchRequestStep requestStep: batchRequestStepsArray) { - if(batchRequestStep.getRequestId().compareTo(requestStep.getRequestId()) == 0) - return false; - } - return batchRequestStepsArray.add(batchRequestStep); + batchRequestStepsHashMap.put(batchRequestStep.getRequestId(), batchRequestStep); + return true; } - public boolean removeBatchRequesStepWithId(String requestId) { - boolean ret = false; - for (int i = batchRequestStepsArray.size()-1; i >= 0; i--) - { - MSBatchRequestStep requestStep = batchRequestStepsArray.get(i); - for (int j = requestStep.getArrayOfDependsOnIds().size() - 1; j >= 0; j--) - { - String dependsOnId = requestStep.getArrayOfDependsOnIds().get(j); - if(dependsOnId.compareTo(requestId) == 0) - { - requestStep.getArrayOfDependsOnIds().remove(j); - ret = true; - } - } - if(requestId.compareTo(requestStep.getRequestId()) == 0) { - batchRequestStepsArray.remove(i); - ret = true; - } - } - return ret; + public boolean removeBatchRequestStepWithId(String requestId) { + boolean removed = false; + if(batchRequestStepsHashMap.containsKey(requestId)) { + batchRequestStepsHashMap.remove(requestId); + removed = true; + } + for(Map.Entry steps : batchRequestStepsHashMap.entrySet()) { + while(steps.getValue().getArrayOfDependsOnIds().remove(requestId)) + removed = true; + } + return removed; } + @SuppressWarnings("unchecked") public String getBatchRequestContent() { - Map>> batchRequestContentMap = new HashMap<>(); - List> batchContentArray = new ArrayList<>(); - for(MSBatchRequestStep requestStep : batchRequestStepsArray) { - batchContentArray.add(getBatchRequestMapFromRequestStep(requestStep)); + JSONObject batchRequestContentMap = new JSONObject(); + JSONArray batchContentArray = new JSONArray(); + for(Map.Entry requestStep : batchRequestStepsHashMap.entrySet()) { + batchContentArray.add(getBatchRequestMapFromRequestStep(requestStep.getValue())); } batchRequestContentMap.put("requests", batchContentArray); - return JSONValue.toJSONString(batchRequestContentMap); + return batchRequestContentMap.toJSONString(); } - private Map getBatchRequestMapFromRequestStep(MSBatchRequestStep batchRequestStep){ - Map contentmap = new HashMap<>(); + @SuppressWarnings("unchecked") + private JSONObject getBatchRequestMapFromRequestStep(final MSBatchRequestStep batchRequestStep){ + JSONObject contentmap = new JSONObject(); contentmap.put("id", batchRequestStep.getRequestId()); - contentmap.put("url", batchRequestStep.getRequest().getRequestLine().getUri()); - contentmap.put("method", batchRequestStep.getRequest().getRequestLine().getMethod()); - Header[] headers = batchRequestStep.getRequest().getAllHeaders(); - if(headers != null && headers.length != 0) { - JSONObject obj = new JSONObject(); - for(Header header: headers) { - obj.put(header.getName(), header.getValue()); + + String url = batchRequestStep.getRequest().url().toString(); + url = url.replaceAll("https://graph.microsoft.com/v1.0", ""); + url = url.replace("https://graph.microsoft.com/beta", ""); + contentmap.put("url", url); + + contentmap.put("method", batchRequestStep.getRequest().method().toString()); + + Headers headers = batchRequestStep.getRequest().headers(); + if(headers != null && headers.size() != 0) { + JSONObject headerMap = new JSONObject(); + for(Map.Entry> entry : headers.toMultimap().entrySet()) { + headerMap.put(entry.getKey(), getHeaderValuesAsString(entry.getValue())); } - contentmap.put("headers", obj.toJSONString()); + contentmap.put("headers", headerMap); } - HttpEntity entity = null; - HttpRequest request = batchRequestStep.getRequest(); - if(request instanceof HttpEntityEnclosingRequestBase) { - HttpEntityEnclosingRequestBase httprequest = (HttpEntityEnclosingRequestBase)request; - entity = httprequest.getEntity(); + + List arrayOfDependsOnIds = batchRequestStep.getArrayOfDependsOnIds(); + if(arrayOfDependsOnIds != null) { + JSONArray array = new JSONArray(); + for(String dependsOnId : arrayOfDependsOnIds) array.add(dependsOnId); + contentmap.put("dependsOn", array); } - if(entity != null) { + + RequestBody body = batchRequestStep.getRequest().body(); + if(body != null) { try { - String body = EntityUtils.toString(entity); - contentmap.put("body", body); - } - catch(Exception e) { + contentmap.put("body", requestBodyToJSONObject(batchRequestStep.getRequest())); + }catch(IOException | ParseException e) { e.printStackTrace(); - } - } - List arrayOfDependsOnIds = batchRequestStep.getArrayOfDependsOnIds(); - if(arrayOfDependsOnIds != null) { - contentmap.put("dependsOn", JSONValue.toJSONString(arrayOfDependsOnIds)); + } } return contentmap; } + + private String getHeaderValuesAsString(final List list) { + StringBuilder builder = new StringBuilder(""); + if(list.size() != 0) { + builder.append(list.get(0)); + for(int i=1;i arrayOfDependsOnIds; - public MSBatchRequestStep(String requestId, HttpRequest request, List arrayOfDependsOnIds) { + public MSBatchRequestStep(String requestId, Request request, List arrayOfDependsOnIds) { + if(requestId == null) + throw new IllegalArgumentException("Request Id cannot be null."); + if(request == null) + new IllegalArgumentException("Request cannot be null."); + if(request.url() == null) + throw new IllegalArgumentException("Request url cannot be null."); + if(request.method() == null) + throw new IllegalArgumentException("Request method cannot be null."); + this.requestId = requestId; this.request = request; this.arrayOfDependsOnIds = arrayOfDependsOnIds; @@ -19,7 +28,7 @@ public String getRequestId() { return requestId; } - public HttpRequest getRequest() { + public Request getRequest() { return request; } diff --git a/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java b/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java index 42c0f44dc..b08f494a8 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java @@ -1,20 +1,19 @@ package com.microsoft.graph.content; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.apache.http.message.BasicHttpResponse; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; +import okhttp3.MediaType; +import okhttp3.Response; +import okhttp3.ResponseBody; + public class MSBatchResponseContent { private JSONObject batchResponseObj; - public MSBatchResponseContent(String batchResponseData ) { + public MSBatchResponseContent(String batchResponseData) { JSONParser parser = new JSONParser(); try { if(batchResponseData != null) @@ -25,7 +24,7 @@ public MSBatchResponseContent(String batchResponseData ) { } } - public HttpResponse getResponseById(String requestId) { + public Response getResponseById(String requestId) { if(batchResponseObj == null) return null; @@ -37,21 +36,29 @@ public HttpResponse getResponseById(String requestId) { JSONObject jsonresponse = (JSONObject)response; String id = (String)jsonresponse.get("id"); if(id.compareTo(requestId) == 0) { - HttpResponse httpresponse = new BasicHttpResponse(null, ((Long)jsonresponse.get("status")).intValue(), null); + Response.Builder builder = new Response.Builder(); + + if(jsonresponse.get("status") != null) { + String status = (String)jsonresponse.get("status"); + builder.code(Integer.parseInt(status)); + } + if(jsonresponse.get("body") != null) { - HttpEntity entity = new StringEntity(jsonresponse.get("body").toString(), ContentType.APPLICATION_JSON); - httpresponse.setEntity(entity); + String bodyAsString = (String)jsonresponse.get("body"); + ResponseBody responseBody = ResponseBody.create(MediaType.parse("application/json; charset=utf-8"), bodyAsString); + builder.body(responseBody); } if(jsonresponse.get("headers") != null){ JSONObject jsonheaders = (JSONObject)jsonresponse.get("headers"); for(Object key: jsonheaders.keySet()) { String strkey = (String)key; String strvalue = (String)jsonheaders.get(strkey); - httpresponse.setHeader(strkey, strvalue); + for(String value : strvalue.split("; ")) { + builder.header(strkey, value); + } } } - return httpresponse; - + return builder.build(); } } return null; diff --git a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java index 65e53490b..dc5ddbdba 100644 --- a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java +++ b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java @@ -21,7 +21,6 @@ public static Builder custom() { * configuration and provided authProvider */ public static OkHttpClient createDefault(IAuthenticationProvider auth) { - return new OkHttpClient.Builder().addInterceptor(new AuthenticationHandler(auth)) .addInterceptor(new RetryHandler()) .addInterceptor(new RedirectHandler()) diff --git a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java index cb1882829..093d90115 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java @@ -30,11 +30,11 @@ public boolean isRedirected(Request request, Response response, int redirectCoun return false; final int statusCode = response.code(); - if(statusCode == HTTP_PERM_REDIRECT || - statusCode == HTTP_MOVED_PERM || - statusCode == HTTP_TEMP_REDIRECT || - statusCode == HTTP_SEE_OTHER || - statusCode == HTTP_MOVED_TEMP) + if(statusCode == HTTP_PERM_REDIRECT || //308 + statusCode == HTTP_MOVED_PERM || //301 + statusCode == HTTP_TEMP_REDIRECT || //307 + statusCode == HTTP_SEE_OTHER || //303 + statusCode == HTTP_MOVED_TEMP) //302 return true; return false; @@ -45,39 +45,26 @@ public Request getRedirect( final Response userResponse) throws ProtocolException { String location = userResponse.header("Location"); if (location == null) return null; - HttpUrl url = userResponse.request().url().resolve(location); + + HttpUrl requestUrl = userResponse.request().url(); + + HttpUrl locationUrl = userResponse.request().url().resolve(location); // Don't follow redirects to unsupported protocols. - if (url == null) return null; + if (locationUrl == null) return null; // Most redirects don't include a request body. Request.Builder requestBuilder = userResponse.request().newBuilder(); - final String method = userResponse.request().method(); - - if (HttpMethod.permitsRequestBody(method)) { - final boolean maintainBody = HttpMethod.redirectsWithBody(method); - if (HttpMethod.redirectsToGet(method)) { - requestBuilder.method("GET", null); - } else { - RequestBody requestBody = maintainBody ? userResponse.request().body() : null; - requestBuilder.method(method, requestBody); - } - if (!maintainBody) { - requestBuilder.removeHeader("Transfer-Encoding"); - requestBuilder.removeHeader("Content-Length"); - requestBuilder.removeHeader("Content-Type"); - } - } // When redirecting across hosts, drop all authentication headers. This // is potentially annoying to the application layer since they have no // way to retain them. - boolean sameScheme = url.scheme().equals(userResponse.request().url().scheme()); - boolean sameHost = url.host().equals(userResponse.request().url().host()); + boolean sameScheme = locationUrl.scheme().equalsIgnoreCase(requestUrl.scheme()); + boolean sameHost = locationUrl.host().toString().equalsIgnoreCase(requestUrl.host().toString()); if (!sameScheme || !sameHost) { requestBuilder.removeHeader("Authorization"); } - return requestBuilder.url(url).build(); + return requestBuilder.url(locationUrl).build(); } @Override diff --git a/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java b/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java index c15448051..a4c37813a 100644 --- a/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java +++ b/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java @@ -1,18 +1,14 @@ package com.microsoft.graph.content; -import static org.junit.Assert.*; +import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.List; -import org.apache.http.HttpRequest; -import org.apache.http.client.methods.HttpGet; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; +import okhttp3.Request; + public class MSBatchRequestContentTest { String testurl = "http://graph.microsoft.com"; @@ -21,7 +17,7 @@ public class MSBatchRequestContentTest { public void testMSBatchRequestContentCreation() { List requestStepArray = new ArrayList<>(); for(int i=0;i<5;i++) { - HttpRequest request = new HttpGet(testurl); + Request request = new Request.Builder().url(testurl).build(); List arrayOfDependsOnIds = new ArrayList<>(); MSBatchRequestStep requestStep = new MSBatchRequestStep("" + i, request, arrayOfDependsOnIds); requestStepArray.add(requestStep); @@ -32,7 +28,7 @@ public void testMSBatchRequestContentCreation() { @Test public void testGetBatchRequestContent() { - HttpRequest request = new HttpGet(testurl); + Request request = new Request.Builder().url(testurl).build(); List arrayOfDependsOnIds = new ArrayList<>(); MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); MSBatchRequestContent requestContent = new MSBatchRequestContent(); @@ -44,8 +40,7 @@ public void testGetBatchRequestContent() { @Test public void testGetBatchRequestContentWithHeader() { - HttpRequest request = new HttpGet(testurl); - request.setHeader("testkey", "testvalue"); + Request request = new Request.Builder().url(testurl).header("testkey", "testvalue").build(); List arrayOfDependsOnIds = new ArrayList<>(); MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); MSBatchRequestContent requestContent = new MSBatchRequestContent(); @@ -57,12 +52,12 @@ public void testGetBatchRequestContentWithHeader() { @Test public void testRemoveBatchRequesStepWithId() { - HttpRequest request = new HttpGet(testurl); + Request request = new Request.Builder().url(testurl).build(); List arrayOfDependsOnIds = new ArrayList<>(); MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); MSBatchRequestContent requestContent = new MSBatchRequestContent(); requestContent.addBatchRequestStep(requestStep); - requestContent.removeBatchRequesStepWithId("1"); + requestContent.removeBatchRequestStepWithId("1"); String content = requestContent.getBatchRequestContent(); String expectedContent = "{\"requests\":[]}"; assertTrue(content.compareTo(expectedContent) == 0); @@ -70,11 +65,11 @@ public void testRemoveBatchRequesStepWithId() { @Test public void testRemoveBatchRequesStepWithIdByAddingMultipleBatchSteps() { - HttpRequest request = new HttpGet(testurl); + Request request = new Request.Builder().url(testurl).build(); List arrayOfDependsOnIds = new ArrayList<>(); MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); - HttpRequest request1 = new HttpGet(testurl); + Request request1 = new Request.Builder().url(testurl).build(); List arrayOfDependsOnIds1 = new ArrayList<>(); arrayOfDependsOnIds1.add("1"); MSBatchRequestStep requestStep1 = new MSBatchRequestStep("2", request1, arrayOfDependsOnIds1); @@ -83,7 +78,7 @@ public void testRemoveBatchRequesStepWithIdByAddingMultipleBatchSteps() { requestContent.addBatchRequestStep(requestStep); requestContent.addBatchRequestStep(requestStep1); - requestContent.removeBatchRequesStepWithId("1"); + requestContent.removeBatchRequestStepWithId("1"); String content = requestContent.getBatchRequestContent(); String expectedContent = "{\"requests\":[{\"method\":\"GET\",\"dependsOn\":\"[]\",\"id\":\"2\",\"url\":\"http:\\/\\/graph.microsoft.com\"}]}"; assertTrue(content.compareTo(expectedContent) == 0); diff --git a/src/test/java/com/microsoft/graph/content/MSBatchRequestStepTest.java b/src/test/java/com/microsoft/graph/content/MSBatchRequestStepTest.java index fa98ec302..d17af87a2 100644 --- a/src/test/java/com/microsoft/graph/content/MSBatchRequestStepTest.java +++ b/src/test/java/com/microsoft/graph/content/MSBatchRequestStepTest.java @@ -5,16 +5,16 @@ import java.util.ArrayList; import java.util.List; -import org.apache.http.HttpRequest; -import org.apache.http.client.methods.HttpGet; import org.junit.Test; +import okhttp3.Request; + public class MSBatchRequestStepTest { @Test public void testMSBatchRequestStepCreation() { - HttpRequest request = new HttpGet("http://graph.microsoft.com"); - List arrayOfDependsOnIds = new ArrayList(); + Request request = new Request.Builder().url("http://graph.microsoft.com").build(); + List arrayOfDependsOnIds = new ArrayList<>(); MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); assertTrue("Test BatchRequestStep creation", requestStep != null); assertTrue("Test Request id", requestStep.getRequestId().compareTo("1") == 0); diff --git a/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java b/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java index bf9652aff..1eebc8219 100644 --- a/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java +++ b/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java @@ -2,18 +2,10 @@ import static org.junit.Assert.assertTrue; -import java.io.IOException; -import java.util.Arrays; - -import org.apache.http.HttpResponse; -import org.apache.http.ParseException; -import org.apache.http.util.EntityUtils; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; +import okhttp3.Response; + public class MSBatchResponseContentTest { @Test @@ -54,7 +46,7 @@ public void testInvalidMSBatchResponseContentWithMalformedResponse() { public void testGetMSBatchResponseContentByID() { String responsedata = "{\"responses\": [{ \"id\": \"1\", \"status\": 302, \"headers\": { \"location\": \"https://b0mpua-by3301.files.1drv.com/y23vmagahszhxzlcvhasdhasghasodfi\" } }, { \"id\": \"3\", \"status\": 401, \"body\": { \"error\": { \"code\": \"Forbidden\", \"message\": \"...\" } } }, { \"id\": \"2\", \"status\": 200, \"body\": { \"@odata.context\": \"https://graph.microsoft.com/v1.0/$metadata#Collection(microsoft.graph.plannerTask)\", \"value\": [] } }, { \"id\": \"4\", \"status\": 204, \"body\": null } ] }"; MSBatchResponseContent batchresponse = new MSBatchResponseContent(responsedata); - HttpResponse response = batchresponse.getResponseById("1"); + Response response = batchresponse.getResponseById("1"); assertTrue(response != null); } } diff --git a/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java index dbd855760..a0bfccbb6 100644 --- a/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java @@ -5,20 +5,22 @@ import java.io.IOException; -import org.apache.http.Header; import org.apache.http.HttpException; -import org.apache.http.HttpRequest; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.protocol.HttpClientContext; import org.junit.Test; +import okhttp3.Request; +import okhttp3.internal.http2.Header; + public class AuthenticationHandlerTest { static String token = "TEST-TOKEN"; public static class AuthProvider implements IAuthenticationProvider{ - public void authenticateRequest(HttpRequest request) { - request.addHeader("Authorization", "Bearer " + token); + public Request authenticateRequest(Request request) { + Request newRequest = request.newBuilder().addHeader("Authorization", "Bearer " + token).build(); + return newRequest; } } @@ -26,7 +28,7 @@ public void authenticateRequest(HttpRequest request) { public void testAuthenticationHandler() { AuthProvider authProvider = new AuthProvider(); AuthenticationHandler authHandler = new AuthenticationHandler(authProvider); - HttpGet httpget = new HttpGet("https://graph.microsoft.com/v1.0/me/"); + Request request = new Request.Builder().url("https://graph.microsoft.com/v1.0/me/").build(); HttpClientContext localContext = HttpClientContext.create(); try { diff --git a/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java b/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java index c084f69fc..feee259b1 100644 --- a/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java @@ -2,20 +2,23 @@ import static org.junit.Assert.assertTrue; -import org.apache.http.HttpRequest; -import org.apache.http.impl.client.CloseableHttpClient; import org.junit.Test; +import okhttp3.OkHttpClient; +import okhttp3.Request; + public class HttpClientsTest { @Test public void testHttpClientCreation() { IAuthenticationProvider authprovider = new IAuthenticationProvider() { - public void authenticateRequest(HttpRequest request) { - request.addHeader("Authorization", "Bearer " + "TOKEN"); - } + public Request authenticateRequest(Request request) { + Request newRequest = request.newBuilder().addHeader("Authorization", "Bearer " + "TOKEN").build(); + return newRequest; + } }; - CloseableHttpClient httpclient = HttpClients.createDefault(authprovider); + + OkHttpClient httpclient = HttpClients.createDefault(authprovider); assertTrue(httpclient != null); } diff --git a/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java index 1e998f761..f53fe097b 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java @@ -3,12 +3,12 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import org.apache.http.Header; +import java.net.ProtocolException; + import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; -import org.apache.http.ProtocolException; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpHead; import org.apache.http.client.methods.HttpPost; @@ -16,6 +16,10 @@ import org.apache.http.message.BasicHttpResponse; import org.junit.Test; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.internal.http2.Header; + public class RedirectHandlerTest { String testmeurl = "https://graph.microsoft.com/v1.0/me/"; @@ -25,8 +29,8 @@ public class RedirectHandlerTest { @Test public void testIsRedirectedFailureByNoLocationHeader() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet(testmeurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); HttpClientContext localContext = HttpClientContext.create(); try { boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); @@ -40,8 +44,8 @@ public void testIsRedirectedFailureByNoLocationHeader() { @Test public void testIsRedirectedFailureByStatusCodeBadRequest() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet(testmeurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_BAD_REQUEST, "Bad Request"); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_BAD_REQUEST, "Bad Request"); response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { @@ -56,8 +60,8 @@ public void testIsRedirectedFailureByStatusCodeBadRequest() { @Test public void testIsRedirectedSuccessWithStatusCodeMovedTemporarily() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet(testmeurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { @@ -72,8 +76,8 @@ public void testIsRedirectedSuccessWithStatusCodeMovedTemporarily() { @Test public void testIsRedirectedSuccessWithStatusCodeMovedPermanently() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet(testmeurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_PERMANENTLY, "Moved Permanently"); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_PERMANENTLY, "Moved Permanently"); response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { @@ -88,8 +92,8 @@ public void testIsRedirectedSuccessWithStatusCodeMovedPermanently() { @Test public void testIsRedirectedSuccessWithStatusCodeTemporaryRedirect() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet(testmeurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_TEMPORARY_REDIRECT, "Temporary Redirect"); + Request httpget = new HttpGet(testmeurl); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_TEMPORARY_REDIRECT, "Temporary Redirect"); response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { @@ -104,8 +108,8 @@ public void testIsRedirectedSuccessWithStatusCodeTemporaryRedirect() { @Test public void testIsRedirectedSuccessWithStatusCodeSeeOther() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet(testmeurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other"); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other"); response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { @@ -120,12 +124,12 @@ public void testIsRedirectedSuccessWithStatusCodeSeeOther() { @Test public void testGetRedirectForGetMethod() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet(testurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); + Request httpget = new Request.Builder().url(testurl).build(); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { - HttpRequest request = redirectHandler.getRedirect(httpget, response, localContext); + Request request = redirectHandler.getRedirect(httpget, response, localContext); assertTrue(request != null); final String method = request.getRequestLine().getMethod(); assertTrue(method.equalsIgnoreCase(HttpGet.METHOD_NAME)); @@ -138,13 +142,13 @@ public void testGetRedirectForGetMethod() { @Test public void testGetRedirectForGetMethodForAuthHeader() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet(testurl); + Request httpget = new Request.Builder().url(testurl).build(); httpget.addHeader("Authorization", "TOKEN"); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); response.setHeader("location", differenthosturl); HttpClientContext localContext = HttpClientContext.create(); try { - HttpRequest request = redirectHandler.getRedirect(httpget, response, localContext); + Request request = redirectHandler.getRedirect(httpget, response, localContext); assertTrue(request != null); final String method = request.getRequestLine().getMethod(); assertTrue(method.equalsIgnoreCase(HttpGet.METHOD_NAME)); @@ -160,11 +164,11 @@ public void testGetRedirectForGetMethodForAuthHeader() { public void testGetRedirectForHeadMethod() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; HttpHead httphead = new HttpHead(testurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { - HttpRequest request = redirectHandler.getRedirect(httphead, response, localContext); + Request request = redirectHandler.getRedirect(httphead, response, localContext); assertTrue(request != null); final String method = request.getRequestLine().getMethod(); assertTrue(method.equalsIgnoreCase(HttpHead.METHOD_NAME)); @@ -177,12 +181,12 @@ public void testGetRedirectForHeadMethod() { @Test public void testGetRedirectForPostMethod() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpPost httppost = new HttpPost(testurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); + Request httppost = new Request.Builder().url(testurl).build(); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { - HttpRequest request = redirectHandler.getRedirect(httppost, response, localContext); + Request request = redirectHandler.getRedirect(httppost, response, localContext); assertTrue(request != null); final String method = request.getRequestLine().getMethod(); assertTrue(method.equalsIgnoreCase(HttpPost.METHOD_NAME)); @@ -195,12 +199,12 @@ public void testGetRedirectForPostMethod() { @Test public void testGetRedirectForPostMethodWithStatusCodeSeeOther() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpPost httppost = new HttpPost(testurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other"); + Request httppost = new Request.Builder().url(testurl).build(); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other"); response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { - HttpRequest request = redirectHandler.getRedirect(httppost, response, localContext); + Request request = redirectHandler.getRedirect(httppost, response, localContext); assertTrue(request != null); final String method = request.getRequestLine().getMethod(); assertTrue(method.equalsIgnoreCase(HttpGet.METHOD_NAME)); diff --git a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java index 36082894e..06299fe1f 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java @@ -6,6 +6,8 @@ import java.io.UnsupportedEncodingException; +import javax.xml.ws.spi.http.HttpContext; + import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; @@ -14,13 +16,15 @@ import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.entity.StringEntity; import org.apache.http.message.BasicHttpResponse; -import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpCoreContext; import org.junit.Test; import com.microsoft.graph.httpcore.middlewareoption.IShouldRetry; import com.microsoft.graph.httpcore.middlewareoption.RetryOptions; +import okhttp3.Request; +import okhttp3.Response; + public class RetryHandlerTest { int maxRetries = 2; @@ -37,7 +41,7 @@ public void testRetryHandlerCreation() { public void testRetryHandlerWithRetryOptions() { RetryOptions option = new RetryOptions(); RetryHandler retryhandler = new RetryHandler(option); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); HttpClientContext localContext = HttpClientContext.create(); assertTrue(retryhandler.retryRequest(response, 1, localContext)); } @@ -45,12 +49,12 @@ public void testRetryHandlerWithRetryOptions() { @Test public void testRetryHandlerWithCustomRetryOptions() { RetryOptions option = new RetryOptions(new IShouldRetry() { - public boolean shouldRetry(HttpResponse response, int executionCount, HttpContext context) { + public boolean shouldRetry(Response response, int executionCount, HttpContext context) { return false; } }); RetryHandler retryhandler = new RetryHandler(option); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); HttpClientContext localContext = HttpClientContext.create(); assertTrue(!retryhandler.retryRequest(response, 1, localContext)); } @@ -58,7 +62,7 @@ public boolean shouldRetry(HttpResponse response, int executionCount, HttpContex @Test public void testRetryRequestWithMaxRetryAttempts() { RetryHandler retryhandler = new RetryHandler(); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); HttpClientContext localContext = HttpClientContext.create(); assertFalse(retryhandler.retryRequest(response, 3, localContext)); } @@ -66,7 +70,7 @@ public void testRetryRequestWithMaxRetryAttempts() { @Test public void testRetryRequestForStatusCode() { RetryHandler retryhandler = new RetryHandler(); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_INTERNAL_SERVER_ERROR, "Internal Server Error"); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_INTERNAL_SERVER_ERROR, "Internal Server Error"); HttpClientContext localContext = HttpClientContext.create(); assertFalse(retryhandler.retryRequest(response, 1, localContext)); } @@ -74,9 +78,9 @@ public void testRetryRequestForStatusCode() { @Test public void testRetryRequestWithTransferEncoding() { RetryHandler retryhandler = new RetryHandler(); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); response.setHeader("Transfer-Encoding", "chunked"); - HttpPost httppost = new HttpPost(testurl); + Request httppost = new Request.Builder().url(testurl).build(); try { HttpEntity entity = new StringEntity("TEST"); @@ -94,8 +98,8 @@ public void testRetryRequestWithTransferEncoding() { @Test public void testRetryRequestWithExponentialBackOff() { RetryHandler retryhandler = new RetryHandler(); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); - HttpPost httppost = new HttpPost(testurl); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); + Request httppost = new Request.Builder().url(testurl).build(); try { HttpEntity entity = new StringEntity("TEST"); @@ -114,9 +118,9 @@ public void testRetryRequestWithExponentialBackOff() { @Test public void testRetryHandlerRetryRequestWithRetryAfterHeader() { RetryHandler retryhandler = new RetryHandler(); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); response.setHeader("Retry-After", "100"); - HttpPost httppost = new HttpPost(testurl); + Request httppost = new Request.Builder().url(testurl).build(); try { HttpEntity entity = new StringEntity("TEST"); From 76a447d3c8aacb0d78981851e4b97db35f717d80 Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Thu, 7 Mar 2019 13:04:18 +0530 Subject: [PATCH 29/38] Added redirect options --- .../middlewareoption/IShouldRedirect.java | 7 +++ .../middlewareoption/RedirectOptions.java | 52 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRedirect.java create mode 100644 src/main/java/com/microsoft/graph/httpcore/middlewareoption/RedirectOptions.java diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRedirect.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRedirect.java new file mode 100644 index 000000000..8ca9cd545 --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRedirect.java @@ -0,0 +1,7 @@ +package com.microsoft.graph.httpcore.middlewareoption; + +import okhttp3.Response; + +public interface IShouldRedirect { + boolean shouldRedirect(final Response response); +} diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RedirectOptions.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RedirectOptions.java new file mode 100644 index 000000000..f4ef54900 --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RedirectOptions.java @@ -0,0 +1,52 @@ +package com.microsoft.graph.httpcore.middlewareoption; + +import okhttp3.Response; + +public class RedirectOptions implements IMiddlewareControl{ + private int maxRedirects; + public static final int DEFAULT_MAX_REDIRECTS = 5; + public static final int MAX_REDIRECTS = 20; + + private IShouldRedirect shouldRedirect; + public static final IShouldRedirect DEFAULT_SHOULD_REDIRECT = new IShouldRedirect() { + @Override + public boolean shouldRedirect(Response response) { + return true; + } + }; + + /* + * Create default instance of redirect options, with default values of max redirects and should redirect + */ + public RedirectOptions() { + this(DEFAULT_MAX_REDIRECTS, DEFAULT_SHOULD_REDIRECT); + } + + /* + * @param maxRedirects Max redirects to occur + * @param shouldRedirect Should redirect callback called before every redirect + */ + public RedirectOptions(int maxRedirects, IShouldRedirect shouldRedirect) { + if(maxRedirects < 0) + throw new IllegalArgumentException("Max redirects cannot be negative"); + if(maxRedirects > MAX_REDIRECTS) + throw new IllegalArgumentException("Max redirect cannot exceed " + MAX_REDIRECTS); + + this.maxRedirects = maxRedirects; + this.shouldRedirect = shouldRedirect != null ? shouldRedirect : DEFAULT_SHOULD_REDIRECT; + } + + /* + * @return max redirects + */ + public int maxRedirects() { + return this.maxRedirects; + } + + /* + * @return should redirect + */ + public IShouldRedirect shouldRedirect() { + return this.shouldRedirect; + } +} From 4cb303162cebef0ce7c558c3e8cdbd3eea7df68f Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Thu, 7 Mar 2019 13:05:50 +0530 Subject: [PATCH 30/38] Migrated batching to OkHttp --- .../graph/content/MSBatchRequestContent.java | 51 +++------ .../graph/content/MSBatchResponseContent.java | 74 +++++++++--- .../content/MSBatchRequestContentTest.java | 105 +++++++++--------- .../content/MSBatchResponseContentTest.java | 54 +++++++-- 4 files changed, 169 insertions(+), 115 deletions(-) diff --git a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java index b944f9e32..877a6ecca 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java @@ -7,21 +7,20 @@ import org.json.simple.JSONArray; import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; +import com.microsoft.graph.httpcore.RequestSerializer; + import okhttp3.Headers; -import okhttp3.Request; import okhttp3.RequestBody; -import okio.Buffer; public class MSBatchRequestContent { private Map batchRequestStepsHashMap; - private final int maxNumberOfRequests = 20; + public static final int MAX_NUMBER_OF_REQUESTS = 20; public MSBatchRequestContent(List batchRequestStepsArray) { - if(batchRequestStepsArray.size() > maxNumberOfRequests) - throw new IllegalArgumentException("Number of batch request steps cannot exceed 20."); + if(batchRequestStepsArray.size() > MAX_NUMBER_OF_REQUESTS) + throw new IllegalArgumentException("Number of batch request steps cannot exceed " + MAX_NUMBER_OF_REQUESTS); this.batchRequestStepsHashMap = new HashMap<>(); for(MSBatchRequestStep requestStep: batchRequestStepsArray) @@ -57,20 +56,24 @@ public String getBatchRequestContent() { JSONObject batchRequestContentMap = new JSONObject(); JSONArray batchContentArray = new JSONArray(); for(Map.Entry requestStep : batchRequestStepsHashMap.entrySet()) { - batchContentArray.add(getBatchRequestMapFromRequestStep(requestStep.getValue())); + batchContentArray.add(getBatchRequestObjectFromRequestStep(requestStep.getValue())); } batchRequestContentMap.put("requests", batchContentArray); - return batchRequestContentMap.toJSONString(); + + String content = batchRequestContentMap.toString(); + return content; } @SuppressWarnings("unchecked") - private JSONObject getBatchRequestMapFromRequestStep(final MSBatchRequestStep batchRequestStep){ + private JSONObject getBatchRequestObjectFromRequestStep(final MSBatchRequestStep batchRequestStep){ JSONObject contentmap = new JSONObject(); contentmap.put("id", batchRequestStep.getRequestId()); String url = batchRequestStep.getRequest().url().toString(); - url = url.replaceAll("https://graph.microsoft.com/v1.0", ""); - url = url.replace("https://graph.microsoft.com/beta", ""); + url = url.replaceAll("https://graph.microsoft.com/v1.0/", ""); + url = url.replaceAll("http://graph.microsoft.com/v1.0/", ""); + url = url.replaceAll("https://graph.microsoft.com/beta/", ""); + url = url.replaceAll("http://graph.microsoft.com/beta/", ""); contentmap.put("url", url); contentmap.put("method", batchRequestStep.getRequest().method().toString()); @@ -79,7 +82,7 @@ private JSONObject getBatchRequestMapFromRequestStep(final MSBatchRequestStep ba if(headers != null && headers.size() != 0) { JSONObject headerMap = new JSONObject(); for(Map.Entry> entry : headers.toMultimap().entrySet()) { - headerMap.put(entry.getKey(), getHeaderValuesAsString(entry.getValue())); + headerMap.put(entry.getKey(), RequestSerializer.getHeaderValuesAsString(entry.getValue())); } contentmap.put("headers", headerMap); } @@ -94,34 +97,12 @@ private JSONObject getBatchRequestMapFromRequestStep(final MSBatchRequestStep ba RequestBody body = batchRequestStep.getRequest().body(); if(body != null) { try { - contentmap.put("body", requestBodyToJSONObject(batchRequestStep.getRequest())); + contentmap.put("body", RequestSerializer.requestBodyToJSONObject(batchRequestStep.getRequest())); }catch(IOException | ParseException e) { e.printStackTrace(); } } - return contentmap; } - private String getHeaderValuesAsString(final List list) { - StringBuilder builder = new StringBuilder(""); - if(list.size() != 0) { - builder.append(list.get(0)); - for(int i=1;i batchRequestsHashMap; + private JSONArray batchResponseArray; - public MSBatchResponseContent(String batchResponseData) { - JSONParser parser = new JSONParser(); - try { - if(batchResponseData != null) - batchResponseObj = (JSONObject) parser.parse(batchResponseData); - } - catch(ParseException e) { - e.printStackTrace(); + public MSBatchResponseContent(Response batchResponse) { + if(batchResponse == null) + throw new IllegalArgumentException("Batch Response cannot be null"); + + this.batchRequestsHashMap = RequestSerializer.createBatchRequestsHashMap(batchResponse); + this.batchResponse = batchResponse; + if(batchResponse.body() != null) { + try { + String batchResponseData = batchResponse.body().string(); + if(batchResponseData != null) { + batchResponseObj = RequestSerializer.stringToJSONObject(batchResponseData); + if(batchResponseObj != null) { + batchResponseArray = (JSONArray)batchResponseObj.get("responses"); + } + } + } catch (IOException e) { + e.printStackTrace(); + } } } @@ -32,28 +49,39 @@ public Response getResponseById(String requestId) { if(responses == null) return null; - for(Object response: responses) { + for(Object response : responses) { JSONObject jsonresponse = (JSONObject)response; String id = (String)jsonresponse.get("id"); if(id.compareTo(requestId) == 0) { Response.Builder builder = new Response.Builder(); + // Put corresponding request into the constructed response + builder.request(batchRequestsHashMap.get(requestId)); + // copy protocol and message same as of batch response + builder.protocol(batchResponse.protocol()); + builder.message(batchResponse.message()); + + // Put status code of the corresponding request in JSONArray if(jsonresponse.get("status") != null) { - String status = (String)jsonresponse.get("status"); - builder.code(Integer.parseInt(status)); + Long status = (Long)jsonresponse.get("status"); + builder.code(status.intValue()); } + // Put body from response array for corresponding id into constructing response if(jsonresponse.get("body") != null) { - String bodyAsString = (String)jsonresponse.get("body"); + JSONObject jsonObject = (JSONObject)jsonresponse.get("body"); + String bodyAsString = jsonObject.toJSONString(); ResponseBody responseBody = ResponseBody.create(MediaType.parse("application/json; charset=utf-8"), bodyAsString); builder.body(responseBody); } + + // Put headers from response array for corresponding id into constructing response if(jsonresponse.get("headers") != null){ JSONObject jsonheaders = (JSONObject)jsonresponse.get("headers"); for(Object key: jsonheaders.keySet()) { String strkey = (String)key; String strvalue = (String)jsonheaders.get(strkey); - for(String value : strvalue.split("; ")) { + for(String value : strvalue.split(";")) { builder.header(strkey, value); } } @@ -64,9 +92,19 @@ public Response getResponseById(String requestId) { return null; } + /* + * @return responses as a string + */ public String getResponses() { - if(batchResponseObj != null) - return ((JSONArray)batchResponseObj.get("responses")).toJSONString(); - return null; + return batchResponseArray != null ? batchResponseArray.toJSONString() : null; + } + + /* + * @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; } } diff --git a/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java b/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java index a4c37813a..ef5835654 100644 --- a/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java +++ b/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java @@ -11,77 +11,78 @@ public class MSBatchRequestContentTest { - String testurl = "http://graph.microsoft.com"; - + String testurl = "http://graph.microsoft.com/me"; + @Test public void testMSBatchRequestContentCreation() { List requestStepArray = new ArrayList<>(); - for(int i=0;i<5;i++) { - Request request = new Request.Builder().url(testurl).build(); - List arrayOfDependsOnIds = new ArrayList<>(); - MSBatchRequestStep requestStep = new MSBatchRequestStep("" + i, request, arrayOfDependsOnIds); - requestStepArray.add(requestStep); - } - MSBatchRequestContent requestContent = new MSBatchRequestContent(requestStepArray); - assertTrue(requestContent.getBatchRequestContent() != null); + for(int i=0;i<5;i++) { + Request request = new Request.Builder().url(testurl).build(); + List arrayOfDependsOnIds = new ArrayList<>(); + MSBatchRequestStep requestStep = new MSBatchRequestStep("" + i, request, arrayOfDependsOnIds); + requestStepArray.add(requestStep); + } + MSBatchRequestContent requestContent = new MSBatchRequestContent(requestStepArray); + assertTrue(requestContent.getBatchRequestContent() != null); } - + @Test public void testGetBatchRequestContent() { Request request = new Request.Builder().url(testurl).build(); - List arrayOfDependsOnIds = new ArrayList<>(); - MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); - MSBatchRequestContent requestContent = new MSBatchRequestContent(); - requestContent.addBatchRequestStep(requestStep); - String content = requestContent.getBatchRequestContent(); - String expectedContent = "{\"requests\":[{\"method\":\"GET\",\"dependsOn\":\"[]\",\"id\":\"1\",\"url\":\"http:\\/\\/graph.microsoft.com\"}]}"; - assertTrue(content.compareTo(expectedContent) == 0); + List arrayOfDependsOnIds = new ArrayList<>(); + MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); + MSBatchRequestContent requestContent = new MSBatchRequestContent(); + requestContent.addBatchRequestStep(requestStep); + String content = requestContent.getBatchRequestContent(); + String expectedContent = "{\"requests\":[{\"method\":\"GET\",\"dependsOn\":[],\"id\":\"1\",\"url\":\"http:\\/\\/graph.microsoft.com\\/me\"}]}"; + assertTrue(content.compareTo(expectedContent) == 0); } - + @Test public void testGetBatchRequestContentWithHeader() { Request request = new Request.Builder().url(testurl).header("testkey", "testvalue").build(); - List arrayOfDependsOnIds = new ArrayList<>(); - MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); - MSBatchRequestContent requestContent = new MSBatchRequestContent(); - requestContent.addBatchRequestStep(requestStep); - String content = requestContent.getBatchRequestContent(); - String expectedContent = "{\"requests\":[{\"headers\":\"{\\\"testkey\\\":\\\"testvalue\\\"}\",\"method\":\"GET\",\"dependsOn\":\"[]\",\"id\":\"1\",\"url\":\"http:\\/\\/graph.microsoft.com\"}]}"; - assertTrue(content.compareTo(expectedContent) == 0); + List arrayOfDependsOnIds = new ArrayList<>(); + MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); + MSBatchRequestContent requestContent = new MSBatchRequestContent(); + requestContent.addBatchRequestStep(requestStep); + String content = requestContent.getBatchRequestContent(); + System.out.println(content); + String expectedContent = "{\"requests\":[{\"headers\":{\"testkey\":\"testvalue\"},\"method\":\"GET\",\"dependsOn\":[],\"id\":\"1\",\"url\":\"http:\\/\\/graph.microsoft.com\\/me\"}]}"; + assertTrue(content.compareTo(expectedContent) == 0); } - + @Test public void testRemoveBatchRequesStepWithId() { Request request = new Request.Builder().url(testurl).build(); - List arrayOfDependsOnIds = new ArrayList<>(); - MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); - MSBatchRequestContent requestContent = new MSBatchRequestContent(); - requestContent.addBatchRequestStep(requestStep); - requestContent.removeBatchRequestStepWithId("1"); - String content = requestContent.getBatchRequestContent(); - String expectedContent = "{\"requests\":[]}"; - assertTrue(content.compareTo(expectedContent) == 0); + List arrayOfDependsOnIds = new ArrayList<>(); + MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); + MSBatchRequestContent requestContent = new MSBatchRequestContent(); + requestContent.addBatchRequestStep(requestStep); + requestContent.removeBatchRequestStepWithId("1"); + String content = requestContent.getBatchRequestContent(); + String expectedContent = "{\"requests\":[]}"; + assertTrue(content.compareTo(expectedContent) == 0); } - + @Test public void testRemoveBatchRequesStepWithIdByAddingMultipleBatchSteps() { Request request = new Request.Builder().url(testurl).build(); - List arrayOfDependsOnIds = new ArrayList<>(); - MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); - - Request request1 = new Request.Builder().url(testurl).build(); - List arrayOfDependsOnIds1 = new ArrayList<>(); - arrayOfDependsOnIds1.add("1"); - MSBatchRequestStep requestStep1 = new MSBatchRequestStep("2", request1, arrayOfDependsOnIds1); - - MSBatchRequestContent requestContent = new MSBatchRequestContent(); - requestContent.addBatchRequestStep(requestStep); - requestContent.addBatchRequestStep(requestStep1); - - requestContent.removeBatchRequestStepWithId("1"); - String content = requestContent.getBatchRequestContent(); - String expectedContent = "{\"requests\":[{\"method\":\"GET\",\"dependsOn\":\"[]\",\"id\":\"2\",\"url\":\"http:\\/\\/graph.microsoft.com\"}]}"; - assertTrue(content.compareTo(expectedContent) == 0); + List arrayOfDependsOnIds = new ArrayList<>(); + MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); + + Request request1 = new Request.Builder().url(testurl).build(); + List arrayOfDependsOnIds1 = new ArrayList<>(); + arrayOfDependsOnIds1.add("1"); + MSBatchRequestStep requestStep1 = new MSBatchRequestStep("2", request1, arrayOfDependsOnIds1); + + MSBatchRequestContent requestContent = new MSBatchRequestContent(); + requestContent.addBatchRequestStep(requestStep); + requestContent.addBatchRequestStep(requestStep1); + + requestContent.removeBatchRequestStepWithId("1"); + String content = requestContent.getBatchRequestContent(); + String expectedContent = "{\"requests\":[{\"method\":\"GET\",\"dependsOn\":[],\"id\":\"2\",\"url\":\"http:\\/\\/graph.microsoft.com\\/me\"}]}"; + assertTrue(content.compareTo(expectedContent) == 0); } } diff --git a/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java b/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java index 1eebc8219..0261889ea 100644 --- a/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java +++ b/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java @@ -1,52 +1,86 @@ package com.microsoft.graph.content; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import java.io.IOException; + import org.junit.Test; +import okhttp3.MediaType; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.RequestBody; import okhttp3.Response; +import okhttp3.ResponseBody; public class MSBatchResponseContentTest { @Test public void testNullMSBatchResponseContent() { - String responsedata = null; - MSBatchResponseContent batchresponse = new MSBatchResponseContent(responsedata); - assertTrue(batchresponse.getResponses() == null); + Response response = null; + try { + MSBatchResponseContent batchresponse = new MSBatchResponseContent(response); + } + catch(IllegalArgumentException e) { + assertNotNull(e); + } } @Test public void testValidMSBatchResponseContent() { - String responsedata = "{\"responses\": [{ \"id\": \"1\", \"status\": 302, \"headers\": { \"location\": \"https://b0mpua-by3301.files.1drv.com/y23vmagahszhxzlcvhasdhasghasodfi\" } }, { \"id\": \"3\", \"status\": 401, \"body\": { \"error\": { \"code\": \"Forbidden\", \"message\": \"...\" } } }, { \"id\": \"2\", \"status\": 200, \"body\": { \"@odata.context\": \"https://graph.microsoft.com/v1.0/$metadata#Collection(microsoft.graph.plannerTask)\", \"value\": [] } }, { \"id\": \"4\", \"status\": 204, \"body\": null } ] }"; + 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() != null); } @Test public void testInvalidMSBatchResponseContentWithEmptyResponse() { - String responsedata = "{\"responses\": [] }"; + String responsebody = "{\"responses\": [] }"; + String requestbody = "{\"requests\":[]}"; + Response responsedata = TestResponse(responsebody, requestbody); MSBatchResponseContent batchresponse = new MSBatchResponseContent(responsedata); assertTrue(batchresponse.getResponseById("1") == null); } @Test public void testInvalidMSBatchResponseContentWithNullResponseString() { - MSBatchResponseContent batchresponse = new MSBatchResponseContent(null); - assertTrue(batchresponse.getResponseById("1") == null); + try{ + new MSBatchResponseContent(null); + }catch(Exception e) { + assertTrue(e instanceof IllegalArgumentException); + } } @Test public void testInvalidMSBatchResponseContentWithMalformedResponse() { - String invalidResponsedata = "{responses: [] }"; + String invalidResponsebody = "{responses: [] }"; + String requestbody = "{requests:[]}"; + Response invalidResponsedata = TestResponse(invalidResponsebody, requestbody); MSBatchResponseContent batchresponse = new MSBatchResponseContent(invalidResponsedata); assertTrue(batchresponse.getResponses() == null); } @Test - public void testGetMSBatchResponseContentByID() { - String responsedata = "{\"responses\": [{ \"id\": \"1\", \"status\": 302, \"headers\": { \"location\": \"https://b0mpua-by3301.files.1drv.com/y23vmagahszhxzlcvhasdhasghasodfi\" } }, { \"id\": \"3\", \"status\": 401, \"body\": { \"error\": { \"code\": \"Forbidden\", \"message\": \"...\" } } }, { \"id\": \"2\", \"status\": 200, \"body\": { \"@odata.context\": \"https://graph.microsoft.com/v1.0/$metadata#Collection(microsoft.graph.plannerTask)\", \"value\": [] } }, { \"id\": \"4\", \"status\": 204, \"body\": null } ] }"; + public void testGetMSBatchResponseContentByID() 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); Response response = batchresponse.getResponseById("1"); assertTrue(response != null); } + + private Response TestResponse(String responsebody, String requestbody) { + Response.Builder builder = new Response.Builder(); + builder.body(ResponseBody.create(MediaType.parse("application/json"), responsebody)); + Request request = new Request.Builder().url("https://graph.microsoft.com/").method("POST", RequestBody.create(MediaType.parse("application/json"), requestbody)).build(); + builder.request(request); + builder.protocol(Protocol.HTTP_1_0); + builder.code(200); + builder.message("test message"); + return builder.build(); + } } From ce595eb65d3c4e3202b5619a0f1691a0011f287d Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Thu, 7 Mar 2019 13:06:50 +0530 Subject: [PATCH 31/38] Migrated redirect, retry handlers and retry options to okhttp --- .../graph/httpcore/RedirectHandler.java | 58 ++++++-- .../graph/httpcore/RetryHandler.java | 131 +++++++++++------- .../middlewareoption/IShouldRetry.java | 2 +- .../middlewareoption/RetryOptions.java | 63 ++++++++- 4 files changed, 187 insertions(+), 67 deletions(-) diff --git a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java index 093d90115..927ed873e 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java @@ -9,26 +9,47 @@ import java.io.IOException; import java.net.ProtocolException; +import com.microsoft.graph.httpcore.middlewareoption.MiddlewareType; +import com.microsoft.graph.httpcore.middlewareoption.RedirectOptions; + import okhttp3.HttpUrl; import okhttp3.Interceptor; import okhttp3.Request; -import okhttp3.RequestBody; import okhttp3.Response; -import okhttp3.internal.http.HttpMethod; public class RedirectHandler implements Interceptor{ - public static final RedirectHandler INSTANCE = new RedirectHandler(); - final int maxRedirect = 5; + public final MiddlewareType MIDDLEWARE_TYPE = MiddlewareType.REDIRECT; - public boolean isRedirected(Request request, Response response, int redirectCount) throws IOException { - - if(redirectCount > maxRedirect) return false; + private RedirectOptions mRedirectOptions; + + /* + * Initialize using default redirect options, default IShouldRedirect and max redirect value + */ + public RedirectHandler() { + this.mRedirectOptions = new RedirectOptions(); + } + + /* + * @param redirectOptions pass instance of redirect options to be used + */ + public RedirectHandler(RedirectOptions redirectOptions) { + this.mRedirectOptions = redirectOptions; + if(redirectOptions == null) { + this.mRedirectOptions = new RedirectOptions(); + } + } + + public boolean isRedirected(Request request, Response response, int redirectCount, RedirectOptions redirectOptions) throws IOException { + // Check max count of redirects reached + if(redirectCount > redirectOptions.maxRedirects()) return false; + // Location header empty then don't redirect final String locationHeader = response.header("location"); if(locationHeader == null) return false; + // If any of 301,302,303,307,308 then redirect final int statusCode = response.code(); if(statusCode == HTTP_PERM_REDIRECT || //308 statusCode == HTTP_MOVED_PERM || //301 @@ -46,12 +67,15 @@ public Request getRedirect( String location = userResponse.header("Location"); if (location == null) return null; + // TODO: If Location header is relative reference then final URL should be relative to original target URL. + HttpUrl requestUrl = userResponse.request().url(); HttpUrl locationUrl = userResponse.request().url().resolve(location); + // Don't follow redirects to unsupported protocols. if (locationUrl == null) return null; - + // Most redirects don't include a request body. Request.Builder requestBuilder = userResponse.request().newBuilder(); @@ -63,25 +87,37 @@ public Request getRedirect( if (!sameScheme || !sameHost) { requestBuilder.removeHeader("Authorization"); } + + // Response status code 303 See Other then POST changes to GET + if(userResponse.code() == HTTP_SEE_OTHER) { + requestBuilder.method("GET", null); + } return requestBuilder.url(locationUrl).build(); } + // Intercept request and response made to network @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Response response = null; - int redirectCount = 1; + int requestsCount = 1; + + // Use should retry pass along with this request + RedirectOptions redirectOptions = request.tag(RedirectOptions.class); + redirectOptions = redirectOptions != null ? redirectOptions : this.mRedirectOptions; + while(true) { response = chain.proceed(request); - boolean shouldRedirect = isRedirected(request, response, redirectCount); + boolean shouldRedirect = redirectOptions.shouldRedirect().shouldRedirect(response) + && isRedirected(request, response, requestsCount, redirectOptions); if(!shouldRedirect) break; Request followup = getRedirect(request, response); if(followup == null) break; request = followup; - redirectCount++; + requestsCount++; } return response; } diff --git a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java index 237dfed87..2a4246545 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java @@ -2,6 +2,9 @@ import java.io.IOException; +import com.microsoft.graph.httpcore.middlewareoption.IShouldRetry; +import com.microsoft.graph.httpcore.middlewareoption.MiddlewareType; +import com.microsoft.graph.httpcore.middlewareoption.RedirectOptions; import com.microsoft.graph.httpcore.middlewareoption.RetryOptions; import okhttp3.Interceptor; @@ -9,86 +12,112 @@ import okhttp3.Response; public class RetryHandler implements Interceptor{ + + public final MiddlewareType MIDDLEWARE_TYPE = MiddlewareType.RETRY; - /** - * Maximum number of allowed retries if the server responds with a HTTP code - * in our retry code list. Default value is 1. - */ - private final int maxRetries = 2; - - /** - * Retry interval between subsequent requests, in milliseconds. Default - * value is 1 second. + private RetryOptions mRetryOption; + + /* + * constant string being used */ - private long retryInterval = 1000; - private final int DELAY_MILLISECONDS = 1000; + private final String RETRY_ATTEMPT_HEADER = "Retry-Attempt"; private final String RETRY_AFTER = "Retry-After"; private final String TRANSFER_ENCODING = "Transfer-Encoding"; + private final String TRANSFER_ENCODING_CHUNKED = "chunked"; + private final String APPLICATION_OCTET_STREAM = "application/octet-stream"; + private final String CONTENT_TYPE = "Content-Type"; + + public static final int MSClientErrorCodeTooManyRequests = 429; + public static final int MSClientErrorCodeServiceUnavailable = 503; + public static final int MSClientErrorCodeGatewayTimeout = 504; - private final int MSClientErrorCodeTooManyRequests = 429; - private final int MSClientErrorCodeServiceUnavailable = 503; - private final int MSClientErrorCodeGatewayTimeout = 504; - private final RetryOptions mRetryOption; + private final long DELAY_MILLISECONDS = 1000; - public RetryHandler(RetryOptions option) { - super(); - this.mRetryOption = option; + /* + * @retryOption Create Retry handler using retry option + */ + public RetryHandler(RetryOptions retryOption) { + this.mRetryOption = retryOption; + if(this.mRetryOption == null) { + this.mRetryOption = new RetryOptions(); + } } - + /* + * Initialize retry handler with default retry option + */ public RetryHandler() { this(null); } - public boolean retryRequest(Response response, int executionCount, Request request) { + private boolean retryRequest(Response response, int executionCount, Request request, RetryOptions retryOptions) { - RetryOptions retryOption = request.tag(RetryOptions.class); - if(retryOption != null) { - return retryOption.shouldRetry().shouldRetry(response, executionCount, request); + // Should retry option + // Use should retry common for all requests + IShouldRetry shouldRetryCallback = null; + if(retryOptions != null) { + shouldRetryCallback = retryOptions.shouldRetry(); } - if(mRetryOption != null) { - return mRetryOption.shouldRetry().shouldRetry(response, executionCount, request); + // Call should retry callback + if(shouldRetryCallback != null) { + shouldRetryCallback.shouldRetry(response, executionCount, request, retryOptions.delay()); } boolean shouldRetry = false; + // Status codes 429 503 504 int statusCode = response.code(); - shouldRetry = (executionCount < maxRetries) && checkStatus(statusCode) && isBuffered(response, request); + // Only requests with payloads that are buffered/rewindable are supported. + // Payloads with forward only streams will be have the responses returned + // without any retry attempt. + shouldRetry = (executionCount <= retryOptions.maxRetries()) && checkStatus(statusCode) && isBuffered(response, request); if(shouldRetry) { - String retryAfterHeader = response.header(RETRY_AFTER); - if(retryAfterHeader != null) - retryInterval = Long.parseLong(retryAfterHeader); - else - retryInterval = (long)Math.pow(2.0, (double)executionCount) * DELAY_MILLISECONDS; + long retryInterval = getRetryAfter(response, retryOptions.delay(), executionCount); + try { + Thread.sleep(retryInterval); + } catch (InterruptedException e) { + e.printStackTrace(); + } } return shouldRetry; } - - public long getRetryInterval() { - return retryInterval; + + private long getRetryAfter(Response response, long delay, int executionCount) { + String retryAfterHeader = response.header(RETRY_AFTER); + long retryDelay = RetryOptions.DEFAULT_DELAY; + if(retryAfterHeader != null) { + retryDelay = Long.parseLong(retryAfterHeader); + } else { + retryDelay = (long)Math.pow(2.0, (double)executionCount) * DELAY_MILLISECONDS; + retryDelay = executionCount < 2 ? retryDelay : retryDelay + delay + (long)Math.random(); + } + return Math.min(retryDelay, RetryOptions.MAX_DELAY); } private boolean checkStatus(int statusCode) { - if (statusCode == MSClientErrorCodeTooManyRequests || statusCode == MSClientErrorCodeServiceUnavailable - || statusCode == MSClientErrorCodeGatewayTimeout) - return true; - return false; + return (statusCode == MSClientErrorCodeTooManyRequests || statusCode == MSClientErrorCodeServiceUnavailable + || statusCode == MSClientErrorCodeGatewayTimeout); } private boolean isBuffered(Response response, Request request) { String methodName = request.method(); + if(methodName.equalsIgnoreCase("GET") || methodName.equalsIgnoreCase("DELETE")) + return true; boolean isHTTPMethodPutPatchOrPost = methodName.equalsIgnoreCase("POST") || methodName.equalsIgnoreCase("PUT") || methodName.equalsIgnoreCase("PATCH"); - //Header transferEncoding = response.getFirstHeader(TRANSFER_ENCODING); - String transferEncoding = response.header(TRANSFER_ENCODING); - boolean isTransferEncodingChunked = (transferEncoding != null) && - transferEncoding.equalsIgnoreCase("chunked"); - - if(request.body() != null && isHTTPMethodPutPatchOrPost && isTransferEncodingChunked) - return false; - return true; + if(isHTTPMethodPutPatchOrPost) { + boolean isStream = response.header(CONTENT_TYPE)!=null && response.header(CONTENT_TYPE).equalsIgnoreCase(APPLICATION_OCTET_STREAM); + if(!isStream) { + String transferEncoding = response.header(TRANSFER_ENCODING); + boolean isTransferEncodingChunked = (transferEncoding != null) && + transferEncoding.equalsIgnoreCase(TRANSFER_ENCODING_CHUNKED); + if(request.body() != null && isTransferEncodingChunked) + return true; + } + } + return false; } @Override @@ -96,8 +125,14 @@ public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Response response = chain.proceed(request); - int executionCount = 0; - while(retryRequest(response, executionCount, request)) { + + // Use should retry pass along with this request + RetryOptions retryOption = request.tag(RetryOptions.class); + retryOption = retryOption != null ? retryOption : this.mRetryOption; + + int executionCount = 1; + while(retryRequest(response, executionCount, request, retryOption)) { + request = request.newBuilder().addHeader(RETRY_ATTEMPT_HEADER, String.valueOf(executionCount)).build(); executionCount++; response = chain.proceed(request); } diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java index 366c310a6..0eeb9b684 100644 --- a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java @@ -4,5 +4,5 @@ import okhttp3.Response; public interface IShouldRetry { - boolean shouldRetry(Response response, int executionCount, Request request); + boolean shouldRetry(Response response, int executionCount, Request request, long delay); } diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java index 57ccfbc29..4714a4c8f 100644 --- a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java @@ -5,20 +5,69 @@ public class RetryOptions implements IMiddlewareControl { private IShouldRetry shouldretry; + public static final IShouldRetry DEFAULT_SHOULD_RETRY = new IShouldRetry() { + @Override + public boolean shouldRetry(Response response, int executionCount, Request request, long delay) { + return true; + } + }; + private int maxRetries; + public static final int MAX_RETRIES = 10; + public static final int DEFAULT_MAX_RETRIES = 3; + + /* + * Delay in seconds + */ + private long delay; + public static final long DEFAULT_DELAY = 3; // 3 seconds default delay + public static final long MAX_DELAY = 180; // 180 second max delay + + /* + * Create default instance of retry options, with default values of delay, max retries and shouldRetry callback. + */ public RetryOptions(){ - this(new IShouldRetry() { - public boolean shouldRetry(Response response, int executionCount, Request request) { - return true; - } - }); + this(DEFAULT_SHOULD_RETRY, DEFAULT_MAX_RETRIES, DEFAULT_DELAY); } - public RetryOptions(IShouldRetry shouldretry){ - this.shouldretry = shouldretry; + /* + * @param shouldRetry Retry callback to be called before making a retry + * @param maxRetries Number of max retires for a request + * @param delay Delay in seconds between retries + */ + public RetryOptions(IShouldRetry shouldRetry, int maxRetries, long delay) { + if(delay > MAX_DELAY) + throw new IllegalArgumentException("Delay cannot exceed " + MAX_DELAY); + if(delay < 0) + throw new IllegalArgumentException("Delay cannot be negative"); + if(maxRetries > MAX_RETRIES) + throw new IllegalArgumentException("Max retires cannot exceed " + MAX_RETRIES); + if(maxRetries < 0) + throw new IllegalArgumentException("Max retires cannot be negative"); + + this.shouldretry = shouldRetry != null ? shouldRetry : DEFAULT_SHOULD_RETRY; + this.maxRetries = maxRetries; + this.delay = delay; } + /* + * @return should retry callback + */ public IShouldRetry shouldRetry() { return shouldretry; } + + /* + * @return Number of max retries + */ + public int maxRetries() { + return maxRetries; + } + + /* + * @return Delay in seconds between retries + */ + public long delay() { + return delay; + } } From c6f788600511e7fe8c91de47b3107bb71f178f34 Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Thu, 7 Mar 2019 17:55:56 +0530 Subject: [PATCH 32/38] Migrated HttpClient and tests to okhttp --- .../graph/httpcore/AuthenticationHandler.java | 4 + .../microsoft/graph/httpcore/HttpClients.java | 1 + .../graph/httpcore/RequestSerializer.java | 117 ++++++++ .../graph/httpcore/RetryHandler.java | 16 +- .../middlewareoption/HttpContextBuilder.java | 33 --- .../middlewareoption/RetryOptions.java | 22 +- .../httpcore/AuthenticationHandlerTest.java | 23 +- .../graph/httpcore/RedirectHandlerTest.java | 263 +++++++++--------- .../graph/httpcore/RetryHandlerTest.java | 163 +++++------ 9 files changed, 368 insertions(+), 274 deletions(-) create mode 100644 src/main/java/com/microsoft/graph/httpcore/RequestSerializer.java delete mode 100644 src/main/java/com/microsoft/graph/httpcore/middlewareoption/HttpContextBuilder.java diff --git a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java index b7eb1003c..ad1992eb6 100644 --- a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java @@ -2,11 +2,15 @@ import java.io.IOException; +import com.microsoft.graph.httpcore.middlewareoption.MiddlewareType; + import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; public class AuthenticationHandler implements Interceptor { + + public final MiddlewareType MIDDLEWARE_TYPE = MiddlewareType.AUTHENTICATION; private IAuthenticationProvider authProvider; diff --git a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java index dc5ddbdba..376f8a660 100644 --- a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java +++ b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java @@ -22,6 +22,7 @@ public static Builder custom() { */ public static OkHttpClient createDefault(IAuthenticationProvider auth) { return new OkHttpClient.Builder().addInterceptor(new AuthenticationHandler(auth)) + .followRedirects(false) .addInterceptor(new RetryHandler()) .addInterceptor(new RedirectHandler()) .build(); diff --git a/src/main/java/com/microsoft/graph/httpcore/RequestSerializer.java b/src/main/java/com/microsoft/graph/httpcore/RequestSerializer.java new file mode 100644 index 000000000..917159d38 --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/RequestSerializer.java @@ -0,0 +1,117 @@ +package com.microsoft.graph.httpcore; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +import okhttp3.MediaType; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.ResponseBody; +import okio.Buffer; + +public class RequestSerializer { + + public static Map createBatchRequestsHashMap(Response batchResponse) { + if(batchResponse == null)return null; + try { + Map batchRequestsHashMap = new HashMap<>(); + JSONObject requestJSONObject = requestBodyToJSONObject(batchResponse.request()); + JSONArray requestArray = (JSONArray)requestJSONObject.get("requests"); + for(Object item : requestArray) { + JSONObject requestObject = (JSONObject)item; + + Request.Builder builder = new Request.Builder(); + + if(requestObject.get("url") != null) { + StringBuilder fullUrl = new StringBuilder(batchResponse.request().url().toString().replace("$batch","")); + fullUrl.append(requestObject.get("url").toString()); + builder.url(fullUrl.toString()); + } + if(requestObject.get("headers") != null) { + JSONObject jsonheaders = (JSONObject)requestObject.get("headers"); + for(Object key: jsonheaders.keySet()) { + String strkey = (String)key; + String strvalue = (String)jsonheaders.get(strkey); + for(String value : strvalue.split("; ")) { + builder.header(strkey, value); + } + } + } + if(requestObject.get("body") != null) { + JSONObject jsonObject = (JSONObject)requestObject.get("body"); + String bodyAsString = jsonObject.toJSONString(); + RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), bodyAsString); + builder.method(requestObject.get("method").toString(), requestBody); + } else { + builder.method(requestObject.get("method").toString(), null); + } + batchRequestsHashMap.put(requestObject.get("id").toString(), builder.build()); + } + return batchRequestsHashMap; + + } catch (IOException | ParseException e) { e.printStackTrace(); } + return null; + } + + /* + * Convert request body to JSONObject + */ + public static JSONObject requestToJSONObject(final Request request) throws IOException, ParseException{ + Request copy = request.newBuilder().build(); + Buffer buffer = new Buffer(); + copy.body().writeTo(buffer); + String body = buffer.readUtf8(); + JSONObject json = (JSONObject)new JSONParser().parse(body); + return json; + } + + /* + * Converts String to JSONObject + */ + public static JSONObject stringToJSONObject(String input) { + JSONParser parser = new JSONParser(); + JSONObject jsonObject = null; + try { + if(input != null) { + jsonObject = (JSONObject) parser.parse(input); + } + } + catch(Exception e) { + e.printStackTrace(); + } + return jsonObject; + } + + /* + * @param list List of parameters of a single header + * @return List of headers to a String seperated by "; " + */ + public static String getHeaderValuesAsString(final List list) { + if(list == null || list.size() == 0)return ""; + StringBuilder builder = new StringBuilder(list.get(0)); + for(int i=1;i MAX_RETRIES) - throw new IllegalArgumentException("Max retires cannot exceed " + MAX_RETRIES); + throw new IllegalArgumentException("Max retries cannot exceed " + MAX_RETRIES); if(maxRetries < 0) - throw new IllegalArgumentException("Max retires cannot be negative"); + throw new IllegalArgumentException("Max retries cannot be negative"); - this.shouldretry = shouldRetry != null ? shouldRetry : DEFAULT_SHOULD_RETRY; - this.maxRetries = maxRetries; - this.delay = delay; + this.mShouldretry = shouldRetry != null ? shouldRetry : DEFAULT_SHOULD_RETRY; + this.mMaxRetries = maxRetries; + this.mDelay = delay; } /* * @return should retry callback */ public IShouldRetry shouldRetry() { - return shouldretry; + return mShouldretry; } /* * @return Number of max retries */ public int maxRetries() { - return maxRetries; + return mMaxRetries; } /* * @return Delay in seconds between retries */ public long delay() { - return delay; + return mDelay; } } diff --git a/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java index a0bfccbb6..e6d6eeea6 100644 --- a/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java @@ -3,16 +3,13 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import java.io.IOException; - -import org.apache.http.HttpException; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.protocol.HttpClientContext; +import org.junit.Ignore; import org.junit.Test; import okhttp3.Request; -import okhttp3.internal.http2.Header; +import okhttp3.internal.http.RealInterceptorChain; +@Ignore public class AuthenticationHandlerTest { static String token = "TEST-TOKEN"; @@ -29,13 +26,17 @@ public void testAuthenticationHandler() { AuthProvider authProvider = new AuthProvider(); AuthenticationHandler authHandler = new AuthenticationHandler(authProvider); Request request = new Request.Builder().url("https://graph.microsoft.com/v1.0/me/").build(); - HttpClientContext localContext = HttpClientContext.create(); + + RealInterceptorChain chain = new RealInterceptorChain(null, null, null, null, 0, request, null, null, 0, 0, 0); try { - authHandler.process(httpget, localContext); - Header header = httpget.getFirstHeader("Authorization"); - assertTrue(header.getValue().equals("Bearer " + token)); - } catch (HttpException | IOException e) { + authHandler.intercept(chain); + + String value = request.header("Authorization"); + assertTrue(value.equals("Bearer " + token)); + + + } catch (Exception e) { e.printStackTrace(); fail("Authentication handler failure"); } diff --git a/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java index f53fe097b..3182b850f 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java @@ -3,22 +3,20 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.io.IOException; +import java.net.HttpURLConnection; import java.net.ProtocolException; -import org.apache.http.HttpRequest; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.HttpVersion; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpHead; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.message.BasicHttpResponse; import org.junit.Test; +import com.microsoft.graph.httpcore.middlewareoption.RedirectOptions; + +import okhttp3.MediaType; +import okhttp3.Protocol; import okhttp3.Request; +import okhttp3.RequestBody; import okhttp3.Response; -import okhttp3.internal.http2.Header; +import okhttp3.internal.http.StatusLine; public class RedirectHandlerTest { @@ -27,112 +25,110 @@ public class RedirectHandlerTest { String differenthosturl = "https://graph.abc.com/v1.0/"; @Test - public void testIsRedirectedFailureByNoLocationHeader() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + public void testIsRedirectedFailureByNoLocationHeader() throws IOException { + RedirectHandler redirectHandler = new RedirectHandler(); Request httpget = new Request.Builder().url(testmeurl).build(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); - HttpClientContext localContext = HttpClientContext.create(); - try { - boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); - assertTrue(!isRedirected); - } catch (ProtocolException e) { - e.printStackTrace(); - fail("Redirect handler testIsRedirectedFailure failure"); - } + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_MOVED_TEMP) + .message("Moved Temporarily") + .request(httpget) + .build(); + boolean isRedirected = redirectHandler.isRedirected(httpget, response, 0, new RedirectOptions()); + assertTrue(!isRedirected); } @Test - public void testIsRedirectedFailureByStatusCodeBadRequest() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + public void testIsRedirectedFailureByStatusCodeBadRequest() throws IOException { + RedirectHandler redirectHandler = new RedirectHandler(); Request httpget = new Request.Builder().url(testmeurl).build(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_BAD_REQUEST, "Bad Request"); - response.setHeader("location", testmeurl); - HttpClientContext localContext = HttpClientContext.create(); - try { - boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); - assertTrue(!isRedirected); - } catch (ProtocolException e) { - e.printStackTrace(); - fail("Redirect handler testIsRedirectedFailure1 failure"); - } + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_BAD_REQUEST) + .message( "Bad Request") + .addHeader("location", testmeurl) + .request(httpget) + .build(); + boolean isRedirected = redirectHandler.isRedirected(httpget, response, 0, new RedirectOptions()); + assertTrue(!isRedirected); } @Test - public void testIsRedirectedSuccessWithStatusCodeMovedTemporarily() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + public void testIsRedirectedSuccessWithStatusCodeMovedTemporarily() throws IOException { + RedirectHandler redirectHandler = new RedirectHandler(); Request httpget = new Request.Builder().url(testmeurl).build(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); - response.setHeader("location", testmeurl); - HttpClientContext localContext = HttpClientContext.create(); - try { - boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); - assertTrue(isRedirected); - } catch (ProtocolException e) { - e.printStackTrace(); - fail("Redirect handler testIsRedirectedSuccess failure"); - } + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_MOVED_TEMP) + .message("Moved Temporarily") + .addHeader("location", testmeurl) + .request(httpget) + .build(); + boolean isRedirected = redirectHandler.isRedirected(httpget, response, 0, new RedirectOptions()); + assertTrue(isRedirected); } @Test - public void testIsRedirectedSuccessWithStatusCodeMovedPermanently() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + public void testIsRedirectedSuccessWithStatusCodeMovedPermanently() throws IOException { + RedirectHandler redirectHandler = new RedirectHandler(); Request httpget = new Request.Builder().url(testmeurl).build(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_PERMANENTLY, "Moved Permanently"); - response.setHeader("location", testmeurl); - HttpClientContext localContext = HttpClientContext.create(); - try { - boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); - assertTrue(isRedirected); - } catch (ProtocolException e) { - e.printStackTrace(); - fail("Redirect handler testIsRedirectedSuccess1 failure"); - } + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_MOVED_PERM) + .message("Moved Permanently") + .addHeader("location", testmeurl) + .request(httpget) + .build(); + boolean isRedirected = redirectHandler.isRedirected(httpget, response, 0, new RedirectOptions()); + assertTrue(isRedirected); } - + @Test - public void testIsRedirectedSuccessWithStatusCodeTemporaryRedirect() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - Request httpget = new HttpGet(testmeurl); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_TEMPORARY_REDIRECT, "Temporary Redirect"); - response.setHeader("location", testmeurl); - HttpClientContext localContext = HttpClientContext.create(); - try { - boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); - assertTrue(isRedirected); - } catch (ProtocolException e) { - e.printStackTrace(); - fail("Redirect handler testIsRedirectedSuccess2 failure"); - } + public void testIsRedirectedSuccessWithStatusCodeTemporaryRedirect() throws IOException { + RedirectHandler redirectHandler = new RedirectHandler(); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(StatusLine.HTTP_TEMP_REDIRECT) + .message("Temporary Redirect") + .addHeader("location", testmeurl) + .request(httpget) + .build(); + boolean isRedirected = redirectHandler.isRedirected(httpget, response,0,new RedirectOptions()); + assertTrue(isRedirected); } - + @Test - public void testIsRedirectedSuccessWithStatusCodeSeeOther() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + public void testIsRedirectedSuccessWithStatusCodeSeeOther() throws IOException { + RedirectHandler redirectHandler = new RedirectHandler(); Request httpget = new Request.Builder().url(testmeurl).build(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other"); - response.setHeader("location", testmeurl); - HttpClientContext localContext = HttpClientContext.create(); - try { - boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); - assertTrue(isRedirected); - } catch (ProtocolException e) { - e.printStackTrace(); - fail("Redirect handler testIsRedirectedSuccess3 failure"); - } + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_SEE_OTHER) + .message( "See Other") + .addHeader("location", testmeurl) + .request(httpget) + .build(); + boolean isRedirected = redirectHandler.isRedirected(httpget, response,0,new RedirectOptions()); + assertTrue(isRedirected); } @Test public void testGetRedirectForGetMethod() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + RedirectHandler redirectHandler = new RedirectHandler(); Request httpget = new Request.Builder().url(testurl).build(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); - response.setHeader("location", testmeurl); - HttpClientContext localContext = HttpClientContext.create(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_MOVED_TEMP) + .message("Moved Temporarily") + .addHeader("location", testmeurl) + .request(httpget) + .build(); try { - Request request = redirectHandler.getRedirect(httpget, response, localContext); + Request request = redirectHandler.getRedirect(httpget, response); assertTrue(request != null); - final String method = request.getRequestLine().getMethod(); - assertTrue(method.equalsIgnoreCase(HttpGet.METHOD_NAME)); + final String method = request.method(); + assertTrue(method.equalsIgnoreCase("GET")); } catch (ProtocolException e) { e.printStackTrace(); fail("Redirect handler testGetRedirectForGetMethod failure"); @@ -141,18 +137,22 @@ public void testGetRedirectForGetMethod() { @Test public void testGetRedirectForGetMethodForAuthHeader() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - Request httpget = new Request.Builder().url(testurl).build(); - httpget.addHeader("Authorization", "TOKEN"); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); - response.setHeader("location", differenthosturl); - HttpClientContext localContext = HttpClientContext.create(); + RedirectHandler redirectHandler = new RedirectHandler(); + Request httpget = new Request.Builder().url(testurl).header("Authorization", "TOKEN").build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_MOVED_TEMP) + .message("Moved Temporarily") + .addHeader("location", differenthosturl) + .request(httpget) + .build(); + try { - Request request = redirectHandler.getRedirect(httpget, response, localContext); + Request request = redirectHandler.getRedirect(httpget, response); assertTrue(request != null); - final String method = request.getRequestLine().getMethod(); - assertTrue(method.equalsIgnoreCase(HttpGet.METHOD_NAME)); - Header header = request.getFirstHeader("Authorization"); + final String method = request.method(); + assertTrue(method.equalsIgnoreCase("GET")); + String header = request.header("Authorization"); assertTrue(header == null); } catch (ProtocolException e) { e.printStackTrace(); @@ -162,16 +162,20 @@ public void testGetRedirectForGetMethodForAuthHeader() { @Test public void testGetRedirectForHeadMethod() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpHead httphead = new HttpHead(testurl); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); - response.setHeader("location", testmeurl); - HttpClientContext localContext = HttpClientContext.create(); + RedirectHandler redirectHandler = new RedirectHandler(); + Request httphead = new Request.Builder().url(testurl).method("HEAD", null).build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_MOVED_TEMP) + .message("Moved Temporarily") + .addHeader("location", testmeurl) + .request(httphead) + .build(); try { - Request request = redirectHandler.getRedirect(httphead, response, localContext); + Request request = redirectHandler.getRedirect(httphead, response); assertTrue(request != null); - final String method = request.getRequestLine().getMethod(); - assertTrue(method.equalsIgnoreCase(HttpHead.METHOD_NAME)); + final String method = request.method(); + assertTrue(method.equalsIgnoreCase("HEAD")); } catch (ProtocolException e) { e.printStackTrace(); fail("Redirect handler testGetRedirectForHeadMethod failure"); @@ -180,16 +184,21 @@ public void testGetRedirectForHeadMethod() { @Test public void testGetRedirectForPostMethod() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - Request httppost = new Request.Builder().url(testurl).build(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); - response.setHeader("location", testmeurl); - HttpClientContext localContext = HttpClientContext.create(); + RedirectHandler redirectHandler = new RedirectHandler(); + RequestBody body = RequestBody.create(MediaType.parse("application/json"),""); + Request httppost = new Request.Builder().url(testurl).post(body).build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_MOVED_TEMP) + .message("Moved Temporarily") + .addHeader("location", testmeurl) + .request(httppost) + .build(); try { - Request request = redirectHandler.getRedirect(httppost, response, localContext); + Request request = redirectHandler.getRedirect(httppost, response); assertTrue(request != null); - final String method = request.getRequestLine().getMethod(); - assertTrue(method.equalsIgnoreCase(HttpPost.METHOD_NAME)); + final String method = request.method(); + assertTrue(method.equalsIgnoreCase("POST")); } catch (ProtocolException e) { e.printStackTrace(); fail("Redirect handler testGetRedirectForPostMethod failure"); @@ -198,16 +207,22 @@ public void testGetRedirectForPostMethod() { @Test public void testGetRedirectForPostMethodWithStatusCodeSeeOther() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + RedirectHandler redirectHandler = new RedirectHandler(); Request httppost = new Request.Builder().url(testurl).build(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other"); - response.setHeader("location", testmeurl); - HttpClientContext localContext = HttpClientContext.create(); + + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_SEE_OTHER) + .message("See Other") + .addHeader("location", testmeurl) + .request(httppost) + .build(); + try { - Request request = redirectHandler.getRedirect(httppost, response, localContext); + Request request = redirectHandler.getRedirect(httppost, response); assertTrue(request != null); - final String method = request.getRequestLine().getMethod(); - assertTrue(method.equalsIgnoreCase(HttpGet.METHOD_NAME)); + final String method = request.method(); + assertTrue(method.equalsIgnoreCase("GET")); } catch (ProtocolException e) { e.printStackTrace(); fail("Redirect handler testGetRedirectForPostMethod1 failure"); diff --git a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java index 06299fe1f..691b9fd75 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java @@ -1,139 +1,128 @@ package com.microsoft.graph.httpcore; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; import javax.xml.ws.spi.http.HttpContext; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.HttpVersion; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.entity.StringEntity; -import org.apache.http.message.BasicHttpResponse; -import org.apache.http.protocol.HttpCoreContext; import org.junit.Test; import com.microsoft.graph.httpcore.middlewareoption.IShouldRetry; import com.microsoft.graph.httpcore.middlewareoption.RetryOptions; +import okhttp3.MediaType; +import okhttp3.Protocol; import okhttp3.Request; +import okhttp3.RequestBody; import okhttp3.Response; +import okhttp3.internal.http.StatusLine; public class RetryHandlerTest { - - int maxRetries = 2; - int retryInterval = 1000; - String testurl = "https://graph.microsoft.com/v1.0/"; + + int maxRetries = 2; + int retryInterval = 1000; + String testmeurl = "https://graph.microsoft.com/v1.0/me"; @Test public void testRetryHandlerCreation() { RetryHandler retryhandler = new RetryHandler(); - assertTrue(retryhandler.getRetryInterval() == retryInterval); + assertNotNull(retryhandler); } - + @Test public void testRetryHandlerWithRetryOptions() { RetryOptions option = new RetryOptions(); RetryHandler retryhandler = new RetryHandler(option); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); - HttpClientContext localContext = HttpClientContext.create(); - assertTrue(retryhandler.retryRequest(response, 1, localContext)); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_GATEWAY_TIMEOUT) + .message("Gateway Timeout") + .request(httpget) + .build(); + assertTrue(retryhandler.retryRequest(response, 1, httpget, option)); } - + @Test public void testRetryHandlerWithCustomRetryOptions() { - RetryOptions option = new RetryOptions(new IShouldRetry() { - public boolean shouldRetry(Response response, int executionCount, HttpContext context) { + IShouldRetry shouldRetry = new IShouldRetry() { + public boolean shouldRetry(Response response, int executionCount, Request request, long delay){ return false; } - }); + }; + RetryOptions option = new RetryOptions(shouldRetry, 5, 0); RetryHandler retryhandler = new RetryHandler(option); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); - HttpClientContext localContext = HttpClientContext.create(); - assertTrue(!retryhandler.retryRequest(response, 1, localContext)); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_GATEWAY_TIMEOUT) + .message("Gateway Timeout") + .request(httpget) + .build(); + assertTrue(!retryhandler.retryRequest(response, 0, httpget, option)); } - + @Test public void testRetryRequestWithMaxRetryAttempts() { RetryHandler retryhandler = new RetryHandler(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); - HttpClientContext localContext = HttpClientContext.create(); - assertFalse(retryhandler.retryRequest(response, 3, localContext)); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_GATEWAY_TIMEOUT) + .message("Gateway Timeout") + .request(httpget) + .build(); + // Default retry options with Number of maxretries default to 3 + RetryOptions retryOptions = new RetryOptions(); + // Try to execute one more than allowed default max retries + int executionCount = RetryOptions.DEFAULT_MAX_RETRIES + 1; + assertFalse(retryhandler.retryRequest(response, executionCount, httpget, retryOptions)); } - + @Test public void testRetryRequestForStatusCode() { RetryHandler retryhandler = new RetryHandler(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_INTERNAL_SERVER_ERROR, "Internal Server Error"); - HttpClientContext localContext = HttpClientContext.create(); - assertFalse(retryhandler.retryRequest(response, 1, localContext)); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + // For status code 500 which is not in (429 503 504), So NO retry + .code(HttpURLConnection.HTTP_SERVER_ERROR) + .message( "Internal Server Error") + .request(httpget) + .build(); + assertFalse(retryhandler.retryRequest(response, 1, httpget, new RetryOptions())); } - + @Test public void testRetryRequestWithTransferEncoding() { RetryHandler retryhandler = new RetryHandler(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); - response.setHeader("Transfer-Encoding", "chunked"); - Request httppost = new Request.Builder().url(testurl).build(); - - try { - HttpEntity entity = new StringEntity("TEST"); - httppost.setEntity(entity); - HttpClientContext localContext = HttpClientContext.create(); - localContext.setAttribute(HttpCoreContext.HTTP_REQUEST, httppost); - assertFalse(retryhandler.retryRequest(response, 1, localContext)); - - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - fail("Retry handler testRetryHandlerRetryRequest3 test failure"); - } + Request httppost = new Request.Builder().url(testmeurl).post(RequestBody.create(MediaType.parse("application/json"), "TEST")).build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_GATEWAY_TIMEOUT) + .message( "gateway timeout") + .request(httppost) + .addHeader("Transfer-Encoding", "chunked") + .build(); + assertTrue(retryhandler.retryRequest(response, 1, httppost, new RetryOptions())); } - + @Test public void testRetryRequestWithExponentialBackOff() { RetryHandler retryhandler = new RetryHandler(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); - Request httppost = new Request.Builder().url(testurl).build(); - - try { - HttpEntity entity = new StringEntity("TEST"); - httppost.setEntity(entity); - HttpClientContext localContext = HttpClientContext.create(); - localContext.setAttribute(HttpCoreContext.HTTP_REQUEST, httppost); - assertTrue(retryhandler.retryRequest(response, 1, localContext)); - assertTrue(retryhandler.getRetryInterval() == 2000); - - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - fail("Retry handler testRetryHandlerRetryRequest3 test failure"); - } - } - - @Test - public void testRetryHandlerRetryRequestWithRetryAfterHeader() { - RetryHandler retryhandler = new RetryHandler(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); - response.setHeader("Retry-After", "100"); - Request httppost = new Request.Builder().url(testurl).build(); + Request httppost = new Request.Builder().url(testmeurl).post(RequestBody.create(MediaType.parse("application/json"), "TEST")).build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_GATEWAY_TIMEOUT) + .message( "gateway timeout") + .request(httppost) + .addHeader("Transfer-Encoding", "chunked") + .build(); - try { - HttpEntity entity = new StringEntity("TEST"); - httppost.setEntity(entity); - HttpClientContext localContext = HttpClientContext.create(); - localContext.setAttribute(HttpCoreContext.HTTP_REQUEST, httppost); - assertTrue(retryhandler.retryRequest(response, 1, localContext)); - assertTrue(retryhandler.getRetryInterval() == 100); - - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - fail("Retry handler testRetryHandlerRetryRequestWithRetryAfterHeader test failure"); - } + assertTrue(retryhandler.retryRequest(response, 1, httppost, new RetryOptions())); } - } From 339089f88acffb27b4355f8ca4e86bf8a3aa4ceb Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Fri, 8 Mar 2019 11:14:03 +0530 Subject: [PATCH 33/38] Added comments and removed suppressed warning --- .../graph/content/MSBatchRequestContent.java | 61 +++++++-- .../graph/content/MSBatchResponseContent.java | 86 ++++++++++++- .../microsoft/graph/httpcore/HttpClients.java | 5 + .../httpcore/IAuthenticationProvider.java | 1 + .../graph/httpcore/RedirectHandler.java | 4 +- .../graph/httpcore/RequestSerializer.java | 117 ------------------ .../graph/httpcore/RetryHandler.java | 1 - .../content/MSBatchResponseContentTest.java | 2 +- .../graph/httpcore/RetryHandlerTest.java | 7 +- 9 files changed, 143 insertions(+), 141 deletions(-) delete mode 100644 src/main/java/com/microsoft/graph/httpcore/RequestSerializer.java diff --git a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java index 877a6ecca..2fd7c5c9a 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java @@ -7,17 +7,25 @@ import org.json.simple.JSONArray; import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; -import com.microsoft.graph.httpcore.RequestSerializer; - import okhttp3.Headers; +import okhttp3.Request; import okhttp3.RequestBody; +import okio.Buffer; public class MSBatchRequestContent { private Map batchRequestStepsHashMap; + + // Maximum number of requests that can be sent in a batch public static final int MAX_NUMBER_OF_REQUESTS = 20; + /* + * Creates Batch request content using list provided + * + * @param batchRequestStepsArray List of batch steps for batching + */ public MSBatchRequestContent(List batchRequestStepsArray) { if(batchRequestStepsArray.size() > MAX_NUMBER_OF_REQUESTS) throw new IllegalArgumentException("Number of batch request steps cannot exceed " + MAX_NUMBER_OF_REQUESTS); @@ -27,10 +35,17 @@ public MSBatchRequestContent(List batchRequestStepsArray) { addBatchRequestStep(requestStep); } + /* + * Creates empty batch request content + */ public MSBatchRequestContent() { batchRequestStepsHashMap = new HashMap(); } + /* + * @param batchRequestStep Batch request step adding to batch content + * @return true or false based on addition or no addition of batch request step given + */ public boolean addBatchRequestStep(MSBatchRequestStep batchRequestStep) { if(batchRequestStepsHashMap.containsKey(batchRequestStep.getRequestId())) return false; @@ -38,20 +53,25 @@ public boolean addBatchRequestStep(MSBatchRequestStep batchRequestStep) { return true; } + /* + * @param requestId Id of Batch request step to be removed + * @return true or false based on removal or no removal of batch request step with given id + */ public boolean removeBatchRequestStepWithId(String requestId) { boolean removed = false; if(batchRequestStepsHashMap.containsKey(requestId)) { batchRequestStepsHashMap.remove(requestId); removed = true; - } - for(Map.Entry steps : batchRequestStepsHashMap.entrySet()) { - while(steps.getValue().getArrayOfDependsOnIds().remove(requestId)) - removed = true; + for(Map.Entry steps : batchRequestStepsHashMap.entrySet()) { + while(steps.getValue().getArrayOfDependsOnIds().remove(requestId)); + } } return removed; } - @SuppressWarnings("unchecked") + /* + * @return Batch request content's json as String + */ public String getBatchRequestContent() { JSONObject batchRequestContentMap = new JSONObject(); JSONArray batchContentArray = new JSONArray(); @@ -60,11 +80,10 @@ public String getBatchRequestContent() { } batchRequestContentMap.put("requests", batchContentArray); - String content = batchRequestContentMap.toString(); + String content = batchRequestContentMap.toString(); return content; } - @SuppressWarnings("unchecked") private JSONObject getBatchRequestObjectFromRequestStep(final MSBatchRequestStep batchRequestStep){ JSONObject contentmap = new JSONObject(); contentmap.put("id", batchRequestStep.getRequestId()); @@ -82,7 +101,7 @@ private JSONObject getBatchRequestObjectFromRequestStep(final MSBatchRequestStep if(headers != null && headers.size() != 0) { JSONObject headerMap = new JSONObject(); for(Map.Entry> entry : headers.toMultimap().entrySet()) { - headerMap.put(entry.getKey(), RequestSerializer.getHeaderValuesAsString(entry.getValue())); + headerMap.put(entry.getKey(), getHeaderValuesAsString(entry.getValue())); } contentmap.put("headers", headerMap); } @@ -97,7 +116,7 @@ private JSONObject getBatchRequestObjectFromRequestStep(final MSBatchRequestStep RequestBody body = batchRequestStep.getRequest().body(); if(body != null) { try { - contentmap.put("body", RequestSerializer.requestBodyToJSONObject(batchRequestStep.getRequest())); + contentmap.put("body", requestBodyToJSONObject(batchRequestStep.getRequest())); }catch(IOException | ParseException e) { e.printStackTrace(); } @@ -105,4 +124,24 @@ private JSONObject getBatchRequestObjectFromRequestStep(final MSBatchRequestStep return contentmap; } + private String getHeaderValuesAsString(final List list) { + if(list == null || list.size() == 0)return ""; + StringBuilder builder = new StringBuilder(list.get(0)); + for(int i=1;i batchRequestsHashMap; private JSONArray batchResponseArray; + /* + * @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 = RequestSerializer.createBatchRequestsHashMap(batchResponse); + this.batchRequestsHashMap = createBatchRequestsHashMap(batchResponse); this.batchResponse = batchResponse; if(batchResponse.body() != null) { try { String batchResponseData = batchResponse.body().string(); if(batchResponseData != null) { - batchResponseObj = RequestSerializer.stringToJSONObject(batchResponseData); + batchResponseObj = stringToJSONObject(batchResponseData); if(batchResponseObj != null) { batchResponseArray = (JSONArray)batchResponseObj.get("responses"); } @@ -41,6 +47,12 @@ public MSBatchResponseContent(Response batchResponse) { } } + /* + * Returns OkHttp Response of given request Id + * + * @param requestId Request Id of batch step + * @return OkHttp Response corresponding to requestId + */ public Response getResponseById(String requestId) { if(batchResponseObj == null) return null; @@ -107,4 +119,70 @@ public String nextLink() { Object nextLinkObject = batchResponseObj.get("nextLink"); return nextLinkObject != null ? ((JSONObject)nextLinkObject).toString() : null; } + + private Map createBatchRequestsHashMap(Response batchResponse) { + if(batchResponse == null)return null; + try { + Map batchRequestsHashMap = new HashMap<>(); + JSONObject requestJSONObject = requestBodyToJSONObject(batchResponse.request()); + JSONArray requestArray = (JSONArray)requestJSONObject.get("requests"); + for(Object item : requestArray) { + JSONObject requestObject = (JSONObject)item; + + Request.Builder builder = new Request.Builder(); + + if(requestObject.get("url") != null) { + StringBuilder fullUrl = new StringBuilder(batchResponse.request().url().toString().replace("$batch","")); + fullUrl.append(requestObject.get("url").toString()); + builder.url(fullUrl.toString()); + } + if(requestObject.get("headers") != null) { + JSONObject jsonheaders = (JSONObject)requestObject.get("headers"); + for(Object key: jsonheaders.keySet()) { + String strkey = (String)key; + String strvalue = (String)jsonheaders.get(strkey); + for(String value : strvalue.split("; ")) { + builder.header(strkey, value); + } + } + } + if(requestObject.get("body") != null) { + JSONObject jsonObject = (JSONObject)requestObject.get("body"); + String bodyAsString = jsonObject.toJSONString(); + RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), bodyAsString); + builder.method(requestObject.get("method").toString(), requestBody); + } else { + builder.method(requestObject.get("method").toString(), null); + } + batchRequestsHashMap.put(requestObject.get("id").toString(), builder.build()); + } + return batchRequestsHashMap; + + } catch (IOException | ParseException e) { e.printStackTrace(); } + return null; + } + + private JSONObject stringToJSONObject(String input) { + JSONParser parser = new JSONParser(); + JSONObject jsonObject = null; + try { + if(input != null) { + jsonObject = (JSONObject) parser.parse(input); + } + } + catch(Exception e) { + e.printStackTrace(); + } + return jsonObject; + } + + private JSONObject requestBodyToJSONObject(final Request request) throws IOException, ParseException{ + if(request == null || request.body() == null)return null; + Request copy = request.newBuilder().build(); + Buffer buffer = new Buffer(); + copy.body().writeTo(buffer); + String requestBody = buffer.readUtf8(); + JSONObject jsonObject = (JSONObject)new JSONParser().parse(requestBody); + return jsonObject; + } } diff --git a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java index 376f8a660..cb646987b 100644 --- a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java +++ b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java @@ -11,6 +11,8 @@ private HttpClients() { /** * Creates builder object for construction of custom * {@link OkHttpClient} instances. + * + * @return OkHttpClient.Builder() custom builder for developer to add its own interceptors to it */ public static Builder custom() { return new OkHttpClient.Builder(); @@ -19,6 +21,9 @@ public static Builder custom() { /** * Creates {@link OkHttpClient} instance with default * configuration and provided authProvider + * + * @param auth Use IAuthenticationProvider instance provided while constructing http client + * @return OkHttpClient build with authentication provider given, default redirect and default retry handlers */ public static OkHttpClient createDefault(IAuthenticationProvider auth) { return new OkHttpClient.Builder().addInterceptor(new AuthenticationHandler(auth)) diff --git a/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java b/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java index 10c64a6f7..37bcd6554 100644 --- a/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java +++ b/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java @@ -7,6 +7,7 @@ public interface IAuthenticationProvider { * Authenticates the request * * @param request the request to authenticate + * @return Request with Authorization header added to it */ Request authenticateRequest(Request request); } diff --git a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java index 927ed873e..97920635d 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java @@ -40,7 +40,7 @@ public RedirectHandler(RedirectOptions redirectOptions) { } } - public boolean isRedirected(Request request, Response response, int redirectCount, RedirectOptions redirectOptions) throws IOException { + boolean isRedirected(Request request, Response response, int redirectCount, RedirectOptions redirectOptions) throws IOException { // Check max count of redirects reached if(redirectCount > redirectOptions.maxRedirects()) return false; @@ -61,7 +61,7 @@ public boolean isRedirected(Request request, Response response, int redirectCoun return false; } - public Request getRedirect( + Request getRedirect( final Request request, final Response userResponse) throws ProtocolException { String location = userResponse.header("Location"); diff --git a/src/main/java/com/microsoft/graph/httpcore/RequestSerializer.java b/src/main/java/com/microsoft/graph/httpcore/RequestSerializer.java deleted file mode 100644 index 917159d38..000000000 --- a/src/main/java/com/microsoft/graph/httpcore/RequestSerializer.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.microsoft.graph.httpcore; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; - -import okhttp3.MediaType; -import okhttp3.Protocol; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; -import okhttp3.ResponseBody; -import okio.Buffer; - -public class RequestSerializer { - - public static Map createBatchRequestsHashMap(Response batchResponse) { - if(batchResponse == null)return null; - try { - Map batchRequestsHashMap = new HashMap<>(); - JSONObject requestJSONObject = requestBodyToJSONObject(batchResponse.request()); - JSONArray requestArray = (JSONArray)requestJSONObject.get("requests"); - for(Object item : requestArray) { - JSONObject requestObject = (JSONObject)item; - - Request.Builder builder = new Request.Builder(); - - if(requestObject.get("url") != null) { - StringBuilder fullUrl = new StringBuilder(batchResponse.request().url().toString().replace("$batch","")); - fullUrl.append(requestObject.get("url").toString()); - builder.url(fullUrl.toString()); - } - if(requestObject.get("headers") != null) { - JSONObject jsonheaders = (JSONObject)requestObject.get("headers"); - for(Object key: jsonheaders.keySet()) { - String strkey = (String)key; - String strvalue = (String)jsonheaders.get(strkey); - for(String value : strvalue.split("; ")) { - builder.header(strkey, value); - } - } - } - if(requestObject.get("body") != null) { - JSONObject jsonObject = (JSONObject)requestObject.get("body"); - String bodyAsString = jsonObject.toJSONString(); - RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), bodyAsString); - builder.method(requestObject.get("method").toString(), requestBody); - } else { - builder.method(requestObject.get("method").toString(), null); - } - batchRequestsHashMap.put(requestObject.get("id").toString(), builder.build()); - } - return batchRequestsHashMap; - - } catch (IOException | ParseException e) { e.printStackTrace(); } - return null; - } - - /* - * Convert request body to JSONObject - */ - public static JSONObject requestToJSONObject(final Request request) throws IOException, ParseException{ - Request copy = request.newBuilder().build(); - Buffer buffer = new Buffer(); - copy.body().writeTo(buffer); - String body = buffer.readUtf8(); - JSONObject json = (JSONObject)new JSONParser().parse(body); - return json; - } - - /* - * Converts String to JSONObject - */ - public static JSONObject stringToJSONObject(String input) { - JSONParser parser = new JSONParser(); - JSONObject jsonObject = null; - try { - if(input != null) { - jsonObject = (JSONObject) parser.parse(input); - } - } - catch(Exception e) { - e.printStackTrace(); - } - return jsonObject; - } - - /* - * @param list List of parameters of a single header - * @return List of headers to a String seperated by "; " - */ - public static String getHeaderValuesAsString(final List list) { - if(list == null || list.size() == 0)return ""; - StringBuilder builder = new StringBuilder(list.get(0)); - for(int i=1;i Date: Fri, 8 Mar 2019 12:14:41 +0530 Subject: [PATCH 34/38] Changed IAuthenticationProvider to ICoreAuthenticationProvider --- .../com/microsoft/graph/httpcore/AuthenticationHandler.java | 4 ++-- src/main/java/com/microsoft/graph/httpcore/HttpClients.java | 2 +- ...ticationProvider.java => ICoreAuthenticationProvider.java} | 2 +- .../microsoft/graph/httpcore/AuthenticationHandlerTest.java | 2 +- .../java/com/microsoft/graph/httpcore/HttpClientsTest.java | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) rename src/main/java/com/microsoft/graph/httpcore/{IAuthenticationProvider.java => ICoreAuthenticationProvider.java} (85%) diff --git a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java index ad1992eb6..42e9fe304 100644 --- a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java @@ -12,9 +12,9 @@ public class AuthenticationHandler implements Interceptor { public final MiddlewareType MIDDLEWARE_TYPE = MiddlewareType.AUTHENTICATION; - private IAuthenticationProvider authProvider; + private ICoreAuthenticationProvider authProvider; - public AuthenticationHandler(IAuthenticationProvider authProvider) { + public AuthenticationHandler(ICoreAuthenticationProvider authProvider) { this.authProvider = authProvider; } diff --git a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java index cb646987b..4084ae91d 100644 --- a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java +++ b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java @@ -25,7 +25,7 @@ public static Builder custom() { * @param auth Use IAuthenticationProvider instance provided while constructing http client * @return OkHttpClient build with authentication provider given, default redirect and default retry handlers */ - public static OkHttpClient createDefault(IAuthenticationProvider auth) { + public static OkHttpClient createDefault(ICoreAuthenticationProvider auth) { return new OkHttpClient.Builder().addInterceptor(new AuthenticationHandler(auth)) .followRedirects(false) .addInterceptor(new RetryHandler()) diff --git a/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java b/src/main/java/com/microsoft/graph/httpcore/ICoreAuthenticationProvider.java similarity index 85% rename from src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java rename to src/main/java/com/microsoft/graph/httpcore/ICoreAuthenticationProvider.java index 37bcd6554..1ca39a432 100644 --- a/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java +++ b/src/main/java/com/microsoft/graph/httpcore/ICoreAuthenticationProvider.java @@ -2,7 +2,7 @@ import okhttp3.Request; -public interface IAuthenticationProvider { +public interface ICoreAuthenticationProvider { /** * Authenticates the request * diff --git a/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java index e6d6eeea6..7f5feba6f 100644 --- a/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java @@ -14,7 +14,7 @@ public class AuthenticationHandlerTest { static String token = "TEST-TOKEN"; - public static class AuthProvider implements IAuthenticationProvider{ + public static class AuthProvider implements ICoreAuthenticationProvider{ public Request authenticateRequest(Request request) { Request newRequest = request.newBuilder().addHeader("Authorization", "Bearer " + token).build(); return newRequest; diff --git a/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java b/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java index feee259b1..85bb76fd5 100644 --- a/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java @@ -11,7 +11,7 @@ public class HttpClientsTest { @Test public void testHttpClientCreation() { - IAuthenticationProvider authprovider = new IAuthenticationProvider() { + ICoreAuthenticationProvider authprovider = new ICoreAuthenticationProvider() { public Request authenticateRequest(Request request) { Request newRequest = request.newBuilder().addHeader("Authorization", "Bearer " + "TOKEN").build(); return newRequest; From 403c32debfe7916ee560b72da177ab0b8df7cb84 Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Fri, 8 Mar 2019 13:12:09 +0530 Subject: [PATCH 35/38] Edited readme --- readme.md | 66 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/readme.md b/readme.md index 22e38fc0a..6394ae630 100644 --- a/readme.md +++ b/readme.md @@ -1,15 +1,12 @@ # Microsoft Graph Core SDK for Java -[ ![Download](https://api.bintray.com/packages/microsoftgraph/Maven/microsoft-graph/images/download.svg) ](https://bintray.com/microsoftgraph/Maven/microsoft-graph/_latestVersion) - - 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! ## 1. Installation ### 1.1 Install via Gradle -Add the repository and a compile dependency for `microsoft-graph` to your project's `build.gradle`: +Add the repository and a compile dependency for `microsoft-graph-core` to your project's `build.gradle`: ```gradle repository { @@ -70,33 +67,59 @@ Register your application by following the steps at [Register your app with the ### 2.2 Create an IAuthenticationProvider object -An instance of the **GraphServiceClient** class handles building requests, sending them to the Microsoft Graph API, and processing the responses. To create a new instance of this class, you need to provide an instance of `IAuthenticationProvider`, which can authenticate requests to Microsoft Graph. - -For an example of authentication in a client application, see the [MSGraph SDK Android MSA Auth for Android Adapter](https://github.com/microsoftgraph/msgraph-sdk-android-msa-auth-for-android-adapter). +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. -### 2.3 Get a HttpClient object -You must get a **HttpClient** object to make requests against the service. +### 2.3 Get a HttpClients object +You must get a **HttpClients** object to make requests against the service. ```java -CloseableHttpClient httpClient = HttpClients.createDefault(authenticationProvider); +OkHttpClient client = HttpClients.createDefault(iCoreAuthenticationProvider); ``` ## 3. Make requests against the service -After you have a HttpClient that is authenticated, you can begin making calls against the service. The requests against the service look like our [REST API](https://developer.microsoft.com/en-us/graph/docs/concepts/overview). +After you have a HttpClients that is authenticated, you can begin making calls against the service. The requests against the service look like our [REST API](https://developer.microsoft.com/en-us/graph/docs/concepts/overview). -### 3.1 Get the user's drive +### 3.1 Get the user's details + +To retrieve the user's details + +```java +Request request = new Request.Builder().url("https://graph.microsoft.com/v1.0/me/").build(); + +client.newCall(request).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) throws IOException { + String responseBody = response.body().string(); + // Your processing with the response body + } + + @Override + public void onFailure(Call call, IOException e) { + e.printStackTrace(); + } +}); +``` + +### 3.2 Get the user's drive To retrieve the user's drive: ```java -HttpGet httpget = new HttpGet("https://graph.microsoft.com/v1.0/me/"); -try{ - HttpResponse response = httpclient.execute(httpget); - //... -}catch(IOException e){ -//Handle exception -} +Request request = new Request.Builder().url("https://graph.microsoft.com/v1.0/me/drive").build(); + +client.newCall(request).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) throws IOException { + String responseBody = response.body().string(); + // Your processing with the response body + } + + @Override + public void onFailure(Call call, IOException e) { + e.printStackTrace(); + } +}); ``` ## 4. Issues @@ -105,11 +128,12 @@ For known issues, see [issues](https://github.com/MicrosoftGraph/msgraph-sdk-jav ## 5. Contributions -The Microsoft Graph SDK is open for contribution. To contribute to this project, see [Contributing](https://github.com/microsoftgraph/msgraph-sdk-java/blob/master/CONTRIBUTING.md). +The Microsoft Graph SDK is open for contribution. To contribute to this project, see [Contributing](https://github.com/microsoftgraph/msgraph-sdk-java-core/blob/master/CONTRIBUTING.md). -[
Deepak Agrawal](https://github.com/deepak2016)
[💻](https://github.com/microsoftgraph/msgraph-sdk-java/commits?author=deepak2016 "Code") +| [
Deepak Agrawal](https://github.com/deepak2016)
[??](https://github.com/microsoftgraph/msgraph-sdk-java-core/commits?author=deepak2016 "Code") | [
Nakul Sabharwal][??](https://github.com/microsoftgraph/msgraph-sdk-java-core/commits?author=NakulSabharwal "Code") (https://developer.microsoft.com/graph)
[](#question-NakulSabharwal "Answering Questions") [](https://github.com/microsoftgraph/msgraph-sdk-android-auth/commits?author=NakulSabharwal "Code") [](https://github.com/microsoftgraph/msgraph-sdk-android-auth/wiki "Documentation") [](#review-NakulSabharwal "Reviewed Pull Requests") [](https://github.com/microsoftgraph/msgraph-sdk-android-auth/commits?author=NakulSabharwal "Tests")
+| :---: | :---: | This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind are welcome! From 32ef267be4c4beaed6812726a96ef2f6cbe2d004 Mon Sep 17 00:00:00 2001 From: NakulSabharwal Date: Fri, 8 Mar 2019 13:16:36 +0530 Subject: [PATCH 36/38] edited contributor list --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 6394ae630..65c6528c4 100644 --- a/readme.md +++ b/readme.md @@ -132,7 +132,7 @@ The Microsoft Graph SDK is open for contribution. To contribute to this project, -| [
Deepak Agrawal](https://github.com/deepak2016)
[??](https://github.com/microsoftgraph/msgraph-sdk-java-core/commits?author=deepak2016 "Code") | [
Nakul Sabharwal][??](https://github.com/microsoftgraph/msgraph-sdk-java-core/commits?author=NakulSabharwal "Code") (https://developer.microsoft.com/graph)
[](#question-NakulSabharwal "Answering Questions") [](https://github.com/microsoftgraph/msgraph-sdk-android-auth/commits?author=NakulSabharwal "Code") [](https://github.com/microsoftgraph/msgraph-sdk-android-auth/wiki "Documentation") [](#review-NakulSabharwal "Reviewed Pull Requests") [](https://github.com/microsoftgraph/msgraph-sdk-android-auth/commits?author=NakulSabharwal "Tests")
+| [
Deepak Agrawal](https://github.com/deepak2016)
[:computer:](https://github.com/microsoftgraph/msgraph-sdk-java-core/commits?author=deepak2016 "Code") | [
Nakul Sabharwal][:computer:](https://github.com/microsoftgraph/msgraph-sdk-java-core/commits?author=NakulSabharwal "Code")
[](#question-NakulSabharwal "Answering Questions") [](https://github.com/microsoftgraph/msgraph-sdk-android-auth/commits?author=NakulSabharwal "Code") [](https://github.com/microsoftgraph/msgraph-sdk-android-auth/wiki "Documentation") [:clipboard:](#review-NakulSabharwal "Reviewed Pull Requests") [](https://github.com/microsoftgraph/msgraph-sdk-android-auth/commits?author=NakulSabharwal "Tests")
| :---: | :---: | From fbe12a7b8e45498b4086f97f0056abec0af71660 Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Fri, 8 Mar 2019 13:44:26 +0530 Subject: [PATCH 37/38] Added null check on removing id in dependsOn --- .../com/microsoft/graph/content/MSBatchRequestContent.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java index 2fd7c5c9a..5ffa80179 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java @@ -63,7 +63,9 @@ public boolean removeBatchRequestStepWithId(String requestId) { batchRequestStepsHashMap.remove(requestId); removed = true; for(Map.Entry steps : batchRequestStepsHashMap.entrySet()) { - while(steps.getValue().getArrayOfDependsOnIds().remove(requestId)); + if(steps.getValue() != null && steps.getValue().getArrayOfDependsOnIds() != null) { + while(steps.getValue().getArrayOfDependsOnIds().remove(requestId)); + } } } return removed; From e731df3e262012bc492bc1b4eada30ebf3bf66ab Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Fri, 8 Mar 2019 17:25:52 +0530 Subject: [PATCH 38/38] Reordered should retry parameters --- .../graph/content/MSBatchRequestStep.java | 6 +----- .../microsoft/graph/httpcore/RedirectHandler.java | 6 +++--- .../microsoft/graph/httpcore/RetryHandler.java | 15 ++++++++------- .../httpcore/middlewareoption/IShouldRetry.java | 2 +- .../httpcore/middlewareoption/RetryOptions.java | 2 +- .../graph/httpcore/RetryHandlerTest.java | 2 +- 6 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/microsoft/graph/content/MSBatchRequestStep.java b/src/main/java/com/microsoft/graph/content/MSBatchRequestStep.java index 33b5fecf1..7386decf8 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchRequestStep.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchRequestStep.java @@ -14,11 +14,7 @@ public MSBatchRequestStep(String requestId, Request request, List arrayO throw new IllegalArgumentException("Request Id cannot be null."); if(request == null) new IllegalArgumentException("Request cannot be null."); - if(request.url() == null) - throw new IllegalArgumentException("Request url cannot be null."); - if(request.method() == null) - throw new IllegalArgumentException("Request method cannot be null."); - + this.requestId = requestId; this.request = request; this.arrayOfDependsOnIds = arrayOfDependsOnIds; diff --git a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java index 97920635d..dbc866990 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java @@ -27,7 +27,7 @@ public class RedirectHandler implements Interceptor{ * Initialize using default redirect options, default IShouldRedirect and max redirect value */ public RedirectHandler() { - this.mRedirectOptions = new RedirectOptions(); + this(null); } /* @@ -109,8 +109,8 @@ public Response intercept(Chain chain) throws IOException { while(true) { response = chain.proceed(request); - boolean shouldRedirect = redirectOptions.shouldRedirect().shouldRedirect(response) - && isRedirected(request, response, requestsCount, redirectOptions); + boolean shouldRedirect = isRedirected(request, response, requestsCount, redirectOptions) + && redirectOptions.shouldRedirect().shouldRedirect(response); if(!shouldRedirect) break; Request followup = getRedirect(request, response); diff --git a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java index 01f8bb242..5d8b18fc8 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java @@ -56,10 +56,6 @@ boolean retryRequest(Response response, int executionCount, Request request, Ret if(retryOptions != null) { shouldRetryCallback = retryOptions.shouldRetry(); } - // Call should retry callback - if(shouldRetryCallback != null && !shouldRetryCallback.shouldRetry(response, executionCount, request, retryOptions.delay())) { - return false; - } boolean shouldRetry = false; // Status codes 429 503 504 @@ -67,7 +63,11 @@ boolean retryRequest(Response response, int executionCount, Request request, Ret // Only requests with payloads that are buffered/rewindable are supported. // Payloads with forward only streams will be have the responses returned // without any retry attempt. - shouldRetry = (executionCount <= retryOptions.maxRetries()) && checkStatus(statusCode) && isBuffered(response, request); + shouldRetry = + (executionCount <= retryOptions.maxRetries()) + && checkStatus(statusCode) && isBuffered(response, request) + && shouldRetryCallback != null + && shouldRetryCallback.shouldRetry(retryOptions.delay(), executionCount, request, response); if(shouldRetry) { long retryInterval = getRetryAfter(response, retryOptions.delay(), executionCount); @@ -86,8 +86,9 @@ long getRetryAfter(Response response, long delay, int executionCount) { if(retryAfterHeader != null) { retryDelay = Long.parseLong(retryAfterHeader); } else { - retryDelay = (long)Math.pow(2.0, (double)executionCount) * DELAY_MILLISECONDS; + retryDelay = (long)((Math.pow(2.0, (double)executionCount)-1)*0.5); retryDelay = executionCount < 2 ? retryDelay : retryDelay + delay + (long)Math.random(); + retryDelay *= DELAY_MILLISECONDS; } return Math.min(retryDelay, RetryOptions.MAX_DELAY); } @@ -99,7 +100,7 @@ boolean checkStatus(int statusCode) { boolean isBuffered(Response response, Request request) { String methodName = request.method(); - if(methodName.equalsIgnoreCase("GET") || methodName.equalsIgnoreCase("DELETE")) + if(methodName.equalsIgnoreCase("GET") || methodName.equalsIgnoreCase("DELETE") || methodName.equalsIgnoreCase("HEAD") || methodName.equalsIgnoreCase("OPTIONS")) return true; boolean isHTTPMethodPutPatchOrPost = methodName.equalsIgnoreCase("POST") || diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java index 0eeb9b684..249a5ba3e 100644 --- a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java @@ -4,5 +4,5 @@ import okhttp3.Response; public interface IShouldRetry { - boolean shouldRetry(Response response, int executionCount, Request request, long delay); + boolean shouldRetry(long delay, int executionCount, Request request,Response response); } diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java index eb183bd1e..9010122f5 100644 --- a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java @@ -7,7 +7,7 @@ public class RetryOptions implements IMiddlewareControl { private IShouldRetry mShouldretry; public static final IShouldRetry DEFAULT_SHOULD_RETRY = new IShouldRetry() { @Override - public boolean shouldRetry(Response response, int executionCount, Request request, long delay) { + public boolean shouldRetry(long delay, int executionCount, Request request, Response response) { return true; } }; diff --git a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java index 48d5fdf5d..1411eb94a 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java @@ -47,7 +47,7 @@ public void testRetryHandlerWithRetryOptions() { @Test public void testRetryHandlerWithCustomRetryOptions() { IShouldRetry shouldRetry = new IShouldRetry() { - public boolean shouldRetry(Response response, int executionCount, Request request, long delay){ + public boolean shouldRetry(long delay, int executionCount, Request request,Response response){ return false; } };