diff --git a/build.gradle b/build.gradle index dc2e30692..3f4ff3392 100644 --- a/build.gradle +++ b/build.gradle @@ -38,8 +38,8 @@ spotbugsMain { excludeFilter = file("spotBugsExcludeFilter.xml") reports { html { - enabled = true - destination = file("$buildDir/reports/spotbugs/main/spotbugs.html") + required + outputLocation = new File("$buildDir/reports/spotbugs/main/spotbugs.html") stylesheet = 'fancy-hist.xsl' } } @@ -49,16 +49,17 @@ spotbugsTest { excludeFilter = file("spotBugsExcludeFilter.xml") reports { html { - enabled = true - destination = file("$buildDir/reports/spotbugs/test/spotbugs.html") + required + outputLocation = new File('$buildDir/reports/spotbugs/test/spotbugs.html') stylesheet = 'fancy-hist.xsl' + } } } jacocoTestReport { reports { - xml.enabled true + xml.required } } @@ -74,7 +75,7 @@ sourceSets { repositories { // You can declare any Maven/Ivy/file repository here. mavenCentral() - maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } // for jacoco, until 0.8.7 gets released + maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }// for jacoco, until 0.8.7 gets released } apply from: "gradle/dependencies.gradle" @@ -90,11 +91,11 @@ def pomConfig = { } sonarqube { - properties { - property "sonar.projectKey", "microsoftgraph_msgraph-sdk-java-core" - property "sonar.organization", "microsoftgraph2" - property "sonar.host.url", "https://sonarcloud.io" - } + properties { + property "sonar.projectKey", "microsoftgraph_msgraph-sdk-java-core" + property "sonar.organization", "microsoftgraph2" + property "sonar.host.url", "https://sonarcloud.io" + } } //Publishing tasks- @@ -128,7 +129,7 @@ publishing { version "${mavenMajorVersion}.${mavenMinorVersion}.${mavenPatchVersion}${mavenArtifactSuffix}" from components.java artifact sourceJar - artifact javadocJar + artifact javadocJar pom.withXml { def root = asNode() root.appendNode('name', 'Microsoft Graph Core SDK for Java') @@ -140,59 +141,59 @@ publishing { } Snapshot(MavenPublication) { - customizePom(pom) - groupId project.property('mavenGroupId') - artifactId project.property('mavenArtifactId') - version "${mavenMajorVersion}.${mavenMinorVersion}.${mavenPatchVersion}${mavenCentralSnapshotArtifactSuffix}" - from components.java - pom.withXml { - def pomFile = file("${project.buildDir}/generated-pom.xml") - writeTo(pomFile) - } - artifact sourceJar - artifact javadocJar - } - - mavenCentralRelease(MavenPublication) { - customizePom(pom) - groupId project.property('mavenGroupId') - artifactId project.property('mavenArtifactId') - version "${mavenMajorVersion}.${mavenMinorVersion}.${mavenPatchVersion}" - from components.java - pom.withXml { - def pomFile = file("${project.buildDir}/generated-pom.xml") - writeTo(pomFile) - } - artifact sourceJar - artifact javadocJar - } + customizePom(pom) + groupId project.property('mavenGroupId') + artifactId project.property('mavenArtifactId') + version "${mavenMajorVersion}.${mavenMinorVersion}.${mavenPatchVersion}${mavenCentralSnapshotArtifactSuffix}" + from components.java + pom.withXml { + def pomFile = file("${project.buildDir}/generated-pom.xml") + writeTo(pomFile) + } + artifact sourceJar + artifact javadocJar + } + + mavenCentralRelease(MavenPublication) { + customizePom(pom) + groupId project.property('mavenGroupId') + artifactId project.property('mavenArtifactId') + version "${mavenMajorVersion}.${mavenMinorVersion}.${mavenPatchVersion}" + from components.java + pom.withXml { + def pomFile = file("${project.buildDir}/generated-pom.xml") + writeTo(pomFile) + } + artifact sourceJar + artifact javadocJar + } } - repositories { + repositories { maven { url = 'https://oss.sonatype.org/content/repositories/snapshots' name = 'sonatypeSnapshot' - + 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') - } + 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 = 'https://oss.sonatype.org/service/local/staging/deploy/maven2' name = 'sonatype' 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') - } + 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') + } } } } @@ -203,7 +204,7 @@ signing { } tasks.withType(Sign)*.enabled = mavenCentralPublishingEnabled.toBoolean() -def fixAscNames = { name -> +def fixAscNames = { name -> if(name.contains('pom')) { "${project.property('mavenArtifactId')}-${mavenMajorVersion}.${mavenMinorVersion}.${mavenPatchVersion}.pom.asc" } else { @@ -212,8 +213,8 @@ def fixAscNames = { name -> } compileJava { - sourceCompatibility = 1.8 - targetCompatibility = 1.8 + sourceCompatibility = '17' + targetCompatibility = '17' } def getVersionCode() { @@ -225,9 +226,9 @@ def getVersionName() { } artifacts { - archives jar - archives sourceJar - archives javadocJar + archives jar + archives sourceJar + archives javadocJar } def customizePom(pom) { @@ -255,14 +256,14 @@ def customizePom(pom) { licenses { license { name "MIT License" - url "http://opensource.org/licenses/MIT" - distribution "repo" + 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' + 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 { @@ -274,13 +275,13 @@ def customizePom(pom) { } gradle.taskGraph.whenReady { taskGraph -> - if (project.rootProject.file('local.properties').exists()) { + 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') } + allprojects { ext."signing.password" = properties.getProperty('signing.password') } } } diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 0c89e350e..dab5e5c13 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -16,4 +16,11 @@ dependencies { compileOnly 'com.github.spotbugs:spotbugs-annotations:4.7.0' testCompileOnly 'net.jcip:jcip-annotations:1.0' testCompileOnly 'com.github.spotbugs:spotbugs-annotations:4.7.0' + + implementation 'com.microsoft.kiota:microsoft-kiota-abstractions:0.0.1-SNAPSHOT' + implementation 'com.microsoft.kiota:microsoft-kiota-authentication-azure:0.0.1-SNAPSHOT' + implementation 'com.microsoft.kiota:microsoft-kiota-http-okHttp:0.0.1-SNAPSHOT' + implementation 'com.microsoft.kiota:microsoft-kiota-serialization-json:0.0.1-SNAPSHOT' + implementation 'com.microsoft.kiota:microsoft-kiota-serialization-text:0.0.1-SNAPSHOT' + } \ No newline at end of file diff --git a/src/main/java/com/microsoft/graph/Requests/BaseClient.java b/src/main/java/com/microsoft/graph/Requests/BaseClient.java new file mode 100644 index 000000000..58b1b4820 --- /dev/null +++ b/src/main/java/com/microsoft/graph/Requests/BaseClient.java @@ -0,0 +1,65 @@ +package com.microsoft.graph.Requests; + +import com.microsoft.graph.content.BatchRequestBuilder; +import com.microsoft.kiota.RequestAdapter; +import com.microsoft.kiota.authentication.AuthenticationProvider; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import okhttp3.OkHttpClient; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * Default client implementation. + */ +public class BaseClient implements IBaseClient{ + + private RequestAdapter requestAdapter; + /** RequestBuilder for completing Batch Requests */ + public BatchRequestBuilder batchRequestBuilder; + + /** + * Constructor requiring only a RequestAdapter. + * + * @param requestAdapter the specified RequestAdapter used to complete requests. + */ + public BaseClient(@Nonnull RequestAdapter requestAdapter) { + setRequestAdapter(requestAdapter); + } + + /** + * Constructor requiring only an AuthenticationProvider. + * + * @param authenticationProvider the specified AuthenticationProvider for use in requests. + */ + public BaseClient(@Nonnull AuthenticationProvider authenticationProvider) { + this(new BaseGraphRequestAdapter(authenticationProvider)); + } + + /** + * Constructor requiring an AuthenticationProvider and Base URL. + * + * @param authenticationProvider the specified AuthenticationProvider for use in requests. + * @param baseUrl the specified base URL for use in requests. + */ + public BaseClient(@Nonnull AuthenticationProvider authenticationProvider, @Nonnull String baseUrl) { + this(new BaseGraphRequestAdapter(authenticationProvider, baseUrl)); + } + + @Override + public void setRequestAdapter(RequestAdapter requestAdapter) { + this.requestAdapter = requestAdapter; + } + + @Override + public RequestAdapter getRequestAdapter() { + return this.requestAdapter; + } + + @Override + public BatchRequestBuilder getBatchRequestBuilder() { + //TODO: Refactor BatchRequestBuilder so that it accepts a request adapter as the param + //return this.batchRequestBuilder != null ? this.batchRequestBuilder : new BatchRequestBuilder(this.requestAdapter) + return this.batchRequestBuilder; + } +} diff --git a/src/main/java/com/microsoft/graph/Requests/BaseGraphRequestAdapter.java b/src/main/java/com/microsoft/graph/Requests/BaseGraphRequestAdapter.java new file mode 100644 index 000000000..ba695dac0 --- /dev/null +++ b/src/main/java/com/microsoft/graph/Requests/BaseGraphRequestAdapter.java @@ -0,0 +1,157 @@ +package com.microsoft.graph.Requests; + +import com.fasterxml.jackson.databind.ser.Serializers; +import com.microsoft.graph.core.ClientException; +import com.microsoft.kiota.authentication.AnonymousAuthenticationProvider; +import com.microsoft.kiota.authentication.AuthenticationProvider; +import com.microsoft.kiota.http.OkHttpRequestAdapter; +import com.microsoft.kiota.serialization.ParseNodeFactory; +import com.microsoft.kiota.serialization.SerializationWriterFactory; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import okhttp3.OkHttpClient; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import java.net.URL; +import java.util.HashMap; + +/** + * Extension of the OkHttpRequestAdapter which is used as the default for Graph Requests. + */ +public class BaseGraphRequestAdapter extends OkHttpRequestAdapter { + + /** + * Enum list of Keys which can be used to access the cloudList map. + */ + public enum Clouds { + /** Key for Global Cloud URL */ + GLOBAL_CLOUD, + /** Key for US GOV Cloud URL */ + USGOV_CLOUD, + /** Key for China Cloud URL */ + CHINA_CLOUD, + /** Key for Germany Cloud URL */ + GERMANY_CLOUD, + /** Key for US DOD Cloud URL */ + USGOV_DOD_CLOUD + } + + /** + * Map of valid cloud urls for use in Graph requests. + * Accessible using a Clouds enum value. + */ + private static final HashMap cloudList = new HashMap() {{ + put( Clouds.GLOBAL_CLOUD, "https://graph.microsoft.com" ); + put( Clouds.USGOV_CLOUD, "https://graph.microsoft.us"); + put( Clouds.CHINA_CLOUD, "https://microsoftgraph.chinacloudapi.cn"); + put( Clouds.GERMANY_CLOUD, "https://graph.microsoft.de"); + put( Clouds.USGOV_DOD_CLOUD, "https://dod-graph.microsoft.us"); + }}; + + + /** + * The default BaseGraphRequestAdapter constructor, includes all configurable properties. + * Note: GraphClientOptions will be ignored if you also choose to include an OKHttpClient. + * + * @param authenticationProvider the AuthenticationProvider for use in requests. + * @param parseNodeFactory the ParseNodeFactory for use in requests. + * @param serializationWriterFactory the SerializationWriterFactory for use in requests. + * @param client the OkHttpClient for use in requests. + * @param graphClientOptions the GraphClientOptions for use in requests. + * @param baseUrl the base URL for use in requests. + */ + public BaseGraphRequestAdapter(@Nonnull final AuthenticationProvider authenticationProvider, @Nullable final ParseNodeFactory parseNodeFactory, @Nullable final SerializationWriterFactory serializationWriterFactory, @Nullable final OkHttpClient client, @Nullable final GraphClientOptions graphClientOptions, @Nullable String baseUrl) { + super(authenticationProvider, parseNodeFactory, serializationWriterFactory, client != null ? client : GraphClientFactory.create(graphClientOptions).build()); + if (baseUrl != null && !baseUrl.isEmpty()) { + setBaseUrl(baseUrl); + } else { + setBaseUrl(determineBaseAddress(null, null)); + } + } + + /** + * Constructor requiring only an AuthenticationProvider + * + * @param authenticationProvider the AuthenticationProvider for use in requests. + */ + public BaseGraphRequestAdapter(@Nonnull AuthenticationProvider authenticationProvider) { + this(authenticationProvider, determineBaseAddress(null, null)); + } + + /** + * Constructor requiring an AuthenticationProvider and a base URL. + * + * @param authenticationProvider the AuthenticationProvider for use in requests. + * @param baseUrl the base URL for use in requests. + */ + public BaseGraphRequestAdapter(@Nonnull AuthenticationProvider authenticationProvider, @Nonnull String baseUrl) { + this(authenticationProvider, baseUrl, new GraphClientOptions()); + } + + /** + * Constructor requiring an AuthenticationProvider, base URL, and an OkHttpClient. + * + * @param authenticationProvider the AuthenticationProvider for use in requests. + * @param baseUrl the base URL for use in requests. + * @param client the OkHttpClient for use in requests. + */ + public BaseGraphRequestAdapter(@Nonnull AuthenticationProvider authenticationProvider, @Nonnull String baseUrl, @Nonnull OkHttpClient client) { + this(authenticationProvider, null, null, client, null, baseUrl); + } + + /** + * Constructor requiring an AuthenticationProvider, base URL, and GraphClientOptions. + * + * @param authenticationProvider the AuthenticationProvider for use in requests. + * @param baseUrl the base URL for use in requests. + * @param graphClientOptions the GraphClientOptions for use in requests. + */ + public BaseGraphRequestAdapter(@Nonnull AuthenticationProvider authenticationProvider, @Nonnull String baseUrl, @Nonnull GraphClientOptions graphClientOptions) { + this(authenticationProvider, null, null, null, graphClientOptions, baseUrl); + } + + /** + * Constructor requiring an AuthenticationProvider, optional National Cloud, and optional Version. + * + * @param authenticationProvider the AuthenticationProvider for use in requests. + * @param cloud the National Cloud for use in requests. + * @param version the Graph version for use in requests. + */ + public BaseGraphRequestAdapter(@Nonnull AuthenticationProvider authenticationProvider, @Nullable Clouds cloud, @Nullable String version) { + this(authenticationProvider, determineBaseAddress(cloud, version)); + } + + /** + * Constructor requiring an AuthenticationProvider, optional National Cloud, optional Version, and required OkHttpClient. + * + * @param authenticationProvider the AuthenticationProvider for use in requests. + * @param cloud the National Cloud for use in requests. + * @param version the Graph version for use in requests. + * @param client the OkHttpClient for use in requests. + */ + public BaseGraphRequestAdapter(@Nonnull AuthenticationProvider authenticationProvider, @Nullable Clouds cloud, @Nullable String version, @Nonnull OkHttpClient client) { + this(authenticationProvider, determineBaseAddress(cloud, version), client); + } + + /** + * Constructor requiring an AuthenticationProvider, optional National Cloud, optional Version, and required GraphClientOptions. + * + * @param authenticationProvider the AuthenticationProvider for use in requests. + * @param cloud the National Cloud for use in requests. + * @param version the Graph version for use in requests. + * @param graphClientOptions the GraphClientOptions for use in requests. + */ + public BaseGraphRequestAdapter(@Nonnull AuthenticationProvider authenticationProvider, @Nullable Clouds cloud, @Nullable String version, @Nonnull GraphClientOptions graphClientOptions) { + this(authenticationProvider, determineBaseAddress(cloud, version), graphClientOptions); + } + + private static String determineBaseAddress(@Nullable Clouds nationalCloud, @Nullable String version) throws IllegalArgumentException { + String cloud = nationalCloud == null ? cloudList.get(Clouds.GLOBAL_CLOUD) : cloudList.get(nationalCloud); + if(cloud == null) { + throw new IllegalArgumentException(String.format("%s is an unexpected national cloud.", nationalCloud)); + } + String baseAddress = version == null ? String.format("%s/%s/",cloud,"v1.0") : String.format("%s/%s/",cloud,version); + return baseAddress; + } +} diff --git a/src/main/java/com/microsoft/graph/Requests/GraphClientFactory.java b/src/main/java/com/microsoft/graph/Requests/GraphClientFactory.java new file mode 100644 index 000000000..3e1630127 --- /dev/null +++ b/src/main/java/com/microsoft/graph/Requests/GraphClientFactory.java @@ -0,0 +1,84 @@ +package com.microsoft.graph.Requests; + +import com.microsoft.graph.httpcore.CompressionHandler; +import com.microsoft.graph.httpcore.GraphTelemetryHandler; +import com.microsoft.kiota.RequestInformation; +import com.microsoft.kiota.http.KiotaClientFactory; +import edu.umd.cs.findbugs.annotations.Nullable; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; + +import javax.annotation.Nonnull; +import java.net.URI; +import java.net.URISyntaxException; +import java.text.Format; +import java.time.temporal.ChronoUnit; +import java.util.*; + +/** + * The GraphClientFactory used to create the OkHttpClient. + */ +public class GraphClientFactory { + private GraphClientFactory() { } + + /** + * The default OkHttpClient Builder for Graph. + * + * @return an OkHttpClient Builder instance. + */ + public static OkHttpClient.Builder create() { + return create(new GraphClientOptions()); + } + + /** + * OkHttpClient Builder for Graph with specified Interceptors. + * + * @param interceptors desired interceptors for use in requests. + * @return an OkHttpClient Builder instance. + */ + public static OkHttpClient.Builder create(@Nonnull Interceptor[] interceptors) { + return create(interceptors, new GraphClientOptions()); + } + + /** + * OkHttpClient Builder for Graph with specified Interceptors and GraphClientOptions. + * + * @param interceptors desired interceptors for use in requests. + * @param graphClientOptions the GraphClientOptions for use in requests. + * @return an OkHttpClient Builder instance. + */ + public static OkHttpClient.Builder create(@Nonnull Interceptor[] interceptors, @Nonnull GraphClientOptions graphClientOptions) { + OkHttpClient.Builder builder = create(graphClientOptions); + for(Interceptor interceptor : interceptors) { + builder.addInterceptor(interceptor); + } + return builder; + } + + /** + * The OkHttpClient Builder with optional GraphClientOptions + * + * @param graphClientOptions the GraphClientOptions for use in requests. + * @return an OkHttpClient Builder instance. + */ + public static OkHttpClient.Builder create(@Nullable GraphClientOptions graphClientOptions) { + GraphClientOptions options = graphClientOptions != null ? graphClientOptions : new GraphClientOptions(); + return KiotaClientFactory.Create(createDefaultGraphInterceptors(options)); + } + + /** + * Creates the default Interceptors for use with Graph. + * + * @param graphClientOptions the GraphClientOptions used to create the GraphTelemetryHandler with. + * @return an array of interceptors. + */ + public static Interceptor[] createDefaultGraphInterceptors(@Nonnull GraphClientOptions graphClientOptions) { + List handlers = new ArrayList<>(); + handlers.add(new GraphTelemetryHandler(graphClientOptions)); + for(final Interceptor interceptor: KiotaClientFactory.CreateDefaultInterceptors()) { + handlers.add(interceptor); + } + return (Interceptor[]) handlers.toArray(); + } +} diff --git a/src/main/java/com/microsoft/graph/Requests/IBaseClient.java b/src/main/java/com/microsoft/graph/Requests/IBaseClient.java new file mode 100644 index 000000000..bab15dd6a --- /dev/null +++ b/src/main/java/com/microsoft/graph/Requests/IBaseClient.java @@ -0,0 +1,31 @@ +package com.microsoft.graph.Requests; + +import com.microsoft.graph.content.BatchRequestBuilder; +import com.microsoft.kiota.RequestAdapter; + +/** + * The default client interface + */ +public interface IBaseClient { + + /** + * Method to set the RequestAdapter property + * + * @param requestAdapter specifies the desired RequestAdapter + */ + public void setRequestAdapter(RequestAdapter requestAdapter); + + /** + * Returns the current RequestAdapter for sending requests + * + * @return the RequestAdapter currently in use + */ + public RequestAdapter getRequestAdapter(); + + /** + * Gets the BatchRequestBuilder for use in Batch Requests + * + * @return the BatchRequestBuilder instance + */ + public BatchRequestBuilder getBatchRequestBuilder(); +}