diff --git a/common/.gitignore b/common/.gitignore
new file mode 100644
index 0000000000000..bfb7f2e650b1d
--- /dev/null
+++ b/common/.gitignore
@@ -0,0 +1,31 @@
+build
+*.class
+target
+gen
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+tmp
+
+# Package Files #
+*.jar
+*.war
+*.ear
+*.MF
+.gitrevision
+.gradle
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+# ide
+.idea
+*.iml
+.DS_Store
+**/temp/
+
+#eclipse
+.project
+.classpath
+.settings
+
diff --git a/common/.travis.yml b/common/.travis.yml
new file mode 100644
index 0000000000000..10c5ba5405405
--- /dev/null
+++ b/common/.travis.yml
@@ -0,0 +1,17 @@
+language: android
+android:
+ components:
+ - build-tools-23.0.1
+ - android-23
+ - platform-tools
+ - extra-android-support
+ - extra-google-m2repository
+ - extra-android-m2repository
+sudo: false
+env:
+- TERM=dumb # Makes Gradle use plain console output
+script:
+- mvn clean install -B -Dstyle.color=always
+- mvn checkstyle:check -B -Dstyle.color=always
+# (ignore android build for now)
+# - cd ./azure-android-client-authentication && ./gradlew check
diff --git a/common/ChangeLog.txt b/common/ChangeLog.txt
new file mode 100644
index 0000000000000..bafac90a6cb73
--- /dev/null
+++ b/common/ChangeLog.txt
@@ -0,0 +1,15 @@
+2.0.0-beta4 (2018-08-06)
+- Added HttpRequest request() property to RestResponse
+- Added isProxyHTTPS() property to HttpClientConfiguration
+
+2.0.0-beta3 (2018-06-26)
+- Added FlowableUtil.ensureLength() operator to better handle cases where the request body had an unexpected size
+
+2.0.0-beta2 (2018-04-23)
+- Major refinements to HTTP content streaming, in large part thanks to contributions by [David Moten](https://github.com/davidmoten).
+- Removed Joda Time in favor of Java 8 DateTime classes
+- NettyClient.Factory now accepts a Netty Bootstrap object allowing for more user configuration of channel attributes, such as the receive buffer size and low/high write watermarks. Currently, specifying an EventLoopGroup or `Class extends Channel>` is not supported.
+- Various other minor improvements
+
+2.0.0-beta1 (2018-03-08)
+- First beta featuring Netty and RxJava 2.
diff --git a/common/LICENSE b/common/LICENSE
new file mode 100644
index 0000000000000..4918d653ba68b
--- /dev/null
+++ b/common/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Microsoft Azure
+
+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.
diff --git a/common/README.md b/common/README.md
new file mode 100644
index 0000000000000..ce52d05ef7290
--- /dev/null
+++ b/common/README.md
@@ -0,0 +1,124 @@
+[![Build Status](https://travis-ci.org/Azure/autorest-clientruntime-for-java.svg?branch=v2)](https://travis-ci.org/Azure/autorest-clientruntime-for-java)
+
+# AutoRest Client Runtimes for Java
+The runtime libraries for [AutoRest](https://github.com/azure/autorest) generated Java clients.
+
+## Usage
+
+### Prerequisites
+
+- JDK 1.8
+
+### Download
+
+```xml
+
+
+
+ com.microsoft.rest.v3
+ client-runtime
+ 2.0.0-beta4
+
+
+
+
+ com.microsoft.azure.v3
+ azure-client-runtime
+ 2.0.0-beta4
+
+
+
+ com.microsoft.azure.v3
+ azure-client-authentication
+ 2.0.0-beta4
+
+
+
+
+
+
+ io.netty
+ netty-tcnative-boringssl-static
+ 2.0.8.Final
+ ${os.detected.classifier}
+
+
+
+
+ io.netty
+ netty-transport-native-epoll
+ 4.1.23.Final
+ ${os.detected.classifier}
+
+
+
+
+ io.netty
+ netty-transport-native-kqueue
+ 4.1.23.Final
+ ${os.detected.classifier}
+
+
+
+
+
+
+
+ kr.motd.maven
+ os-maven-plugin
+ 1.6.0
+
+
+
+```
+
+### Usage
+
+Non-Azure generated clients will have a constructor that takes no arguments for simple scenarios, while Azure generated clients will require a `ServiceClientCredentials` argument at a minimum.
+
+If you want to have more control over configuration, consider using HttpPipeline. This enables performing transformations on all HTTP messages sent by a client, similar to interceptors or filters in other HTTP clients.
+
+You can build an HttpPipeline out of a sequence of RequestPolicyFactories. These policies will get applied in-order to outgoing requests, and then in reverse order for incoming responses. HttpPipelineBuilder includes convenience methods for adding several built-in RequestPolicyFactories, including policies for credentials, logging, response decoding (deserialization), cookies support, and several others.
+
+```java
+// For Java generator
+HttpPipeline pipeline = new HttpPipelineBuilder()
+ .withHostPolicy("http://localhost")
+ .withDecodingPolicy()
+ .build();
+AutoRestJavaClient client = new AutoRestJavaClientImpl(pipeline);
+
+// For Azure.Java generator
+HttpPipeline azurePipeline = new HttpPipelineBuilder()
+ .withCredentialsPolicy(AzureCliCredentials.create())
+ .withHttpLoggingPolicy(HttpLogDetailLevel.HEADERS)
+ .withDecodingPolicy()
+ .build();
+FooServiceClient azureClient = new FooServiceClientImpl(azurePipeline);
+```
+
+## Components
+
+### client-runtime
+This is the generic runtime. Add this package as a dependency if you are using `Java` generator in AutoRest. This package depends on [Netty](https://github.com/netty/netty), [Jackson](http://wiki.fasterxml.com/JacksonHome), and [RxJava](https://github.com/ReactiveX/RxJava) for making and processing REST requests.
+
+### azure-client-runtime
+This is the runtime with Azure Resource Management customizations. Add this package as a dependency if you are using `--azure-arm` or `--azure-arm --fluent` generator flags in AutoRest.
+
+This combination provides a set of Azure specific behaviors, including long running operations, special handling of HEAD operations, and paginated `list()` calls.
+
+### azure-client-authentication (beta)
+This package provides access to Active Directory authentication on JDK using OrgId or application ID / secret combinations. There are currently 3 types of authentication provided:
+
+- Service principal authentication: `ApplicationTokenCredentials`
+- Username / password login without multi-factor auth: `UserTokenCredentials`
+- Use the credentials logged in [Azure CLI](https://github.com/azure/azure-cli): `AzureCliCredentials`
+
+### azure-android-client-authentication (beta)
+This package provides access to Active Directory authentication on Android. You can login with Microsoft accounts, OrgId, with or without multi-factor auth.
+
+## Build
+To build this repository, you will need maven 2.0+ and gradle 1.6+.
+
+## Contributing
+This repository is for runtime & authentication specifically. For issues in the generated code, please report in [AutoRest](https://github.com/Azure/autorest). For bugs in the Azure SDK, please report in [Azure SDK for Java](https://github.com/Azure/azure-sdk-for-java). If you are unsure, please file here and state that clearly in the issue. Pull requests are welcomed with clear Javadocs.
diff --git a/common/azure-android-client-authentication/build.gradle b/common/azure-android-client-authentication/build.gradle
new file mode 100644
index 0000000000000..b93e53c502be0
--- /dev/null
+++ b/common/azure-android-client-authentication/build.gradle
@@ -0,0 +1,117 @@
+buildscript {
+ repositories {
+ mavenCentral()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.3.0'
+ }
+}
+
+apply plugin: 'com.android.library'
+apply plugin: 'maven'
+
+android {
+ compileSdkVersion 23
+ buildToolsVersion "23.0.1"
+
+ defaultConfig {
+ minSdkVersion 15
+ targetSdkVersion 23
+ versionCode 1
+ versionName "1.0.0-beta6-SNAPSHOT"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_7
+ targetCompatibility JavaVersion.VERSION_1_7
+ }
+
+ lintOptions {
+ abortOnError false
+ }
+}
+
+configurations {
+ deployerJars
+}
+
+repositories {
+ mavenCentral()
+ maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ compile 'com.android.support:appcompat-v7:23.0.1'
+ compile 'com.microsoft.aad:adal:1.1.11'
+ compile 'com.microsoft.azure:azure-client-runtime:1.0.0-beta2'
+ testCompile 'junit:junit:4.12'
+ testCompile 'junit:junit-dep:4.11'
+ deployerJars "org.apache.maven.wagon:wagon-ftp:2.10"
+}
+
+uploadArchives {
+ repositories {
+ mavenDeployer {
+ configuration = configurations.deployerJars
+ snapshotRepository(url: "ftp://waws-prod-bay-005.ftp.azurewebsites.windows.net/site/wwwroot/") {
+ authentication(userName: username, password: password)
+ }
+ repository(url: "file://$buildDir/repository")
+ pom.setArtifactId "azure-android-client-authentication"
+ pom.project {
+ name 'Microsoft Azure AutoRest Authentication Library for Java'
+ description 'This is the authentication library for AutoRest generated Azure Java clients.'
+ url 'https://github.com/Azure/autorest'
+
+ scm {
+ url 'scm:git:https://github.com/Azure/AutoRest'
+ connection 'scm:git:git://github.com/Azure/AutoRest.git'
+ }
+
+ licenses {
+ license {
+ name 'The MIT License (MIT)'
+ url 'http://opensource.org/licenses/MIT'
+ distribution 'repo'
+ }
+ }
+
+ developers {
+ developer {
+ id 'microsoft'
+ name 'Microsoft'
+ }
+ }
+ }
+ }
+ }
+}
+
+task sourcesJar(type: Jar) {
+ from android.sourceSets.main.java.srcDirs
+ classifier = 'sources'
+}
+
+task javadoc(type: Javadoc) {
+ source = android.sourceSets.main.java.srcDirs
+ classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
+ options.encoding = 'UTF-8'
+}
+
+task javadocJar(type: Jar, dependsOn: [javadoc]) {
+ classifier = 'javadoc'
+ from javadoc.destinationDir
+}
+
+artifacts {
+ archives sourcesJar
+ archives javadocJar
+}
diff --git a/common/azure-android-client-authentication/gradle.properties b/common/azure-android-client-authentication/gradle.properties
new file mode 100644
index 0000000000000..7311d1b56e3bb
--- /dev/null
+++ b/common/azure-android-client-authentication/gradle.properties
@@ -0,0 +1,2 @@
+username = fake
+password = fake
\ No newline at end of file
diff --git a/common/azure-android-client-authentication/gradle/wrapper/gradle-wrapper.jar b/common/azure-android-client-authentication/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000000..05ef575b0cd01
Binary files /dev/null and b/common/azure-android-client-authentication/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/common/azure-android-client-authentication/gradle/wrapper/gradle-wrapper.properties b/common/azure-android-client-authentication/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000000..3ae0abbd2b66d
--- /dev/null
+++ b/common/azure-android-client-authentication/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Nov 11 13:21:00 PST 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-bin.zip
diff --git a/common/azure-android-client-authentication/gradlew b/common/azure-android-client-authentication/gradlew
new file mode 100755
index 0000000000000..9d82f78915133
--- /dev/null
+++ b/common/azure-android-client-authentication/gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# 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
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# 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
+
+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" ] ; 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
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/common/azure-android-client-authentication/gradlew.bat b/common/azure-android-client-authentication/gradlew.bat
new file mode 100644
index 0000000000000..f4c57b05d5739
--- /dev/null
+++ b/common/azure-android-client-authentication/gradlew.bat
@@ -0,0 +1,90 @@
+@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
+
+@rem Add default JVM pipelineOptions here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM pipelineOptions to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@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 Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_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=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+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/common/azure-android-client-authentication/proguard-rules.pro b/common/azure-android-client-authentication/proguard-rules.pro
new file mode 100644
index 0000000000000..51508f487ebc5
--- /dev/null
+++ b/common/azure-android-client-authentication/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in E:\Users\jianghlu\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/common/azure-android-client-authentication/src/main/AndroidManifest.xml b/common/azure-android-client-authentication/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000000..281c2ce4932ba
--- /dev/null
+++ b/common/azure-android-client-authentication/src/main/AndroidManifest.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/common/azure-android-client-authentication/src/main/java/com/microsoft/azure/credentials/AzureEnvironment.java b/common/azure-android-client-authentication/src/main/java/com/microsoft/azure/credentials/AzureEnvironment.java
new file mode 100644
index 0000000000000..ddb02625b0399
--- /dev/null
+++ b/common/azure-android-client-authentication/src/main/java/com/microsoft/azure/credentials/AzureEnvironment.java
@@ -0,0 +1,85 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.credentials;
+
+/**
+ * An instance of this class describes an environment in Azure.
+ */
+public final class AzureEnvironment {
+ /**
+ * ActiveDirectory Endpoint for the Azure Environment.
+ */
+ private String authenticationEndpoint;
+ /**
+ * Token audience for an endpoint.
+ */
+ private String tokenAudience;
+ /**
+ * Determines whether the authentication endpoint should
+ * be validated with Azure AD. Default value is true.
+ */
+ private boolean validateAuthority;
+
+ /**
+ * Initializes an instance of AzureEnvironment class.
+ *
+ * @param authenticationEndpoint ActiveDirectory Endpoint for the Azure Environment.
+ * @param tokenAudience token audience for an endpoint.
+ * @param validateAuthority whether the authentication endpoint should
+ * be validated with Azure AD.
+ */
+ public AzureEnvironment(String authenticationEndpoint, String tokenAudience, boolean validateAuthority) {
+ this.authenticationEndpoint = authenticationEndpoint;
+ this.tokenAudience = tokenAudience;
+ this.validateAuthority = validateAuthority;
+ }
+
+ /**
+ * Provides the settings for authentication with Azure.
+ */
+ public static final AzureEnvironment AZURE = new AzureEnvironment(
+ "https://login.windows.net/",
+ "https://management.core.windows.net/",
+ true);
+
+ /**
+ * Provides the settings for authentication with Azure China.
+ */
+ public static final AzureEnvironment AZURE_CHINA = new AzureEnvironment(
+ "https://login.chinacloudapi.cn/",
+ "https://management.core.chinacloudapi.cn/",
+ true);
+
+ /**
+ * Gets the ActiveDirectory Endpoint for the Azure Environment.
+ *
+ * @return the ActiveDirectory Endpoint for the Azure Environment.
+ */
+ public String getAuthenticationEndpoint() {
+ return authenticationEndpoint;
+ }
+
+ /**
+ * Gets the token audience for an endpoint.
+ *
+ * @return the token audience for an endpoint.
+ */
+ public String getTokenAudience() {
+ return tokenAudience;
+ }
+
+ /**
+ * Gets whether the authentication endpoint should
+ * be validated with Azure AD.
+ *
+ * @return true if the authentication endpoint should be validated with
+ * Azure AD, false otherwise.
+ */
+ public boolean isValidateAuthority() {
+ return validateAuthority;
+ }
+}
diff --git a/common/azure-android-client-authentication/src/main/java/com/microsoft/azure/credentials/UserTokenCredentials.java b/common/azure-android-client-authentication/src/main/java/com/microsoft/azure/credentials/UserTokenCredentials.java
new file mode 100644
index 0000000000000..95d0c14f12f54
--- /dev/null
+++ b/common/azure-android-client-authentication/src/main/java/com/microsoft/azure/credentials/UserTokenCredentials.java
@@ -0,0 +1,189 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.microsoft.azure.credentials;
+
+import android.app.Activity;
+
+import com.microsoft.aad.adal.AuthenticationCallback;
+import com.microsoft.aad.adal.AuthenticationContext;
+import com.microsoft.aad.adal.AuthenticationResult;
+import com.microsoft.aad.adal.DefaultTokenCacheStore;
+import com.microsoft.aad.adal.PromptBehavior;
+import com.microsoft.rest.credentials.TokenCredentials;
+
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.util.concurrent.CountDownLatch;
+
+import javax.crypto.NoSuchPaddingException;
+
+/**
+ * Token based credentials for use with a REST Service Client.
+ */
+public class UserTokenCredentials extends TokenCredentials {
+ /** The Active Directory application client id. */
+ private String clientId;
+ /** The domain or tenant id containing this application. */
+ private String domain;
+ /** The Uri where the user will be redirected after authenticating with AD. */
+ private String clientRedirectUri;
+ /** The Azure environment to authenticate with. */
+ private AzureEnvironment environment;
+ /** The caller activity. */
+ private Activity activity;
+ /** The count down latch to synchronize token acquisition. */
+ private CountDownLatch signal = new CountDownLatch(1);
+ /** The static token cache. */
+ private static DefaultTokenCacheStore tokenCacheStore;
+ /** The behavior of when to prompt a login. */
+ private PromptBehavior promptBehavior;
+
+ /**
+ * Initializes a new instance of the UserTokenCredentials.
+ *
+ * @param activity The caller activity.
+ * @param clientId the active directory application client id.
+ * @param domain the domain or tenant id containing this application.
+ * @param clientRedirectUri the Uri where the user will be redirected after authenticating with AD.
+ */
+ public UserTokenCredentials(
+ Activity activity,
+ String clientId,
+ String domain,
+ String clientRedirectUri) {
+ this(activity, clientId, domain, clientRedirectUri, PromptBehavior.Auto, AzureEnvironment.AZURE);
+ }
+
+ /**
+ * Initializes a new instance of the UserTokenCredentials.
+ *
+ * @param activity The caller activity.
+ * @param clientId the active directory application client id.
+ * @param domain the domain or tenant id containing this application.
+ * @param clientRedirectUri the Uri where the user will be redirected after authenticating with AD.
+ * @param promptBehavior the behavior of when to prompt a login.
+ * @param environment the Azure environment to authenticate with.
+ * If null is provided, AzureEnvironment.AZURE will be used.
+ */
+ public UserTokenCredentials(
+ Activity activity,
+ String clientId,
+ String domain,
+ String clientRedirectUri,
+ PromptBehavior promptBehavior,
+ AzureEnvironment environment) {
+ super(null, null); // defer token acquisition
+ this.clientId = clientId;
+ this.domain = domain;
+ this.clientRedirectUri = clientRedirectUri;
+ this.activity = activity;
+ this.promptBehavior = promptBehavior;
+ this.environment = environment;
+ if (tokenCacheStore == null) {
+ try {
+ tokenCacheStore = new DefaultTokenCacheStore(activity);
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+ tokenCacheStore = null;
+ }
+ }
+ }
+
+ /**
+ * Clear the items stored in token cache.
+ */
+ public static void clearTokenCache() {
+ tokenCacheStore.removeAll();
+ }
+
+ /**
+ * Gets the active directory application client id.
+ *
+ * @return the active directory application client id.
+ */
+ public String getClientId() {
+ return clientId;
+ }
+
+ /**
+ * Gets the tenant or domain containing the application.
+ *
+ * @return the tenant or domain containing the application.
+ */
+ public String getDomain() {
+ return domain;
+ }
+
+ /**
+ * Sets the tenant of domain containing the application.
+ *
+ * @param domain the tenant or domain containing the application.
+ */
+ public void setDomain(String domain) {
+ this.domain = domain;
+ }
+
+ /**
+ * Gets the Uri where the user will be redirected after authenticating with AD.
+ *
+ * @return the redirecting Uri.
+ */
+ public String getClientRedirectUri() {
+ return clientRedirectUri;
+ }
+
+ /**
+ * Gets the Azure environment to authenticate with.
+ *
+ * @return the Azure environment to authenticate with.
+ */
+ public AzureEnvironment getEnvironment() {
+ return environment;
+ }
+
+ @Override
+ public String getToken() throws IOException {
+ refreshToken();
+ return token;
+ }
+
+ @Override
+ public void refreshToken() throws IOException {
+ acquireAccessToken();
+ }
+
+ private void acquireAccessToken() throws IOException {
+ final String authorityUrl = this.getEnvironment().getAuthenticationEndpoint() + this.getDomain();
+ AuthenticationContext context = new AuthenticationContext(activity, authorityUrl, true, tokenCacheStore);
+ final UserTokenCredentials self = this;
+ context.acquireToken(
+ this.getEnvironment().getTokenAudience(),
+ this.getClientId(),
+ this.getClientRedirectUri(),
+ null,
+ promptBehavior,
+ null,
+ new AuthenticationCallback() {
+ @Override
+ public void onSuccess(AuthenticationResult authenticationResult) {
+ if (authenticationResult != null && authenticationResult.getAccessToken() != null) {
+ self.setToken(authenticationResult.getAccessToken());
+ signal.countDown();
+ } else {
+ onError(new IOException("Failed to acquire access token"));
+ }
+ }
+
+ @Override
+ public void onError(Exception e) {
+ signal.countDown();
+ }
+ });
+ try {
+ signal.await();
+ } catch (InterruptedException e) { /* Ignore */ }
+ }
+}
diff --git a/common/azure-android-client-authentication/src/main/java/com/microsoft/azure/credentials/package-info.java b/common/azure-android-client-authentication/src/main/java/com/microsoft/azure/credentials/package-info.java
new file mode 100644
index 0000000000000..2f23671d5be16
--- /dev/null
+++ b/common/azure-android-client-authentication/src/main/java/com/microsoft/azure/credentials/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * The package provides 2 credential classes that work with AutoRest
+ * generated Azure clients for authentication purposes through Azure.
+ */
+package com.microsoft.azure.credentials;
\ No newline at end of file
diff --git a/common/azure-android-client-authentication/src/main/res/values/strings.xml b/common/azure-android-client-authentication/src/main/res/values/strings.xml
new file mode 100644
index 0000000000000..e2639a86a6c96
--- /dev/null
+++ b/common/azure-android-client-authentication/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ azure-android-client-authentication
+
diff --git a/common/azure-common-auth/pom.xml b/common/azure-common-auth/pom.xml
new file mode 100644
index 0000000000000..df55011eea293
--- /dev/null
+++ b/common/azure-common-auth/pom.xml
@@ -0,0 +1,104 @@
+
+
+ 4.0.0
+
+ com.azure
+ azure-common-parent
+ 1.0.0-SNAPSHOT
+ ../pom.xml
+
+
+ com.azure
+ azure-common-auth
+ jar
+ 1.0.0-SNAPSHOT
+
+ Azure Authentication Java Common Library
+ This package contains the authentication connectors to Active Directory for Azure Java Clients.
+ https://github.com/Azure/autorest-clientruntime-for-java
+
+
+
+ The MIT License (MIT)
+ http://opensource.org/licenses/MIT
+ repo
+
+
+
+
+ scm:git:https://github.com/Azure/autorest-clientruntime-for-java
+ scm:git:git@github.com:Azure/autorest-clientruntime-for-java.git
+ HEAD
+
+
+
+ UTF-8
+
+
+
+
+
+ microsoft
+ Microsoft
+
+
+
+
+
+ com.azure
+ azure-common
+ 1.0.0-SNAPSHOT
+
+
+ com.microsoft.azure
+ adal4j
+
+
+ junit
+ junit
+ test
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.1
+
+
+ 1.8
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 2.8
+
+ *.implementation.*;*.utils.*;com.microsoft.schemas._2003._10.serialization;*.blob.core.storage
+ /**
+
* Copyright (c) Microsoft Corporation. All rights reserved.
+
* Licensed under the MIT License. See License.txt in the project root for
+
* license information.
+
*/]]>
+
+
+
+
+
+
diff --git a/common/azure-common-auth/src/main/java/com/azure/common/auth/credentials/ApplicationTokenCredentials.java b/common/azure-common-auth/src/main/java/com/azure/common/auth/credentials/ApplicationTokenCredentials.java
new file mode 100644
index 0000000000000..1b6b1f9034d3b
--- /dev/null
+++ b/common/azure-common-auth/src/main/java/com/azure/common/auth/credentials/ApplicationTokenCredentials.java
@@ -0,0 +1,181 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.azure.common.auth.credentials;
+
+import com.microsoft.aad.adal4j.AsymmetricKeyCredential;
+import com.microsoft.aad.adal4j.AuthenticationContext;
+import com.microsoft.aad.adal4j.AuthenticationException;
+import com.microsoft.aad.adal4j.AuthenticationResult;
+import com.microsoft.aad.adal4j.ClientCredential;
+import com.azure.common.AzureEnvironment;
+import reactor.core.Exceptions;
+import reactor.core.publisher.Mono;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Token based credentials for use with a REST Service Client.
+ */
+public class ApplicationTokenCredentials extends AzureTokenCredentials {
+ /** A mapping from resource endpoint to its cached access token. */
+ private Map tokens;
+ /** The active directory application client id. */
+ private String clientId;
+ /** The authentication secret for the application. */
+ private String clientSecret;
+ /** The PKCS12 certificate byte array. */
+ private byte[] clientCertificate;
+ /** The certificate password. */
+ private String clientCertificatePassword;
+
+ /**
+ * Initializes a new instance of the ApplicationTokenCredentials.
+ *
+ * @param clientId the active directory application client id.
+ * @param domain the domain or tenant id containing this application.
+ * @param secret the authentication secret for the application.
+ * @param environment the Azure environment to authenticate with.
+ * If null is provided, AzureEnvironment.AZURE will be used.
+ */
+ public ApplicationTokenCredentials(String clientId, String domain, String secret, AzureEnvironment environment) {
+ super(environment, domain); // defer token acquisition
+ this.clientId = clientId;
+ this.clientSecret = secret;
+ this.tokens = new HashMap<>();
+ }
+
+ /**
+ * Initializes a new instance of the ApplicationTokenCredentials.
+ *
+ * @param clientId the active directory application client id.
+ * @param domain the domain or tenant id containing this application.
+ * @param certificate the PKCS12 certificate file content
+ * @param password the password to the certificate file
+ * @param environment the Azure environment to authenticate with.
+ * If null is provided, AzureEnvironment.AZURE will be used.
+ */
+ public ApplicationTokenCredentials(String clientId, String domain, byte[] certificate, String password, AzureEnvironment environment) {
+ super(environment, domain);
+ this.clientId = clientId;
+ this.clientCertificate = certificate;
+ this.clientCertificatePassword = password;
+ this.tokens = new HashMap<>();
+ }
+
+ /**
+ * Initializes the credentials based on the provided credentials file.
+ *
+ * @param credentialsFile A file with credentials, using the standard Java properties format.
+ * and the following keys:
+ * subscription=<subscription-id>
+ * tenant=<tenant-id>
+ * client=<client-id>
+ * key=<client-key>
+ * managementURI=<management-URI>
+ * baseURL=<base-URL>
+ * authURL=<authentication-URL>
+ * or a JSON format and the following keys
+ * {
+ * "clientId": "<client-id>",
+ * "clientSecret": "<client-key>",
+ * "subscriptionId": "<subscription-id>",
+ * "tenantId": "<tenant-id>",
+ * }
+ * and any custom endpoints listed in {@link AzureEnvironment}.
+ *
+ * @return The credentials based on the file.
+ * @throws IOException exception thrown from file access errors.
+ */
+ public static ApplicationTokenCredentials fromFile(File credentialsFile) throws IOException {
+ return AuthFile.parse(credentialsFile).generateCredentials();
+ }
+
+ /**
+ * Gets the active directory application client id.
+ *
+ * @return the active directory application client id.
+ */
+ public String clientId() {
+ return clientId;
+ }
+
+ String clientSecret() {
+ return clientSecret;
+ }
+
+ byte[] clientCertificate() {
+ return clientCertificate;
+ }
+
+ String clientCertificatePassword() {
+ return clientCertificatePassword;
+ }
+
+ @Override
+ public synchronized Mono getToken(String resource) {
+ AuthenticationResult authenticationResult = tokens.get(resource);
+ if (authenticationResult != null && authenticationResult.getExpiresOnDate().after(new Date())) {
+ return Mono.just(authenticationResult.getAccessToken());
+ } else {
+ return acquireAccessToken(resource)
+ .map(ar -> {
+ tokens.put(resource, ar);
+ return ar.getAccessToken();
+ });
+ }
+ }
+
+ private Mono acquireAccessToken(String resource) {
+ String authorityUrl = this.environment().activeDirectoryEndpoint() + this.domain();
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ AuthenticationContext context;
+ try {
+ context = new AuthenticationContext(authorityUrl, false, executor);
+ } catch (MalformedURLException mue) {
+ executor.shutdown();
+ throw Exceptions.propagate(mue);
+ }
+ if (proxy() != null) {
+ context.setProxy(proxy());
+ }
+ Mono authMono;
+ if (clientSecret != null) {
+ authMono = Mono.create(callback -> {
+ context.acquireToken(
+ resource,
+ new ClientCredential(this.clientId(), clientSecret),
+ Util.authenticationDelegate(callback));
+ });
+ } else if (clientCertificate != null && clientCertificatePassword != null) {
+ authMono = Mono.create(callback -> {
+ AsymmetricKeyCredential keyCredential = Util.createAsymmetricKeyCredential(clientId, clientCertificate, clientCertificatePassword);
+ context.acquireToken(
+ resource,
+ keyCredential,
+ Util.authenticationDelegate(callback));
+ });
+ } else if (clientCertificate != null) {
+ AsymmetricKeyCredential keyCredential = AsymmetricKeyCredential.create(clientId(), Util.privateKeyFromPem(new String(clientCertificate)), Util.publicKeyFromPem(new String(clientCertificate)));
+ authMono = Mono.create(callback -> {
+ context.acquireToken(
+ resource,
+ keyCredential,
+ Util.authenticationDelegate(callback));
+ });
+ } else {
+ authMono = Mono.error(new AuthenticationException("Please provide either a non-null secret or a non-null certificate."));
+ }
+ return authMono.doFinally(s -> executor.shutdown());
+ }
+}
diff --git a/common/azure-common-auth/src/main/java/com/azure/common/auth/credentials/AuthFile.java b/common/azure-common-auth/src/main/java/com/azure/common/auth/credentials/AuthFile.java
new file mode 100644
index 0000000000000..2ca1c92d0cfca
--- /dev/null
+++ b/common/azure-common-auth/src/main/java/com/azure/common/auth/credentials/AuthFile.java
@@ -0,0 +1,169 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for
+ * license information.
+ */
+
+package com.azure.common.auth.credentials;
+
+import com.azure.common.AzureEnvironment;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.google.gson.reflect.TypeToken;
+import com.azure.common.annotations.Beta;
+import com.azure.common.implementation.serializer.SerializerEncoding;
+import com.azure.common.implementation.serializer.jackson.JacksonAdapter;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * This class describes the information from a .azureauth file.
+ */
+@Beta(since = "v1.1.0")
+final class AuthFile {
+
+ private String clientId;
+ private String tenantId;
+ private String clientSecret;
+ private String clientCertificate;
+ private String clientCertificatePassword;
+ private String subscriptionId;
+
+ @JsonIgnore
+ private AzureEnvironment environment;
+ @JsonIgnore
+ private static final JacksonAdapter ADAPTER = new JacksonAdapter();
+ @JsonIgnore
+ private String authFilePath;
+
+ private AuthFile() {
+ environment = new AzureEnvironment(new HashMap());
+ environment.endpoints().putAll(AzureEnvironment.AZURE.endpoints());
+ }
+
+ /**
+ * Parses an auth file and read into an AuthFile object.
+ * @param file the auth file to read
+ * @return the AuthFile object created
+ * @throws IOException thrown when the auth file or the certificate file cannot be read or parsed
+ */
+ static AuthFile parse(File file) throws IOException {
+ String content = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8);
+
+ AuthFile authFile;
+ if (isJsonBased(content)) {
+ authFile = ADAPTER.deserialize(content, AuthFile.class, SerializerEncoding.JSON);
+ Map endpoints = ADAPTER.deserialize(content, new TypeToken