From c32417f7f2ecd511d93717ef15bed7f1865dfeeb Mon Sep 17 00:00:00 2001 From: Summers Pittman Date: Thu, 20 Jul 2017 09:56:43 -0400 Subject: [PATCH 1/4] Removing travis --- .travis.yml | 89 ----------------------------------------------------- 1 file changed, 89 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 886e057..0000000 --- a/.travis.yml +++ /dev/null @@ -1,89 +0,0 @@ -# See: Travis Support did recomment moving Android builds to GCE. -# Which is on 'precise' and has larger VMs: https://docs.travis-ci.com/user/ci-environment/#Virtualization-environments -sudo: required -dist: precise - -notifications: - irc: "irc.freenode.org#aerogear" - -language: android - -jdk: - - oraclejdk8 - -android: - components: - - platform-tools - - tools - - build-tools-24.0.3 - - android-24 - - extra-google-m2repository - - extra-android-m2repository - -env: - matrix: - - ANDROID_SDK="android-24" ANDROID_EMULATOR="android-16" ANDROID_ABI="armeabi-v7a" ANDROID_PKGS="sys-img-armeabi-v7a-android-16" - - ANDROID_SDK="android-24" ANDROID_EMULATOR="android-17" ANDROID_ABI="armeabi-v7a" ANDROID_PKGS="sys-img-armeabi-v7a-android-17" - - ANDROID_SDK="android-24" ANDROID_EMULATOR="android-18" ANDROID_ABI="armeabi-v7a" ANDROID_PKGS="sys-img-armeabi-v7a-android-18" - - ANDROID_SDK="android-24" ANDROID_EMULATOR="android-19" ANDROID_ABI="armeabi-v7a" ANDROID_PKGS="sys-img-armeabi-v7a-android-19" - - ANDROID_SDK="android-24" ANDROID_EMULATOR="android-21" ANDROID_ABI="armeabi-v7a" ANDROID_PKGS="sys-img-armeabi-v7a-android-21" - - ANDROID_SDK="android-24" ANDROID_EMULATOR="android-22" ANDROID_ABI="armeabi-v7a" ANDROID_PKGS="sys-img-armeabi-v7a-android-22" -# - ANDROID_SDK="android-24" ANDROID_EMULATOR="android-23" ANDROID_ABI="armeabi-v7a" ANDROID_PKGS="sys-img-armeabi-v7a-android-23" - - ANDROID_SDK="android-24" ANDROID_EMULATOR="android-24" ANDROID_ABI="armeabi-v7a" ANDROID_PKGS="sys-img-armeabi-v7a-android-24" - -before_install: - - ################################################# - ########## maven-android-sdk-deployer ########### - ################################################# - - # Install Android dependencies only on this Matrix - - echo y | android update sdk --no-ui --all --filter ${ANDROID_EMULATOR},${ANDROID_PKGS} - - # Checkout maven-android-sdk-deployer - - git clone git://github.com/mosabua/maven-android-sdk-deployer.git - - # Install android maven repository - - cd $PWD/maven-android-sdk-deployer/platforms/$ANDROID_SDK - - mvn install -N --quiet - - cd - - - - cd $PWD/maven-android-sdk-deployer/repositories - - mvn install --quiet - - cd - - - - ################################################# - ############ Snapshot dependencies ############## - ################################################# - - # AeroGear Android Core - - git clone git://github.com/aerogear/aerogear-android-core.git - - cd $PWD/aerogear-android-core - - mvn install -N --quiet - - cd - - - # AeroGear Android Security - - git clone git://github.com/aerogear/aerogear-android-security.git - - cd $PWD/aerogear-android-security - - mvn install -DskipTests -fn --quiet - - cd - - - # AeroGear Android Store - - git clone git://github.com/aerogear/aerogear-android-store.git - - cd $PWD/aerogear-android-store/ - - mvn install -DskipTests -fn --quiet - - cd - - - # AeroGear Android Pipe - - git clone git://github.com/aerogear/aerogear-android-pipe.git - - cd $PWD/aerogear-android-pipe/ - - mvn install -DskipTests -fn --quiet - - cd - - -before_script: - - - echo no | android create avd --force -n test -t $ANDROID_EMULATOR --abi $ANDROID_ABI - - emulator -avd test -no-audio -no-window & - - android-wait-for-emulator - - adb shell input keyevent 82 & From 1c41937473f63c59ea82fe0b8f336e1df8d69713 Mon Sep 17 00:00:00 2001 From: Summers Pittman Date: Thu, 20 Jul 2017 09:56:54 -0400 Subject: [PATCH 2/4] Initial move to gradle --- README.md | 6 +- aerogear-android-authz-test/pom.xml | 147 -------------- aerogear-android-authz/pom.xml | 180 ------------------ build.gradle | 20 ++ gradle-mvn-push.gradle | 130 +++++++++++++ gradle.properties | 22 +++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54208 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 172 +++++++++++++++++ gradlew.bat | 84 ++++++++ library/.gitignore | 1 + .../androidTest}/src/main/AndroidManifest.xml | 0 .../authorization/test/MainActivity.java | 0 .../authorization/test/helper/Data.java | 0 .../test/helper/DataWithNoIdConfigured.java | 0 .../test/helper/DataWithNoPropertyId.java | 0 .../test/helper/ObjectVarArgsMatcher.java | 0 .../test/oauth2/AuthzServiceTest.java | 0 .../oauth2/IntentOAuth2AuthzModuleTest.java | 0 .../test/oauth2/OAuth2AuthzModuleTest.java | 0 ...atchedActivityInstrumentationTestCase.java | 0 .../authorization/test/util/StubActivity.java | 0 .../authorization/test/util/VoidCallback.java | 0 .../src/main/res/layout/activity_main.xml | 0 .../androidTest}/src/main/res/menu/main.xml | 0 .../src/main/res/values/dimens.xml | 0 .../src/main/res/values/strings.xml | 0 library/build.gradle | 41 ++++ library/gradle.properties | 3 + .../src/main/AndroidManifest.xml | 0 .../AuthorizationConfiguration.java | 0 .../authorization/AuthorizationManager.java | 0 .../android/authorization/AuthzModule.java | 0 .../OnAuthorizationCreatedListener.java | 0 .../OAuth2AuthorizationConfiguration.java | 0 .../oauth2/OAuth2AuthorizationException.java | 0 ...th2AuthroizationConfigurationProvider.java | 0 .../oauth2/OAuth2AuthzModule.java | 0 .../oauth2/OAuth2AuthzService.java | 0 .../oauth2/OAuth2AuthzSession.java | 0 .../oauth2/OAuth2FetchAccess.java | 0 .../oauth2/OAuth2Properties.java | 0 .../authorization/oauth2/OAuth2Utils.java | 0 .../OAuth2WebFragmentFetchAutorization.java | 0 .../oauth2/OAuthWebViewDialog.java | 0 .../intent/OAuth2IntentAuthzModule.java | 0 .../webview/OAuth2WebViewAuthzModule.java | 0 .../src/main/res/layout/oauth_web_view.xml | 0 .../src/main/res/values/strings.xml | 0 .../src/main/res/values/styles.xml | 0 pom.xml | 122 ------------ settings.gradle | 1 + 52 files changed, 482 insertions(+), 453 deletions(-) delete mode 100644 aerogear-android-authz-test/pom.xml delete mode 100644 aerogear-android-authz/pom.xml create mode 100644 build.gradle create mode 100644 gradle-mvn-push.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 library/.gitignore rename {aerogear-android-authz-test => library/androidTest}/src/main/AndroidManifest.xml (100%) rename {aerogear-android-authz-test => library/androidTest}/src/main/java/org/jboss/aerogear/android/authorization/test/MainActivity.java (100%) rename {aerogear-android-authz-test => library/androidTest}/src/main/java/org/jboss/aerogear/android/authorization/test/helper/Data.java (100%) rename {aerogear-android-authz-test => library/androidTest}/src/main/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoIdConfigured.java (100%) rename {aerogear-android-authz-test => library/androidTest}/src/main/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoPropertyId.java (100%) rename {aerogear-android-authz-test => library/androidTest}/src/main/java/org/jboss/aerogear/android/authorization/test/helper/ObjectVarArgsMatcher.java (100%) rename {aerogear-android-authz-test => library/androidTest}/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/AuthzServiceTest.java (100%) rename {aerogear-android-authz-test => library/androidTest}/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/IntentOAuth2AuthzModuleTest.java (100%) rename {aerogear-android-authz-test => library/androidTest}/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/OAuth2AuthzModuleTest.java (100%) rename {aerogear-android-authz-test => library/androidTest}/src/main/java/org/jboss/aerogear/android/authorization/test/util/PatchedActivityInstrumentationTestCase.java (100%) rename {aerogear-android-authz-test => library/androidTest}/src/main/java/org/jboss/aerogear/android/authorization/test/util/StubActivity.java (100%) rename {aerogear-android-authz-test => library/androidTest}/src/main/java/org/jboss/aerogear/android/authorization/test/util/VoidCallback.java (100%) rename {aerogear-android-authz-test => library/androidTest}/src/main/res/layout/activity_main.xml (100%) rename {aerogear-android-authz-test => library/androidTest}/src/main/res/menu/main.xml (100%) rename {aerogear-android-authz-test => library/androidTest}/src/main/res/values/dimens.xml (100%) rename {aerogear-android-authz-test => library/androidTest}/src/main/res/values/strings.xml (100%) create mode 100644 library/build.gradle create mode 100644 library/gradle.properties rename {aerogear-android-authz => library}/src/main/AndroidManifest.xml (100%) rename {aerogear-android-authz => library}/src/main/java/org/jboss/aerogear/android/authorization/AuthorizationConfiguration.java (100%) rename {aerogear-android-authz => library}/src/main/java/org/jboss/aerogear/android/authorization/AuthorizationManager.java (100%) rename {aerogear-android-authz => library}/src/main/java/org/jboss/aerogear/android/authorization/AuthzModule.java (100%) rename {aerogear-android-authz => library}/src/main/java/org/jboss/aerogear/android/authorization/OnAuthorizationCreatedListener.java (100%) rename {aerogear-android-authz => library}/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthorizationConfiguration.java (100%) rename {aerogear-android-authz => library}/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthorizationException.java (100%) rename {aerogear-android-authz => library}/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthroizationConfigurationProvider.java (100%) rename {aerogear-android-authz => library}/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthzModule.java (100%) rename {aerogear-android-authz => library}/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthzService.java (100%) rename {aerogear-android-authz => library}/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthzSession.java (100%) rename {aerogear-android-authz => library}/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2FetchAccess.java (100%) rename {aerogear-android-authz => library}/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2Properties.java (100%) rename {aerogear-android-authz => library}/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2Utils.java (100%) rename {aerogear-android-authz => library}/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2WebFragmentFetchAutorization.java (100%) rename {aerogear-android-authz => library}/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuthWebViewDialog.java (100%) rename {aerogear-android-authz => library}/src/main/java/org/jboss/aerogear/android/authorization/oauth2/intent/OAuth2IntentAuthzModule.java (100%) rename {aerogear-android-authz => library}/src/main/java/org/jboss/aerogear/android/authorization/oauth2/webview/OAuth2WebViewAuthzModule.java (100%) rename {aerogear-android-authz => library}/src/main/res/layout/oauth_web_view.xml (100%) rename {aerogear-android-authz => library}/src/main/res/values/strings.xml (100%) rename {aerogear-android-authz => library}/src/main/res/values/styles.xml (100%) delete mode 100644 pom.xml create mode 100644 settings.gradle diff --git a/README.md b/README.md index d939126..130a3e7 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,11 @@ # AeroGear Android Authz [![Maintenance](https://img.shields.io/maintenance/yes/2016.svg)](http://github.com/aerogear/aerogear-android-authz) -[![Travis](https://img.shields.io/travis/aerogear/aerogear-android-authz.svg)](http://travis-ci.org/aerogear/aerogear-android-authz) [![License](https://img.shields.io/badge/-Apache%202.0-blue.svg)](https://opensource.org/s/Apache-2.0) [![Maven Central](https://img.shields.io/maven-central/v/org.jboss.aerogear/aerogear-android-authz.svg)](http://search.maven.org/#search%7Cga%7C1%7Caerogear-android-authz) [![Javadocs](http://www.javadoc.io/badge/org.jboss.aerogear/aerogear-android-authz.svg?color=blue)](http://www.javadoc.io/doc/org.jboss.aerogear/aerogear-android-authz) -AeroGear's Android libraries were built as jar and aar packages using [Maven](http://maven.apache.org/) and the [android-maven-plugin](https://github.com/jayway/maven-android-plugin). The project follows the standard Maven layout so it can be imported directly into most IDEs as a Maven project. - +AeroGear's Android libraries were built as jar and aar packages using [Gradle](http://gradle.org/) and the [Android SDK](https://developer.android.com/studio/index.html). ## Authz AeroGear Android Authz provides ability to integrate their Android application with RESTful services secured with OAuth 2 using Pipe. @@ -15,7 +13,7 @@ AeroGear Android Authz provides ability to integrate their Android application w | | Project Info | | --------------- | ------------- | | License: | Apache License, Version 2.0 | -| Build: | Maven | +| Build: | Gradle | | Documentation: | https://aerogear.org/android/ | | Issue tracker: | https://issues.jboss.org/browse/AGDROID | | Mailing lists: | [aerogear-users](http://aerogear-users.1116366.n5.nabble.com/) ([subscribe](https://lists.jboss.org/mailman/listinfo/aerogear-users)) | diff --git a/aerogear-android-authz-test/pom.xml b/aerogear-android-authz-test/pom.xml deleted file mode 100644 index 4ee0f8b..0000000 --- a/aerogear-android-authz-test/pom.xml +++ /dev/null @@ -1,147 +0,0 @@ - - - - 4.0.0 - - aerogear-android-authz-test - apk - AeroGear Android Authz Test - http://aerogear.org - - - org.jboss.aerogear - aerogear-android-authz-parent - 3.1.2-SNAPSHOT - - - - - - 1.10.19 - 1.2 - 1.2 - 0.5 - - -Xms256m - -Xmx2048m - - - - - - - org.jboss.aerogear - aerogear-android-authz - ${project.version} - aar - - - - org.mockito - mockito-all - ${mockito.version} - - - hamcrest-core - org.hamcrest - - - - - - com.google.dexmaker - dexmaker - ${dexmaker.version} - - - hamcrest-core - org.hamcrest - - - - - - com.google.dexmaker - dexmaker-mockito - ${dexmaker.mockito.version} - - - org.mockito - mockito-core - - - hamcrest-core - org.hamcrest - - - - - - com.android.support.test - runner - ${android.support.test.version} - aar - - - org.hamcrest - hamcrest-core - - - junit - junit-dep - - - - - - com.android.support.test - rules - ${android.support.test.version} - aar - - - - - - - - com.simpligility.maven.plugins - android-maven-plugin - - - ${android.debug} - - - ${android.platform} - - - ${proguard.skip} - - true - false - - - ${android.maven.plugin.dex.xms} - ${android.maven.plugin.dex.xmx} - - - - - - - diff --git a/aerogear-android-authz/pom.xml b/aerogear-android-authz/pom.xml deleted file mode 100644 index ebe0ce9..0000000 --- a/aerogear-android-authz/pom.xml +++ /dev/null @@ -1,180 +0,0 @@ - - - - 4.0.0 - - org.jboss.aerogear - aerogear-android-authz - 3.1.2-SNAPSHOT - aar - AeroGear Android Authorization Library - http://aerogear.org - - - org.jboss.aerogear - aerogear-android-authz-parent - 3.1.2-SNAPSHOT - - - - scm:git:git@github.com:aerogear/aerogear-android-auth.git - scm:git:git@github.com:aerogear/aerogear-android-auth.git - git@github.com:aerogear/aerogear-android-auth.git - HEAD - - - - - - 3.1.0 - 3.1.0 - 3.2.0 - - - 1.10 - - - - - - - org.jboss.aerogear - aerogear-android-core - ${aerogear.android.core.version} - aar - - - - org.jboss.aerogear - aerogear-android-core - ${aerogear.android.core.version} - jar - provided - - - - org.jboss.aerogear - aerogear-android-store - ${aerogear.android.store.version} - aar - - - - org.jboss.aerogear - aerogear-android-store - ${aerogear.android.store.version} - jar - provided - - - - org.jboss.aerogear - aerogear-android-pipe - ${aerogear.android.pipe.version} - aar - - - - org.jboss.aerogear - aerogear-android-pipe - ${aerogear.android.pipe.version} - jar - provided - - - - com.google.code.gson - gson - - - - - - - - com.simpligility.maven.plugins - android-maven-plugin - - - ${android.debug} - - - ${android.platform} - - - ${proguard.skip} - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - ${maven.compiler.source} - ${maven.compiler.target} - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - - attach-sources - - jar - - - - - ${basedir}/src - - - **com/google/** - - **/R.java - - - - - - org.codehaus.mojo - build-helper-maven-plugin - - - package - - attach-artifact - - - - - jar - ${project.build.directory}/${project.build.finalName}.jar - - - - - - - - - - - diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..50b2e40 --- /dev/null +++ b/build.gradle @@ -0,0 +1,20 @@ +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +allprojects { + repositories { + jcenter() + mavenLocal() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/gradle-mvn-push.gradle b/gradle-mvn-push.gradle new file mode 100644 index 0000000..e7ba952 --- /dev/null +++ b/gradle-mvn-push.gradle @@ -0,0 +1,130 @@ +/* + * Copyright 2013 Chris Banes + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +apply plugin: 'maven' +apply plugin: 'signing' +apply plugin: 'com.github.dcendents.android-maven' + +def isReleaseBuild() { + return VERSION_NAME.contains("SNAPSHOT") == false +} + +def getReleaseRepositoryUrl() { + return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL + : "https://oss.sonatype.org/service/local/staging/deploy/maven2/" +} + +def getSnapshotRepositoryUrl() { + return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL + : "https://oss.sonatype.org/content/repositories/snapshots/" +} + +def getRepositoryUsername() { + return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : "" +} + +def getRepositoryPassword() { + return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "" +} + +group = POM_GROUP_ID +project.archivesBaseName = POM_ARTIFACT_ID +version = VERSION_NAME + +afterEvaluate { project -> + uploadArchives { + repositories { + mavenDeployer { + beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + + pom.groupId = POM_GROUP_ID + pom.artifactId = POM_ARTIFACT_ID + pom.version = VERSION_NAME + + repository(url: getReleaseRepositoryUrl()) { + authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) + } + snapshotRepository(url: getSnapshotRepositoryUrl()) { + authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) + } + + pom.project { + name POM_NAME + packaging POM_PACKAGING + description POM_DESCRIPTION + url POM_URL + + scm { + url POM_SCM_URL + connection POM_SCM_CONNECTION + developerConnection POM_SCM_DEV_CONNECTION + } + + licenses { + license { + name POM_LICENCE_NAME + url POM_LICENCE_URL + distribution POM_LICENCE_DIST + } + } + + developers { + developer { + id POM_DEVELOPER_ID + name POM_DEVELOPER_NAME + } + } + } + } + } + } + + signing { + required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") } + sign configurations.archives + } + + android.libraryVariants.all { variant -> + def javadocTask = task("generate${variant.name.capitalize()}Javadoc", type: Javadoc) { + description "Generates Javadoc for $variant.name." + source = variant.javaCompile.source + ext.androidJar = project.files(android.getBootClasspath().join(File.pathSeparator)) + classpath = files(variant.javaCompile.classpath.files) + files(ext.androidJar) + exclude '**/BuildConfig.java' + exclude '**/R.java' + } + + javadocTask.dependsOn variant.javaCompile + + def jarJavadocTask = task("jar${variant.name.capitalize()}Javadoc", type: Jar) { + description "Generate Javadoc Jar for $variant.name" + classifier = 'javadoc' + from javadocTask.destinationDir + } + + jarJavadocTask.dependsOn javadocTask + artifacts.add('archives', jarJavadocTask) + + def jarSourceTask = task("jar${variant.name.capitalize()}Sources", type: Jar) { + description "Generates Java Sources for $variant.name." + classifier = 'sources' + from variant.javaCompile.source + } + + jarSourceTask.dependsOn variant.javaCompile + artifacts.add('archives', jarSourceTask) + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..3ff2288 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,22 @@ +# Android Stuff + +VERSION_CODE=311 +VERSION_NAME=3.1.1 + +# Bintray Stuff + +REPO_NAME=aerogear-android-authz + +# Maven Stuff + +POM_GROUP_ID=org.jboss.aerogear +POM_DESCRIPTION=AeroGear Android Authz +POM_URL=http://aerogear.org +POM_SCM_URL=https://github.com/aerogear/aerogear-android-authz +POM_SCM_CONNECTION=scm:git@github.com:aerogear/aerogear-android-authz.git +POM_SCM_DEV_CONNECTION=scm:git@github.com:aerogear/aerogear-android-authz.git +POM_LICENCE_NAME=The Apache Software License, Version 2.0 +POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt +POM_LICENCE_DIST=repo +POM_DEVELOPER_ID=aerogear +POM_DEVELOPER_NAME=aerogear diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..ca9f9f90aa99e090ca37ba31a5ab869a4c9defe9 GIT binary patch literal 54208 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 literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..921e902 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Jul 20 09:55:58 EDT 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..4453cce --- /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 0000000..f955316 --- /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/library/.gitignore b/library/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/library/.gitignore @@ -0,0 +1 @@ +/build diff --git a/aerogear-android-authz-test/src/main/AndroidManifest.xml b/library/androidTest/src/main/AndroidManifest.xml similarity index 100% rename from aerogear-android-authz-test/src/main/AndroidManifest.xml rename to library/androidTest/src/main/AndroidManifest.xml diff --git a/aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/MainActivity.java b/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/MainActivity.java similarity index 100% rename from aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/MainActivity.java rename to library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/MainActivity.java diff --git a/aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/helper/Data.java b/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/helper/Data.java similarity index 100% rename from aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/helper/Data.java rename to library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/helper/Data.java diff --git a/aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoIdConfigured.java b/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoIdConfigured.java similarity index 100% rename from aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoIdConfigured.java rename to library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoIdConfigured.java diff --git a/aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoPropertyId.java b/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoPropertyId.java similarity index 100% rename from aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoPropertyId.java rename to library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoPropertyId.java diff --git a/aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/helper/ObjectVarArgsMatcher.java b/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/helper/ObjectVarArgsMatcher.java similarity index 100% rename from aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/helper/ObjectVarArgsMatcher.java rename to library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/helper/ObjectVarArgsMatcher.java diff --git a/aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/AuthzServiceTest.java b/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/AuthzServiceTest.java similarity index 100% rename from aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/AuthzServiceTest.java rename to library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/AuthzServiceTest.java diff --git a/aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/IntentOAuth2AuthzModuleTest.java b/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/IntentOAuth2AuthzModuleTest.java similarity index 100% rename from aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/IntentOAuth2AuthzModuleTest.java rename to library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/IntentOAuth2AuthzModuleTest.java diff --git a/aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/OAuth2AuthzModuleTest.java b/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/OAuth2AuthzModuleTest.java similarity index 100% rename from aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/OAuth2AuthzModuleTest.java rename to library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/OAuth2AuthzModuleTest.java diff --git a/aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/util/PatchedActivityInstrumentationTestCase.java b/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/util/PatchedActivityInstrumentationTestCase.java similarity index 100% rename from aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/util/PatchedActivityInstrumentationTestCase.java rename to library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/util/PatchedActivityInstrumentationTestCase.java diff --git a/aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/util/StubActivity.java b/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/util/StubActivity.java similarity index 100% rename from aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/util/StubActivity.java rename to library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/util/StubActivity.java diff --git a/aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/util/VoidCallback.java b/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/util/VoidCallback.java similarity index 100% rename from aerogear-android-authz-test/src/main/java/org/jboss/aerogear/android/authorization/test/util/VoidCallback.java rename to library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/util/VoidCallback.java diff --git a/aerogear-android-authz-test/src/main/res/layout/activity_main.xml b/library/androidTest/src/main/res/layout/activity_main.xml similarity index 100% rename from aerogear-android-authz-test/src/main/res/layout/activity_main.xml rename to library/androidTest/src/main/res/layout/activity_main.xml diff --git a/aerogear-android-authz-test/src/main/res/menu/main.xml b/library/androidTest/src/main/res/menu/main.xml similarity index 100% rename from aerogear-android-authz-test/src/main/res/menu/main.xml rename to library/androidTest/src/main/res/menu/main.xml diff --git a/aerogear-android-authz-test/src/main/res/values/dimens.xml b/library/androidTest/src/main/res/values/dimens.xml similarity index 100% rename from aerogear-android-authz-test/src/main/res/values/dimens.xml rename to library/androidTest/src/main/res/values/dimens.xml diff --git a/aerogear-android-authz-test/src/main/res/values/strings.xml b/library/androidTest/src/main/res/values/strings.xml similarity index 100% rename from aerogear-android-authz-test/src/main/res/values/strings.xml rename to library/androidTest/src/main/res/values/strings.xml diff --git a/library/build.gradle b/library/build.gradle new file mode 100644 index 0000000..b115b51 --- /dev/null +++ b/library/build.gradle @@ -0,0 +1,41 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion 25 + buildToolsVersion "25.0.3" + + defaultConfig { + minSdkVersion 16 + targetSdkVersion 25 + + versionCode Integer.parseInt(project.property("VERSION_CODE")) + versionName project.property("VERSION_NAME") + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + compile 'com.android.support:appcompat-v7:25.3.1' + compile 'org.jboss.aerogear:aerogear-android-core:3.1.0' + compile 'org.jboss.aerogear:aerogear-android-store:3.1.0' + compile 'org.jboss.aerogear:aerogear-android-pipe:3.2.0' + compile 'com.google.code.gson:gson:2.8.1' + + testCompile 'junit:junit:4.12' + + androidTestCompile 'com.linkedin.dexmaker:dexmaker-mockito:2.2.0' + androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { + exclude group: 'com.android.support', module: 'support-annotations' + }) + +} + +apply from: '../gradle-mvn-push.gradle' diff --git a/library/gradle.properties b/library/gradle.properties new file mode 100644 index 0000000..b60c71d --- /dev/null +++ b/library/gradle.properties @@ -0,0 +1,3 @@ +POM_NAME=AeroGear Android Authz +POM_ARTIFACT_ID=aerogear-android-authz +POM_PACKAGING=aar diff --git a/aerogear-android-authz/src/main/AndroidManifest.xml b/library/src/main/AndroidManifest.xml similarity index 100% rename from aerogear-android-authz/src/main/AndroidManifest.xml rename to library/src/main/AndroidManifest.xml diff --git a/aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/AuthorizationConfiguration.java b/library/src/main/java/org/jboss/aerogear/android/authorization/AuthorizationConfiguration.java similarity index 100% rename from aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/AuthorizationConfiguration.java rename to library/src/main/java/org/jboss/aerogear/android/authorization/AuthorizationConfiguration.java diff --git a/aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/AuthorizationManager.java b/library/src/main/java/org/jboss/aerogear/android/authorization/AuthorizationManager.java similarity index 100% rename from aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/AuthorizationManager.java rename to library/src/main/java/org/jboss/aerogear/android/authorization/AuthorizationManager.java diff --git a/aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/AuthzModule.java b/library/src/main/java/org/jboss/aerogear/android/authorization/AuthzModule.java similarity index 100% rename from aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/AuthzModule.java rename to library/src/main/java/org/jboss/aerogear/android/authorization/AuthzModule.java diff --git a/aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/OnAuthorizationCreatedListener.java b/library/src/main/java/org/jboss/aerogear/android/authorization/OnAuthorizationCreatedListener.java similarity index 100% rename from aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/OnAuthorizationCreatedListener.java rename to library/src/main/java/org/jboss/aerogear/android/authorization/OnAuthorizationCreatedListener.java diff --git a/aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthorizationConfiguration.java b/library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthorizationConfiguration.java similarity index 100% rename from aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthorizationConfiguration.java rename to library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthorizationConfiguration.java diff --git a/aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthorizationException.java b/library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthorizationException.java similarity index 100% rename from aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthorizationException.java rename to library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthorizationException.java diff --git a/aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthroizationConfigurationProvider.java b/library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthroizationConfigurationProvider.java similarity index 100% rename from aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthroizationConfigurationProvider.java rename to library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthroizationConfigurationProvider.java diff --git a/aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthzModule.java b/library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthzModule.java similarity index 100% rename from aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthzModule.java rename to library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthzModule.java diff --git a/aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthzService.java b/library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthzService.java similarity index 100% rename from aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthzService.java rename to library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthzService.java diff --git a/aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthzSession.java b/library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthzSession.java similarity index 100% rename from aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthzSession.java rename to library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2AuthzSession.java diff --git a/aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2FetchAccess.java b/library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2FetchAccess.java similarity index 100% rename from aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2FetchAccess.java rename to library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2FetchAccess.java diff --git a/aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2Properties.java b/library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2Properties.java similarity index 100% rename from aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2Properties.java rename to library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2Properties.java diff --git a/aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2Utils.java b/library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2Utils.java similarity index 100% rename from aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2Utils.java rename to library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2Utils.java diff --git a/aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2WebFragmentFetchAutorization.java b/library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2WebFragmentFetchAutorization.java similarity index 100% rename from aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2WebFragmentFetchAutorization.java rename to library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuth2WebFragmentFetchAutorization.java diff --git a/aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuthWebViewDialog.java b/library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuthWebViewDialog.java similarity index 100% rename from aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuthWebViewDialog.java rename to library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/OAuthWebViewDialog.java diff --git a/aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/intent/OAuth2IntentAuthzModule.java b/library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/intent/OAuth2IntentAuthzModule.java similarity index 100% rename from aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/intent/OAuth2IntentAuthzModule.java rename to library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/intent/OAuth2IntentAuthzModule.java diff --git a/aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/webview/OAuth2WebViewAuthzModule.java b/library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/webview/OAuth2WebViewAuthzModule.java similarity index 100% rename from aerogear-android-authz/src/main/java/org/jboss/aerogear/android/authorization/oauth2/webview/OAuth2WebViewAuthzModule.java rename to library/src/main/java/org/jboss/aerogear/android/authorization/oauth2/webview/OAuth2WebViewAuthzModule.java diff --git a/aerogear-android-authz/src/main/res/layout/oauth_web_view.xml b/library/src/main/res/layout/oauth_web_view.xml similarity index 100% rename from aerogear-android-authz/src/main/res/layout/oauth_web_view.xml rename to library/src/main/res/layout/oauth_web_view.xml diff --git a/aerogear-android-authz/src/main/res/values/strings.xml b/library/src/main/res/values/strings.xml similarity index 100% rename from aerogear-android-authz/src/main/res/values/strings.xml rename to library/src/main/res/values/strings.xml diff --git a/aerogear-android-authz/src/main/res/values/styles.xml b/library/src/main/res/values/styles.xml similarity index 100% rename from aerogear-android-authz/src/main/res/values/styles.xml rename to library/src/main/res/values/styles.xml diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 630c1cc..0000000 --- a/pom.xml +++ /dev/null @@ -1,122 +0,0 @@ - - - - 4.0.0 - - org.jboss.aerogear - aerogear-android-authz-parent - 3.1.2-SNAPSHOT - pom - AeroGear Android Authorization Parent - http://aerogear.org - - - org.jboss.aerogear - aerogear-parent - 0.2.21 - - - - aerogear-android-authz - - - - scm:git:git@github.com:aerogear/aerogear-android-authz.git - scm:git:git@github.com:aerogear/aerogear-android-authz.git - git@github.com:aerogear/aerogear-android-authz.git - HEAD - - - - - - 0.2.21 - - - 4.4.3 - - - 24 - false - true - - - - - - - - - org.jboss.aerogear - aerogear-bom - ${aerogear.bom.version} - pom - import - - - - - org.jboss.aerogear - aerogear-android-bom - ${aerogear.bom.version} - pom - import - - - - - - - - - - android - android - provided - - - - - - - - - com.simpligility.maven.plugins - android-maven-plugin - ${maven.android.plugin.version} - true - - - - - - - android-tests - - - !release - - - - aerogear-android-authz-test - - - - - - diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..d8f14a1 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +include ':library' From 9a7c78c4452354c8dc66ff34ffbaec9e5b52f6aa Mon Sep 17 00:00:00 2001 From: Summers Pittman Date: Thu, 20 Jul 2017 11:26:46 -0400 Subject: [PATCH 3/4] Porting to gradle cont. Working out proguard and 65k method issues --- gradle/wrapper/gradle-wrapper.properties | 4 +- .../authorization/test/MainActivity.java | 173 ------------------ ...atchedActivityInstrumentationTestCase.java | 54 ------ library/build.gradle | 24 ++- .../androidTest}/AndroidManifest.xml | 0 .../authorization/test/helper/Data.java | 0 .../test/helper/DataWithNoIdConfigured.java | 0 .../test/helper/DataWithNoPropertyId.java | 0 .../test/helper/ObjectVarArgsMatcher.java | 3 +- .../test/oauth2/AuthzServiceTest.java | 31 ++-- .../oauth2/IntentOAuth2AuthzModuleTest.java | 32 ++-- .../test/oauth2/OAuth2AuthzModuleTest.java | 38 ++-- .../authorization/test/util/StubActivity.java | 0 .../test/util/UnitTestUtils.java | 130 +++++++++++++ .../authorization/test/util/VoidCallback.java | 0 .../androidTest}/res/layout/activity_main.xml | 0 .../androidTest}/res/menu/main.xml | 0 .../androidTest}/res/values/dimens.xml | 0 .../androidTest}/res/values/strings.xml | 0 library/src/main/AndroidManifest.xml | 2 +- 20 files changed, 200 insertions(+), 291 deletions(-) delete mode 100644 library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/MainActivity.java delete mode 100644 library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/util/PatchedActivityInstrumentationTestCase.java rename library/{androidTest/src/main => src/androidTest}/AndroidManifest.xml (100%) rename library/{androidTest/src/main => src/androidTest}/java/org/jboss/aerogear/android/authorization/test/helper/Data.java (100%) rename library/{androidTest/src/main => src/androidTest}/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoIdConfigured.java (100%) rename library/{androidTest/src/main => src/androidTest}/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoPropertyId.java (100%) rename library/{androidTest/src/main => src/androidTest}/java/org/jboss/aerogear/android/authorization/test/helper/ObjectVarArgsMatcher.java (94%) rename library/{androidTest/src/main => src/androidTest}/java/org/jboss/aerogear/android/authorization/test/oauth2/AuthzServiceTest.java (94%) rename library/{androidTest/src/main => src/androidTest}/java/org/jboss/aerogear/android/authorization/test/oauth2/IntentOAuth2AuthzModuleTest.java (83%) rename library/{androidTest/src/main => src/androidTest}/java/org/jboss/aerogear/android/authorization/test/oauth2/OAuth2AuthzModuleTest.java (90%) rename library/{androidTest/src/main => src/androidTest}/java/org/jboss/aerogear/android/authorization/test/util/StubActivity.java (100%) create mode 100644 library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/util/UnitTestUtils.java rename library/{androidTest/src/main => src/androidTest}/java/org/jboss/aerogear/android/authorization/test/util/VoidCallback.java (100%) rename library/{androidTest/src/main => src/androidTest}/res/layout/activity_main.xml (100%) rename library/{androidTest/src/main => src/androidTest}/res/menu/main.xml (100%) rename library/{androidTest/src/main => src/androidTest}/res/values/dimens.xml (100%) rename library/{androidTest/src/main => src/androidTest}/res/values/strings.xml (100%) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 921e902..dd166ba 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Jul 20 09:55:58 EDT 2017 +#Thu Jul 20 10:35:25 EDT 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip diff --git a/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/MainActivity.java b/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/MainActivity.java deleted file mode 100644 index 251333d..0000000 --- a/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/MainActivity.java +++ /dev/null @@ -1,173 +0,0 @@ -/** - * JBoss, Home of Professional Open Source - * Copyright Red Hat, Inc., and individual contributors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jboss.aerogear.android.authorization.test; - -import android.app.Activity; -import android.os.Bundle; -import android.view.Menu; -import android.view.WindowManager; -import org.jboss.aerogear.android.core.reflection.FieldNotFoundException; -import org.mockito.Mockito; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -public class MainActivity extends Activity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - getWindow().addFlags( - WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED - | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON - | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON - | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD); - - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - // Inflate the menu; this adds items to the action bar if it is present. - getMenuInflater().inflate(R.menu.main, menu); - return true; - } - - public static class UnitTestUtils { - - public static void setPrivateField(Object target, String fieldName, - Object value) throws NoSuchFieldException, - IllegalArgumentException, IllegalAccessException { - List fields = getAllFields(new ArrayList(), target.getClass()); - - for (Field field : fields) { - if (field.getName().equals(fieldName)) { - field.setAccessible(true); - field.set(target, value); - return; - } - } - - throw new FieldNotFoundException(target.getClass(), fieldName); - - } - - public static Object getPrivateField(Object target, String fieldName) - throws NoSuchFieldException, IllegalArgumentException, - IllegalAccessException { - Field field = target.getClass().getDeclaredField(fieldName); - field.setAccessible(true); - return field.get(target); - } - - public static Object getSuperPrivateField(Object target, String fieldName) - throws NoSuchFieldException, IllegalArgumentException, - IllegalAccessException { - Field field = target.getClass().getSuperclass().getDeclaredField(fieldName); - field.setAccessible(true); - return field.get(target); - } - - public static T getPrivateField(Object target, String fieldName, - Class type) throws NoSuchFieldException, - IllegalArgumentException, IllegalAccessException { - Field field = target.getClass().getDeclaredField(fieldName); - field.setAccessible(true); - return (T) field.get(target); - } - - /** - * - * This method extracts a named field, replaces it with a spy, and returns - * the spy. - * - * @param target The object requiring a hot spy injection - * @param fieldName the field to spy on - * @param type The type of the spy - * @return a spy which has replaced the field from fieldName - * - * @param the class of object which is being replaced with a spy. - * - * @throws NoSuchFieldException if a field is not found. (Thrown from the java reflection API) - * @throws IllegalArgumentException if an argument is illegal. (Thrown from the java reflection API) - * @throws IllegalAccessException if access is exceptional. (Thrown from the java reflection API) - */ - public static T replaceWithSpy(Object target, String fieldName, - Class type) throws NoSuchFieldException, - IllegalArgumentException, IllegalAccessException { - Field field = target.getClass().getDeclaredField(fieldName); - field.setAccessible(true); - T object = (T) field.get(target); - object = Mockito.spy(object); - setPrivateField(target, fieldName, object); - return object; - } - - public static List getAllFields(List fields, Class type) { - Collections.addAll(fields, type.getDeclaredFields()); - - if (type.getSuperclass() != null) { - fields = getAllFields(fields, type.getSuperclass()); - } - - return fields; - } - - public static void callMethod(Object target, String methodName) { - try { - Method method = target.getClass().getDeclaredMethod(methodName); - method.setAccessible(true); - method.invoke(target); - } catch (IllegalAccessException ex) { - Logger.getLogger(UnitTestUtils.class.getName()).log(Level.SEVERE, null, ex); - throw new RuntimeException(ex); - } catch (IllegalArgumentException ex) { - Logger.getLogger(UnitTestUtils.class.getName()).log(Level.SEVERE, null, ex); - throw new RuntimeException(ex); - } catch (InvocationTargetException ex) { - Logger.getLogger(UnitTestUtils.class.getName()).log(Level.SEVERE, null, ex); - throw new RuntimeException(ex); - } catch (NoSuchMethodException ex) { - Logger.getLogger(UnitTestUtils.class.getName()).log(Level.SEVERE, null, ex); - throw new RuntimeException(ex); - } catch (SecurityException ex) { - Logger.getLogger(UnitTestUtils.class.getName()).log(Level.SEVERE, null, ex); - throw new RuntimeException(ex); - } - } - - public static Object getPrivateEnum(Class klass, String enumName, String constantName) { - for (Class declaredClass : klass.getDeclaredClasses()) { - if (declaredClass.getCanonicalName().equals(enumName)) { - for (Object t : declaredClass.getEnumConstants()) { - if (t.toString().equals(constantName)) { - return t; - } - } - } - } - return null; - } - } -} diff --git a/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/util/PatchedActivityInstrumentationTestCase.java b/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/util/PatchedActivityInstrumentationTestCase.java deleted file mode 100644 index 053219d..0000000 --- a/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/util/PatchedActivityInstrumentationTestCase.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * JBoss, Home of Professional Open Source - * Copyright Red Hat, Inc., and individual contributors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jboss.aerogear.android.authorization.test.util; - -import android.app.Activity; -import android.content.Intent; -import android.support.test.rule.ActivityTestRule; -import org.junit.Before; - -/** - * All tests which use Mockito should extend this class. - * - * In Android 4.3 the dexcache is not set as it was previously and Mockito will - * throw an Exception. This class sets the dexcache directory correctly during - * test setup. - * - */ -public abstract class PatchedActivityInstrumentationTestCase { - - - private final ActivityTestRule rule; - - public PatchedActivityInstrumentationTestCase(Class klass) { - rule = new ActivityTestRule(klass, false, false); - } - - @Before - /** - * Sets the dexcache property before test execution. - */ - public void setDexcacheDir() throws Exception { - rule.launchActivity(new Intent(Intent.ACTION_MAIN)); - System.setProperty("dexmaker.dexcache", rule.getActivity().getCacheDir().getPath()); - } - - protected Activity getActivity() { - return rule.getActivity(); - } - -} \ No newline at end of file diff --git a/library/build.gradle b/library/build.gradle index b115b51..3bd1503 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -15,21 +15,31 @@ android { } buildTypes { - release { + debug { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } } + packagingOptions { + exclude 'META-INF/NOTICE' + exclude 'META-INF/LICENSE' + exclude 'META-INF/ASL-2.0.txt' + exclude 'META-INF/LGPL-3.0.txt' + exclude 'META-INF/INDEX.LIST' + exclude 'APK META-INF/io.netty.versions.properties' + exclude 'META-INF/io.netty.versions.properties' + } + lintOptions { + disable 'InvalidPackage'//aerogear-crypto includes a namespace that isn't exposed by our APIs + } } dependencies { - compile 'com.android.support:appcompat-v7:25.3.1' - compile 'org.jboss.aerogear:aerogear-android-core:3.1.0' compile 'org.jboss.aerogear:aerogear-android-store:3.1.0' - compile 'org.jboss.aerogear:aerogear-android-pipe:3.2.0' - compile 'com.google.code.gson:gson:2.8.1' - - testCompile 'junit:junit:4.12' + compile ('org.jboss.aerogear:aerogear-android-pipe:3.2.0') { + exclude group: 'com.android.support', module: "support-v4" + } androidTestCompile 'com.linkedin.dexmaker:dexmaker-mockito:2.2.0' androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { diff --git a/library/androidTest/src/main/AndroidManifest.xml b/library/src/androidTest/AndroidManifest.xml similarity index 100% rename from library/androidTest/src/main/AndroidManifest.xml rename to library/src/androidTest/AndroidManifest.xml diff --git a/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/helper/Data.java b/library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/helper/Data.java similarity index 100% rename from library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/helper/Data.java rename to library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/helper/Data.java diff --git a/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoIdConfigured.java b/library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoIdConfigured.java similarity index 100% rename from library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoIdConfigured.java rename to library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoIdConfigured.java diff --git a/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoPropertyId.java b/library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoPropertyId.java similarity index 100% rename from library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoPropertyId.java rename to library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/helper/DataWithNoPropertyId.java diff --git a/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/helper/ObjectVarArgsMatcher.java b/library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/helper/ObjectVarArgsMatcher.java similarity index 94% rename from library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/helper/ObjectVarArgsMatcher.java rename to library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/helper/ObjectVarArgsMatcher.java index 904b439..017cfb8 100644 --- a/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/helper/ObjectVarArgsMatcher.java +++ b/library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/helper/ObjectVarArgsMatcher.java @@ -23,8 +23,7 @@ * Convenience class for matching varargs. * */ -public class ObjectVarArgsMatcher extends ArgumentMatcher implements - VarargMatcher { +public class ObjectVarArgsMatcher implements ArgumentMatcher, VarargMatcher { private static final long serialVersionUID = 1L; private final Object[] expectedValues; diff --git a/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/AuthzServiceTest.java b/library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/oauth2/AuthzServiceTest.java similarity index 94% rename from library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/AuthzServiceTest.java rename to library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/oauth2/AuthzServiceTest.java index 0ce4091..b5ee983 100644 --- a/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/AuthzServiceTest.java +++ b/library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/oauth2/AuthzServiceTest.java @@ -17,54 +17,51 @@ package org.jboss.aerogear.android.authorization.test.oauth2; import android.support.test.runner.AndroidJUnit4; + import com.google.gson.JsonObject; -import java.net.HttpURLConnection; import org.jboss.aerogear.android.authorization.oauth2.OAuth2AuthorizationException; import org.jboss.aerogear.android.authorization.oauth2.OAuth2AuthzService; import org.jboss.aerogear.android.authorization.oauth2.OAuth2AuthzSession; import org.jboss.aerogear.android.authorization.oauth2.OAuth2Properties; -import org.jboss.aerogear.android.authorization.test.MainActivity; -import org.jboss.aerogear.android.store.Store; +import org.jboss.aerogear.android.authorization.test.util.UnitTestUtils; import org.jboss.aerogear.android.pipe.http.HeaderAndBody; -import org.jboss.aerogear.android.pipe.http.HttpProvider; import org.jboss.aerogear.android.pipe.http.HttpException; +import org.jboss.aerogear.android.pipe.http.HttpProvider; +import org.jboss.aerogear.android.store.Store; import org.jboss.aerogear.android.store.sql.SQLStore; -import org.jboss.aerogear.android.authorization.test.util.PatchedActivityInstrumentationTestCase; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; +import java.net.HttpURLConnection; import java.net.URL; import java.util.Calendar; import java.util.HashMap; import static java.util.Calendar.HOUR; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @RunWith(AndroidJUnit4.class) -public class AuthzServiceTest extends PatchedActivityInstrumentationTestCase { +public class AuthzServiceTest { @Rule public ExpectedException expectedEx = ExpectedException.none(); - + private OAuth2AuthzService service; private Store mockStore; private OAuth2AuthzSession account; private URL baseUrl; private HttpProvider mockProvider; - public AuthzServiceTest() { - super(MainActivity.class); - } @Before public void setUp() throws Exception { @@ -78,7 +75,7 @@ protected HttpProvider getHttpProvider(URL url) { } }; - MainActivity.UnitTestUtils.setPrivateField(service, "sessionStore", mockStore); + UnitTestUtils.setPrivateField(service, "sessionStore", mockStore); account = new OAuth2AuthzSession(); account.setAccessToken("testToken"); diff --git a/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/IntentOAuth2AuthzModuleTest.java b/library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/oauth2/IntentOAuth2AuthzModuleTest.java similarity index 83% rename from library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/IntentOAuth2AuthzModuleTest.java rename to library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/oauth2/IntentOAuth2AuthzModuleTest.java index f52fd1f..7a601f5 100644 --- a/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/IntentOAuth2AuthzModuleTest.java +++ b/library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/oauth2/IntentOAuth2AuthzModuleTest.java @@ -18,11 +18,7 @@ import android.app.Activity; import android.os.Looper; import android.support.test.runner.AndroidJUnit4; -import java.lang.reflect.Method; -import java.net.MalformedURLException; -import java.net.URL; -import org.jboss.aerogear.android.core.Callback; import org.jboss.aerogear.android.authorization.AuthorizationManager; import org.jboss.aerogear.android.authorization.AuthzModule; import org.jboss.aerogear.android.authorization.oauth2.OAuth2AuthorizationConfiguration; @@ -30,13 +26,18 @@ import org.jboss.aerogear.android.authorization.oauth2.OAuth2AuthzSession; import org.jboss.aerogear.android.authorization.oauth2.OAuth2Properties; import org.jboss.aerogear.android.authorization.oauth2.intent.OAuth2IntentAuthzModule; -import org.jboss.aerogear.android.authorization.test.MainActivity; -import org.jboss.aerogear.android.authorization.test.util.PatchedActivityInstrumentationTestCase; +import org.jboss.aerogear.android.authorization.test.util.UnitTestUtils; +import org.jboss.aerogear.android.core.Callback; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; -import static org.mockito.Matchers.any; import org.mockito.Mockito; + +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; + +import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; @@ -44,7 +45,8 @@ * Tests the {@link OAuth2IntentAuthzModule} class. */ @RunWith(AndroidJUnit4.class) -public class IntentOAuth2AuthzModuleTest extends PatchedActivityInstrumentationTestCase { +public class IntentOAuth2AuthzModuleTest { + private static final URL BASE_URL; @@ -55,10 +57,8 @@ public class IntentOAuth2AuthzModuleTest extends PatchedActivityInstrumentationT throw new RuntimeException(ex); } } - public IntentOAuth2AuthzModuleTest() { - super(MainActivity.class); - } - + + /** * If the OAuth2 Config Object has withIntent set then asModule should return * a OAuth2IntentAuthzModule instance. @@ -86,8 +86,8 @@ public void testIntentPutsAccountOnModule() throws Exception { config.setAccountId("ignore"); config.setWithIntent(true); AuthzModule module = config.asModule(); - Assert.assertNull(MainActivity.UnitTestUtils.getSuperPrivateField(module, "account")); -// /String state, Activity activity, Callback callback, OAuth2AuthzService.AGAuthzServiceConnection instance + Assert.assertNull(UnitTestUtils.getSuperPrivateField(module, "account")); + Method doRequestAccessMethod = OAuth2IntentAuthzModule.class.getDeclaredMethod("doRequestAccess", String.class, Activity.class, Callback.class, OAuth2AuthzService.AGAuthzServiceConnection.class); OAuth2AuthzService.AGAuthzServiceConnection mockConnection = mock(OAuth2AuthzService.AGAuthzServiceConnection.class); OAuth2AuthzService mockService = mock(OAuth2AuthzService.class); @@ -100,8 +100,8 @@ public void testIntentPutsAccountOnModule() throws Exception { Looper.prepare(); doRequestAccessMethod.setAccessible(true); - doRequestAccessMethod.invoke(module, "ignore", getActivity(), mock(Callback.class), mockConnection); - Assert.assertNotNull(MainActivity.UnitTestUtils.getSuperPrivateField(module, "account")); + doRequestAccessMethod.invoke(module, "ignore", mock(Activity.class), mock(Callback.class), mockConnection); + Assert.assertNotNull(UnitTestUtils.getSuperPrivateField(module, "account")); } diff --git a/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/OAuth2AuthzModuleTest.java b/library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/oauth2/OAuth2AuthzModuleTest.java similarity index 90% rename from library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/OAuth2AuthzModuleTest.java rename to library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/oauth2/OAuth2AuthzModuleTest.java index 24ac47d..ed9fa3b 100644 --- a/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/oauth2/OAuth2AuthzModuleTest.java +++ b/library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/oauth2/OAuth2AuthzModuleTest.java @@ -19,37 +19,39 @@ import android.app.Activity; import android.content.Intent; import android.content.ServiceConnection; -import android.support.test.runner.AndroidJUnit4; import android.support.test.annotation.UiThreadTest; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.net.MalformedURLException; -import java.net.URL; -import org.jboss.aerogear.android.core.Callback; +import android.support.test.runner.AndroidJUnit4; + import org.jboss.aerogear.android.authorization.AuthorizationManager; -import org.jboss.aerogear.android.authorization.test.MainActivity; import org.jboss.aerogear.android.authorization.oauth2.OAuth2AuthorizationConfiguration; -import org.jboss.aerogear.android.authorization.oauth2.OAuth2AuthzService; import org.jboss.aerogear.android.authorization.oauth2.OAuth2AuthorizationException; import org.jboss.aerogear.android.authorization.oauth2.OAuth2AuthzModule; +import org.jboss.aerogear.android.authorization.oauth2.OAuth2AuthzService; import org.jboss.aerogear.android.authorization.oauth2.OAuth2AuthzSession; import org.jboss.aerogear.android.authorization.oauth2.webview.OAuth2WebViewAuthzModule; -import org.jboss.aerogear.android.authorization.test.util.PatchedActivityInstrumentationTestCase; +import org.jboss.aerogear.android.authorization.test.util.UnitTestUtils; import org.jboss.aerogear.android.authorization.test.util.VoidCallback; +import org.jboss.aerogear.android.core.Callback; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.net.URL; + import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.matches; -import org.mockito.Mockito; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; @RunWith(AndroidJUnit4.class) -public class OAuth2AuthzModuleTest extends PatchedActivityInstrumentationTestCase { +public class OAuth2AuthzModuleTest { private static final URL BASE_URL; @@ -61,9 +63,6 @@ public class OAuth2AuthzModuleTest extends PatchedActivityInstrumentationTestCas } } - public OAuth2AuthzModuleTest() { - super(MainActivity.class); - } @Test(expected = IllegalStateException.class) public void testRequiresBaseURL() { @@ -85,6 +84,7 @@ public void testCreation() throws MalformedURLException { Assert.assertEquals(module, AuthorizationManager.getModule("name")); } + @SuppressWarnings("WrongConstant") @Test public void testRequestAccess() { OAuth2AuthorizationConfiguration config = AuthorizationManager.config("name", OAuth2AuthorizationConfiguration.class); @@ -94,7 +94,7 @@ public void testRequestAccess() { Activity mockActivity = mock(Activity.class); Callback mockCallback = mock(Callback.class); when(mockActivity.bindService(any(Intent.class), any(ServiceConnection.class), any(Integer.class))).thenReturn(Boolean.TRUE); - when(mockActivity.getApplicationContext()).thenReturn(super.getActivity()); + when(mockActivity.getApplicationContext()).thenReturn(mockActivity); module.requestAccess(mockActivity, mockCallback); Mockito.verify(mockActivity, times(1)).bindService((Intent) any(), (ServiceConnection) any(), any(Integer.class)); @@ -111,7 +111,7 @@ public void testGetAccessTokens() throws NoSuchFieldException, IllegalArgumentEx OAuth2AuthzSession account = new OAuth2AuthzSession(); account.setAccessToken("testToken"); - MainActivity.UnitTestUtils.setPrivateField(module, "account", account); + UnitTestUtils.setPrivateField(module, "account", account); Assert.assertEquals("Bearer testToken", module.getAuthorizationFields(null, null, null).getHeaders().get(0).second); Assert.assertEquals("Authorization", module.getAuthorizationFields(null, null, null).getHeaders().get(0).first); @@ -138,7 +138,7 @@ public void testOAuth2AuthorizationCallback() throws ClassNotFoundException, NoS Callback callback = (Callback) constructor.newInstance(module, mockActivity, new VoidCallback(), mockServiceConnection); - MainActivity.UnitTestUtils.setPrivateField(module, "service", mockService); + UnitTestUtils.setPrivateField(module, "service", mockService); callback.onSuccess("testCode"); @@ -169,11 +169,11 @@ public void testOAuth2AccessCallback() throws ClassNotFoundException, NoSuchMeth Callback callback = (Callback) constructor.newInstance(module, mockActivity, new VoidCallback(), mockServiceConnection); - MainActivity.UnitTestUtils.setPrivateField(module, "service", mockService); + UnitTestUtils.setPrivateField(module, "service", mockService); callback.onSuccess("testToken"); Mockito.verify(mockActivity, times(1)).unbindService(eq(mockServiceConnection)); - Assert.assertEquals("testToken", ((OAuth2AuthzSession)MainActivity.UnitTestUtils.getSuperPrivateField(module, "account")).getAccessToken()); + Assert.assertEquals("testToken", ((OAuth2AuthzSession) UnitTestUtils.getSuperPrivateField(module, "account")).getAccessToken()); } } diff --git a/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/util/StubActivity.java b/library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/util/StubActivity.java similarity index 100% rename from library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/util/StubActivity.java rename to library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/util/StubActivity.java diff --git a/library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/util/UnitTestUtils.java b/library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/util/UnitTestUtils.java new file mode 100644 index 0000000..9e77b43 --- /dev/null +++ b/library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/util/UnitTestUtils.java @@ -0,0 +1,130 @@ +package org.jboss.aerogear.android.authorization.test.util; + +import org.jboss.aerogear.android.core.reflection.FieldNotFoundException; +import org.mockito.Mockito; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Created by summers on 7/20/17. + */ +public class UnitTestUtils { + + public static void setPrivateField(Object target, String fieldName, + Object value) throws NoSuchFieldException, + IllegalArgumentException, IllegalAccessException { + List fields = getAllFields(new ArrayList(), target.getClass()); + + for (Field field : fields) { + if (field.getName().equals(fieldName)) { + field.setAccessible(true); + field.set(target, value); + return; + } + } + + throw new FieldNotFoundException(target.getClass(), fieldName); + + } + + public static Object getPrivateField(Object target, String fieldName) + throws NoSuchFieldException, IllegalArgumentException, + IllegalAccessException { + Field field = target.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + return field.get(target); + } + + public static Object getSuperPrivateField(Object target, String fieldName) + throws NoSuchFieldException, IllegalArgumentException, + IllegalAccessException { + Field field = target.getClass().getSuperclass().getDeclaredField(fieldName); + field.setAccessible(true); + return field.get(target); + } + + public static T getPrivateField(Object target, String fieldName, + Class type) throws NoSuchFieldException, + IllegalArgumentException, IllegalAccessException { + Field field = target.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + return (T) field.get(target); + } + + /** + * This method extracts a named field, replaces it with a spy, and returns + * the spy. + * + * @param target The object requiring a hot spy injection + * @param fieldName the field to spy on + * @param type The type of the spy + * @param the class of object which is being replaced with a spy. + * @return a spy which has replaced the field from fieldName + * @throws NoSuchFieldException if a field is not found. (Thrown from the java reflection API) + * @throws IllegalArgumentException if an argument is illegal. (Thrown from the java reflection API) + * @throws IllegalAccessException if access is exceptional. (Thrown from the java reflection API) + */ + public static T replaceWithSpy(Object target, String fieldName, + Class type) throws NoSuchFieldException, + IllegalArgumentException, IllegalAccessException { + Field field = target.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + T object = (T) field.get(target); + object = Mockito.spy(object); + setPrivateField(target, fieldName, object); + return object; + } + + public static List getAllFields(List fields, Class type) { + Collections.addAll(fields, type.getDeclaredFields()); + + if (type.getSuperclass() != null) { + fields = getAllFields(fields, type.getSuperclass()); + } + + return fields; + } + + public static void callMethod(Object target, String methodName) { + try { + Method method = target.getClass().getDeclaredMethod(methodName); + method.setAccessible(true); + method.invoke(target); + } catch (IllegalAccessException ex) { + Logger.getLogger(UnitTestUtils.class.getName()).log(Level.SEVERE, null, ex); + throw new RuntimeException(ex); + } catch (IllegalArgumentException ex) { + Logger.getLogger(UnitTestUtils.class.getName()).log(Level.SEVERE, null, ex); + throw new RuntimeException(ex); + } catch (InvocationTargetException ex) { + Logger.getLogger(UnitTestUtils.class.getName()).log(Level.SEVERE, null, ex); + throw new RuntimeException(ex); + } catch (NoSuchMethodException ex) { + Logger.getLogger(UnitTestUtils.class.getName()).log(Level.SEVERE, null, ex); + throw new RuntimeException(ex); + } catch (SecurityException ex) { + Logger.getLogger(UnitTestUtils.class.getName()).log(Level.SEVERE, null, ex); + throw new RuntimeException(ex); + } + } + + public static Object getPrivateEnum(Class klass, String enumName, String constantName) { + for (Class declaredClass : klass.getDeclaredClasses()) { + if (declaredClass.getCanonicalName().equals(enumName)) { + for (Object t : declaredClass.getEnumConstants()) { + if (t.toString().equals(constantName)) { + return t; + } + } + } + } + return null; + } +} diff --git a/library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/util/VoidCallback.java b/library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/util/VoidCallback.java similarity index 100% rename from library/androidTest/src/main/java/org/jboss/aerogear/android/authorization/test/util/VoidCallback.java rename to library/src/androidTest/java/org/jboss/aerogear/android/authorization/test/util/VoidCallback.java diff --git a/library/androidTest/src/main/res/layout/activity_main.xml b/library/src/androidTest/res/layout/activity_main.xml similarity index 100% rename from library/androidTest/src/main/res/layout/activity_main.xml rename to library/src/androidTest/res/layout/activity_main.xml diff --git a/library/androidTest/src/main/res/menu/main.xml b/library/src/androidTest/res/menu/main.xml similarity index 100% rename from library/androidTest/src/main/res/menu/main.xml rename to library/src/androidTest/res/menu/main.xml diff --git a/library/androidTest/src/main/res/values/dimens.xml b/library/src/androidTest/res/values/dimens.xml similarity index 100% rename from library/androidTest/src/main/res/values/dimens.xml rename to library/src/androidTest/res/values/dimens.xml diff --git a/library/androidTest/src/main/res/values/strings.xml b/library/src/androidTest/res/values/strings.xml similarity index 100% rename from library/androidTest/src/main/res/values/strings.xml rename to library/src/androidTest/res/values/strings.xml diff --git a/library/src/main/AndroidManifest.xml b/library/src/main/AndroidManifest.xml index db77d29..e243dbe 100644 --- a/library/src/main/AndroidManifest.xml +++ b/library/src/main/AndroidManifest.xml @@ -1,5 +1,5 @@ - + From 10268eee3246e827968df51c93707d85ebeec8f9 Mon Sep 17 00:00:00 2001 From: Daniel Passos Date: Thu, 20 Jul 2017 15:56:39 -0300 Subject: [PATCH 4/4] Add circleci --- circle.yml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 circle.yml diff --git a/circle.yml b/circle.yml new file mode 100644 index 0000000..8aad797 --- /dev/null +++ b/circle.yml @@ -0,0 +1,34 @@ +machine: + java: + version: oraclejdk8 + environment: + QEMU_AUDIO_DRV: none + ANDROID_SDK: "android-25" + BUILD_TOOLS: "25.0.3" + ANDROID_EMULATOR: "circleci-android24" + ANDROID_ABI: "armeabi-v7a" + +dependencies: + pre: + # Android SDK Platform + - if [ ! -d "/usr/local/android-sdk-linux/platforms/$ANDROID_SDK" ]; then echo y | android update sdk --no-ui --all --filter "$ANDROID_SDK"; fi + # Android SDK Build-tools + - if [ ! -d "/usr/local/android-sdk-linux/build-tools/$BUILD_TOOLS" ]; then echo y | android update sdk --no-ui --all --filter "build-tools-$BUILD_TOOLS"; fi + # Android m2repository and extra support + - echo y | android update sdk --no-ui --all --filter "extra-google-m2repository, extra-android-m2repository, extra-android-support" + + cache_directories: + - /usr/local/android-sdk-linux + - ~/.gradle + +test: + pre: + # Launch the emulator + - emulator -avd $ANDROID_EMULATOR -no-window: + background: true + parallel: true + # Wait to emulator get ready + - circle-android wait-for-boot + + override: + - ./gradlew build connectedCheck