[
  {
    "path": ".gitignore",
    "content": "# Built application files\n*.apk\n*.ap_\n\n# Files for the Dalvik VM\n*.dex\n\n# Java class files\n*.class\n\n# Generated files\nbin/\ngen/\n\n# Gradle files\n.gradle/\n**/build/\n\n# Local configuration file (sdk path, etc)\nlocal.properties\n\n# Proguard folder generated by Eclipse\nproguard/\n\n# Log Files\n*.log\n\n# Android Studio\n.navigation/\n.idea/\n**/*.iml\n\n# Android Studio captures folder\ncaptures/\n\n# .DS_Store files\n**/.DS_Store\n\n# Credentials\napp/src/androidTest/java/org/fuckboilerplate/rxsocialconnect/Credentials.java\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2016 Fuck Boilerplate\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License."
  },
  {
    "path": "README.md",
    "content": ":warning: Deprecated :warning:\n\nUse [SocialConnect](https://github.com/cookpad/SocialConnect) instead.\n\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-RxSocialConnect--Android-brightgreen.svg?style=flat)](http://android-arsenal.com/details/1/3616)\n\nOAuth RxJava extension for Android. iOS version is located at this [repository](https://github.com/FuckBoilerplate/RxSocialConnect-iOS).\n\n# RxSocialConnect\n\nRxSocialConnect simplifies the process of retrieving authorizations tokens from multiple social networks to a minimalist observable call, from any Fragment or Activity.\n\n```java\nOAuth20Service facebookService = //...\n\nRxSocialConnect.with(fragmentOrActivity, facebookService)\n                    .subscribe(response -> response.targetUI().showResponse(response.token()));\n```\n\n## Features:\n\n* Webview implementation to handle the sequent steps of oauth process.\n* Storage of tokens encrypted locally\n* Automatic refreshing tokens taking care of expiration date.\n* I/O operations performed on secondary threads and automatic sync with user interface on the main thread, thanks to [RxAndroid](https://github.com/ReactiveX/RxAndroid)\n* Mayor social network supported, more than 16 providers; including Facebook, Twitter, GooglePlus, LinkedIn and so on. Indeed, it supports as many providers as [ScribeJava](https://github.com/scribejava/scribejava/tree/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples) does, because RxSocialConnect is a reactive-android wrapper around it.\n* Honors the observable chain. [RxOnActivityResult](https://github.com/VictorAlbertos/RxActivityResult) allows RxSocialConnect to transform every oauth process into an observable for a wonderful chaining process.\n\n## Setup\n\nAdd the JitPack repository in your build.gradle (top level module):\n```gradle\nallprojects {\n    repositories {\n        jcenter()\n        maven { url \"https://jitpack.io\" }\n    }\n}\n```\n\nAnd add next dependencies in the build.gradle of android app module:\n```gradle\ndependencies {\n    compile 'com.github.VictorAlbertos.RxSocialConnect-Android:core:1.0.1-2.x'\n    compile 'io.reactivex.rxjava2:rxjava:2.0.5'\n}\n```\n\n## Usage\nBecause RxSocialConnect uses RxActivityResult to deal with intent calls, all its requirements and features are inherited too.\n\nBefore attempting to use RxSocialConnect, you need to call `RxSocialConnect.register` in your Android `Application` class, supplying as parameter the current instance and an encryption key in order to save the tokens on disk encrypted, as long as an implementation of [JSONConverter](https://github.com/FuckBoilerplate/RxSocialConnect-Android/blob/master/core/src/main/java/org/fuckboilerplate/rx_social_connect/JSONConverter.java) interface.\n\nBecause RxSocialConnect uses internally [Jolyglot](https://github.com/VictorAlbertos/Jolyglot) to save on disk the tokens retrieved, you need to add one of the next dependency to gradle.\n\n```gradle\ndependencies {\n    // To use Gson\n    compile 'com.github.VictorAlbertos.Jolyglot:gson:0.0.3'\n\n    // To use Jackson\n    compile 'com.github.VictorAlbertos.Jolyglot:jackson:0.0.3'\n\n    // To use Moshi\n    compile 'com.github.VictorAlbertos.Jolyglot:moshi:0.0.3'\n}\n```\n\n```java\npublic class SampleApp extends Application {\n\n    @Override public void onCreate() {\n        super.onCreate();\n\n        RxSocialConnect.register(this, \"myEncryptionKey\")\n            .using(new GsonSpeaker());\n    }\n}\n```\n\nEvery feature RxSocialConnect exposes can be accessed from both, an `activity` or a `fragment` instance.\n\n**Limitation:**: Your fragments need to extend from `android.support.v4.app.Fragment` instead of `android.app.Fragment`, otherwise they won't be notified.\n\nThe generic type of the `observable` returned by RxSocialConnect when subscribing to any of its providers is always an instance of [Response](https://github.com/FuckBoilerplate/RxSocialConnect-Android/blob/master/core/src/main/java/org/fuckboilerplate/rx_social_connect/Response.java) class.\n\nThis instance holds a reference to the current Activity/Fragment, accessible calling `targetUI()` method. Because the original one may be recreated it would be unsafe calling it. Instead, you must call any method/variable of your Activity/Fragment from this instance encapsulated in the `response` instance.\n\nAlso, this instance holds a reference to the token.\n\n### Retrieving tokens using OAuth1.\n\nOn social networks which use OAuth1 protocol to authenticate users (such us Twitter), you need to build a [OAuth10aService](https://github.com/scribejava/scribejava/blob/master/scribejava-core/src/main/java/com/github/scribejava/core/oauth/OAuth10aService.java) instance and pass it to RxSocialConnect.\n\n```java\nOAuth10aService twitterService = new ServiceBuilder()\n                .apiKey(consumerKey)\n                .apiSecret(consumerSecret)\n                .callback(callbackUrl)\n                .build(TwitterApi.instance());\n\nRxSocialConnect.with(fragmentOrActivity, twitterService)\n                    .subscribe(response -> {\n                        OAuth1AccessToken token = response.token();\n                        response.targetUI().showToken(token.getToken());\n                        response.targetUI().showToken(token.getTokenSecret());\n                    });\n```\n\nOnce the OAuth1 process has been successfully completed, you can retrieve the cached token calling `RxSocialConnect.getTokenOAuth1(defaultApi10aClass)` -where `defaultApi10aClass` is the provider `class` used on the oauth1 process.\n\n```java\n        RxSocialConnect.getTokenOAuth1(TwitterApi.class)\n                .subscribe(token -> showResponse(token),\n                        error -> showError(error));\n```\n\n### Retrieving tokens using OAuth2.\n\nOn social networks which use OAuth2 protocol to authenticate users (such us Facebook, Google+ or LinkedIn), you need to build a [OAuth20Service](https://github.com/scribejava/scribejava/blob/master/scribejava-core/src/main/java/com/github/scribejava/core/oauth/OAuth20Service.java) instance and pass it to RxSocialConnect.\n\n```java\nOAuth20Service facebookService = new ServiceBuilder()\n                .apiKey(appId)\n                .apiSecret(appSecret)\n                .callback(callbackUrl)\n                .scope(\"public_profile\")\n                .build(FacebookApi.instance());\n\nRxSocialConnect.with(fragmentOrActivity, facebookService)\n                    .subscribe(response -> {\n                        OAuth2AccessToken token = response.token();\n                        response.targetUI().showToken(token.getAccessToken());\n                    });\n```\n\nOnce the OAuth2 process has been successfully completed, you can retrieve the cached token calling `RxSocialConnect.getTokenOAuth2(defaultApi20Class)` -where `defaultApi20Class` is the provider `class` used on the oauth2 process.\n\n```java\n        RxSocialConnect.getTokenOAuth2(FacebookApi.class)\n                .subscribe(token -> showResponse(token),\n                        error -> showError(error));\n```\n\n\n### Token lifetime.\nAfter retrieving the token, RxSocialConnect will save it on disk to return it on future calls without doing again the oauth process. This token only will be evicted from cache if it is a OAuth2AccessToken instance and its expiration time has been fulfilled.\n\nBut, if you need to close an specific connection (or delete the token from the disk for that matters), you can call `RxSocialConnect.closeConnection(baseApiClass)` at any time to evict the cached token -where `baseApiClass` is the provider `class` used on the oauth process.\n\n```java\n//Facebook\nRxSocialConnect.closeConnection(FacebookApi.class)\n                .subscribe(_I ->  showToast(\"Facebook disconnected\"));\n\n//Twitter\nRxSocialConnect.closeConnection(TwitterApi.class)\n                .subscribe(_I ->  showToast(\"Twitter disconnected\"));\n```\n\nYou can also close all the connections at once, calling `RxSocialConnect.closeConnections()`\n\n```java\nRxSocialConnect.closeConnections()\n                .subscribe(_I ->  showToast(\"All disconnected\"));\n```\n\n\n### OkHttp interceptors.\nRxSocialConnect can be powered with [OkHttp](https://github.com/square/okhttp) (or [Retrofit](https://github.com/square/retrofit) for that matters) to bypass authentication header configuration when dealing with specific endpoints.\nUsing the interceptors provided by RxSocialConnect, it's a 0 configuration process to be able to reach any http resource from any api client (Facebook, Twitter, etc).\n\nFirst of all, install RxSocialConnectInterceptors library using gradle:\n\n```gradle\ndependencies {\n    compile 'com.github.VictorAlbertos.RxSocialConnect-Android:okhttp_interceptors:1.0.1-2.x'\n}\n```\n\nAfter you have retrieved a valid token -if you attempt to use these interceptors prior to retrieving a valid token a [NotActiveTokenFoundException](https://github.com/FuckBoilerplate/RxSocialConnect-Android/blob/master/core/src/main/java/org/fuckboilerplate/rx_social_connect/NotActiveTokenFoundException.java) will be thrown, you can now use [OAuth1Interceptor](https://github.com/FuckBoilerplate/RxSocialConnect-Android/blob/master/okhttp_interceptors/src/main/java/io/victoralbertos/rx_social_connect/OAuth1Interceptor.java) or [OAuth2Interceptor](https://github.com/FuckBoilerplate/RxSocialConnect-Android/blob/master/okhttp_interceptors/src/main/java/io/victoralbertos/rx_social_connect/OAuth2Interceptor.java) classes to bypass the authentication headers configuration, depending on the OAuth version of your social network of interest.\n\n#### OAuth1Interceptor.\n```java\nOAuth10aService yahooService = //...\n\nOkHttpClient client = new OkHttpClient.Builder()\n                .addInterceptor(new OAuth1Interceptor(yahooService))\n                .build();\n\n//If using retrofit...\nYahooApiRest yahooApiRest = new Retrofit.Builder()\n        .baseUrl(\"\")\n        .client(client)\n        .build().create(YahooApiRest.class);\n```\n\n#### OAuth2Interceptor.\n```java\nOkHttpClient client = new OkHttpClient.Builder()\n                .addInterceptor(new OAuth2Interceptor(FacebookApi.class))\n                .build();\n\n//If using retrofit...\nFacebookApiRest facebookApiRest = new Retrofit.Builder()\n        .baseUrl(\"\")\n        .client(client)\n        .build().create(FacebookApiRest.class);\n```\n\nNow you are ready to perform any http call against any api in the same way you would do it for no OAuth apis.\n\n## Examples\n* Social networks connections examples can be found [here](https://github.com/FuckBoilerplate/RxSocialConnect-Android/tree/master/app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections).\n* OkHttp interceptors examples can be found [here](https://github.com/FuckBoilerplate/RxSocialConnect-Android/tree/master/app/src/main/java/org/fuckboilerplate/rxsocialconnect/interceptors).\n\n## Proguard\n```\n-dontwarn javax.xml.bind.DatatypeConverter\n-dontwarn org.apache.commons.codec.**\n-dontwarn com.ning.http.client.**\n\nkeep class org.fuckboilerplate.rx_social_connect.internal.persistence.OAuth1AccessToken {\n    <fields>;\n}\n-keep class org.fuckboilerplate.rx_social_connect.internal.persistence.OAuth2AccessToken {\n    <fields>;\n}\n```\n\n## Credits\n* Oauth core authentication: [ScribeJava](https://github.com/scribejava/scribejava)\n\n## Author\n**Víctor Albertos**\n* <https://twitter.com/_victorAlbertos>\n* <https://www.linkedin.com/in/victoralbertos>\n* <https://github.com/VictorAlbertos>\n\n## Another author's libraries using RxJava:\n* [RxCache](https://github.com/VictorAlbertos/RxCache): Reactive caching library for Android and Java.\n* [Mockery](https://github.com/VictorAlbertos/Mockery): Android and Java library for mocking and testing networking layers with built-in support for Retrofit\n* [RxActivityResult](https://github.com/VictorAlbertos/RxActivityResult): A reactive-tiny-badass-vindictive library to break with the OnActivityResult implementation as it breaks the observables chain.\n* [RxFcm](https://github.com/VictorAlbertos/RxFcm): RxJava extension for Android Firebase Cloud Messaging (aka fcm).\n* [RxPaparazzo](https://github.com/FuckBoilerplate/RxPaparazzo): RxJava extension for Android to take images using camera and gallery.\n"
  },
  {
    "path": "app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "app/build.gradle",
    "content": "apply plugin: 'com.android.application'\napply plugin: 'me.tatarka.retrolambda'\n\nbuildscript {\n    repositories {\n        mavenCentral()\n        jcenter()\n    }\n\n    dependencies {\n        classpath 'me.tatarka:gradle-retrolambda:3.2.4'\n    }\n}\n\nandroid {\n    compileSdkVersion 25\n    buildToolsVersion \"25.0.0\"\n\n    defaultConfig {\n        applicationId \"org.fuckboilerplate.rxsocialconnect\"\n        minSdkVersion 18\n        targetSdkVersion 25\n        versionCode 1\n        versionName \"1.0\"\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n    lintOptions {\n        abortOnError false\n    }\n    packagingOptions {\n        exclude 'META-INF/maven/com.google.guava/guava/pom.properties'\n        exclude 'META-INF/maven/com.google.guava/guava/pom.xml'\n    }\n}\n\ndependencies {\n    compile fileTree(dir: 'libs', include: ['*.jar'])\n    compile 'com.android.support:appcompat-v7:25.1.1'\n    compile 'com.android.support:design:25.1.1'\n    compile project(':core')\n    compile project(':okhttp_interceptors')\n\n    compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'\n    compile 'com.squareup.retrofit2:converter-gson:2.1.0'\n    compile \"com.github.VictorAlbertos.Jolyglot:gson:0.0.3\"\n    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'\n\n    compile 'com.android.support:support-annotations:25.1.1'\n\n    testCompile 'junit:junit:4.12'\n\n    androidTestCompile (\"com.android.support.test:runner:0.5\") {\n        exclude module: 'support-annotations'\n    }\n    androidTestCompile (\"com.android.support.test:rules:0.5\") {\n        exclude module: 'support-annotations'\n    }\n    androidTestCompile (\"com.android.support.test.espresso:espresso-web:2.2.2\") {\n        exclude module: 'support-annotations'\n        exclude module: 'support-v4'\n        exclude module: 'appcompat-v7'\n        exclude module: 'design'\n        exclude module: 'support-v13'\n    }\n    androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'\n}\n"
  },
  {
    "path": "app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /Users/victor/Documents/AndroidStudio/android_sdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "app/src/androidTest/java/org/fuckboilerplate/rxsocialconnect/ActivityTest.java",
    "content": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rxsocialconnect;\n\nimport android.support.test.rule.ActivityTestRule;\n\nimport org.fuckboilerplate.rxsocialconnect.connections.ConnectionsActivity;\nimport org.junit.Rule;\n\npublic class ActivityTest extends RxSocialConnectTest {\n    @Rule public ActivityTestRule<ConnectionsActivity> mActivityRule = new ActivityTestRule(ConnectionsActivity.class);\n}\n"
  },
  {
    "path": "app/src/androidTest/java/org/fuckboilerplate/rxsocialconnect/FragmentTest.java",
    "content": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rxsocialconnect;\n\nimport android.support.test.rule.ActivityTestRule;\n\nimport org.fuckboilerplate.rxsocialconnect.connections.HostActivityFragment;\nimport org.junit.Rule;\n\npublic class FragmentTest extends RxSocialConnectTest {\n    @Rule public ActivityTestRule<HostActivityFragment> mActivityRule = new ActivityTestRule(HostActivityFragment.class);\n}\n"
  },
  {
    "path": "app/src/androidTest/java/org/fuckboilerplate/rxsocialconnect/RxSocialConnectInterceptorsTest.java",
    "content": "package org.fuckboilerplate.rxsocialconnect;\n\nimport android.support.test.espresso.matcher.BoundedMatcher;\nimport android.support.test.espresso.web.webdriver.DriverAtoms;\nimport android.support.test.espresso.web.webdriver.Locator;\nimport android.support.test.rule.ActivityTestRule;\nimport android.support.test.runner.AndroidJUnit4;\nimport android.view.View;\nimport android.widget.TextView;\n\nimport org.fuckboilerplate.rxsocialconnect.interceptors.InterceptorsActivity;\nimport org.hamcrest.Description;\nimport org.hamcrest.Matcher;\nimport org.junit.FixMethodOrder;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.MethodSorters;\n\nimport static android.support.test.espresso.Espresso.onView;\nimport static android.support.test.espresso.action.ViewActions.click;\nimport static android.support.test.espresso.assertion.ViewAssertions.matches;\nimport static android.support.test.espresso.matcher.ViewMatchers.withId;\nimport static android.support.test.espresso.web.sugar.Web.onWebView;\nimport static android.support.test.espresso.web.webdriver.DriverAtoms.findElement;\nimport static android.support.test.espresso.web.webdriver.DriverAtoms.webClick;\n\n/**\n * To run the test first revoke permissions app from Facebook user profile.\n * Also, be aware that running these test will change the token value, so the unit tests of rx_social_connect_interceptors\n * related with yahoo and facebook will fail because the token will not longer be valid. So you need to update the token value\n * in the appropriate files after running this test.\n */\n@RunWith(AndroidJUnit4.class)\n@FixMethodOrder(MethodSorters.NAME_ASCENDING)\npublic class RxSocialConnectInterceptorsTest {\n    @Rule public ActivityTestRule<InterceptorsActivity> mActivityRule = new ActivityTestRule(InterceptorsActivity.class);\n\n    @Test public void _a1_Connect_With_Facebook() {\n        onView(withId(R.id.bt_connect_facebook)).perform(click());\n\n        waitTime();\n        onWebView()\n                .withElement(findElement(Locator.NAME, \"email\"))\n                .perform(DriverAtoms.webKeys(Credentials.EMAIL))\n                .withElement(findElement(Locator.NAME, \"pass\"))\n                .perform(DriverAtoms.webKeys(Credentials.PASSWORD))\n                .withElement(findElement(Locator.NAME, \"login\"))\n                .perform(webClick());\n\n        waitTime();\n        onWebView()\n                .withElement(findElement(Locator.NAME, \"__CONFIRM__\"))\n                .perform(webClick());\n        waitTime();\n    }\n\n    @Test public void _a2_Show_Profile_Facebook() {\n        onView(withId(R.id.tv_profile)).check(matches(shouldBeEmpty(true)));\n        onView(withId(R.id.bt_show_profile_facebook)).perform(click());\n        waitTime();\n        onView(withId(R.id.tv_profile)).check(matches(shouldBeEmpty(false)));\n    }\n\n    @Test public void _b1_Connect_With_Yahoo() {\n        onView(withId(R.id.bt_connect_yahoo)).perform(click());\n\n        waitTime();\n        onWebView()\n                .withElement(findElement(Locator.NAME, \"username\"))\n                .perform(DriverAtoms.webKeys(Credentials.EMAIL_YAHOO))\n                .withElement(findElement(Locator.NAME, \"signin\"))\n                .perform(webClick());\n\n        waitTime();\n        onWebView()\n                .withElement(findElement(Locator.NAME, \"passwd\"))\n                .perform(DriverAtoms.webKeys(Credentials.PASSWORD))\n                .withElement(findElement(Locator.NAME, \"signin\"))\n                .perform(webClick());\n\n        waitTime();\n        onWebView()\n                .withElement(findElement(Locator.NAME, \"agree\"))\n                .perform(webClick());\n        waitTime();\n    }\n\n    @Test public void _b2_Show_Profile_Yahoo() {\n        onView(withId(R.id.tv_profile)).check(matches(shouldBeEmpty(true)));\n        onView(withId(R.id.bt_show_profile_yahoo)).perform(click());\n        waitTime();\n        onView(withId(R.id.tv_profile)).check(matches(shouldBeEmpty(false)));\n    }\n\n    private Matcher<View> shouldBeEmpty(boolean shouldBeEmpty) {\n        return new BoundedMatcher<View, TextView>(TextView.class) {\n            @Override public void describeTo(Description description) {\n                description.appendText(\"no empty text: \");\n            }\n\n            @Override public boolean matchesSafely(TextView textView) {\n                String text = textView.getText().toString();\n                if (shouldBeEmpty) return text.isEmpty();\n                else return !text.isEmpty();\n            }\n        };\n    }\n\n    private void waitTime() {\n        try {Thread.sleep(3500);}\n        catch (InterruptedException e) { e.printStackTrace();}\n    }\n}"
  },
  {
    "path": "app/src/androidTest/java/org/fuckboilerplate/rxsocialconnect/RxSocialConnectTest.java",
    "content": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rxsocialconnect;\n\nimport android.os.RemoteException;\nimport android.support.test.InstrumentationRegistry;\nimport android.support.test.espresso.matcher.BoundedMatcher;\nimport android.support.test.espresso.web.webdriver.DriverAtoms;\nimport android.support.test.espresso.web.webdriver.Locator;\nimport android.support.test.runner.AndroidJUnit4;\nimport android.support.test.uiautomator.UiDevice;\nimport android.view.View;\nimport android.widget.TextView;\n\nimport org.hamcrest.Description;\nimport org.hamcrest.Matcher;\nimport org.junit.FixMethodOrder;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.MethodSorters;\n\nimport static android.support.test.espresso.Espresso.onView;\nimport static android.support.test.espresso.action.ViewActions.click;\nimport static android.support.test.espresso.assertion.ViewAssertions.matches;\nimport static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;\nimport static android.support.test.espresso.matcher.ViewMatchers.withId;\nimport static android.support.test.espresso.web.sugar.Web.onWebView;\nimport static android.support.test.espresso.web.webdriver.DriverAtoms.findElement;\nimport static android.support.test.espresso.web.webdriver.DriverAtoms.webClick;\n\n/**\n * Remove permissions for the app from facebook user profile before to run the test.\n */\n@RunWith(AndroidJUnit4.class)\n@FixMethodOrder(MethodSorters.NAME_ASCENDING)\npublic abstract class RxSocialConnectTest {\n\n    @Test public void _a1_Connect_With_Facebook() {\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n\n        onView(withId(R.id.bt_facebook)).perform(click());\n\n        waitTime();\n        rotateDevice();\n\n        onWebView()\n                .withElement(findElement(Locator.NAME, \"email\"))\n                .perform(DriverAtoms.webKeys(Credentials.EMAIL))\n                .withElement(findElement(Locator.NAME, \"pass\"))\n                .perform(DriverAtoms.webKeys(Credentials.PASSWORD))\n                .withElement(findElement(Locator.NAME, \"login\"))\n                .perform(webClick())\n                .withElement(findElement(Locator.NAME, \"__CONFIRM__\"))\n                .perform(webClick());\n\n        waitTime();\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));\n    }\n\n    @Test public void _a2_Connected_Facebook() {\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n        onView(withId(R.id.bt_facebook)).perform(click());\n        waitTime();\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));\n    }\n\n    @Test public void _a3_Get_Token_Facebook() {\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n        onView(withId(R.id.bt_facebook_get_token)).perform(click());\n        waitTime();\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));\n    }\n\n    @Test public void _a4_Disconnect_Facebook() {\n        onView(withId(R.id.bt_facebook_disconnect)).perform(click());\n        waitTime();\n    }\n\n    @Test public void _a5_Get_Token_Error_Facebook() {\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n        onView(withId(R.id.bt_facebook_get_token)).perform(click());\n        waitTime();\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n    }\n\n    @Test public void _a6_Facebook_Does_Not_Store_Cookies() {\n        onView(withId(R.id.bt_facebook)).perform(click());\n        waitTime();\n        onView(withId(R.id.webview)).check(matches(isDisplayed()));\n    }\n\n    @Test public void _b1_Connect_With_Google() {\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n\n        onView(withId(R.id.bt_google)).perform(click());\n\n        waitTime();\n        rotateDevice();\n\n        onWebView()\n                .withElement(findElement(Locator.NAME, \"Email\"))\n                .perform(DriverAtoms.webKeys(Credentials.EMAIL))\n                .withElement(findElement(Locator.NAME, \"signIn\"))\n                .perform(webClick());\n        waitTime();\n\n        onWebView()\n                .withElement(findElement(Locator.NAME, \"Passwd\"))\n                .perform(DriverAtoms.webKeys(Credentials.PASSWORD))\n                .withElement(findElement(Locator.ID, \"signIn\"))\n                .perform(webClick());\n\n        waitTime();\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));\n    }\n\n    @Test public void _b2_Connected_Google() {\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n        onView(withId(R.id.bt_google)).perform(click());\n        waitTime();\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));\n    }\n\n    @Test public void _b3_Get_Token_Google() {\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n        onView(withId(R.id.bt_google_get_token)).perform(click());\n        waitTime();\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));\n    }\n\n    @Test public void _b4_Disconnect_Google() {\n        onView(withId(R.id.bt_google_disconnect)).perform(click());\n        waitTime();\n    }\n\n    @Test public void _b5_Get_Token_Error_Google() {\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n        onView(withId(R.id.bt_google_get_token)).perform(click());\n        waitTime();\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n    }\n\n    @Test public void _b6_Google_Does_Not_Store_Cookies() {\n        onView(withId(R.id.bt_google)).perform(click());\n        waitTime();\n        onView(withId(R.id.webview)).check(matches(isDisplayed()));\n    }\n\n    @Test public void _d1_Connect_With_LinkedIn() {\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n\n        onView(withId(R.id.bt_linkedin)).perform(click());\n\n        waitTime();\n        rotateDevice();\n\n        onWebView()\n                .withElement(findElement(Locator.NAME, \"session_key\"))\n                .perform(DriverAtoms.webKeys(Credentials.EMAIL))\n                .withElement(findElement(Locator.NAME, \"session_password\"))\n                .perform(DriverAtoms.webKeys(Credentials.PASSWORD))\n                .withElement(findElement(Locator.NAME, \"authorize\"))\n                .perform(webClick());\n\n        waitTime();\n        waitTime();\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));\n    }\n\n    @Test public void _d2_Connected_LinkedIn() {\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n        onView(withId(R.id.bt_linkedin)).perform(click());\n        waitTime();\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));\n    }\n\n    @Test public void _d3_Get_Token_LinkedIn() {\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n        onView(withId(R.id.bt_linkedin_get_token)).perform(click());\n        waitTime();\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));\n    }\n\n    @Test public void _d4_Disconnect_LinkedIn() {\n        onView(withId(R.id.bt_linkedin_disconnect)).perform(click());\n        waitTime();\n    }\n\n    @Test public void _d5_Get_Token_Error_LinkedIn() {\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n        onView(withId(R.id.bt_linkedin_get_token)).perform(click());\n        waitTime();\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n    }\n\n    @Test public void _d6_LinkedIn_Does_Not_Store_Cookies() {\n        onView(withId(R.id.bt_linkedin)).perform(click());\n        waitTime();\n        onView(withId(R.id.webview)).check(matches(isDisplayed()));\n    }\n\n    @Test public void _e1_Connect_With_Yahoo() {\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n\n        onView(withId(R.id.bt_yahoo)).perform(click());\n\n        waitTime();\n        rotateDevice();\n\n        onWebView()\n                .withElement(findElement(Locator.NAME, \"username\"))\n                .perform(DriverAtoms.webKeys(Credentials.EMAIL_YAHOO))\n                .withElement(findElement(Locator.NAME, \"signin\"))\n                .perform(webClick());\n\n        waitTime();\n\n        onWebView()\n                .withElement(findElement(Locator.NAME, \"passwd\"))\n                .perform(DriverAtoms.webKeys(Credentials.PASSWORD))\n                .withElement(findElement(Locator.NAME, \"signin\"))\n                .perform(webClick());\n\n        waitTime();\n\n        onWebView()\n                .withElement(findElement(Locator.NAME, \"agree\"))\n                .perform(webClick());\n\n        waitTime();\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));\n    }\n\n    @Test public void _e2_Connected_Yahoo() {\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n        onView(withId(R.id.bt_yahoo)).perform(click());\n        waitTime();\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));\n    }\n\n    @Test public void _e3_Get_Token_Yahoo() {\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n        onView(withId(R.id.bt_yahoo_get_token)).perform(click());\n        waitTime();\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(false)));\n    }\n\n    @Test public void _e4_Disconnect_Yahoo() {\n        onView(withId(R.id.bt_yahoo_disconnect)).perform(click());\n        waitTime();\n    }\n\n    @Test public void _e5_Get_Token_Error_Yahoo() {\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n        onView(withId(R.id.bt_yahoo_get_token)).perform(click());\n        waitTime();\n        onView(withId(R.id.tv_token)).check(matches(shouldBeEmpty(true)));\n    }\n\n    @Test public void _e6_Yahoo_Does_Not_Store_Cookies() {\n        onView(withId(R.id.bt_yahoo)).perform(click());\n        waitTime();\n        onView(withId(R.id.webview)).check(matches(isDisplayed()));\n    }\n\n    //Twitter, github Can not be performed due to security restrictions.\n    //Exception: Caused by: java.lang.RuntimeException: Fatal exception checking document state: Evaluation: status: 13 value: {message=Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: \"script-src https://abs.twimg.com https://abs-0.twimg.com https://twitter.com https://mobile.twitter.com\".\n    //} hasMessage: true message: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: \"script-src https://abs.twimg.com https://abs-0.twimg.com https://twitter.com https://mobile.twitter.com\".\n\n    private Matcher<View> shouldBeEmpty(boolean shouldBeEmpty) {\n        return new BoundedMatcher<View, TextView>(TextView.class) {\n            @Override public void describeTo(Description description) {\n                description.appendText(\"no empty text: \");\n            }\n\n            @Override public boolean matchesSafely(TextView textView) {\n                String text = textView.getText().toString();\n                if (shouldBeEmpty) return text.isEmpty();\n                else return !text.isEmpty();\n            }\n        };\n    }\n\n    private void waitTime() {\n        try {Thread.sleep(3500);}\n        catch (InterruptedException e) { e.printStackTrace();}\n    }\n\n    private void rotateDevice() {\n        UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());\n        try {\n            uiDevice.setOrientationLeft();\n            waitTime();\n            uiDevice.setOrientationNatural();\n            waitTime();\n        } catch (RemoteException e) {\n            e.printStackTrace();\n        }\n    }\n\n}"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"org.fuckboilerplate.rxsocialconnect\">\n\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:name=\".SampleApp\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\">\n        <activity\n            android:name=\".StartActivity\"\n            android:label=\"@string/app_name\"\n            android:theme=\"@style/AppTheme.NoActionBar\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n        <activity\n            android:name=\".interceptors.InterceptorsActivity\"\n            android:label=\"@string/app_name\"\n            android:theme=\"@style/AppTheme.NoActionBar\"/>\n        <activity\n            android:name=\".connections.ChooseActivityOrFragment\"\n            android:label=\"@string/app_name\"\n            android:theme=\"@style/AppTheme.NoActionBar\"/>\n        <activity\n            android:name=\".connections.ConnectionsActivity\"\n            android:label=\"@string/app_name\"\n            android:theme=\"@style/AppTheme.NoActionBar\"/>\n        <activity\n            android:name=\".connections.HostActivityFragment\"\n            android:label=\"@string/app_name\"\n            android:theme=\"@style/AppTheme.NoActionBar\"/>\n    </application>\n\n</manifest>"
  },
  {
    "path": "app/src/main/java/org/fuckboilerplate/rxsocialconnect/SampleApp.java",
    "content": "package org.fuckboilerplate.rxsocialconnect;\n\nimport android.app.Application;\nimport io.victoralbertos.jolyglot.GsonSpeaker;\nimport org.fuckboilerplate.rx_social_connect.RxSocialConnect;\n\n/**\n * Created by victor on 17/05/16.\n */\npublic class SampleApp extends Application {\n\n    @Override public void onCreate() {\n        super.onCreate();\n\n        RxSocialConnect\n                .register(this, \"myEncryptionKey\")\n                .using(new GsonSpeaker());\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/org/fuckboilerplate/rxsocialconnect/StartActivity.java",
    "content": "package org.fuckboilerplate.rxsocialconnect;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android.os.Bundle;\n\nimport org.fuckboilerplate.rxsocialconnect.connections.ChooseActivityOrFragment;\nimport org.fuckboilerplate.rxsocialconnect.interceptors.InterceptorsActivity;\n\n/**\n * Created by victor on 24/05/16.\n */\npublic class StartActivity extends Activity {\n\n    @Override protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.start_activity);\n\n        findViewById(R.id.bt_connections).setOnClickListener(v ->\n                startActivity(new Intent(this, ChooseActivityOrFragment.class))\n        );\n\n        findViewById(R.id.bt_interceptors).setOnClickListener(v ->\n                startActivity(new Intent(this, InterceptorsActivity.class))\n        );\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/ChooseActivityOrFragment.java",
    "content": "package org.fuckboilerplate.rxsocialconnect.connections;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android.os.Bundle;\n\nimport org.fuckboilerplate.rxsocialconnect.R;\n\n/**\n * Created by victor on 20/05/16.\n */\npublic class ChooseActivityOrFragment extends Activity {\n\n    @Override protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.choose_activity_or_fragment);\n\n        findViewById(R.id.bt_activity)\n                .setOnClickListener(v -> startActivity(new Intent(this, ConnectionsActivity.class)));\n\n        findViewById(R.id.bt_fragment)\n                .setOnClickListener(v -> startActivity(new Intent(this, HostActivityFragment.class)));\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/ConnectionsActivity.java",
    "content": "package org.fuckboilerplate.rxsocialconnect.connections;\n\nimport android.os.Bundle;\nimport android.support.v7.app.AppCompatActivity;\n\nimport com.github.scribejava.apis.FacebookApi;\nimport com.github.scribejava.apis.GitHubApi;\nimport com.github.scribejava.apis.GoogleApi20;\nimport com.github.scribejava.apis.LinkedInApi20;\nimport com.github.scribejava.apis.TwitterApi;\nimport com.github.scribejava.apis.YahooApi;\n\nimport org.fuckboilerplate.rx_social_connect.RxSocialConnect;\nimport org.fuckboilerplate.rxsocialconnect.R;\n\npublic class ConnectionsActivity extends AppCompatActivity {\n    private Helper helper;\n\n    @Override protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.connections);\n\n        helper = new Helper(this);\n\n        setUpTwitter();\n        setUpFacebook();\n        setUpGoogle();\n        setUpLinkedIn();\n        setUpYahoo();\n        setUpGithub();\n\n        findViewById(R.id.bt_all_disconnect).setOnClickListener(v -> helper.closeAllConnection());\n    }\n\n    private void setUpTwitter() {\n        findViewById(R.id.bt_twitter).setOnClickListener(v -> {\n            RxSocialConnect.with(ConnectionsActivity.this, helper.twitterService())\n                    .subscribe(response -> response.targetUI().helper.showResponse(response.token()),\n                            error -> helper.showError(error));\n        });\n\n        findViewById(R.id.bt_twitter_get_token).setOnClickListener(v -> helper.showTokenOAuth1(TwitterApi.class));\n\n        findViewById(R.id.bt_twitter_disconnect).setOnClickListener(v -> helper.closeConnection(TwitterApi.class));\n    }\n\n    private void setUpFacebook() {\n        findViewById(R.id.bt_facebook).setOnClickListener(v -> {\n            RxSocialConnect.with(ConnectionsActivity.this, helper.facebookService())\n                    .subscribe(response -> response.targetUI().helper.showResponse(response.token()),\n                            error -> helper.showError(error));\n        });\n\n        findViewById(R.id.bt_facebook_get_token).setOnClickListener(v -> helper.showTokenOAuth2(FacebookApi.class));\n\n        findViewById(R.id.bt_facebook_disconnect).setOnClickListener(v -> helper.closeConnection(FacebookApi.class));\n    }\n\n    private void setUpGoogle() {\n        findViewById(R.id.bt_google).setOnClickListener(v -> {\n            RxSocialConnect.with(ConnectionsActivity.this, helper.googleService())\n                    .subscribe(response -> response.targetUI().helper.showResponse(response.token()),\n                            error -> helper.showError(error));\n        });\n\n        findViewById(R.id.bt_google_get_token).setOnClickListener(v -> helper.showTokenOAuth2(GoogleApi20.class));\n\n        findViewById(R.id.bt_google_disconnect).setOnClickListener(v -> helper.closeConnection(GoogleApi20.class));\n    }\n\n    private void setUpLinkedIn() {\n        findViewById(R.id.bt_linkedin).setOnClickListener(v -> {\n            RxSocialConnect.with(ConnectionsActivity.this, helper.linkedinService())\n                    .subscribe(response -> response.targetUI().helper.showResponse(response.token()),\n                            error -> helper.showError(error));\n        });\n\n        findViewById(R.id.bt_linkedin_get_token).setOnClickListener(v -> helper.showTokenOAuth2(LinkedInApi20.class));\n\n        findViewById(R.id.bt_linkedin_disconnect).setOnClickListener(v -> helper.closeConnection(LinkedInApi20.class));\n    }\n\n    private void setUpYahoo() {\n        findViewById(R.id.bt_yahoo).setOnClickListener(v -> {\n            RxSocialConnect.with(ConnectionsActivity.this, helper.yahooService())\n                    .subscribe(response -> response.targetUI().helper.showResponse(response.token()),\n                            error -> helper.showError(error));\n        });\n\n        findViewById(R.id.bt_yahoo_get_token).setOnClickListener(v -> helper.showTokenOAuth1(YahooApi.class));\n\n        findViewById(R.id.bt_yahoo_disconnect).setOnClickListener(v -> helper.closeConnection(YahooApi.class));\n    }\n\n    private void setUpGithub() {\n        findViewById(R.id.bt_github).setOnClickListener(v -> {\n            RxSocialConnect.with(ConnectionsActivity.this, helper.githubService())\n                .subscribe(response -> response.targetUI().helper.showResponse(response.token()),\n                    error -> helper.showError(error));\n        });\n\n        findViewById(R.id.bt_github_get_token).setOnClickListener(v -> helper.showTokenOAuth2(GitHubApi.class));\n\n        findViewById(R.id.bt_github_disconnect).setOnClickListener(v -> helper.closeConnection(GitHubApi.class));\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/ConnectionsFragment.java",
    "content": "package org.fuckboilerplate.rxsocialconnect.connections;\n\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\n\nimport com.github.scribejava.apis.FacebookApi;\nimport com.github.scribejava.apis.GitHubApi;\nimport com.github.scribejava.apis.GoogleApi20;\nimport com.github.scribejava.apis.LinkedInApi20;\nimport com.github.scribejava.apis.TwitterApi;\nimport com.github.scribejava.apis.YahooApi;\n\nimport org.fuckboilerplate.rx_social_connect.RxSocialConnect;\nimport org.fuckboilerplate.rxsocialconnect.R;\n\npublic class ConnectionsFragment extends Fragment {\n    private Helper helper;\n\n    @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        return inflater.inflate(R.layout.connections, container, false);\n    }\n\n    @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) {\n        super.onActivityCreated(savedInstanceState);\n\n        helper = new Helper(this);\n\n        setUpTwitter();\n        setUpFacebook();\n        setUpGoogle();\n        setUpLinkedIn();\n        setUpYahoo();\n        setUpGithub();\n\n        findViewById(R.id.bt_all_disconnect).setOnClickListener(v -> helper.closeAllConnection());\n    }\n\n    private void setUpTwitter() {\n        findViewById(R.id.bt_twitter).setOnClickListener(v -> {\n            RxSocialConnect.with(ConnectionsFragment.this, helper.twitterService())\n                    .subscribe(response -> response.targetUI().helper.showResponse(response.token()),\n                            error -> helper.showError(error));\n        });\n\n        findViewById(R.id.bt_twitter_get_token).setOnClickListener(v -> helper.showTokenOAuth1(TwitterApi.class));\n\n        findViewById(R.id.bt_twitter_disconnect).setOnClickListener(v -> helper.closeConnection(TwitterApi.class));\n    }\n\n    private void setUpFacebook() {\n        findViewById(R.id.bt_facebook).setOnClickListener(v -> {\n            RxSocialConnect.with(ConnectionsFragment.this, helper.facebookService())\n                    .subscribe(response -> response.targetUI().helper.showResponse(response.token()),\n                            error -> helper.showError(error));\n        });\n\n        findViewById(R.id.bt_facebook_get_token).setOnClickListener(v -> helper.showTokenOAuth2(FacebookApi.class));\n\n        findViewById(R.id.bt_facebook_disconnect).setOnClickListener(v -> helper.closeConnection(FacebookApi.class));\n    }\n\n    private void setUpGoogle() {\n        findViewById(R.id.bt_google).setOnClickListener(v -> {\n            RxSocialConnect.with(ConnectionsFragment.this, helper.googleService())\n                    .subscribe(response -> response.targetUI().helper.showResponse(response.token()),\n                            error -> helper.showError(error));\n        });\n\n        findViewById(R.id.bt_google_get_token).setOnClickListener(v -> helper.showTokenOAuth2(GoogleApi20.class));\n\n        findViewById(R.id.bt_google_disconnect).setOnClickListener(v -> helper.closeConnection(GoogleApi20.class));\n    }\n\n    private void setUpLinkedIn() {\n        findViewById(R.id.bt_linkedin).setOnClickListener(v -> {\n            RxSocialConnect.with(ConnectionsFragment.this, helper.linkedinService())\n                    .subscribe(response -> response.targetUI().helper.showResponse(response.token()),\n                            error -> helper.showError(error));\n        });\n\n        findViewById(R.id.bt_linkedin_get_token).setOnClickListener(v -> helper.showTokenOAuth2(LinkedInApi20.class));\n\n        findViewById(R.id.bt_linkedin_disconnect).setOnClickListener(v -> helper.closeConnection(LinkedInApi20.class));\n    }\n\n    private void setUpYahoo() {\n        findViewById(R.id.bt_yahoo).setOnClickListener(v -> {\n            RxSocialConnect.with(ConnectionsFragment.this, helper.yahooService())\n                    .subscribe(response -> response.targetUI().helper.showResponse(response.token()),\n                            error -> helper.showError(error));\n        });\n\n        findViewById(R.id.bt_yahoo_get_token).setOnClickListener(v -> helper.showTokenOAuth1(YahooApi.class));\n\n        findViewById(R.id.bt_yahoo_disconnect).setOnClickListener(v -> helper.closeConnection(YahooApi.class));\n    }\n\n    private void setUpGithub() {\n        findViewById(R.id.bt_github).setOnClickListener(v -> {\n            RxSocialConnect.with(ConnectionsFragment.this, helper.githubService())\n                .subscribe(response -> response.targetUI().helper.showResponse(response.token()),\n                    error -> helper.showError(error));\n        });\n\n        findViewById(R.id.bt_github_get_token).setOnClickListener(v -> helper.showTokenOAuth2(GitHubApi.class));\n\n        findViewById(R.id.bt_github_disconnect).setOnClickListener(v -> helper.closeConnection(GitHubApi.class));\n    }\n\n    private View findViewById(int resId) {\n        return getView().findViewById(resId);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/Helper.java",
    "content": "package org.fuckboilerplate.rxsocialconnect.connections;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.support.v4.app.Fragment;\nimport android.view.View;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.github.scribejava.apis.FacebookApi;\nimport com.github.scribejava.apis.GitHubApi;\nimport com.github.scribejava.apis.GoogleApi20;\nimport com.github.scribejava.apis.LinkedInApi20;\nimport com.github.scribejava.apis.TwitterApi;\nimport com.github.scribejava.apis.YahooApi;\nimport com.github.scribejava.core.builder.ServiceBuilder;\nimport com.github.scribejava.core.builder.api.BaseApi;\nimport com.github.scribejava.core.builder.api.DefaultApi10a;\nimport com.github.scribejava.core.builder.api.DefaultApi20;\nimport com.github.scribejava.core.model.OAuth1AccessToken;\nimport com.github.scribejava.core.model.OAuth2AccessToken;\nimport com.github.scribejava.core.oauth.OAuth10aService;\nimport com.github.scribejava.core.oauth.OAuth20Service;\n\nimport org.fuckboilerplate.rx_social_connect.RxSocialConnect;\nimport org.fuckboilerplate.rxsocialconnect.R;\n\npublic class Helper {\n    private final Object targetUI;\n\n    public Helper(Object targetUI) {\n        this.targetUI = targetUI;\n    }\n\n    OAuth10aService twitterService() {\n        String consumerKey = \"3wEAwhjvJmBpJpUfIXiY9PQOg\";\n        String consumerSecret = \"8N47XdpE4GSlswMcBTOZFc3fDcil7WnK4RINfUyKf2d0rFrF2I\";\n        String callbackUrl = \"http://victoralbertos.com\";\n\n        return new ServiceBuilder()\n                .apiKey(consumerKey)\n                .apiSecret(consumerSecret)\n                .callback(callbackUrl)\n                .build(TwitterApi.instance());\n    }\n\n    OAuth20Service facebookService() {\n        String appId = \"452930454916873\";\n        String appSecret = \"4a643dd4c4537f01411ab7bb44736f1f\";\n        String callbackUrl = \"http://victoralbertos.com/\";\n        String permissions = \"public_profile, email\";\n\n        return new ServiceBuilder()\n                .apiKey(appId)\n                .apiSecret(appSecret)\n                .callback(callbackUrl)\n                .scope(permissions)\n                .build(FacebookApi.instance());\n    }\n\n    OAuth20Service googleService() {\n        String clientId = \"112202070176-3b8b2s85rtt39k6ga5f2001p937i57fq.apps.googleusercontent.com\";\n        String clientSecret = \"-zkjJwn3j_2JOyPSDHExJ6cO\";\n        String callbackUrl = \"http://victoralbertos.com/\";\n        String permissions = \"profile\";\n\n        return new ServiceBuilder()\n                .apiKey(clientId)\n                .apiSecret(clientSecret)\n                .callback(callbackUrl)\n                .scope(permissions)\n                .build(GoogleApi20.instance());\n    }\n\n    OAuth20Service linkedinService() {\n        String clientId = \"77u9plrpoq0g6t\";\n        String clientSecret = \"VlH229TNkzJysxbq\";\n        String callbackUrl = \"http://victoralbertos.com\";\n        String permissions = \"r_basicprofile\";\n\n        return new ServiceBuilder()\n                .apiKey(clientId)\n                .apiSecret(clientSecret)\n                .callback(callbackUrl)\n                .scope(permissions)\n                .build(LinkedInApi20.instance());\n    }\n\n    OAuth10aService yahooService() {\n        String clientId = \"dj0yJmk9Sk9NZUlPc0RaODVDJmQ9WVdrOVRubHlWMWRuTTJVbWNHbzlNQS0tJnM9Y29uc3VtZXJzZWNyZXQmeD0wNw--\";\n        String clientSecret = \"449b2d2f06d986297d65df7fc020544bf71eb10c\";\n        String callbackUrl = \"http://victoralbertos.com\";\n\n        return new ServiceBuilder()\n                .apiKey(clientId)\n                .apiSecret(clientSecret)\n                .callback(callbackUrl)\n                .build(YahooApi.instance());\n    }\n\n    OAuth20Service githubService() {\n        String appId = \"725a59980165855cc986\";\n        String appSecret = \"38733b4bf1c8646af86e38797f345847a0b61388\";\n        String callbackUrl = \"http://victoralbertos.com/\";\n\n        return new ServiceBuilder()\n            .apiKey(appId)\n            .apiSecret(appSecret)\n            .callback(callbackUrl)\n            .build(GitHubApi.instance());\n    }\n\n    void showTokenOAuth1(Class<? extends DefaultApi10a> clazz) {\n        RxSocialConnect.getTokenOAuth1(clazz)\n                .subscribe(token -> showResponse(token),\n                        error -> showError(error));\n    }\n\n    void showTokenOAuth2(Class<? extends DefaultApi20> clazz) {\n        RxSocialConnect.getTokenOAuth2(clazz)\n                .subscribe(token -> showResponse(token),\n                        error -> showError(error));\n    }\n\n    void closeConnection(Class<? extends BaseApi> clazz) {\n        RxSocialConnect\n                .closeConnection(clazz)\n                .subscribe(_I -> {\n                    showToast(clazz.getName() + \" disconnected\");\n                    clearEditTexts();\n                }, error -> showError(error));\n    }\n\n    void closeAllConnection() {\n        RxSocialConnect\n                .closeConnections()\n                .subscribe(_I -> {\n                    showToast(\"All disconnected\");\n                    clearEditTexts();\n                }, error -> showError(error));\n    }\n\n    void showResponse(OAuth1AccessToken token) {\n        clearEditTexts();\n        ((TextView)findViewById(R.id.tv_token)).setText(token.getToken());\n        ((TextView)findViewById(R.id.tv_secret)).setText(token.getTokenSecret());\n    }\n\n    void showResponse(OAuth2AccessToken token) {\n        clearEditTexts();\n        ((TextView)findViewById(R.id.tv_token)).setText(token.getAccessToken());\n    }\n\n    private void clearEditTexts() {\n        ((TextView)findViewById(R.id.tv_token)).setText(\"\");\n        ((TextView)findViewById(R.id.tv_secret)).setText(\"\");\n    }\n\n    void showError(Throwable throwable) {\n        clearEditTexts();\n        showToast(throwable.getMessage());\n    }\n\n    private View findViewById(int resId) {\n        if (targetUI instanceof Activity) return ((Activity) targetUI).findViewById(resId);\n        else return ((Fragment) targetUI).getView().findViewById(resId);\n    }\n\n    private void showToast(String message) {\n        Toast.makeText(getContext(), message, Toast.LENGTH_LONG).show();\n    }\n\n    private Context getContext() {\n        if (targetUI instanceof Activity) return  ((Activity) targetUI);\n        else return((Fragment) targetUI).getActivity();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/org/fuckboilerplate/rxsocialconnect/connections/HostActivityFragment.java",
    "content": "package org.fuckboilerplate.rxsocialconnect.connections;\n\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v7.app.AppCompatActivity;\n\nimport org.fuckboilerplate.rxsocialconnect.R;\n\n/**\n * Created by victor on 20/05/16.\n */\npublic class HostActivityFragment extends AppCompatActivity {\n\n    @Override protected void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.host_activity_fragment);\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/org/fuckboilerplate/rxsocialconnect/interceptors/InterceptorsActivity.java",
    "content": "package org.fuckboilerplate.rxsocialconnect.interceptors;\n\nimport android.os.Bundle;\nimport android.support.v7.app.AppCompatActivity;\nimport android.widget.TextView;\nimport android.widget.Toast;\nimport com.github.scribejava.core.model.OAuth1AccessToken;\nimport com.github.scribejava.core.model.OAuth2AccessToken;\nimport io.reactivex.android.schedulers.AndroidSchedulers;\nimport io.reactivex.schedulers.Schedulers;\nimport org.fuckboilerplate.rx_social_connect.RxSocialConnect;\nimport org.fuckboilerplate.rxsocialconnect.R;\n\npublic class InterceptorsActivity extends AppCompatActivity {\n    private Repository repository;\n\n    @Override protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.interceptors);\n        repository = new Repository();\n\n        setUpFacebook();\n        setUpYahoo();\n    }\n\n    private void setUpFacebook() {\n        findViewById(R.id.bt_connect_facebook).setOnClickListener(v ->\n            RxSocialConnect.with(this, repository.facebookService())\n                    .subscribe(response -> response.targetUI().showToken(response.token()),\n                            error -> showError(error))\n        );\n\n        findViewById(R.id.bt_show_profile_facebook).setOnClickListener(v ->\n                repository.getFacebookApi().me()\n                        .subscribeOn(Schedulers.io())\n                        .observeOn(AndroidSchedulers.mainThread())\n                        .subscribe(user -> showUserProfile(user.toString()),\n                                    error -> showError(error))\n        );\n    }\n\n    private void setUpYahoo() {\n        findViewById(R.id.bt_connect_yahoo).setOnClickListener(v ->\n                RxSocialConnect.with(this, repository.yahooService())\n                        .subscribe(response -> response.targetUI().showToken(response.token()),\n                                error -> showError(error))\n        );\n\n        findViewById(R.id.bt_show_profile_yahoo).setOnClickListener(v ->\n                repository.getYahooApiRest().me()\n                        .subscribeOn(Schedulers.io())\n                        .observeOn(AndroidSchedulers.mainThread())\n                        .subscribe(user -> showUserProfile(user.toString()),\n                                error -> showError(error))\n        );\n    }\n\n    private void showUserProfile(String userProfileJSON) {\n        clearTextViewToken();\n        TextView tv_profile = (TextView) findViewById(R.id.tv_profile);\n        tv_profile.setText(userProfileJSON);\n    }\n\n    private void showToken(OAuth2AccessToken oAuth2AccessToken) {\n        clearTextViewToken();\n        Toast.makeText(this, oAuth2AccessToken.getAccessToken(), Toast.LENGTH_SHORT).show();\n    }\n\n    private void showToken(OAuth1AccessToken token) {\n        clearTextViewToken();\n        Toast.makeText(this, token.getToken(), Toast.LENGTH_SHORT).show();\n    }\n\n    private void showError(Throwable error) {\n        clearTextViewToken();\n        Toast.makeText(this, error.getMessage(), Toast.LENGTH_SHORT).show();\n    }\n\n    private void clearTextViewToken() {\n        ((TextView) findViewById(R.id.tv_profile)).setText(\"\");\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/org/fuckboilerplate/rxsocialconnect/interceptors/Repository.java",
    "content": "package org.fuckboilerplate.rxsocialconnect.interceptors;\n\nimport com.github.scribejava.apis.FacebookApi;\nimport com.github.scribejava.apis.YahooApi;\nimport com.github.scribejava.core.builder.ServiceBuilder;\nimport com.github.scribejava.core.oauth.OAuth10aService;\nimport com.github.scribejava.core.oauth.OAuth20Service;\nimport com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;\nimport io.reactivex.Observable;\nimport io.victoralbertos.rx_social_connect.OAuth1Interceptor;\nimport io.victoralbertos.rx_social_connect.OAuth2Interceptor;\nimport okhttp3.OkHttpClient;\nimport retrofit2.Retrofit;\nimport retrofit2.converter.gson.GsonConverterFactory;\nimport retrofit2.http.GET;\n\npublic class Repository {\n    private final YahooApiRest yahooApiRest;\n    private final FacebookApiRest facebookApi;\n\n    public Repository() {\n        yahooApiRest = initYahooApiRest();\n        facebookApi = initFacebookApiRest();\n    }\n\n    private FacebookApiRest initFacebookApiRest() {\n        OkHttpClient client = new OkHttpClient.Builder()\n                .addInterceptor(new OAuth2Interceptor(FacebookApi.class))\n                .build();\n\n        return new Retrofit.Builder()\n                .baseUrl(FacebookApiRest.URL_BASE)\n                .client(client)\n                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())\n                .addConverterFactory(GsonConverterFactory.create())\n                .build().create(FacebookApiRest.class);\n    }\n\n    private YahooApiRest initYahooApiRest() {\n        OkHttpClient client = new OkHttpClient.Builder()\n                .addInterceptor(new OAuth1Interceptor(yahooService()))\n                .build();\n\n        return new Retrofit.Builder()\n                .baseUrl(YahooApiRest.URL_BASE)\n                .client(client)\n                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())\n                .addConverterFactory(GsonConverterFactory.create())\n                .build().create(YahooApiRest.class);\n    }\n\n    FacebookApiRest getFacebookApi() {\n        return facebookApi;\n    }\n\n    YahooApiRest getYahooApiRest() {\n        return yahooApiRest;\n    }\n\n    interface YahooApiRest {\n        String URL_BASE = \"https://social.yahooapis.com\";\n\n        @GET(\"/v1/user/me/profile?format=json\") Observable<Object> me();\n    }\n\n    interface FacebookApiRest {\n        String URL_BASE = \"https://graph.facebook.com\";\n\n        @GET(\"/v2.5/me\")\n        Observable<Object> me();\n    }\n\n    OAuth20Service facebookService() {\n        String appId = \"452930454916873\";\n        String appSecret = \"4a643dd4c4537f01411ab7bb44736f1f\";\n        String callbackUrl = \"http://victoralbertos.com/\";\n        String permissions = \"public_profile, email\";\n\n        return new ServiceBuilder()\n                .apiKey(appId)\n                .apiSecret(appSecret)\n                .callback(callbackUrl)\n                .scope(permissions)\n                .build(FacebookApi.instance());\n    }\n\n    OAuth10aService yahooService() {\n        String clientId = \"dj0yJmk9Sk9NZUlPc0RaODVDJmQ9WVdrOVRubHlWMWRuTTJVbWNHbzlNQS0tJnM9Y29uc3VtZXJzZWNyZXQmeD0wNw--\";\n        String clientSecret = \"449b2d2f06d986297d65df7fc020544bf71eb10c\";\n        String callbackUrl = \"http://victoralbertos.com\";\n\n        return new ServiceBuilder()\n                .apiKey(clientId)\n                .apiSecret(clientSecret)\n                .callback(callbackUrl)\n                .build(YahooApi.instance());\n    }\n}\n"
  },
  {
    "path": "app/src/main/res/layout/choose_activity_or_fragment.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n\n    <Button\n        android:id=\"@+id/bt_activity\"\n        android:text=\"Activity\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" />\n\n    <Button\n        android:id=\"@+id/bt_fragment\"\n        android:text=\"Fragment\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" />\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/connections.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ScrollView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:fitsSystemWindows=\"true\"\n        android:orientation=\"vertical\">\n\n        <LinearLayout\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"horizontal\">\n\n            <TextView\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Twitter: \" />\n\n            <Button\n                android:id=\"@+id/bt_twitter\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Connect\" />\n\n            <Button\n                android:id=\"@+id/bt_twitter_get_token\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Get token\" />\n\n            <Button\n                android:id=\"@+id/bt_twitter_disconnect\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Disconnect\" />\n\n        </LinearLayout>\n\n        <LinearLayout\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"horizontal\">\n\n            <TextView\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Facebook: \" />\n\n            <Button\n                android:id=\"@+id/bt_facebook\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Connect\" />\n\n            <Button\n                android:id=\"@+id/bt_facebook_get_token\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Get token\" />\n\n            <Button\n                android:id=\"@+id/bt_facebook_disconnect\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Disconnect\" />\n\n        </LinearLayout>\n\n        <LinearLayout\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"horizontal\">\n\n            <TextView\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Google: \" />\n\n            <Button\n                android:id=\"@+id/bt_google\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Connect\" />\n\n            <Button\n                android:id=\"@+id/bt_google_get_token\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Get token\" />\n\n            <Button\n                android:id=\"@+id/bt_google_disconnect\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Disconnect\" />\n\n        </LinearLayout>\n\n        <LinearLayout\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"horizontal\">\n\n            <TextView\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Linkedin: \" />\n\n            <Button\n                android:id=\"@+id/bt_linkedin\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Connect\" />\n\n            <Button\n                android:id=\"@+id/bt_linkedin_get_token\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Get token\" />\n\n            <Button\n                android:id=\"@+id/bt_linkedin_disconnect\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Disconnect\" />\n\n        </LinearLayout>\n\n        <LinearLayout\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"horizontal\">\n\n            <TextView\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Yahoo: \" />\n\n            <Button\n                android:id=\"@+id/bt_yahoo\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Connect\" />\n\n            <Button\n                android:id=\"@+id/bt_yahoo_get_token\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Get token\" />\n\n            <Button\n                android:id=\"@+id/bt_yahoo_disconnect\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Disconnect\" />\n\n        </LinearLayout>\n\n        <LinearLayout\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"horizontal\">\n\n            <TextView\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Github: \" />\n\n            <Button\n                android:id=\"@+id/bt_github\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Connect\" />\n\n            <Button\n                android:id=\"@+id/bt_github_get_token\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Get token\" />\n\n            <Button\n                android:id=\"@+id/bt_github_disconnect\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"Disconnect\" />\n\n        </LinearLayout>\n\n        <TextView\n            android:id=\"@+id/tv_token\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\" />\n\n        <TextView\n            android:id=\"@+id/tv_secret\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\" />\n\n        <Button\n            android:id=\"@+id/bt_all_disconnect\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"All disconnect\" />\n    </LinearLayout>\n</ScrollView>"
  },
  {
    "path": "app/src/main/res/layout/host_activity_fragment.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <fragment\n        android:id=\"@+id/rxSocialConnectFragment\"\n        android:name=\"org.fuckboilerplate.rxsocialconnect.connections.ConnectionsFragment\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        tools:layout=\"@layout/connections\" />\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/interceptors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n\n    <LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"horizontal\">\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"Facebook\" />\n\n        <Button\n            android:id=\"@+id/bt_connect_facebook\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"Connect\" />\n\n        <Button\n            android:id=\"@+id/bt_show_profile_facebook\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"Show profile\" />\n\n    </LinearLayout>\n\n    <LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"horizontal\">\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"Yahoo\" />\n\n        <Button\n            android:id=\"@+id/bt_connect_yahoo\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"Connect\" />\n\n        <Button\n            android:id=\"@+id/bt_show_profile_yahoo\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"Show profile\" />\n\n    </LinearLayout>\n\n    <TextView\n        android:id=\"@+id/tv_profile\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" />\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/start_activity.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:orientation=\"vertical\" android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <Button\n        android:id=\"@+id/bt_connections\"\n        android:text=\"Connections\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" />\n\n    <Button\n        android:id=\"@+id/bt_interceptors\"\n        android:text=\"Interceptors\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" />\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n    <dimen name=\"fab_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">RxSocialConnect</string>\n    <string name=\"action_settings\">Settings</string>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n    <style name=\"AppTheme.NoActionBar\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n    </style>\n\n    <style name=\"AppTheme.AppBarOverlay\" parent=\"ThemeOverlay.AppCompat.Dark.ActionBar\" />\n\n    <style name=\"AppTheme.PopupOverlay\" parent=\"ThemeOverlay.AppCompat.Light\" />\n\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values-v21/styles.xml",
    "content": "<resources>\n\n    <style name=\"AppTheme.NoActionBar\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n        <item name=\"android:windowDrawsSystemBarBackgrounds\">true</item>\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n    </style>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:2.2.3'\n        classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1'\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        jcenter()\n        maven { url \"https://jitpack.io\" }\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "core/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "core/build.gradle",
    "content": "apply plugin: 'com.android.library'\napply plugin: 'com.github.dcendents.android-maven'\ngroup='com.github.VictorAlbertos'\nversion='1.0.1-2.x'\n\nandroid {\n    compileSdkVersion 25\n    buildToolsVersion \"25.0.0\"\n\n    defaultConfig {\n        minSdkVersion 16\n        targetSdkVersion 25\n        versionCode 1\n        versionName \"1.0\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n    lintOptions {\n        abortOnError false\n    }\n}\n\ndependencies {\n    compile fileTree(dir: 'libs', include: ['*.jar'])\n    testCompile 'junit:junit:4.12'\n    compile 'com.android.support:appcompat-v7:25.1.1'\n\n    compile 'com.github.scribejava:scribejava-apis:3.2.0'\n    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'\n    compile 'io.reactivex.rxjava2:rxjava:2.0.6'\n\n    compile \"com.github.VictorAlbertos:RxActivityResult:0.4.1-2.x\"\n    compile 'com.github.VictorAlbertos.Jolyglot:api:0.0.3'\n\n    testCompile 'com.github.VictorAlbertos.Jolyglot:gson:0.0.3'\n    testCompile \"org.mockito:mockito-core:1.10.19\"\n}\n\n// build a jar with source files\ntask sourcesJar(type: Jar) {\n    from android.sourceSets.main.java.srcDirs\n    classifier = 'sources'\n}\n\ntask javadoc(type: Javadoc) {\n    failOnError  false\n    source = android.sourceSets.main.java.sourceFiles\n    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))\n    classpath += configurations.compile\n}\n\n// build a jar with javadoc\ntask javadocJar(type: Jar, dependsOn: javadoc) {\n    classifier = 'javadoc'\n    from javadoc.destinationDir\n}\n\nartifacts {\n    archives sourcesJar\n    archives javadocJar\n}"
  },
  {
    "path": "core/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /Users/victor/Documents/AndroidStudio/android_sdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "core/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"org.fuckboilerplate.rx_social_connect\">\n\n    <application>\n\n        <activity\n            android:name=\".internal.ActivityConnect\"\n            android:label=\"@string/app_name\"\n            android:theme=\"@style/Theme.AppCompat.NoActionBar\"/>\n\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/NotActiveTokenFoundException.java",
    "content": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rx_social_connect;\n\npublic class NotActiveTokenFoundException extends RuntimeException {\n\n    public NotActiveTokenFoundException() {\n        super(\"There is no active token for the provider requested\");\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/Response.java",
    "content": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rx_social_connect;\n\nimport com.github.scribejava.core.model.Token;\n\npublic final class Response<T, D extends Token> {\n    private final T targetUI;\n    private final D token;\n\n    public Response(T targetUI, D token) {\n        this.targetUI = targetUI;\n        this.token = token;\n    }\n\n    public T targetUI() {\n        return targetUI;\n    }\n\n    public D token() {\n        return token;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/RxSocialConnect.java",
    "content": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rx_social_connect;\n\nimport android.app.Activity;\nimport android.app.Application;\nimport android.content.Intent;\nimport android.support.v4.app.Fragment;\nimport com.github.scribejava.core.builder.api.BaseApi;\nimport com.github.scribejava.core.builder.api.DefaultApi10a;\nimport com.github.scribejava.core.builder.api.DefaultApi20;\nimport com.github.scribejava.core.model.Token;\nimport com.github.scribejava.core.oauth.OAuth10aService;\nimport com.github.scribejava.core.oauth.OAuth20Service;\nimport com.github.scribejava.core.oauth.OAuthService;\nimport io.reactivex.Observable;\nimport io.reactivex.ObservableSource;\nimport io.reactivex.functions.Function;\nimport io.victoralbertos.jolyglot.Jolyglot;\nimport java.util.concurrent.Callable;\nimport org.fuckboilerplate.rx_social_connect.internal.ActivityConnect;\nimport org.fuckboilerplate.rx_social_connect.internal.persistence.OAuth1AccessToken;\nimport org.fuckboilerplate.rx_social_connect.internal.persistence.OAuth2AccessToken;\nimport org.fuckboilerplate.rx_social_connect.internal.persistence.TokenCache;\nimport org.fuckboilerplate.rx_social_connect.internal.services.OAuth1Service;\nimport org.fuckboilerplate.rx_social_connect.internal.services.OAuth2Service;\nimport org.fuckboilerplate.rx_social_connect.internal.services.Service;\nimport rx_activity_result2.Result;\nimport rx_activity_result2.RxActivityResult;\n\npublic final class RxSocialConnect {\n    private static final String ERROR_ENCRYPTION_KEY_IS_NULL = \"Error encryption key must not be null\";\n\n    /**\n     * Register RxSocialConnect calling this method on onCreate android application method.\n     */\n    public static Builder register(Application application, String encryptionKey) {\n        if (encryptionKey == null) throw new RuntimeException(ERROR_ENCRYPTION_KEY_IS_NULL);\n        RxActivityResult.register(application);\n        return new Builder(application, encryptionKey);\n    }\n\n    public static class Builder {\n        private final Application application;\n        private final String encryptionKey;\n\n        public Builder(Application application, String encryptionKey) {\n            this.application = application;\n            this.encryptionKey = encryptionKey;\n        }\n\n        public void using(Jolyglot jolyglot) {\n            TokenCache.INSTANCE.init(application, encryptionKey, jolyglot);\n        }\n    }\n\n    /**\n     * Performs an oauth http call using oauth1 protocol and retrieve the associated token calling it from an activity.\n     * @param activity the activity calling\n     * @param oAuth10aService the oauth1 service containing the provider as long as the provider credentials.\n     * @param <A> the activity calling\n     * @return a response instance holding the OAuth1AccessToken and the current valid activity instance.\n     * @see com.github.scribejava.core.model.OAuth1AccessToken\n     */\n    public static <A extends Activity> Observable<Response<A, com.github.scribejava.core.model.OAuth1AccessToken>> with(A activity, OAuth10aService oAuth10aService) {\n        return startActivity(activity, new OAuth1Service(oAuth10aService),\n                oAuth10aService.getApi().getClass().getSimpleName(), OAuth1AccessToken.class)\n                .map(new Function<Response<Object, OAuth1AccessToken>, Response<A, com.github.scribejava.core.model.OAuth1AccessToken>>() {\n                    @Override public Response<A, com.github.scribejava.core.model.OAuth1AccessToken> apply(Response<Object, OAuth1AccessToken> response) {\n                        return new Response(response.targetUI(), response.token());\n                    }\n                });\n    }\n\n    /**\n     * Performs an oauth http call using oauth2 protocol and retrieve the associated token calling it from an activity.\n     * @param activity the activity calling\n     * @param oAuth20Service the oauth2 service containing the provider as long as the provider credentials.\n     * @param <A> the activity calling\n     * @return a response instance holding the OAuth1AccessToken and the current valid activity instance.\n     * @see com.github.scribejava.core.model.OAuth2AccessToken\n     */\n    public static <A extends Activity> Observable<Response<A, com.github.scribejava.core.model.OAuth2AccessToken>> with(A activity, OAuth20Service oAuth20Service) {\n        return startActivity(activity, new OAuth2Service(oAuth20Service),\n                oAuth20Service.getApi().getClass().getSimpleName(), OAuth2AccessToken.class)\n                .map(new Function<Response<Object, OAuth2AccessToken>, Response<A, com.github.scribejava.core.model.OAuth2AccessToken>>() {\n                    @Override public Response<A, com.github.scribejava.core.model.OAuth2AccessToken> apply(Response<Object, OAuth2AccessToken> response) {\n                        return new Response(response.targetUI(), response.token());\n                    }\n                });\n    }\n\n    /**\n     * Performs an oauth http call using oauth1 protocol and retrieve the associated token calling it from a fragment.\n     * @param fragment the fragment calling\n     * @param oAuth10aService the oauth1 service containing the provider as long as the provider credentials.\n     * @param <F> the fragment calling\n     * @return a response instance holding the OAuth1AccessToken and the current valid activity fragment.\n     * @see com.github.scribejava.core.model.OAuth1AccessToken\n     */\n    public static <F extends Fragment> Observable<Response<F, com.github.scribejava.core.model.OAuth1AccessToken>> with(F fragment, OAuth10aService oAuth10aService) {\n        return startActivity(fragment, new OAuth1Service(oAuth10aService),\n                oAuth10aService.getApi().getClass().getSimpleName(), OAuth1AccessToken.class)\n                .map(new Function<Response<Object, OAuth1AccessToken>, Response<F, com.github.scribejava.core.model.OAuth1AccessToken>>() {\n                    @Override public Response<F, com.github.scribejava.core.model.OAuth1AccessToken> apply(Response<Object, OAuth1AccessToken> response) {\n                        return new Response(response.targetUI(), response.token());\n                    }\n                });\n    }\n\n    /**\n     * Performs an oauth http call using oauth2 protocol and retrieve the associated token calling it from a fragment.\n     * @param fragment the fragment calling\n     * @param oAuth20Service the oauth2 service containing the provider as long as the provider credentials.\n     * @param <F> the fragment calling\n     * @return a response instance holding the OAuth2AccessToken and the current valid activity fragment.\n     * @see com.github.scribejava.core.model.OAuth2AccessToken\n     */\n    public static <F extends Fragment> Observable<Response<F, com.github.scribejava.core.model.OAuth2AccessToken>> with(F fragment, OAuth20Service oAuth20Service) {\n        return startActivity(fragment, new OAuth2Service(oAuth20Service),\n                oAuth20Service.getApi().getClass().getSimpleName(), OAuth2AccessToken.class)\n                .map(new Function<Response<Object, OAuth2AccessToken>, Response<F, com.github.scribejava.core.model.OAuth2AccessToken>>() {\n                    @Override public Response<F, com.github.scribejava.core.model.OAuth2AccessToken> apply(Response<Object, OAuth2AccessToken> response) {\n                        return new Response(response.targetUI(), response.token());\n                    }\n                });\n    }\n\n    /**\n     * Remove an stored token from a previous oauth authentication cached on disk.\n     * @see BaseApi\n     */\n    public static Observable<Object> closeConnection(final Class<? extends BaseApi> classApi) {\n        return Observable.defer(new Callable<ObservableSource<? extends Object>>() {\n            @Override public ObservableSource<? extends Object> call() throws Exception {\n                String keyToken = classApi.getSimpleName();\n                TokenCache.INSTANCE.evict(keyToken);\n                return Observable.just(1);\n            }\n        });\n    }\n\n    /**\n     * Remove all stored tokens from previous oauth authentications cached on disk.\n     */\n    public static Observable<Object> closeConnections() {\n        return Observable.defer(new Callable<ObservableSource<? extends Object>>() {\n            @Override public ObservableSource<? extends Object> call() throws Exception {\n                TokenCache.INSTANCE.evictAll();\n                return Observable.just(1);\n            }\n        });\n    }\n\n    /**\n     * Retrieve the token stored resulting from previous Oauth1 authentication.\n     * @param classApi a class provider which extends from DefaultApi10a. The same one used to build the OAuthService.\n     * @return observable containing an OAuth1AccessToken or if not token cached observable which throws NotTokenFoundException\n     */\n    public static Observable<com.github.scribejava.core.model.OAuth1AccessToken> getTokenOAuth1(final Class<? extends DefaultApi10a> classApi) {\n        return Observable.defer(\n            new Callable<ObservableSource<? extends com.github.scribejava.core.model.OAuth1AccessToken>>() {\n                @Override public ObservableSource<? extends com.github.scribejava.core.model.OAuth1AccessToken> call()\n                    throws Exception {\n                    String keyToken = classApi.getSimpleName();\n\n                    Observable<OAuth1AccessToken> token = (Observable<OAuth1AccessToken>) TokenCache.INSTANCE.get(keyToken, OAuth1AccessToken.class);\n                    if (token != null) {\n                        return token.map(new Function<OAuth1AccessToken, com.github.scribejava.core.model.OAuth1AccessToken>() {\n                            @Override public com.github.scribejava.core.model.OAuth1AccessToken apply(OAuth1AccessToken token) {\n                                return token.toOAuth1AccessTokenScribe();\n                            }\n                        });\n                    }\n\n                    return Observable.error(new NotActiveTokenFoundException());\n                }\n            });\n    }\n\n    /**\n     * Retrieve the token stored resulting from previous Oauth2 authentication.\n     * @param classApi a class provider which extends from DefaultApi20. The same one used to build the OAuthService.\n     * @return observable containing an OAuth2AccessToken or if not token cached observable which throws NotTokenFoundException\n     */\n    public static Observable<com.github.scribejava.core.model.OAuth2AccessToken> getTokenOAuth2(final Class<? extends DefaultApi20> classApi) {\n        return Observable.defer(new Callable<ObservableSource<? extends com.github.scribejava.core.model.OAuth2AccessToken>>() {\n                @Override public ObservableSource<? extends com.github.scribejava.core.model.OAuth2AccessToken> call()\n                    throws Exception {\n                    String keyToken = classApi.getSimpleName();\n\n                    Observable<OAuth2AccessToken> oToken = (Observable<OAuth2AccessToken>) TokenCache.INSTANCE.get(keyToken, OAuth2AccessToken.class);\n                    if (oToken != null) {\n                        return oToken.map(new Function<OAuth2AccessToken, com.github.scribejava.core.model.OAuth2AccessToken>() {\n                            @Override public com.github.scribejava.core.model.OAuth2AccessToken apply(OAuth2AccessToken token) {\n                                return token.toOAuth2AccessTokenScribe();\n                            }\n                        });\n                    }\n\n                    return Observable.error(new NotActiveTokenFoundException());\n                }\n            });\n    }\n\n    private static final String ERROR_RETRIEVING_TOKEN = \"Error retrieving token\";\n    private static <T extends Token> Observable<Response<Object, T>> startActivity(final Object targetUI, Service<T, ? extends OAuthService> service, final String keyToken, final Class<T> classToken) {\n        Activity activity = targetUI instanceof Activity ? (Activity) targetUI : ((Fragment) targetUI).getActivity();\n\n        Observable<T> response = (Observable<T>) TokenCache.INSTANCE.get(keyToken, classToken);\n        if (response != null) return response.map(new Function<T, Response<Object, T>>() {\n            @Override public Response<Object, T> apply(T token) {\n                return new Response(targetUI, token);\n            }\n        });\n\n        ActivityConnect.service = service;\n        Intent intent = new Intent(activity, ActivityConnect.class);\n\n        Observable oTempResponse;\n\n        if (targetUI instanceof Activity) {\n            oTempResponse = RxActivityResult.on((Activity) targetUI)\n                    .startIntent(intent);\n        } else {\n            oTempResponse = RxActivityResult.on((Fragment) targetUI)\n                    .startIntent(intent);\n        }\n\n        Observable<Result> oResponse = (Observable<Result>) oTempResponse;\n        return oResponse.map(new Function<Result, Response<Object, T>>() {\n            @Override public Response<Object, T> apply(Result result) {\n                ActivityConnect.service = null;\n\n                if (result.data() == null) throw new RuntimeException(ERROR_RETRIEVING_TOKEN);\n\n                if (result.resultCode() == Activity.RESULT_OK) {\n                    T token = (T) result.data().getExtras().getSerializable(ActivityConnect.KEY_RESULT);\n                    TokenCache.INSTANCE.save(keyToken, token);\n                    return new Response(targetUI, token);\n                }\n\n                String errorMessage = result.data().getExtras().getString(ActivityConnect.KEY_RESULT, \"\");\n                if (!errorMessage.isEmpty()) throw new RuntimeException(errorMessage);\n                else throw new RuntimeException(ERROR_RETRIEVING_TOKEN);\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/ActivityConnect.java",
    "content": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rx_social_connect.internal;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android.os.Build;\nimport android.os.Bundle;\nimport android.view.View;\nimport android.webkit.CookieManager;\nimport android.webkit.CookieSyncManager;\nimport android.webkit.WebView;\nimport android.webkit.WebViewClient;\n\nimport com.github.scribejava.core.model.Token;\nimport com.github.scribejava.core.oauth.OAuthService;\n\nimport org.fuckboilerplate.rx_social_connect.R;\nimport org.fuckboilerplate.rx_social_connect.internal.services.Service;\n\nimport io.reactivex.functions.Consumer;\n\npublic class ActivityConnect extends Activity {\n    public static final String KEY_RESULT = \"key_result\";\n    public static Service<? extends Token, ? extends OAuthService> service;\n\n    @Override protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.connection_activity);\n        initWebView();\n    }\n\n    protected void initWebView() {\n        final WebView webView = (WebView) findViewById(R.id.webview);\n        clearCookies(webView);\n\n        webView.setWebViewClient(new WebViewClient() {\n            @Override public boolean shouldOverrideUrlLoading(WebView view, String url) {\n                if (service == null || !url.startsWith(service.callbackUrl())) return super.shouldOverrideUrlLoading(view, url);\n\n                webView.setVisibility(View.GONE);\n\n                service.oResponse(url).subscribe(new Consumer<Token>() {\n                    @Override public void accept(Token token) throws Exception {\n                        finishWithToken(token);\n                    }\n                }, new Consumer<Throwable>() {\n                    @Override public void accept(Throwable error) throws Exception {\n                        finishWithError(error);\n                    }\n                });\n\n                return true;\n            }\n\n            @Override public void onPageFinished(WebView view, String url) {}\n        });\n\n        webView.getSettings().setJavaScriptEnabled(true);\n        webView.getSettings().setDomStorageEnabled(true);\n\n        service.oAuthUrl().subscribe(new Consumer<String>() {\n            @Override public void accept(String url) throws Exception {\n                webView.loadUrl(url);\n            }\n        }, new Consumer<Throwable>() {\n            @Override public void accept(Throwable error) throws Exception {\n                finishWithError(error);\n            }\n        });\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    private void clearCookies(WebView webView) {\n        webView.clearCache(true);\n        webView.clearHistory();\n\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {\n            CookieManager.getInstance().removeAllCookies(null);\n            CookieManager.getInstance().flush();\n        } else {\n            CookieSyncManager cookieSyncManager = CookieSyncManager.createInstance(this);\n            cookieSyncManager.startSync();\n\n            CookieManager cookieManager = CookieManager.getInstance();\n            cookieManager.removeAllCookie();\n            cookieManager.removeSessionCookie();\n\n            cookieSyncManager.stopSync();\n            cookieSyncManager.sync();\n        }\n    }\n\n    private void finishWithError(Throwable error) {\n        Intent intent = new Intent();\n\n        String message = error.getMessage();\n        if (message == null && error.getCause() != null) message = error.getCause().getMessage();\n\n        intent.putExtra(KEY_RESULT, message);\n        setResult(Activity.RESULT_CANCELED, intent);\n        finish();\n    }\n\n    private void finishWithToken(Token token) {\n        Intent intent = new Intent();\n        intent.putExtra(KEY_RESULT, token);\n        setResult(Activity.RESULT_OK, intent);\n        finish();\n    }\n}"
  },
  {
    "path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/encryption/BuiltInEncryptor.java",
    "content": "/*\n * Copyright 2015 Victor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rx_social_connect.internal.encryption;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.security.SecureRandom;\n\nimport javax.crypto.Cipher;\nimport javax.crypto.CipherInputStream;\nimport javax.crypto.CipherOutputStream;\nimport javax.crypto.KeyGenerator;\nimport javax.crypto.SecretKey;\nimport javax.crypto.spec.SecretKeySpec;\n\n/**\n * Encrypt/Decrypt the file data\n */\npublic class BuiltInEncryptor implements Encryptor {\n    private static final int KEY_LENGTH = 128;  // Max 128 bits by default. See http://stackoverflow.com/a/24907555/5502014\n    private static final int FILE_BUF = 1024;\n    private Cipher encryptCipher;\n    private Cipher decryptCipher;\n\n\n    public BuiltInEncryptor() {\n    }\n\n    @Override public void encrypt(String key, File decryptedFile, File encryptedFile) {\n        initCiphers(key);\n\n        try {\n            CipherInputStream cis = new CipherInputStream(new FileInputStream(decryptedFile), encryptCipher);\n            write(cis, new FileOutputStream(encryptedFile));\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n    }\n\n    @Override public void decrypt(String key, File encryptedFile, File decryptedFile) {\n        initCiphers(key);\n\n        try {\n            CipherOutputStream cos = new CipherOutputStream(new FileOutputStream(decryptedFile), decryptCipher);\n            write(new FileInputStream(encryptedFile), cos);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n    }\n\n    private void initCiphers(String key) {\n        try {\n            SecretKeySpec secretKey = generateSecretKey(key);\n\n            encryptCipher = Cipher.getInstance(\"AES\");\n            encryptCipher.init(Cipher.ENCRYPT_MODE, secretKey);\n\n            decryptCipher = Cipher.getInstance(\"AES\");\n            decryptCipher.init(Cipher.DECRYPT_MODE, secretKey);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n    }\n\n    private SecretKeySpec generateSecretKey(String key) throws Exception {\n        SecureRandom secureRandom = SecureRandom.getInstance(\"SHA1PRNG\");\n        secureRandom.setSeed(key.getBytes(\"UTF-8\"));\n        KeyGenerator keyGenerator = KeyGenerator.getInstance(\"AES\");\n        keyGenerator.init(KEY_LENGTH, secureRandom);\n        SecretKey secretKey = keyGenerator.generateKey();\n\n        return new SecretKeySpec(secretKey.getEncoded(), \"AES\");\n    }\n\n    private void write(InputStream is, OutputStream os) {\n        byte[] bytes = new byte[FILE_BUF];\n        int numBytes;\n\n        try {\n            while ((numBytes = is.read(bytes)) != -1) {\n                os.write(bytes, 0, numBytes);\n            }\n        } catch (IOException e) {\n            e.printStackTrace();\n        } finally {\n            try {\n                is.close();\n                os.flush();\n                os.close();\n            } catch (IOException ex) {\n                ex.printStackTrace();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/encryption/Encryptor.java",
    "content": "/*\n * Copyright 2015 Victor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rx_social_connect.internal.encryption;\n\nimport java.io.File;\n\n/**\n * Interface to Encrypt/Decrypt the file data\n */\npublic interface Encryptor {\n\n    /**\n     * Encrypts the {@code decryptedFile} data and saves it into {@code encryptedFile}\n     *\n     * @param key Key used by the algorithm to encrypt/decrypt the data\n     * @param decryptedFile Input file with the data to encrypt\n     * @param encryptedFile Output file with the encrypted data\n     */\n    void encrypt(String key, File decryptedFile, File encryptedFile);\n\n    /**\n     * Decrypts the {@code encryptedFile} data and saves it into {@code decryptedFile}\n     *\n     * @param key Key used by the algorithm to encrypt/decrypt the data\n     * @param encryptedFile Input file with the encrypted data\n     * @param decryptedFile Output file with the data without encrypt\n     */\n    void decrypt(String key, File encryptedFile, File decryptedFile);\n}\n"
  },
  {
    "path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/encryption/FileEncryptor.java",
    "content": "/*\n * Copyright 2016 Victor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rx_social_connect.internal.encryption;\n\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileOutputStream;\nimport java.nio.channels.FileChannel;\n\npublic class FileEncryptor {\n    private static final String SUFFIX_TMP = \"-tmp\";\n    private final Encryptor encryptor;\n\n    public FileEncryptor(Encryptor encryptor) {\n        this.encryptor = encryptor;\n    }\n\n    public File encrypt(String key, File file) {\n        if (key == null || !file.exists()) return file;\n\n        String filenameInput = file.getAbsolutePath();\n        file = rename(file, new File(filenameInput + SUFFIX_TMP));\n        File fileOutput = new File(filenameInput);\n\n        encryptor.encrypt(key, file, fileOutput);\n        file.delete();\n\n        return fileOutput;\n    }\n\n    public File decrypt(String key, File file) {\n        if (key == null || !file.exists()) return file;\n\n        String filenameInput = file.getAbsolutePath();\n        File fileOutput = new File(filenameInput + SUFFIX_TMP);\n        encryptor.decrypt(key, file, fileOutput);\n\n        return fileOutput;\n    }\n\n    private File rename(File fileSrc, File fileDst) {\n        FileChannel inputChannel = null;\n        FileChannel outputChannel = null;\n\n        try {\n            inputChannel = new FileInputStream(fileSrc).getChannel();\n            outputChannel = new FileOutputStream(fileDst).getChannel();\n\n            inputChannel.transferTo(0, inputChannel.size(), outputChannel);\n            fileSrc.delete();\n        } catch (Exception e) {\n            e.printStackTrace();\n        } finally {\n            try {\n                if (inputChannel != null) {\n                    inputChannel.close();\n                }\n                if (outputChannel != null) {\n                    outputChannel.close();\n                }\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n        }\n\n        return fileDst;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/persistence/Disk.java",
    "content": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rx_social_connect.internal.persistence;\n\nimport com.github.scribejava.core.model.Token;\nimport io.reactivex.Observable;\nimport io.victoralbertos.jolyglot.Jolyglot;\nimport java.io.File;\nimport java.io.FileWriter;\nimport java.io.IOException;\nimport org.fuckboilerplate.rx_social_connect.internal.encryption.BuiltInEncryptor;\nimport org.fuckboilerplate.rx_social_connect.internal.encryption.FileEncryptor;\n\npublic class Disk<T extends Token> {\n    private final File cacheDirectory;\n    private static final String NAME_DIR = \"RxSocialConnect\";\n    private final Jolyglot jolyglot;\n    private final String encryptionKey;\n    private final FileEncryptor fileEncryptor;\n\n    public Disk(File file, String encryptionKey, Jolyglot jolyglot) {\n        this.fileEncryptor = new FileEncryptor(new BuiltInEncryptor());\n        this.encryptionKey = encryptionKey;\n        this.cacheDirectory = new File(file + File.separator + NAME_DIR);\n        if (!this.cacheDirectory.exists()) cacheDirectory.mkdir();\n        this.jolyglot = jolyglot;\n    }\n\n    public void save(String key, T data) {\n        String wrapperJSONSerialized = jolyglot.toJson(data);\n        FileWriter fileWriter = null;\n\n        try {\n            File file = new File(cacheDirectory, key);\n\n            fileWriter = new FileWriter(file, false);\n            fileWriter.write(wrapperJSONSerialized);\n            fileWriter.flush();\n            fileWriter.close();\n            fileWriter = null;\n\n            fileEncryptor.encrypt(encryptionKey, new File(cacheDirectory, key));\n        } catch (Exception e) {\n            throw new RuntimeException(e.getMessage());\n        } finally {\n            try {\n                if (fileWriter != null) {\n                    fileWriter.flush();\n                    fileWriter.close();\n                }\n            } catch (IOException e) {\n                e.printStackTrace();\n            }\n        }\n    }\n\n    public Observable<T> get(String keyToken, Class<T> classToken) {\n        T response = retrieve(keyToken, classToken);\n\n        if (response != null) {\n            if (response instanceof OAuth2AccessToken) {\n                if (!((OAuth2AccessToken)response).isExpired()) {\n                    return Observable.just(response);\n                }\n            } else {\n                return Observable.just(response);\n            }\n        }\n\n        return null;\n    }\n\n    private T retrieve(String key, Class<T> clazz) {\n        File file = new File(cacheDirectory, key);\n        file = fileEncryptor.decrypt(encryptionKey, file);\n\n        try {\n            T data = jolyglot.fromJson(file, clazz);\n            file.delete();\n\n            return data;\n        } catch (Exception ignore) {\n            return null;\n        } finally {\n            file.delete();\n        }\n    }\n\n    public void evict(String key) {\n        File file = new File(cacheDirectory, key);\n        file.delete();\n    }\n\n    public void evictAll() {\n        File[] tokens = cacheDirectory.listFiles();\n\n        if (tokens == null) return;\n\n        for (File token : tokens) {\n            token.delete();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/persistence/OAuth1AccessToken.java",
    "content": "package org.fuckboilerplate.rx_social_connect.internal.persistence;\n\npublic final class OAuth1AccessToken extends com.github.scribejava.core.model.OAuth1AccessToken {\n\n  /**\n   * Exists just to make happy some json providers\n   */\n  public OAuth1AccessToken() {\n    super(\"stub\", \"stub\", \"stub\");\n  }\n\n  public OAuth1AccessToken(com.github.scribejava.core.model.OAuth1AccessToken oAuth1AccessToken) {\n    super(oAuth1AccessToken.getToken(),\n        oAuth1AccessToken.getTokenSecret(),\n        oAuth1AccessToken.getRawResponse());\n  }\n\n  public com.github.scribejava.core.model.OAuth1AccessToken toOAuth1AccessTokenScribe() {\n    return this;\n  }\n}\n"
  },
  {
    "path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/persistence/OAuth2AccessToken.java",
    "content": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rx_social_connect.internal.persistence;\n\npublic final class OAuth2AccessToken extends com.github.scribejava.core.model.OAuth2AccessToken {\n    private final long expirationDate;\n\n    /**\n     * Exists just to make happy some json providers\n     */\n    public OAuth2AccessToken() {\n        super(\"stub\", \"stub\", 0, \"stub\", \"stub\", \"stub\");\n        expirationDate = 0;\n    }\n\n    public OAuth2AccessToken(com.github.scribejava.core.model.OAuth2AccessToken oAuth2AccessToken) {\n        super(oAuth2AccessToken.getAccessToken(), oAuth2AccessToken.getTokenType(), oAuth2AccessToken.getExpiresIn(),\n                oAuth2AccessToken.getRefreshToken(), oAuth2AccessToken.getScope(), oAuth2AccessToken.getRawResponse());\n\n        if (oAuth2AccessToken.getExpiresIn() == null) this.expirationDate = 0;\n        else this.expirationDate = System.currentTimeMillis() + (oAuth2AccessToken.getExpiresIn() * 1000);\n    }\n\n    public boolean isExpired() {\n        if (expirationDate == 0) return false;\n        return System.currentTimeMillis() > expirationDate;\n    }\n\n    public com.github.scribejava.core.model.OAuth2AccessToken toOAuth2AccessTokenScribe() {\n        return this;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/persistence/TokenCache.java",
    "content": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rx_social_connect.internal.persistence;\n\nimport android.content.Context;\nimport android.support.annotation.VisibleForTesting;\nimport com.github.scribejava.core.model.Token;\nimport io.reactivex.Observable;\nimport io.victoralbertos.jolyglot.Jolyglot;\nimport java.io.File;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\n\npublic enum TokenCache {\n    INSTANCE();\n\n    private Disk disk;\n    private ConcurrentMap<String, Observable<? extends Token>> memory;\n\n    public void init(Context context, String encryptionKey, Jolyglot jolyglot) {\n        disk = new Disk(context.getFilesDir(), encryptionKey, jolyglot);\n        memory = new ConcurrentHashMap();\n    }\n\n    @VisibleForTesting void init(File file, String encryptionKey, Jolyglot jolyglot) {\n        disk = new Disk(file, encryptionKey, jolyglot);\n        memory = new ConcurrentHashMap();\n    }\n\n    public <T extends Token> void save(String key, T data) {\n        memory.put(key, Observable.just(data));\n        disk.save(key, data);\n    }\n\n    public Observable<? extends Token> get(String keyToken, Class<? extends Token> classToken) {\n        Observable<? extends Token> token = memory.get(keyToken);\n        if (token == null) {\n            token = disk.get(keyToken, classToken);\n            if (token != null) memory.put(keyToken, token);\n        }\n        return token;\n    }\n\n    public void evict(String key) {\n        memory.remove(key);\n        disk.evict(key);\n    }\n\n    public void evictAll() {\n        for (String key : memory.keySet()) {\n            memory.remove(key);\n        }\n        disk.evictAll();\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/services/OAuth1Service.java",
    "content": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rx_social_connect.internal.services;\n\nimport android.net.Uri;\nimport com.github.scribejava.core.model.OAuth1RequestToken;\nimport com.github.scribejava.core.oauth.OAuth10aService;\nimport org.fuckboilerplate.rx_social_connect.internal.persistence.OAuth1AccessToken;\nimport org.fuckboilerplate.rx_social_connect.query_string.QueryString;\nimport org.fuckboilerplate.rx_social_connect.query_string.QueryStringStrategy;\n\npublic final class OAuth1Service extends Service<OAuth1AccessToken, OAuth10aService> {\n\n    public OAuth1Service(OAuth10aService service) {\n        super(service);\n    }\n\n    @Override public OAuth1AccessToken token(String url) throws Exception {\n        Uri uri = Uri.parse(url);\n\n        QueryStringStrategy strategy = QueryString.PARSER.getStrategyOAuth1();\n\n        String error = strategy.extractError(uri);\n        if (error != null && !error.isEmpty()) throw new RuntimeException(error);\n\n        String verifier = strategy.extractCode(uri);\n        return new OAuth1AccessToken(\n            service.getAccessToken(oAuth1RequestToken, verifier)\n        );\n    }\n\n    private OAuth1RequestToken oAuth1RequestToken;\n    @Override protected String authUrl() throws Exception {\n        oAuth1RequestToken = service.getRequestToken();\n        return service.getAuthorizationUrl(oAuth1RequestToken);\n    }\n\n    @Override public String callbackUrl() {\n        return service.getConfig().getCallback();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/services/OAuth2Service.java",
    "content": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rx_social_connect.internal.services;\n\nimport android.net.Uri;\nimport com.github.scribejava.core.oauth.OAuth20Service;\nimport org.fuckboilerplate.rx_social_connect.internal.persistence.OAuth2AccessToken;\nimport org.fuckboilerplate.rx_social_connect.query_string.QueryString;\nimport org.fuckboilerplate.rx_social_connect.query_string.QueryStringStrategy;\n\npublic final class OAuth2Service extends Service<OAuth2AccessToken, OAuth20Service> {\n\n    public OAuth2Service(OAuth20Service service) {\n        super(service);\n    }\n\n    @Override public OAuth2AccessToken token(String url) throws Exception {\n        Uri uri = Uri.parse(url);\n\n        QueryStringStrategy strategy = QueryString.PARSER.getStrategyOAuth2();\n\n        String error = strategy.extractError(uri);\n        if (error != null && !error.isEmpty()) throw new RuntimeException(error);\n\n        String code = strategy.extractCode(uri);\n        com.github.scribejava.core.model.OAuth2AccessToken accessToken = service.getAccessToken(code);\n        return new OAuth2AccessToken(accessToken);\n    }\n\n    @Override protected String authUrl() throws Exception {\n        return service.getAuthorizationUrl();\n    }\n\n    @Override public String callbackUrl() {\n        return service.getConfig().getCallback();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/internal/services/Service.java",
    "content": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rx_social_connect.internal.services;\n\nimport com.github.scribejava.core.model.Token;\nimport com.github.scribejava.core.oauth.OAuthService;\n\nimport io.reactivex.Observable;\nimport io.reactivex.ObservableSource;\nimport io.reactivex.schedulers.Schedulers;\nimport java.util.concurrent.Callable;\nimport io.reactivex.android.schedulers.AndroidSchedulers;\n\npublic abstract class Service<T extends Token, S extends OAuthService> {\n    protected final S service;\n\n    public Service(S service) {\n        this.service = service;\n    }\n\n    public Observable<T> oResponse(final String url) {\n        return Observable.defer(new Callable<ObservableSource<? extends T>>() {\n            @Override public ObservableSource<? extends T> call() throws Exception {\n                try {\n                    return Observable.just(token(url));\n                } catch (Exception e) {\n                    return Observable.error(e);\n                }\n            }\n        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());\n    }\n\n    public abstract T token(String url) throws Exception;\n\n    public Observable<String> oAuthUrl() {\n        return Observable.defer(new Callable<ObservableSource<? extends String>>() {\n            @Override public ObservableSource<? extends String> call() throws Exception {\n                try {\n                    return Observable.just(authUrl());\n                } catch (Exception e) {\n                    return Observable.error(e);\n                }\n            }\n        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());\n    }\n\n    protected abstract String authUrl() throws Exception;\n    public abstract String callbackUrl();\n}\n"
  },
  {
    "path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/query_string/QueryString.java",
    "content": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rx_social_connect.query_string;\n\nimport android.net.Uri;\n\n/**\n * Handle the current QueryStringStrategy and provide and entry point for further customization.\n *\n * @see QueryStringStrategy\n */\npublic enum QueryString {\n  PARSER;\n\n  private QueryStringStrategy strategyOAuth1;\n  private QueryStringStrategy strategyOAuth2;\n\n  QueryString() {\n    strategyOAuth1 = defaultStrategyOAuth1();\n    strategyOAuth2 = defaultStrategyOAuth2();\n  }\n\n  /**\n   * Replace current QueryStringStrategy for OAuth1 providers\n   */\n  public void replaceStrategyOAuth1(QueryStringStrategy strategyOauth1) {\n    this.strategyOAuth1 = strategyOauth1;\n  }\n\n  /**\n   * Replace current QueryStringStrategy for OAuth2 providers\n   */\n  public void replaceStrategyOAuth2(QueryStringStrategy strategyOauth2) {\n    this.strategyOAuth2 = strategyOauth2;\n  }\n\n  /**\n   * Reset QueryStringStrategy for OAuth1 providers to default\n   */\n  public void resetStrategyOAuth1() {\n    this.strategyOAuth1 = defaultStrategyOAuth1();\n  }\n\n  /**\n   * Reset QueryStringStrategy for OAuth2 providers to default\n   */\n  public void resetStrategyOAuth2() {\n    this.strategyOAuth2 = defaultStrategyOAuth2();\n  }\n\n  public QueryStringStrategy getStrategyOAuth1() {\n    return strategyOAuth1;\n  }\n\n  public QueryStringStrategy getStrategyOAuth2() {\n    return strategyOAuth2;\n  }\n\n  private QueryStringStrategy defaultStrategyOAuth1() {\n    return new QueryStringStrategy() {\n      @Override public String extractCode(Uri uri) {\n        return uri.getQueryParameter(\"oauth_verifier\");\n      }\n\n      @Override public String extractError(Uri uri) {\n        return uri.getQueryParameter(\"error\");\n      }\n    };\n  }\n\n  private QueryStringStrategy defaultStrategyOAuth2() {\n    return new QueryStringStrategy() {\n      @Override public String extractCode(Uri uri) {\n        return uri.getQueryParameter(\"code\");\n      }\n\n      @Override public String extractError(Uri uri) {\n        return uri.getQueryParameter(\"error\");\n      }\n    };\n  }\n}"
  },
  {
    "path": "core/src/main/java/org/fuckboilerplate/rx_social_connect/query_string/QueryStringStrategy.java",
    "content": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rx_social_connect.query_string;\n\nimport android.net.Uri;\nimport android.support.annotation.Nullable;\n\n/**\n * Use it when some provider does not honor the standard query string formatter.\n */\npublic interface QueryStringStrategy {\n  /**\n   * Given an uri, parse the query string to extract the associated oauth code.\n   * @param uri the uri\n   * @return the param code\n   */\n  String extractCode(Uri uri);\n\n  /**\n   * Given an uri, parse the query string to extract the associated error.\n   * @param uri the uri\n   * @return the error message\n   */\n  @Nullable\n  String extractError(Uri uri);\n}"
  },
  {
    "path": "core/src/main/res/layout/connection_activity.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <WebView\n        android:id=\"@+id/webview\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" />\n\n</FrameLayout>"
  },
  {
    "path": "core/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">rx_social_connect</string>\n</resources>\n"
  },
  {
    "path": "core/src/test/java/org/fuckboilerplate/rx_social_connect/OAuth2AccessTokenTest.java",
    "content": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rx_social_connect;\n\n\nimport org.fuckboilerplate.rx_social_connect.internal.persistence.OAuth2AccessToken;\nimport org.junit.Test;\n\nimport static org.hamcrest.core.Is.is;\nimport static org.junit.Assert.assertThat;\n\npublic class OAuth2AccessTokenTest {\n\n    @Test public void When_Token_Expires_Then_Expire() throws Exception {\n        Integer expiresInThreeSecond = 3;\n        OAuth2AccessToken oAuth2AccessToken = new OAuth2AccessToken(createToken(expiresInThreeSecond));\n\n        waitTime(3500);\n\n        assertThat(oAuth2AccessToken.isExpired(), is(true));\n    }\n\n    @Test public void When_Token_Not_Expire_Then_Not_Expire() throws Exception {\n        Integer expiresInOneSecond = 1;\n        OAuth2AccessToken oAuth2AccessToken = new OAuth2AccessToken(createToken(expiresInOneSecond));\n\n        waitTime(550);\n\n        assertThat(oAuth2AccessToken.isExpired(), is(false));\n    }\n\n    private com.github.scribejava.core.model.OAuth2AccessToken createToken(Integer expiresOnSeconds) {\n        return new com.github.scribejava.core.model.OAuth2AccessToken(\"\", \"\", expiresOnSeconds, \"\", \"\", \"\");\n    }\n\n    private void waitTime(long time) {\n        try {Thread.sleep(time);}\n        catch (InterruptedException e) { e.printStackTrace();}\n    }\n\n}"
  },
  {
    "path": "core/src/test/java/org/fuckboilerplate/rx_social_connect/QueryStringTest.java",
    "content": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rx_social_connect;\n\nimport android.net.Uri;\nimport android.support.annotation.Nullable;\nimport org.fuckboilerplate.rx_social_connect.query_string.QueryString;\nimport org.fuckboilerplate.rx_social_connect.query_string.QueryStringStrategy;\nimport org.junit.FixMethodOrder;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.runners.MethodSorters;\nimport org.mockito.Mock;\nimport org.mockito.junit.MockitoJUnit;\nimport org.mockito.junit.MockitoRule;\n\nimport static org.hamcrest.core.Is.is;\nimport static org.junit.Assert.assertThat;\nimport static org.mockito.Mockito.when;\n\n@FixMethodOrder(MethodSorters.NAME_ASCENDING)\npublic final class QueryStringTest {\n  @Rule public MockitoRule mockitoRule = MockitoJUnit.rule();\n  @Mock Uri uri;\n\n  @Test public void _1_Verify_Replace_OAuth1_Strategy() {\n    when(uri.getQueryParameter(\"oauth_verifier_custom\")).thenReturn(\"success\");\n    when(uri.getQueryParameter(\"error_custom\")).thenReturn(\"error\");\n\n    QueryString.PARSER.replaceStrategyOAuth1(new QueryStringStrategy() {\n      @Override public String extractCode(Uri uri) {\n        return uri.getQueryParameter(\"oauth_verifier_custom\");\n      }\n\n      @Nullable @Override public String extractError(Uri uri) {\n        return uri.getQueryParameter(\"error_custom\");\n      }\n    });\n\n    QueryStringStrategy strategy = QueryString.PARSER.getStrategyOAuth1();\n    assertThat(strategy.extractCode(uri), is(\"success\"));\n    assertThat(strategy.extractError(uri), is(\"error\"));\n  }\n\n  @Test public void _2_Verify_Replace_OAuth2_Strategy() {\n    when(uri.getQueryParameter(\"code_custom\")).thenReturn(\"success\");\n    when(uri.getQueryParameter(\"error_custom\")).thenReturn(\"error\");\n\n    QueryString.PARSER.replaceStrategyOAuth2(new QueryStringStrategy() {\n      @Override public String extractCode(Uri uri) {\n        return uri.getQueryParameter(\"code_custom\");\n      }\n\n      @Nullable @Override public String extractError(Uri uri) {\n        return uri.getQueryParameter(\"error_custom\");\n      }\n    });\n\n    QueryStringStrategy strategy = QueryString.PARSER.getStrategyOAuth2();\n    assertThat(strategy.extractCode(uri), is(\"success\"));\n    assertThat(strategy.extractError(uri), is(\"error\"));\n  }\n\n  @Test public void _3_Verify_Default_OAuth1_Strategy() {\n    QueryString.PARSER.resetStrategyOAuth1();\n\n    when(uri.getQueryParameter(\"oauth_verifier\")).thenReturn(\"success\");\n    when(uri.getQueryParameter(\"error\")).thenReturn(\"error\");\n\n    QueryStringStrategy strategy = QueryString.PARSER.getStrategyOAuth1();\n    assertThat(strategy.extractCode(uri), is(\"success\"));\n    assertThat(strategy.extractError(uri), is(\"error\"));\n  }\n\n  @Test public void _4_Verify_Default_OAuth2_Strategy() {\n    QueryString.PARSER.resetStrategyOAuth2();\n\n    when(uri.getQueryParameter(\"code\")).thenReturn(\"success\");\n    when(uri.getQueryParameter(\"error\")).thenReturn(\"error\");\n\n    QueryStringStrategy strategy = QueryString.PARSER.getStrategyOAuth2();\n    assertThat(strategy.extractCode(uri), is(\"success\"));\n    assertThat(strategy.extractError(uri), is(\"error\"));\n  }\n}"
  },
  {
    "path": "core/src/test/java/org/fuckboilerplate/rx_social_connect/internal/persistence/TokenCacheTest.java",
    "content": "/*\n * Copyright 2016 FuckBoilerplate\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.fuckboilerplate.rx_social_connect.internal.persistence;\n\nimport com.github.scribejava.apis.FacebookApi;\nimport com.github.scribejava.apis.TwitterApi;\nimport io.reactivex.Observable;\nimport io.reactivex.observers.TestObserver;\nimport io.victoralbertos.jolyglot.GsonSpeaker;\nimport io.victoralbertos.jolyglot.Jolyglot;\nimport org.junit.ClassRule;\nimport org.junit.FixMethodOrder;\nimport org.junit.Test;\nimport org.junit.rules.TemporaryFolder;\nimport org.junit.runners.MethodSorters;\n\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertThat;\n\n@FixMethodOrder(MethodSorters.NAME_ASCENDING)\npublic class TokenCacheTest {\n    private static final String TOKEN_KEY = TwitterApi.class.getSimpleName(), TOKEN_KEY_2 = FacebookApi.class.getSimpleName(), TOKEN = \"TOKEN\", TOKEN_SECRET = \"TOKEN_SECRET\", RAW_RESPONSE = \"RAW_RESPONSE\";\n    private static final com.github.scribejava.core.model.OAuth1AccessToken OAUTH1_ACCESS_TOKEN = new com.github.scribejava.core.model.OAuth1AccessToken(TOKEN, TOKEN_SECRET, RAW_RESPONSE);\n    private static final com.github.scribejava.core.model.OAuth2AccessToken OAUTH2_ACCESS_TOKEN = new com.github.scribejava.core.model.OAuth2AccessToken(TOKEN, RAW_RESPONSE);\n\n    @ClassRule public static TemporaryFolder temporaryFolder = new TemporaryFolder();\n\n    @Test public void _1_When_Save_Token_And_Retrieve_It_Get_It() {\n        TokenCache.INSTANCE.init(temporaryFolder.getRoot(), \"key\", jsonConverter());\n\n        TokenCache.INSTANCE.save(TOKEN_KEY, OAUTH1_ACCESS_TOKEN);\n\n        TestObserver<com.github.scribejava.core.model.OAuth1AccessToken> testSubscriber = new TestObserver<>();\n        Observable<com.github.scribejava.core.model.OAuth1AccessToken> oToken = (Observable<com.github.scribejava.core.model.OAuth1AccessToken>) TokenCache.INSTANCE.get(TOKEN_KEY, OAuth1AccessToken.class);\n        oToken.subscribe(testSubscriber);\n        testSubscriber.awaitTerminalEvent();\n\n        assertThat(testSubscriber.values().get(0).getToken(), is(TOKEN));\n    }\n\n    @Test public void _2_When_Retrieve_After_Memory_Destroyed_Get_It() {\n        TokenCache.INSTANCE.init(temporaryFolder.getRoot(), \"key\", jsonConverter());\n\n        TestObserver<com.github.scribejava.core.model.OAuth1AccessToken> testSubscriber = new TestObserver<>();\n        Observable<com.github.scribejava.core.model.OAuth1AccessToken> oToken = (Observable<com.github.scribejava.core.model.OAuth1AccessToken>) TokenCache.INSTANCE.get(TOKEN_KEY, OAuth1AccessToken.class);\n        oToken.subscribe(testSubscriber);\n        testSubscriber.awaitTerminalEvent();\n\n        assertThat(testSubscriber.values().get(0).getToken(), is(TOKEN));\n    }\n\n    @Test public void _3_When_Evict_And_Retrieve_It_Get_Null() {\n        TokenCache.INSTANCE.init(temporaryFolder.getRoot(), \"key\", jsonConverter());\n\n        TokenCache.INSTANCE.evict(TOKEN_KEY);\n        Observable<com.github.scribejava.core.model.OAuth1AccessToken> oToken = (Observable<com.github.scribejava.core.model.OAuth1AccessToken>) TokenCache.INSTANCE.get(TOKEN_KEY, OAuth1AccessToken.class);\n        assertNull(oToken);\n    }\n\n    @Test public void _4_When_Evict_All_And_Retrieve_It_Get_Null() {\n        TokenCache.INSTANCE.init(temporaryFolder.getRoot(), \"key\", jsonConverter());\n\n        TokenCache.INSTANCE.save(TOKEN_KEY, OAUTH1_ACCESS_TOKEN);\n        TokenCache.INSTANCE.save(TOKEN_KEY_2, OAUTH2_ACCESS_TOKEN);\n\n        TestObserver<com.github.scribejava.core.model.OAuth1AccessToken> testSubscriberToken1 = new TestObserver<>();\n        Observable<com.github.scribejava.core.model.OAuth1AccessToken> oToken = (Observable<com.github.scribejava.core.model.OAuth1AccessToken>) TokenCache.INSTANCE.get(TOKEN_KEY, OAuth1AccessToken.class);\n        oToken.subscribe(testSubscriberToken1);\n        testSubscriberToken1.awaitTerminalEvent();\n\n        assertThat(testSubscriberToken1.values().get(0).getToken(), is(TOKEN));\n\n        TestObserver<com.github.scribejava.core.model.OAuth2AccessToken> testSubscriberToken2 = new TestObserver<>();\n        Observable<com.github.scribejava.core.model.OAuth2AccessToken> oToken2 = (Observable<com.github.scribejava.core.model.OAuth2AccessToken>) TokenCache.INSTANCE.get(TOKEN_KEY_2, OAuth2AccessToken.class);\n        oToken2.subscribe(testSubscriberToken2);\n        testSubscriberToken2.awaitTerminalEvent();\n\n        assertThat(testSubscriberToken2.values().get(0).getAccessToken(), is(TOKEN));\n\n        TokenCache.INSTANCE.evict(TOKEN_KEY);\n        TokenCache.INSTANCE.evict(TOKEN_KEY_2);\n\n        oToken = (Observable<com.github.scribejava.core.model.OAuth1AccessToken>) TokenCache.INSTANCE.get(TOKEN_KEY, OAuth1AccessToken.class);\n        assertNull(oToken);\n\n        oToken2 = (Observable<com.github.scribejava.core.model.OAuth2AccessToken>) TokenCache.INSTANCE.get(TOKEN_KEY_2, OAuth2AccessToken.class);\n        assertNull(oToken2);\n    }\n\n    private Jolyglot jsonConverter() {\n        return new GsonSpeaker();\n    }\n\n}"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Thu Sep 15 14:35:02 CEST 2016\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-2.14.1-all.zip\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\n# Default value: -Xmx10248m -XX:MaxPermSize=256m\n# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:init\r\n@rem Get command-line arguments, handling Windowz variants\r\n\r\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\r\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\r\n\r\n:win9xME_args\r\n@rem Slurp the command line arguments.\r\nset CMD_LINE_ARGS=\r\nset _SKIP=2\r\n\r\n:win9xME_args_slurp\r\nif \"x%~1\" == \"x\" goto execute\r\n\r\nset CMD_LINE_ARGS=%*\r\ngoto execute\r\n\r\n:4NT_args\r\n@rem Get arguments from the 4NT Shell from JP Software\r\nset CMD_LINE_ARGS=%$\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "gson_converter/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "gson_converter/build.gradle",
    "content": "apply plugin: 'com.android.library'\napply plugin: 'com.github.dcendents.android-maven'\n\ngroup='com.github.FuckBoilerplate'\n\nandroid {\n    compileSdkVersion 23\n    buildToolsVersion \"25.0.2\"\n\n    defaultConfig {\n        minSdkVersion 16\n        targetSdkVersion 23\n        versionCode 1\n        versionName \"1.0\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n}\n\ndependencies {\n    compile fileTree(dir: 'libs', include: ['*.jar'])\n    compile 'com.android.support:appcompat-v7:23.4.0'\n    compile 'com.google.code.gson:gson:2.6.2'\n    compile project(':core')\n\n    testCompile 'junit:junit:4.12'\n}\n\n// build a jar with source files\ntask sourcesJar(type: Jar) {\n    from android.sourceSets.main.java.srcDirs\n    classifier = 'sources'\n}\n\ntask javadoc(type: Javadoc) {\n    failOnError  false\n    source = android.sourceSets.main.java.sourceFiles\n    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))\n    classpath += configurations.compile\n}\n\n// build a jar with javadoc\ntask javadocJar(type: Jar, dependsOn: javadoc) {\n    classifier = 'javadoc'\n    from javadoc.destinationDir\n}\n\nartifacts {\n    archives sourcesJar\n    archives javadocJar\n}"
  },
  {
    "path": "gson_converter/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /Users/victor/Documents/AndroidStudio/android_sdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "gson_converter/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"io.victoralbertos.rx_social_connect_gson_converter\">\n\n    <application\n        android:allowBackup=\"true\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\">\n\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "gson_converter/src/main/java/io/victoralbertos/rx_social_connect/GsonConverter.java",
    "content": "package io.victoralbertos.rx_social_connect;\n\nimport com.google.gson.Gson;\n\nimport java.io.File;\nimport java.io.FileReader;\n\n/**\n * JSONConverter implementation using gson.\n * @see JSONConverter\n */\npublic class GsonConverter implements JSONConverter {\n\n    public static GsonConverter create() {\n        return new GsonConverter();\n    }\n\n    private GsonConverter() {}\n\n    @Override public <T> T fromJson(File file, Class<T> clazz) throws Exception {\n        T data = new Gson().fromJson(new FileReader(file.getAbsoluteFile()), clazz);\n        return data;\n    }\n\n    @Override public String toJson(Object object) {\n        return new Gson().toJson(object);\n    }\n}\n"
  },
  {
    "path": "gson_converter/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">rx_social_connect_gson_converter</string>\n</resources>\n"
  },
  {
    "path": "gson_converter/src/test/java/io/victoralbertos/rx_social_connect/ExampleUnitTest.java",
    "content": "package io.victoralbertos.rx_social_connect;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * To work on unit tests, switch the Test Artifact in the Build Variants view.\n */\npublic class ExampleUnitTest {\n    @Test\n    public void addition_isCorrect() throws Exception {\n        assertEquals(4, 2 + 2);\n    }\n}"
  },
  {
    "path": "okhttp_interceptors/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "okhttp_interceptors/build.gradle",
    "content": "apply plugin: 'com.android.library'\napply plugin: 'com.github.dcendents.android-maven'\ngroup='com.github.VictorAlbertos'\nversion='1.0.1-2.x'\n\nandroid {\n    compileSdkVersion 25\n    buildToolsVersion \"25.0.0\"\n\n    defaultConfig {\n        minSdkVersion 16\n        targetSdkVersion 25\n        versionCode 1\n        versionName \"1.0\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n}\n\ndependencies {\n    compile fileTree(dir: 'libs', include: ['*.jar'])\n    compile project(':core')\n\n    compile 'com.android.support:appcompat-v7:25.1.1'\n    compile 'com.squareup.okhttp3:okhttp:3.6.0'\n\n    testCompile 'junit:junit:4.12'\n    testCompile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'\n    testCompile \"com.squareup.retrofit2:converter-gson:2.1.0\"\n}\n\n// build a jar with source files\ntask sourcesJar(type: Jar) {\n    from android.sourceSets.main.java.srcDirs\n    classifier = 'sources'\n}\n\ntask javadoc(type: Javadoc) {\n    failOnError  false\n    source = android.sourceSets.main.java.sourceFiles\n    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))\n    classpath += configurations.compile\n}\n\n// build a jar with javadoc\ntask javadocJar(type: Jar, dependsOn: javadoc) {\n    classifier = 'javadoc'\n    from javadoc.destinationDir\n}\n\nartifacts {\n    archives sourcesJar\n    archives javadocJar\n}\n"
  },
  {
    "path": "okhttp_interceptors/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /Users/victor/Documents/AndroidStudio/android_sdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "okhttp_interceptors/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"io.victoralbertos.rx_social_connect_interceptors\">\n\n    <application>\n\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "okhttp_interceptors/src/main/java/io/victoralbertos/rx_social_connect/OAuth1Interceptor.java",
    "content": "/*\n * Copyright 2016 Copyright 2016 Víctor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage io.victoralbertos.rx_social_connect;\n\nimport com.github.scribejava.core.model.OAuth1AccessToken;\nimport com.github.scribejava.core.model.OAuthRequest;\nimport com.github.scribejava.core.model.Verb;\nimport com.github.scribejava.core.oauth.OAuth10aService;\n\nimport io.reactivex.Observable;\nimport org.fuckboilerplate.rx_social_connect.NotActiveTokenFoundException;\nimport org.fuckboilerplate.rx_social_connect.RxSocialConnect;\n\nimport java.io.IOException;\nimport java.util.Map;\n\nimport okhttp3.Interceptor;\nimport okhttp3.Request;\nimport okhttp3.Response;\n\npublic class OAuth1Interceptor implements Interceptor {\n    protected final OAuth10aService service;\n\n    public OAuth1Interceptor(OAuth10aService service) {\n        this.service = service;\n    }\n\n    @Override public Response intercept(Chain chain) throws IOException, NotActiveTokenFoundException {\n        Request request = chain.request();\n\n        String url = request.url().toString();\n        Verb verb = apply(request.method());\n\n        OAuthRequest requestOAuth = new OAuthRequest(verb, url, service);\n        Request.Builder builderRequest = request.newBuilder();\n\n        OAuth1AccessToken token = getOToken().blockingFirst();\n        service.signRequest(token, requestOAuth);\n\n        Map<String, String> headers = requestOAuth.getHeaders();\n\n        for (Map.Entry<String, String> header : headers.entrySet()) {\n            builderRequest.addHeader(header.getKey(), header.getValue());\n        }\n\n        Response response = chain.proceed(builderRequest.build());\n        return response;\n    }\n\n    private Verb apply(String method) {\n        if (method.equalsIgnoreCase(\"GET\")) return Verb.GET;\n        else if (method.equalsIgnoreCase(\"POST\")) return Verb.POST;\n        else if (method.equalsIgnoreCase(\"PUT\")) return Verb.PUT;\n        else if (method.equalsIgnoreCase(\"DELETE\")) return Verb.DELETE;\n        else if (method.equalsIgnoreCase(\"HEAD\")) return Verb.HEAD;\n        else if (method.equalsIgnoreCase(\"OPTIONS\")) return Verb.OPTIONS;\n        else if (method.equalsIgnoreCase(\"TRACE\")) return Verb.TRACE;\n        else if (method.equalsIgnoreCase(\"PATCH\")) return Verb.PATCH;\n        return null;\n    }\n\n    //Exists for testing purposes\n    protected Observable<OAuth1AccessToken> getOToken() {\n        return RxSocialConnect.getTokenOAuth1(service.getApi().getClass());\n    }\n}\n"
  },
  {
    "path": "okhttp_interceptors/src/main/java/io/victoralbertos/rx_social_connect/OAuth2Interceptor.java",
    "content": "/*\n * Copyright 2016 Copyright 2016 Víctor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage io.victoralbertos.rx_social_connect;\n\nimport com.github.scribejava.core.builder.api.DefaultApi20;\nimport com.github.scribejava.core.model.OAuth2AccessToken;\nimport io.reactivex.Observable;\nimport java.io.IOException;\nimport okhttp3.Interceptor;\nimport okhttp3.Request;\nimport okhttp3.Response;\nimport org.fuckboilerplate.rx_social_connect.NotActiveTokenFoundException;\nimport org.fuckboilerplate.rx_social_connect.RxSocialConnect;\n\npublic class OAuth2Interceptor implements Interceptor {\n    private final Class<? extends DefaultApi20> apiClass;\n\n    public OAuth2Interceptor(Class<? extends DefaultApi20> apiClass) {\n        this.apiClass = apiClass;\n    }\n\n    @Override public Response intercept(Chain chain) throws IOException, NotActiveTokenFoundException {\n        String token = getOToken().blockingFirst().getAccessToken();\n        Request request = chain.request();\n\n        Request.Builder builderRequest = request.newBuilder();\n        builderRequest.addHeader(\"Authorization\", \"Bearer \" + token);\n        request = builderRequest.build();\n\n        Response response = chain.proceed(request);\n\n        return response;\n    }\n\n    //Exists for testing purposes\n    protected Observable<OAuth2AccessToken> getOToken() {\n        return RxSocialConnect.getTokenOAuth2(apiClass);\n    }\n}\n"
  },
  {
    "path": "okhttp_interceptors/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">rx_social_connect_interceptors</string>\n</resources>\n"
  },
  {
    "path": "okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth1TwitterInterceptorTest.java",
    "content": "/*\n * Copyright 2016 Copyright 2016 Víctor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage io.victoralbertos.rx_social_connect;\n\nimport com.github.scribejava.apis.TwitterApi;\nimport com.github.scribejava.core.builder.ServiceBuilder;\nimport com.github.scribejava.core.model.OAuth1AccessToken;\nimport com.github.scribejava.core.oauth.OAuth10aService;\nimport com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;\nimport io.reactivex.Observable;\nimport io.victoralbertos.rx_social_connect.base.OAuth1InterceptorTest;\nimport okhttp3.OkHttpClient;\nimport retrofit2.Retrofit;\nimport retrofit2.converter.gson.GsonConverterFactory;\nimport retrofit2.http.GET;\n\npublic class OAuth1TwitterInterceptorTest extends OAuth1InterceptorTest {\n\n    @Override protected OAuth10aService getService() {\n        String consumerKey = \"3wEAwhjvJmBpJpUfIXiY9PQOg\";\n        String consumerSecret = \"8N47XdpE4GSlswMcBTOZFc3fDcil7WnK4RINfUyKf2d0rFrF2I\";\n\n        return new ServiceBuilder()\n                .apiKey(consumerKey)\n                .apiSecret(consumerSecret)\n                .build(TwitterApi.instance());\n    }\n\n    @Override protected OAuth1AccessToken getToken() {\n        String token = \"732545483974053888-YD0xBTx9261ghVNRxTnxTqDd6feBF7h\";\n        String tokenSecret = \"kwXNB0IzLtH5aZA9T5Fvg5Gh1cLVjayAFWfDYWV3AtW1p\";\n\n        OAuth1AccessToken twitterToken = new OAuth1AccessToken(token, tokenSecret);\n        return twitterToken;\n    }\n\n    @Override protected Observable<Object> getApiCallWithoutInterceptor() {\n        return new Retrofit.Builder()\n                .baseUrl(OAuth1Api.URL_BASE)\n                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())\n                .addConverterFactory(GsonConverterFactory.create())\n                .build().create(OAuth1Api.class)\n                .me();\n    }\n\n    @Override protected Observable<Object> getApiCallWithInterceptor(OAuth1Interceptor interceptor) {\n        OkHttpClient client = new OkHttpClient.Builder()\n                .addInterceptor(interceptor)\n                .build();\n\n        return new Retrofit.Builder()\n                .baseUrl(OAuth1Api.URL_BASE)\n                .client(client)\n                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())\n                .addConverterFactory(GsonConverterFactory.create())\n                .build().create(OAuth1Api.class)\n                .me();\n    }\n\n    private interface OAuth1Api {\n        String URL_BASE = \"https://api.twitter.com\";\n\n        @GET(\"/1.1/account/verify_credentials.json\")\n        Observable<Object> me();\n    }\n}\n"
  },
  {
    "path": "okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth1YahooInterceptorTest.java",
    "content": "/*\n * Copyright 2016 Copyright 2016 Víctor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage io.victoralbertos.rx_social_connect;\n\nimport com.github.scribejava.apis.YahooApi;\nimport com.github.scribejava.core.builder.ServiceBuilder;\nimport com.github.scribejava.core.model.OAuth1AccessToken;\nimport com.github.scribejava.core.oauth.OAuth10aService;\nimport com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;\nimport io.reactivex.Observable;\nimport io.victoralbertos.rx_social_connect.base.OAuth1InterceptorTest;\nimport okhttp3.OkHttpClient;\nimport retrofit2.Retrofit;\nimport retrofit2.converter.gson.GsonConverterFactory;\nimport retrofit2.http.GET;\n\npublic class OAuth1YahooInterceptorTest extends OAuth1InterceptorTest {\n\n    @Override protected OAuth10aService getService() {\n        String clientId = \"dj0yJmk9Sk9NZUlPc0RaODVDJmQ9WVdrOVRubHlWMWRuTTJVbWNHbzlNQS0tJnM9Y29uc3VtZXJzZWNyZXQmeD0wNw--\";\n        String clientSecret = \"449b2d2f06d986297d65df7fc020544bf71eb10c\";\n\n        return new ServiceBuilder()\n                .apiKey(clientId)\n                .apiSecret(clientSecret)\n                .build(YahooApi.instance());\n    }\n\n    @Override protected OAuth1AccessToken getToken() {\n        String token = \"A=bKGw61fClQst5jvXVpOpwRyYXz..2es7g7C7m5k2_HwuKSKfi6VTnJeJJdGnaRRuISwGZcCRQ3J4ldwcbezZL0giYmYZDIZb_OcPttEmpwYneb030se5gWj4yPIKhciYtwruba8CKk6B96MEtPKIfNZ7sdeAB0MPRAGEe_.gZl9k.4L72qFoWzStHpTd79Wg3r8M3ClfFIT64zajfIldkLatEesiE6mqdfWLbNlJ1Zp8QJ.WSJq_aSc.rHZQ_gCx6J6QMMImF9BzCuevhoYN75G9aGkE_28HnqZUm5mCozGGx4ILXTDp4V_CWAL02M5wq1qC.28k8d7z0HnbXx80Y6PeIayqfog0BKaaY1GeM4elGY7kVBVNu5BzlsLfKOUXzRYS3JfYHWYxB3B3fdixE1DKFItaJ3bukVlTksZkgS6oYp3cmXF9iBEIxkmYr0B9u33jAn9Rc3cLfMF9u8LqsTUdVVkCO46dMvGvNwFCW410VelgVvG6lYfaFNtNMluBtyaDYjpXf2XH1Fx7nQ65Ma7CVrKr5EK61rXGYc1OwhsCn88IDUTShdqWW0xTk1sAsdz75pmofw5iR9ehZEJNeHKoDNLxihhBSLT5HC8eRl_FOgA7yuePnJceJuM._Jhsdm6BB2ocLKDEU3s2h.Djk9KLq640s6KfTR.AjM.G9.4DVrHiTA0JA2VxYPXWqOkrbfidIKthITd0ffIsMi6Tghw2vxYSWsF2oe6NrHdtTU04ahAuY3sRsEII04R9YDO.GeTVAb915yL9mo7ELQ_wjddxfh38rdDOeEfNotsfgMaAZB2zsDvMPtmIX9123jkdSyRf19aMy7viifHdi0zN.HHew4QGD3p04DYuJ60VweMrXoHfCvw605D2gLjvEvmN\";\n        String tokenSecret = \"f021440f68b8d9141849df4c233d3524789eaca8\";\n\n        OAuth1AccessToken twitterToken = new OAuth1AccessToken(token, tokenSecret);\n        return twitterToken;\n    }\n\n    @Override protected Observable<Object> getApiCallWithoutInterceptor() {\n        return new Retrofit.Builder()\n                .baseUrl(OAuth1Api.URL_BASE)\n                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())\n                .addConverterFactory(GsonConverterFactory.create())\n                .build().create(OAuth1Api.class)\n                .me();\n    }\n\n    @Override protected Observable<Object> getApiCallWithInterceptor(OAuth1Interceptor interceptor) {\n        OkHttpClient client = new OkHttpClient.Builder()\n                .addInterceptor(interceptor)\n                .build();\n\n        return new Retrofit.Builder()\n                .baseUrl(OAuth1Api.URL_BASE)\n                .client(client)\n                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())\n                .addConverterFactory(GsonConverterFactory.create())\n                .build().create(OAuth1Api.class)\n                .me();\n    }\n\n    private interface OAuth1Api {\n        String URL_BASE = \"https://social.yahooapis.com\";\n\n        @GET(\"/v1/user/me/profile?format=json\")\n        Observable<Object> me();\n    }\n}\n\n\n"
  },
  {
    "path": "okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth2FacebookInterceptorTest.java",
    "content": "/*\n * Copyright 2016 Copyright 2016 Víctor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage io.victoralbertos.rx_social_connect;\n\nimport com.github.scribejava.core.model.OAuth2AccessToken;\nimport com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;\nimport io.reactivex.Observable;\nimport io.victoralbertos.rx_social_connect.base.OAuth2InterceptorTest;\nimport okhttp3.OkHttpClient;\nimport retrofit2.Retrofit;\nimport retrofit2.converter.gson.GsonConverterFactory;\nimport retrofit2.http.GET;\n\npublic class OAuth2FacebookInterceptorTest extends OAuth2InterceptorTest {\n\n    @Override protected Observable<Object> getApiCallWithoutInterceptor() {\n        return new Retrofit.Builder()\n                .baseUrl(OAuth2Api.URL_BASE)\n                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())\n                .addConverterFactory(GsonConverterFactory.create())\n                .build().create(OAuth2Api.class)\n                .me();\n    }\n\n    @Override protected Observable<Object> getApiCallWithInterceptor(OAuth2Interceptor oAuth2Interceptor) {\n        OkHttpClient client = new OkHttpClient.Builder()\n                .addInterceptor(oAuth2Interceptor)\n                .build();\n\n        return new Retrofit.Builder()\n                .baseUrl(OAuth2Api.URL_BASE)\n                .client(client)\n                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())\n                .addConverterFactory(GsonConverterFactory.create())\n                .build().create(OAuth2Api.class)\n                .me();\n    }\n\n    @Override protected OAuth2AccessToken getToken() {\n        String accessToken = \"EAAGb8BbfjwkBAO8n69r93IbiBkQTPwesBWbBmKFNAXPcDjhho7duR3LGr8DVp5DdeQ4T16VEWtrdS21cGpnbD52rqNV45lMPInmwdbQYdZBMnERANgUGkVGxNTbpbHBVpFR1JiZCU5TgNGxWNmU43jzD5AuZB6H7c2J72sHEQZDZD\";\n        OAuth2AccessToken token = new OAuth2AccessToken(accessToken);\n        return token;\n    }\n\n    interface OAuth2Api {\n        String URL_BASE = \"https://graph.facebook.com\";\n\n        @GET(\"/v2.5/me\")\n        Observable<Object> me();\n    }\n}\n"
  },
  {
    "path": "okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth2GoogleInterceptorTest.java",
    "content": "/*\n * Copyright 2016 Copyright 2016 Víctor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage io.victoralbertos.rx_social_connect;\n\nimport com.github.scribejava.core.model.OAuth2AccessToken;\nimport com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;\nimport io.reactivex.Observable;\nimport io.victoralbertos.rx_social_connect.base.OAuth2InterceptorTest;\nimport okhttp3.OkHttpClient;\nimport retrofit2.Retrofit;\nimport retrofit2.converter.gson.GsonConverterFactory;\nimport retrofit2.http.GET;\n\npublic class OAuth2GoogleInterceptorTest extends OAuth2InterceptorTest {\n\n    @Override protected Observable<Object> getApiCallWithoutInterceptor() {\n        return new Retrofit.Builder()\n                .baseUrl(OAuth2Api.URL_BASE)\n                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())\n                .addConverterFactory(GsonConverterFactory.create())\n                .build().create(OAuth2Api.class)\n                .me();\n    }\n\n    @Override protected Observable<Object> getApiCallWithInterceptor(OAuth2Interceptor oAuth2Interceptor) {\n        OkHttpClient client = new OkHttpClient.Builder()\n                .addInterceptor(oAuth2Interceptor)\n                .build();\n\n        return new Retrofit.Builder()\n                .baseUrl(OAuth2Api.URL_BASE)\n                .client(client)\n                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())\n                .addConverterFactory(GsonConverterFactory.create())\n                .build().create(OAuth2Api.class)\n                .me();\n    }\n\n    @Override protected OAuth2AccessToken getToken() {\n        String accessToken = \"ya29.CjLsAkgBIih0ud7W_a82uKsm6nIWbjg4YuBnK0smznICod4npYiVwz08YB6jPznOHpC6Ig\";\n        OAuth2AccessToken token = new OAuth2AccessToken(accessToken);\n        return token;\n    }\n\n\n    interface OAuth2Api {\n        String URL_BASE = \"https://www.googleapis.com\";\n\n        @GET(\"/plus/v1/people/me\")\n        Observable<Object> me();\n    }\n}\n"
  },
  {
    "path": "okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/OAuth2LinkedinInterceptorTest.java",
    "content": "/*\n * Copyright 2016 Copyright 2016 Víctor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage io.victoralbertos.rx_social_connect;\n\nimport com.github.scribejava.core.model.OAuth2AccessToken;\nimport com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;\nimport io.reactivex.Observable;\nimport io.victoralbertos.rx_social_connect.base.OAuth2InterceptorTest;\nimport okhttp3.OkHttpClient;\nimport retrofit2.Retrofit;\nimport retrofit2.converter.gson.GsonConverterFactory;\nimport retrofit2.http.GET;\n\npublic class OAuth2LinkedinInterceptorTest extends OAuth2InterceptorTest {\n\n    @Override protected Observable<Object> getApiCallWithoutInterceptor() {\n        return new Retrofit.Builder()\n                .baseUrl(OAuth2Api.URL_BASE)\n                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())\n                .addConverterFactory(GsonConverterFactory.create())\n                .build().create(OAuth2Api.class)\n                .me();\n    }\n\n    @Override protected Observable<Object> getApiCallWithInterceptor(OAuth2Interceptor oAuth2Interceptor) {\n        OkHttpClient client = new OkHttpClient.Builder()\n                .addInterceptor(oAuth2Interceptor)\n                .build();\n\n        return new Retrofit.Builder()\n                .baseUrl(OAuth2Api.URL_BASE)\n                .client(client)\n                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())\n                .addConverterFactory(GsonConverterFactory.create())\n                .build().create(OAuth2Api.class)\n                .me();\n    }\n\n    @Override protected OAuth2AccessToken getToken() {\n        String accessToken = \"AQXMnxg_nqVmTo9N5uSvnv-t0jZv6yTEwYPVrQrOZDBAaZPr6Sfltnnchy4C2UlYnjR4rVHjimkgftmEzdcbSIY6nGhh2f0XzkFuuvJWf1vRAf1dayYylobHtpjbSRFW4jCj9Au1mDYpOrLbtWPePnS3I4sSvvvP0MbwLtthYVFVC8jDl9I\";\n        OAuth2AccessToken token = new OAuth2AccessToken(accessToken);\n        return token;\n    }\n\n    interface OAuth2Api {\n        String URL_BASE = \"https://api.linkedin.com\";\n\n        @GET(\"/v1/people/~?format=json\")\n        Observable<Object> me();\n    }\n}\n"
  },
  {
    "path": "okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/base/OAuth1InterceptorTest.java",
    "content": "/*\n * Copyright 2016 Copyright 2016 Víctor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage io.victoralbertos.rx_social_connect.base;\n\nimport com.github.scribejava.core.model.OAuth1AccessToken;\nimport com.github.scribejava.core.oauth.OAuth10aService;\nimport com.jakewharton.retrofit2.adapter.rxjava2.HttpException;\nimport io.reactivex.Observable;\nimport io.reactivex.observers.TestObserver;\nimport io.victoralbertos.rx_social_connect.OAuth1Interceptor;\nimport java.io.IOException;\nimport org.fuckboilerplate.rx_social_connect.NotActiveTokenFoundException;\nimport org.junit.Test;\n\npublic abstract class OAuth1InterceptorTest {\n\n    @Test public void Get_Method_Throws_HttpException_Without_Interceptor() throws IOException {\n        TestObserver<Object> testSubscriber = new TestObserver<>();\n\n        getApiCallWithoutInterceptor().subscribe(testSubscriber);\n        testSubscriber.awaitTerminalEvent();\n        testSubscriber.assertNoValues();\n        testSubscriber.assertError(HttpException.class);\n    }\n\n    @Test public void Get_Method_Throws_NotActiveTokenFoundException_With_Interceptor_With_Invalid_Token() throws IOException {\n        OAuth1Interceptor interceptor = new OAuthInterceptorInvalidToken(getService());\n\n        TestObserver<Object> testSubscriber = new TestObserver<>();\n\n        getApiCallWithInterceptor(interceptor).subscribe(testSubscriber);\n        testSubscriber.awaitTerminalEvent();\n        testSubscriber.assertNoValues();\n        testSubscriber.assertError(NotActiveTokenFoundException.class);\n    }\n\n    @Test public void Get_Method_Success_With_Interceptor_With_Valid_Token() throws IOException {\n        OAuth1Interceptor interceptor = new OAuthInterceptorValidToken(getService());\n        TestObserver<Object> testSubscriber = new TestObserver<>();\n\n        getApiCallWithInterceptor(interceptor).subscribe(testSubscriber);\n        testSubscriber.awaitTerminalEvent();\n        testSubscriber.assertValueCount(1);\n        testSubscriber.assertNoErrors();\n    }\n\n    private class OAuthInterceptorInvalidToken extends OAuth1Interceptor {\n        public OAuthInterceptorInvalidToken(OAuth10aService service) {\n            super(service);\n        }\n\n        @Override protected Observable<OAuth1AccessToken> getOToken() {\n            return Observable.error(new NotActiveTokenFoundException());\n        }\n    }\n\n    private class OAuthInterceptorValidToken extends OAuth1Interceptor {\n\n        public OAuthInterceptorValidToken(OAuth10aService service) {\n            super(service);\n        }\n\n        @Override protected Observable<OAuth1AccessToken> getOToken() {\n            return Observable.just(getToken());\n        }\n    }\n\n    protected abstract Observable<Object> getApiCallWithoutInterceptor();\n    protected abstract Observable<Object> getApiCallWithInterceptor(OAuth1Interceptor oAuth1Interceptor);\n    protected abstract OAuth10aService getService();\n    protected abstract OAuth1AccessToken getToken();\n}\n"
  },
  {
    "path": "okhttp_interceptors/src/test/java/io/victoralbertos/rx_social_connect/base/OAuth2InterceptorTest.java",
    "content": "/*\n * Copyright 2016 Copyright 2016 Víctor Albertos\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage io.victoralbertos.rx_social_connect.base;\n\nimport com.github.scribejava.core.builder.api.DefaultApi20;\nimport com.github.scribejava.core.model.OAuth2AccessToken;\nimport com.jakewharton.retrofit2.adapter.rxjava2.HttpException;\nimport io.reactivex.Observable;\nimport io.reactivex.observers.TestObserver;\nimport io.victoralbertos.rx_social_connect.OAuth2Interceptor;\nimport java.io.IOException;\nimport org.fuckboilerplate.rx_social_connect.NotActiveTokenFoundException;\nimport org.junit.Test;\n\npublic abstract class OAuth2InterceptorTest {\n\n    @Test public void Get_Method_Throws_HttpException_Without_Interceptor() throws IOException {\n        TestObserver<Object> testSubscriber = new TestObserver<>();\n\n        getApiCallWithoutInterceptor().subscribe(testSubscriber);\n        testSubscriber.awaitTerminalEvent();\n        testSubscriber.assertNoValues();\n        testSubscriber.assertError(HttpException.class);\n    }\n\n    @Test public void Get_Method_Throws_NotActiveTokenFoundException_With_Interceptor_With_Invalid_Token() throws IOException {\n        OAuth2Interceptor interceptor = new OAuthInterceptorInvalidToken(null);\n\n        TestObserver<Object> testSubscriber = new TestObserver<>();\n\n        getApiCallWithInterceptor(interceptor).subscribe(testSubscriber);\n        testSubscriber.awaitTerminalEvent();\n        testSubscriber.assertNoValues();\n        testSubscriber.assertError(NotActiveTokenFoundException.class);\n    }\n\n    @Test public void Get_Method_Success_With_Interceptor_With_Valid_Token() throws IOException {\n        OAuth2Interceptor interceptor = new OAuthInterceptorValidToken(null);\n        TestObserver<Object> testSubscriber = new TestObserver<>();\n\n        getApiCallWithInterceptor(interceptor).subscribe(testSubscriber);\n        testSubscriber.awaitTerminalEvent();\n        testSubscriber.assertValueCount(1);\n        testSubscriber.assertNoErrors();\n    }\n\n    private class OAuthInterceptorInvalidToken extends OAuth2Interceptor {\n        public OAuthInterceptorInvalidToken(Class<? extends DefaultApi20> apiClass) {\n            super(apiClass);\n        }\n\n        @Override protected Observable<OAuth2AccessToken> getOToken() {\n            return Observable.error(new NotActiveTokenFoundException());\n        }\n    }\n\n    private class OAuthInterceptorValidToken extends OAuth2Interceptor {\n\n        public OAuthInterceptorValidToken(Class<? extends DefaultApi20> apiClass) {\n            super(apiClass);\n        }\n\n        @Override protected Observable<OAuth2AccessToken> getOToken() {\n            return Observable.just(getToken());\n        }\n    }\n\n    protected abstract Observable<Object> getApiCallWithoutInterceptor();\n    protected abstract Observable<Object> getApiCallWithInterceptor(OAuth2Interceptor oAuth2Interceptor);\n    protected abstract OAuth2AccessToken getToken();\n}\n"
  },
  {
    "path": "settings.gradle",
    "content": "include ':app', ':core', ':okhttp_interceptors'\n"
  }
]