diff --git a/.gitignore b/.gitignore
index a6b51d0..43a2ba3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,8 @@
build/
+service-account.json
+
*.class
*.war
*.ear
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 9b1ae84..29d3f33 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,6 +1,6 @@
-# Contributing to the Firebase Node.JS Quickstarts
+# Contributing to the Firebase Java Quickstarts
-We'd love for you to contribute to our source code and to make the Firebase Node.JS Quickstarts even better than it is today! Here are the guidelines we'd like you to follow:
+We'd love for you to contribute to our source code and to make the Firebase Java Quickstarts even better than it is today! Here are the guidelines we'd like you to follow:
- [Code of Conduct](#coc)
- [Question or Problem?](#question)
@@ -12,19 +12,19 @@ We'd love for you to contribute to our source code and to make the Firebase Node
## Code of Conduct
-As contributors and maintainers of the Firebase Node.JS Quickstarts project, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities.
+As contributors and maintainers of the Firebase Java Quickstarts project, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities.
Communication through any of Firebase's channels (GitHub, StackOverflow, Google+, Twitter, etc.) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
We promise to extend courtesy and respect to everyone involved in this project regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to the project to do the same.
-If any member of the community violates this code of conduct, the maintainers of the Firebase Node.JS Quickstarts project may take action, removing issues, comments, and PRs or blocking accounts as deemed appropriate.
+If any member of the community violates this code of conduct, the maintainers of the Firebase Java Quickstarts project may take action, removing issues, comments, and PRs or blocking accounts as deemed appropriate.
If you are subject to or witness unacceptable behavior, or have any other concerns, please drop us a line at nivco@google.com.
## Got a Question or Problem?
-If you have questions about how to use the Firebase Node.JS Quickstarts, please direct these to [StackOverflow][stackoverflow] and use the `firebase` tag. We are also available on GitHub issues.
+If you have questions about how to use the Firebase Javqa Quickstarts, please direct these to [StackOverflow][stackoverflow] and use the `firebase` tag. We are also available on GitHub issues.
If you feel that we're missing an important bit of documentation, feel free to
file an issue so we can help. Here's an example to get you started:
diff --git a/README.md b/README.md
index a7fa4a9..c4de05e 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,12 @@
# Firebase Quickstarts for Java
-A collection of quickstart samples demonstrating the Firebase APIs using the Java Server SDK. For more information, see https://firebase.google.com.
+A collection of quickstart samples demonstrating the Firebase APIs using the Admin Java SDK. For more information, see https://firebase.google.com.
## How to make contributions?
Please read and follow the steps in the [CONTRIBUTING.md](CONTRIBUTING.md)
## License
See [LICENSE](LICENSE)
+
+## Build Status
+[](https://travis-ci.org/firebase/quickstart-java)
\ No newline at end of file
diff --git a/auth/README.md b/auth/README.md
deleted file mode 100644
index 0fa2700..0000000
--- a/auth/README.md
+++ /dev/null
@@ -1,33 +0,0 @@
-Firebase Java Auth Quickstart
-==========================================
-
-This directory contains example snippets for the Firebase Admin Authentication SDK, mostly for use
-in documentation.
-
-
-Introduction
-------------
-
-- [Read more about Firebase Auth](https://firebase.google.com/docs/auth/)
-
-Getting Started
----------------
-
-- Create your project on the [Firebase Console](https://console.firebase.google.com).
-- Create a service account as described in [Adding Firebase to your Server](https://firebase.google.com/docs/admin/setup) and download the JSON file.
- - Copy the json file to this folder and rename it to `service-account.json`.
-
-
-Run
---------------
-- From the `auth` directory run `./gradlew build run` to start run the quickstart.
-
-Support
--------
-
-https://firebase.google.com/support/
-
-License
--------
-
-© Google, 2017. Licensed under an [Apache-2](../LICENSE) license.
diff --git a/auth/build.gradle b/auth/build.gradle
deleted file mode 100644
index 244863d..0000000
--- a/auth/build.gradle
+++ /dev/null
@@ -1,20 +0,0 @@
-group 'com.google.firebase.quickstart'
-version '1.0'
-
-apply plugin: 'groovy'
-apply plugin: 'java'
-
-apply plugin: 'application'
-mainClassName = 'com.google.firebase.quickstart.AuthSnippets'
-
-sourceCompatibility = 1.8
-
-repositories {
- mavenCentral()
- mavenLocal()
-}
-
-dependencies {
- // Firebase Java SDK
- compile 'com.google.firebase:firebase-admin:5.0.2-SNAPSHOT'
-}
diff --git a/auth/src/main/java/com/google/firebase/quickstart/AuthSnippets.java b/auth/src/main/java/com/google/firebase/quickstart/AuthSnippets.java
deleted file mode 100644
index 287534a..0000000
--- a/auth/src/main/java/com/google/firebase/quickstart/AuthSnippets.java
+++ /dev/null
@@ -1,155 +0,0 @@
-package com.google.firebase.quickstart;
-
-import com.google.firebase.FirebaseApp;
-import com.google.firebase.FirebaseOptions;
-import com.google.firebase.auth.FirebaseAuth;
-import com.google.firebase.auth.FirebaseCredentials;
-import com.google.firebase.auth.UserRecord;
-import com.google.firebase.auth.UserRecord.CreateRequest;
-import com.google.firebase.auth.UserRecord.UpdateRequest;
-import com.google.firebase.tasks.Task;
-import java.io.FileInputStream;
-import java.io.IOException;
-
-/**
- * Auth snippets for documentation.
- *
- * See:
- * https://firebase.google.com/docs/auth/admin
- */
-public class AuthSnippets {
-
- public static Task getUserById(String uid) {
- // [START get_user_by_id]
- Task task = FirebaseAuth.getInstance().getUser(uid)
- .addOnSuccessListener(userRecord -> {
- // See the UserRecord reference doc for the contents of userRecord.
- System.out.println("Successfully fetched user data: " + userRecord.getUid());
- })
- .addOnFailureListener(e -> {
- System.err.println("Error fetching user data: " + e.getMessage());
- });
- // [END get_user_by_id]
-
- return task;
- }
-
- public static Task getUserByEmail(String email) {
- // [START get_user_by_email]
- Task task = FirebaseAuth.getInstance().getUserByEmail(email)
- .addOnSuccessListener(userRecord -> {
- // See the UserRecord reference doc for the contents of userRecord.
- System.out.println("Successfully fetched user data: " + userRecord.getEmail());
- })
- .addOnFailureListener(e -> {
- System.err.println("Error fetching user data: " + e.getMessage());
- });
- // [END get_user_by_email]
-
- return task;
- }
-
- public static Task createUser() {
- // [START create_user]
- CreateRequest request = new CreateRequest()
- .setEmail("user@example.com")
- .setEmailVerified(false)
- .setPassword("secretPassword")
- .setDisplayName("John Doe")
- .setPhotoUrl("http://www.example.com/12345678/photo.png")
- .setDisabled(false);
-
- Task task = FirebaseAuth.getInstance().createUser(request)
- .addOnSuccessListener(userRecord -> {
- // See the UserRecord reference doc for the contents of userRecord.
- System.out.println("Successfully created new user: " + userRecord.getUid());
- })
- .addOnFailureListener(e -> {
- System.err.println("Error creating new user: " + e.getMessage());
- });
- // [END create_user]
-
- return task;
- }
-
- public static Task createUserWithUid() {
- // [START create_user_with_uid]
- CreateRequest request = new CreateRequest()
- .setUid("some-uid")
- .setEmail("user@example.com");
-
- Task task = FirebaseAuth.getInstance().createUser(request)
- .addOnSuccessListener(userRecord -> {
- // See the UserRecord reference doc for the contents of userRecord.
- System.out.println("Successfully created new user: " + userRecord.getUid());
- })
- .addOnFailureListener(e -> {
- System.err.println("Error creating new user: " + e.getMessage());
- });
- // [END create_user_with_uid]
-
- return task;
- }
-
- public static Task updateUser(String uid) {
- // [START update_user]
- UpdateRequest request = new UpdateRequest(uid)
- .setEmail("user@example.com")
- .setEmailVerified(true)
- .setPassword("newPassword")
- .setDisplayName("Jane Doe")
- .setPhotoUrl("http://www.example.com/12345678/photo.png")
- .setDisabled(true);
-
- Task task = FirebaseAuth.getInstance().updateUser(request)
- .addOnSuccessListener(userRecord -> {
- // See the UserRecord reference doc for the contents of userRecord.
- System.out.println("Successfully updated user: " + userRecord.getUid());
- })
- .addOnFailureListener(e -> {
- System.err.println("Error updating user: " + e.getMessage());
- });
- // [END update_user]
-
- return task;
- }
-
- public static Task deleteUser(String uid) {
- // [START delete_user]
- Task task = FirebaseAuth.getInstance().deleteUser(uid)
- .addOnSuccessListener(aVoid -> System.out.println("Successfully deleted user."))
- .addOnFailureListener(e -> System.err.println("Error updating user: " + e.getMessage()));
- // [END delete_user]
-
- return task;
- }
-
- public static void main(String[] args) {
- System.out.println("Hello, AuthSnippets!");
-
- // Initialize Firebase
- try {
- // [START initialize]
- FileInputStream serviceAccount = new FileInputStream("service-account.json");
- FirebaseOptions options = new FirebaseOptions.Builder()
- .setCredential(FirebaseCredentials.fromCertificate(serviceAccount))
- .build();
- FirebaseApp.initializeApp(options);
- // [END initialize]
- } catch (IOException e) {
- System.out.println("ERROR: invalid service account credentials. See README.");
- System.out.println(e.getMessage());
-
- System.exit(1);
- }
-
- // Smoke test
- createUserWithUid()
- .continueWithTask(task -> getUserById("some-uid"))
- .continueWithTask(task -> getUserByEmail("user@example.com"))
- .continueWithTask(task -> updateUser("some-uid"))
- .continueWithTask(task -> deleteUser("some-uid"))
- .addOnCompleteListener(task -> System.out.println("Done! Success: " + task.isSuccessful()));
- }
-
-}
diff --git a/build.gradle b/build.gradle
index 0e0abac..5b9d0fb 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,6 +3,10 @@ allprojects {
mavenCentral()
mavenLocal()
}
+ dependencies {
+ // Add the dependency for the Google services Gradle plugin
+ classpath 'com.google.gms:google-services:4.3.15'
+ }
}
task clean(type: Delete) {
diff --git a/auth/.gitignore b/config/.gitignore
similarity index 65%
rename from auth/.gitignore
rename to config/.gitignore
index 595bf6a..a90cb68 100644
--- a/auth/.gitignore
+++ b/config/.gitignore
@@ -1 +1,2 @@
service-account.json
+config.json
\ No newline at end of file
diff --git a/config/LICENSE b/config/LICENSE
new file mode 100644
index 0000000..5e741d0
--- /dev/null
+++ b/config/LICENSE
@@ -0,0 +1,211 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2017 Google Inc
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ All code in any directories or sub-directories that end with *.html or
+ *.css is licensed under the Creative Commons Attribution International
+ 4.0 License, which full text can be found here:
+ https://creativecommons.org/licenses/by/4.0/legalcode.
+
+ As an exception to this license, all html or css that is generated by
+ the software at the direction of the user is copyright the user. The
+ user has full ownership and control over such content, including
+ whether and how they wish to license it.
diff --git a/config/README.md b/config/README.md
new file mode 100644
index 0000000..54d15e4
--- /dev/null
+++ b/config/README.md
@@ -0,0 +1,108 @@
+Firebase Remote Config REST API Java Quickstart
+===============================================
+
+The [Firebase Remote Config](https://firebase.google.com/docs/remote-config/) Java quickstart app demonstrates retrieving and
+updating the Firebase Remote Config template.
+
+Introduction
+------------
+
+This is a simple example of using the Firebase Remote Config REST API to update
+the Remote Config template being used by clients apps.
+
+Getting started
+---------------
+
+1. [Add Firebase to your Android Project](https://firebase.google.com/docs/android/setup).
+2. Create a service account as described in [Adding Firebase to your Server](https://firebase.google.com/docs/admin/setup) and download the JSON file.
+ - Copy the private key JSON file to this folder and rename it to `service-account.json`.
+3. Change the build.gradle file under config/, to replace '[YOUR_SERVICE_ACCOUNT_JSON_DIR]' to the directory of `service-account.json`.
+
+Run
+---
+
+- Get active template
+ - From the `config` directory run `./gradlew run -Paction=get` to retrieve the template.
+ - The returned template is stored in a file named `config.json`.
+ - Note the ETag printed to the console you will need to use it when publishing template updates.
+- Update the template
+ - If your template already has parameters, adjust one or more of the values.
+ - If your template is empty, update it to look like this:
+
+ {
+ "conditions": [
+ {
+ "name": "AndroidUsers",
+ "expression": "device.os == 'android'",
+ "tagColor": "PURPLE"
+ },
+ {
+ "name": "iOSUsers",
+ "expression": "device.os == 'ios'",
+ "tagColor": "GREEN"
+ }
+ ],
+ "parameters": {
+ "welcome_message": {
+ "defaultValue": {
+ "value": "Welcome"
+ },
+ "conditionalValues": {
+ "AndroidUsers": {
+ "value": "Welcome Android User"
+ },
+ "iOSUsers": {
+ "value": "Welcome iOS User"
+ }
+ }
+ }
+ }
+ }
+
+ - From the `config` directory run `./gradlew run -Paction=publish -Petag=''` to update the template.
+ - Be sure to set the etag to the one that was last printed in the console.
+ - Confirm in the console that the template has been updated.
+ - At this point mobile clients can fetch the updated values.
+- View existing versions
+ - From the `config` directory run `./gradlew run -Paction=versions` to print the
+ last 5 template versions.
+- Roll back to an existing template
+ - From the `config` directory run `./gradlew run -Paction=rollback -Pversion=` to
+ activate the template with the matching version number.
+
+Best practices
+--------------
+
+This section provides some additional information about how the Remote Config
+REST API should be used when retrieving and updating templates.
+
+### [Versions](https://firebase.google.com/docs/remote-config/templates) ###
+
+Each time you update parameters, {{remote_config}} creates a
+new versioned {{remote_config}} template and stores the previous template as
+a version that you can retrieve or roll back to as needed.
+
+All non-active versions expire and are removed if they are older than 90 days or if
+there are more than 300 newer template versions. Since template versions expire, any
+versions that need to be retrieved later on should be persisted externally.
+
+Use the `listVersions` [query parameters](https://firebase.google.com/docs/reference/remote-config/rest/v1/projects.remoteConfig/listVersions#query-parameters)
+to filter the versions that are returned.
+
+### ETags ###
+
+Each time the Remote Config template it retrieved an ETag is included. This ETag is a
+unique identifier of the current template on the server. When submitting updates
+to the template you must include the latest ETag to ensure that your updates are consistent.
+
+In the event that you want to completely overwrite the server's template use
+an ETag of "\*". Use this with caution since this operation cannot be undone.
+
+**NOTE:** To get the ETag your request must accept the gzip encoding. Add the header
+`Accept-Encoding: gzip` to receive the ETag in the response header `ETag`.
+
+Support
+-------
+
+- [Stack Overflow](https://stackoverflow.com/questions/tagged/firebase-remote-config)
+- [Firebase Support](https://firebase.google.com/support/)
diff --git a/config/build.gradle b/config/build.gradle
new file mode 100644
index 0000000..2dc03aa
--- /dev/null
+++ b/config/build.gradle
@@ -0,0 +1,31 @@
+apply plugin: 'java'
+apply plugin: 'application'
+mainClassName = 'com.google.firebase.samples.config.Configure'
+
+sourceCompatibility = 1.8
+
+repositories {
+ mavenCentral()
+}
+
+# run.doFirst { environment 'GOOGLE_APPLICATION_CREDENTIALS', '[YOUR_SERVICE_ACCOUNT_JSON_DIR]' }
+
+run {
+ if (project.hasProperty("action")) {
+ args = args << "${action}"
+ }
+ if (project.hasProperty("etag")) {
+ args = args << "${etag}"
+ }
+ if (project.hasProperty("version") && !project.version.equals("unspecified")) {
+ args = args << "${version}"
+ }
+ standardInput = System.in
+}
+
+dependencies {
+ testCompile group: 'junit', name: 'junit', version: '4.12'
+ compile 'com.google.auth:google-auth-library-oauth2-http:0.26.0'
+ compile 'com.google.code.gson:gson:2.8.7'
+ implementation 'com.google.firebase:firebase-admin:9.1.1'
+}
diff --git a/auth/gradle/wrapper/gradle-wrapper.jar b/config/gradle/wrapper/gradle-wrapper.jar
similarity index 99%
rename from auth/gradle/wrapper/gradle-wrapper.jar
rename to config/gradle/wrapper/gradle-wrapper.jar
index 20c81d8..fc02a97 100644
Binary files a/auth/gradle/wrapper/gradle-wrapper.jar and b/config/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/auth/gradle/wrapper/gradle-wrapper.properties b/config/gradle/wrapper/gradle-wrapper.properties
similarity index 80%
rename from auth/gradle/wrapper/gradle-wrapper.properties
rename to config/gradle/wrapper/gradle-wrapper.properties
index 62ae997..70e10dd 100644
--- a/auth/gradle/wrapper/gradle-wrapper.properties
+++ b/config/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Mon Jun 05 12:47:30 PDT 2017
+#Tue Jul 18 12:41:35 PDT 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip
diff --git a/auth/gradlew b/config/gradlew
similarity index 100%
rename from auth/gradlew
rename to config/gradlew
diff --git a/auth/gradlew.bat b/config/gradlew.bat
similarity index 100%
rename from auth/gradlew.bat
rename to config/gradlew.bat
diff --git a/config/settings.gradle b/config/settings.gradle
new file mode 100644
index 0000000..82435c2
--- /dev/null
+++ b/config/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = 'config'
+
diff --git a/config/src/main/java/com/google/firebase/samples/config/Configure.java b/config/src/main/java/com/google/firebase/samples/config/Configure.java
new file mode 100644
index 0000000..9ed5088
--- /dev/null
+++ b/config/src/main/java/com/google/firebase/samples/config/Configure.java
@@ -0,0 +1,205 @@
+package com.google.firebase.samples.config;
+
+import com.google.auth.oauth2.GoogleCredentials;
+import com.google.firebase.FirebaseApp;
+import com.google.firebase.FirebaseOptions;
+import com.google.firebase.remoteconfig.FirebaseRemoteConfig;
+import com.google.firebase.remoteconfig.FirebaseRemoteConfigException;
+import com.google.firebase.remoteconfig.ListVersionsOptions;
+import com.google.firebase.remoteconfig.ListVersionsPage;
+import com.google.firebase.remoteconfig.Template;
+import com.google.firebase.remoteconfig.Version;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonParser;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+
+/**
+ * Retrieve and publish templates for Firebase Remote Config using the REST API.
+ */
+public class Configure {
+
+ /**
+ * Gets current Firebase Remote Config template from server and store it locally.
+ *
+ * @throws IOException
+ */
+ private static void getTemplate() throws IOException {
+ try {
+ Template template = FirebaseRemoteConfig.getInstance().getTemplate();
+ JsonParser jsonParser = new JsonParser();
+ JsonElement jsonElement = jsonParser.parse(template.toJSON());
+ Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
+ String jsonStr = gson.toJson(jsonElement);
+
+ File file = new File("config.json");
+ PrintWriter printWriter = new PrintWriter(new FileWriter(file));
+ printWriter.print(jsonStr);
+ printWriter.flush();
+ printWriter.close();
+ System.out.println("Template retrieved and has been written to config.json");
+
+ // Print ETag
+ String etag = template.getETag();
+ System.out.println("ETag from server: " + etag);
+ } catch (FirebaseRemoteConfigException e) {
+ System.out.println(e.getHttpResponse().getContent());
+ }
+ }
+
+ /**
+ * Prints the last 5 available Firebase Remote Config template metadata from the server.
+ */
+ private static void getVersions() {
+ ListVersionsOptions listVersionsOptions = ListVersionsOptions.builder().setPageSize(5).build();
+ try {
+ ListVersionsPage page = FirebaseRemoteConfig.getInstance().listVersions(listVersionsOptions);
+ System.out.println("Versions: ");
+ System.out.println(versionsToJSONString(page));
+ } catch (FirebaseRemoteConfigException e) {
+ System.out.println(e.getHttpResponse().getContent());
+ }
+ }
+
+ /**
+ * Rolls back to an available version of Firebase Remote Config template.
+ *
+ * @param version The version to roll back to.
+ */
+ private static void rollback(int version) {
+ try {
+ Template template = FirebaseRemoteConfig.getInstance().rollback(version);
+ System.out.println("Rolled back to: " + version);
+ System.out.println(template.toJSON());
+ System.out.println("ETag from server: " + template.getETag());
+ } catch (FirebaseRemoteConfigException e) {
+ System.out.println("Error:");
+ System.out.println(e.getHttpResponse().getContent());
+ }
+ }
+
+ /**
+ * Publishes local template to Firebase server.
+ *
+ * @throws IOException
+ */
+ private static void publishTemplate(String etag) throws IOException {
+ if (etag.equals("*")) {
+ Scanner scanner = new Scanner(System.in);
+ System.out.println("Are you sure you would like to force replace the template? Yes (y), No (n)");
+ String answer = scanner.nextLine();
+ if (!answer.equalsIgnoreCase("y")) {
+ System.out.println("Publish canceled.");
+ return;
+ }
+ }
+
+ System.out.println("Publishing template...");
+
+ String templateStr = readConfig();
+ try {
+ Template template = Template.fromJSON(templateStr);
+ if (etag.equals("*")) {
+ Template publishedTemplate = FirebaseRemoteConfig.getInstance()
+ .forcePublishTemplate(template);
+ } else {
+ Template publishedTemplate = FirebaseRemoteConfig.getInstance()
+ .publishTemplate(template);
+ }
+ System.out.println("Template has been published.");
+ }
+ catch (FirebaseRemoteConfigException e) {
+ System.out.println("Error:");
+ System.out.println(e.getHttpResponse().getContent());
+ }
+ }
+
+ /**
+ * Reads the Firebase Remote Config template from config.json file.
+ *
+ * @return String with contents of config.json file.
+ * @throws FileNotFoundException
+ */
+ private static String readConfig() throws FileNotFoundException {
+ File file = new File("config.json");
+ Scanner scanner = new Scanner(file);
+
+ StringBuilder stringBuilder = new StringBuilder();
+ while (scanner.hasNext()) {
+ stringBuilder.append(scanner.nextLine());
+ }
+ return stringBuilder.toString();
+ }
+
+ /**
+ * Converts the list of versions into a formatted JSON string.
+ *
+ * @return String representing the list of versions.
+ */
+ private static String versionsToJSONString(ListVersionsPage page) {
+ Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
+ JsonParser jsonParser = new JsonParser();
+
+ JsonArray versionsJsonArray = new JsonArray();
+ for (Version version : page.iterateAll()) {
+ versionsJsonArray.add(jsonParser.parse(gson.toJson(version)));
+ }
+
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.add("versions", versionsJsonArray);
+ return gson.toJson(jsonParser.parse(jsonObject.toString()));
+ }
+
+ public static void initializeWithDefaultCredentials() throws IOException {
+ // [START initialize_sdk_with_application_default]
+ FirebaseOptions options = new FirebaseOptions.Builder()
+ .setCredentials(GoogleCredentials.getApplicationDefault())
+ .build();
+
+ FirebaseApp.initializeApp(options);
+ // [END initialize_sdk_with_application_default]
+ }
+
+ public static void main(String[] args) throws IOException {
+ initializeWithDefaultCredentials();
+ if (args.length > 1 && args[0].equals("publish")) {
+ publishTemplate(args[1]);
+ } else if (args.length == 1 && args[0].equals("get")) {
+ getTemplate();
+ } else if (args.length == 1 && args[0].equals("versions")) {
+ getVersions();
+ } else if (args.length > 1 && args[0].equals("rollback")) {
+ rollback(Integer.parseInt(args[1]));
+ } else {
+ System.err.println("Invalid request. Please use one of the following commands:");
+ // To get the current template from the server.
+ System.err.println("./gradlew run -Paction=get");
+ // To publish the template in config.json to the server.
+ System.err.println("./gradlew run -Paction=publish -Petag=''");
+ // To get the available template versions from the server.
+ System.err.println("./gradlew run -Paction=versions");
+ // To roll back to a particular version.
+ System.err.println("./gradlew run -Paction=rollback -Pversion=");
+ }
+ }
+
+}
diff --git a/database/.gitignore b/database/.gitignore
deleted file mode 100644
index 595bf6a..0000000
--- a/database/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-service-account.json
diff --git a/database/README.md b/database/README.md
deleted file mode 100644
index 18ae923..0000000
--- a/database/README.md
+++ /dev/null
@@ -1,42 +0,0 @@
-Firebase Java Realtime Database Quickstart
-==========================================
-
-The Java Firebase Database quickstart demonstrates how to connect to and use the Firebase Realtime Database using Java through a simple social blogging app. It will interoperate with the Web, iOS and Android database quickstarts.
-
-This server will:
- - Update the star counts for all posts.
- - Send notifications when a post has been stared.
- - Run weekly job listing the top 5 posts.
-
-Introduction
-------------
-
-- [Read more about Firebase Database](https://firebase.google.com/docs/database/)
-
-Getting Started
----------------
-
-- Create your project on the [Firebase Console](https://console.firebase.google.com).
-- Create a service account as described in [Adding Firebase to your Server](https://firebase.google.com/docs/admin/setup) and download the JSON file.
- - Copy the json file to this folder and rename it to `service-account.json`.
-- Change the `DATATBASE_URL` variable in `Database.java` to be the URL of your Firebase Database.
-
-
-Run
---------------
-- From the `database` directory run `./gradlew build run` to start run the quickstart.
-- Configure and run one of the Database quickstarts for [Web](https://github.com/firebase/quickstart-js/tree/master/database),
- [iOS](https://github.com/firebase/quickstart-ios/tree/master/database) or
- [Android](https://github.com/firebase/quickstart-android/tree/master/database).
- Then use one of these apps to publish new posts: you should see console output when one of your posts have
- received a new star and the starred counter should be kept up to date by the app.
-
-Support
--------
-
-https://firebase.google.com/support/
-
-License
--------
-
-© Google, 2016. Licensed under an [Apache-2](../LICENSE) license.
diff --git a/database/build.gradle b/database/build.gradle
deleted file mode 100644
index 5b04dd8..0000000
--- a/database/build.gradle
+++ /dev/null
@@ -1,22 +0,0 @@
-group 'com.google.firebase.quickstart'
-version '1.0'
-
-apply plugin: 'java'
-
-apply plugin: 'application'
-mainClassName = 'com.google.firebase.quickstart.Database'
-
-sourceCompatibility = 1.8
-
-repositories {
- mavenCentral()
- mavenLocal()
-}
-
-dependencies {
- // Firebase Java SDK
- compile 'com.google.firebase:firebase-admin:4.1.1'
-
- // Sundial Job Scheduler
- compile 'org.knowm:sundial:2.1.1'
-}
diff --git a/database/gradle/wrapper/gradle-wrapper.jar b/database/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index 9411448..0000000
Binary files a/database/gradle/wrapper/gradle-wrapper.jar and /dev/null differ
diff --git a/database/settings.gradle b/database/settings.gradle
deleted file mode 100644
index 527b65e..0000000
--- a/database/settings.gradle
+++ /dev/null
@@ -1,2 +0,0 @@
-rootProject.name = 'database'
-
diff --git a/database/src/main/java/com/google/firebase/quickstart/Database.java b/database/src/main/java/com/google/firebase/quickstart/Database.java
deleted file mode 100644
index 4dab0dd..0000000
--- a/database/src/main/java/com/google/firebase/quickstart/Database.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/**
- * Copyright Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.google.firebase.quickstart;
-
-import com.google.firebase.FirebaseApp;
-import com.google.firebase.FirebaseOptions;
-import com.google.firebase.auth.FirebaseCredentials;
-import com.google.firebase.database.*;
-import com.google.firebase.quickstart.email.MyEmailer;
-import com.google.firebase.quickstart.model.Post;
-import com.google.firebase.quickstart.model.User;
-import org.knowm.sundial.SundialJobScheduler;
-
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-
-/**
- * Firebase Database quickstart sample for the Java Admin SDK.
- * See: https://firebase.google.com/docs/admin/setup#add_firebase_to_your_app
- */
-public class Database {
-
- private static final String DATABASE_URL = "https://.firebaseio.com/";
-
- private static DatabaseReference database;
-
- /**
- * Notify a user of a new start and then update the last notification time.
- */
- private static void sendNotificationToUser(final String uid, final String postId) {
- // [START single_value_read]
- final DatabaseReference userRef = database.child("users").child(uid);
- userRef.addListenerForSingleValueEvent(new ValueEventListener() {
- public void onDataChange(DataSnapshot dataSnapshot) {
- User user = dataSnapshot.getValue(User.class);
- if (user.email != null) {
- // Send email notification
- MyEmailer.sendNotificationEmail(user.email, uid, postId);
- }
- }
-
- public void onCancelled(DatabaseError databaseError) {
- System.out.println("Unable to get user data from " + userRef.getKey());
- System.out.println("Error: " + databaseError.getMessage());
- }
- });
- // [END single_value_read]
- }
-
- /**
- * Update the startCount value to equal the number of stars in the map.
- */
- private static void updateStarCount(DatabaseReference postRef) {
- // [START post_stars_transaction]
- postRef.runTransaction(new Transaction.Handler() {
- public Transaction.Result doTransaction(MutableData mutableData) {
- Post post = mutableData.getValue(Post.class);
- if (post != null) {
- // Update the starCount to be the same as the number of members in the stars map.
- if (post.stars != null) {
- post.starCount = post.stars.size();
- } else {
- post.starCount = 0;
- }
-
- mutableData.setValue(post);
- return Transaction.success(mutableData);
- } else {
- return Transaction.success(mutableData);
- }
- }
-
- public void onComplete(DatabaseError databaseError, boolean complete, DataSnapshot dataSnapshot) {
- System.out.println("updateStarCount:onComplete:" + complete);
- }
- });
- // [END post_stars_transaction]
- }
-
- /**
- * Start global listener for all Posts.
- */
- public static void startListeners() {
- database.child("posts").addChildEventListener(new ChildEventListener() {
-
- public void onChildAdded(DataSnapshot dataSnapshot, String prevChildName) {
- final String postId = dataSnapshot.getKey();
- final Post post = dataSnapshot.getValue(Post.class);
-
- // Listen for changes in the number of stars and update starCount
- addStarsChangedListener(post, postId);
-
- // Listen for new stars on the post, notify users on changes
- addNewStarsListener(dataSnapshot.getRef(), post);
- }
-
- public void onChildChanged(DataSnapshot dataSnapshot, String prevChildName) {}
-
- public void onChildRemoved(DataSnapshot dataSnapshot) {}
-
- public void onChildMoved(DataSnapshot dataSnapshot, String prevChildName) {}
-
- public void onCancelled(DatabaseError databaseError) {
- System.out.println("startListeners: unable to attach listener to posts");
- System.out.println("startListeners: " + databaseError.getMessage());
- }
- });
- }
-
- /**
- * Listen for stars added or removed and update the starCount.
- */
- private static void addStarsChangedListener(Post post, String postId) {
- // Get references to the post in both locations
- final DatabaseReference postRef = database.child("posts").child(postId);
- final DatabaseReference userPostRef = database.child("user-posts").child(post.uid).child(postId);
-
- // When the post changes, update the star counts
- // [START post_value_event_listener]
- postRef.child("stars").addValueEventListener(new ValueEventListener() {
- public void onDataChange(DataSnapshot dataSnapshot) {
- updateStarCount(postRef);
- // [START_EXCLUDE]
- updateStarCount(userPostRef);
- // [END_EXCLUDE]
- }
-
- public void onCancelled(DatabaseError databaseError) {
- System.out.println("Unable to attach listener to stars for post: " + postRef.getKey());
- System.out.println("Error: " + databaseError.getMessage());
- }
- });
- // [END post_value_event_listener]
- }
-
- /**
- * Send email to author when new star is received.
- */
- private static void addNewStarsListener(final DatabaseReference postRef, final Post post) {
- // [START child_event_listener_recycler]
- postRef.child("stars").addChildEventListener(new ChildEventListener() {
- public void onChildAdded(DataSnapshot dataSnapshot, String prevChildName) {
- // New star added, notify the author of the post
- sendNotificationToUser(post.uid, postRef.getKey());
- }
-
- public void onChildChanged(DataSnapshot dataSnapshot, String prevChildName) {}
-
- public void onChildRemoved(DataSnapshot dataSnapshot) {}
-
- public void onChildMoved(DataSnapshot dataSnapshot, String prevChildName) {}
-
- public void onCancelled(DatabaseError databaseError) {
- System.out.println("Unable to attach new star listener to: " + postRef.getKey());
- System.out.println("Error: " + databaseError.getMessage());
- }
- });
- // [END child_event_listener_recycler]
- }
-
- /**
- * Send an email listing the top posts every Sunday.
- */
- private static void startWeeklyTopPostEmailer() {
- SundialJobScheduler.startScheduler("com.google.firebase.quickstart.email");
- }
-
- public static void main(String[] args) {
- // Initialize Firebase
- try {
- // [START initialize]
- FileInputStream serviceAccount = new FileInputStream("service-account.json");
- FirebaseOptions options = new FirebaseOptions.Builder()
- .setCredential(FirebaseCredentials.fromCertificate(serviceAccount))
- .setDatabaseUrl(DATABASE_URL)
- .build();
- FirebaseApp.initializeApp(options);
- // [END initialize]
- } catch (FileNotFoundException e) {
- System.out.println("ERROR: invalid service account credentials. See README.");
- System.out.println(e.getMessage());
-
- System.exit(1);
- }
-
- // Shared Database reference
- database = FirebaseDatabase.getInstance().getReference();
-
- // Start listening to the Database
- startListeners();
-
- // Kick off weekly email task
- startWeeklyTopPostEmailer();
- }
-
-}
diff --git a/database/src/main/java/com/google/firebase/quickstart/email/MyEmailer.java b/database/src/main/java/com/google/firebase/quickstart/email/MyEmailer.java
deleted file mode 100644
index a3686c3..0000000
--- a/database/src/main/java/com/google/firebase/quickstart/email/MyEmailer.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * Copyright Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.google.firebase.quickstart.email;
-
-import com.google.firebase.database.DatabaseReference;
-import com.google.firebase.database.FirebaseDatabase;
-import com.google.firebase.database.ServerValue;
-import com.google.firebase.quickstart.model.Post;
-import com.google.firebase.quickstart.model.User;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Class to send email notifications from the server.
- */
-public class MyEmailer {
-
- public static void sendNotificationEmail(String email, String uid, String postId) {
- // TODO(developer): send email to user notifying them that one of their posts got a new star
- System.out.println("sendNotificationEmail: MOCK IMPLEMENTATION");
- System.out.println("sendNotificationEmail: " + email);
-
- // Save the date of the last notification sent
- // [START write_fan_out]
- Map update = new HashMap();
- update.put("/posts/" + postId + "/lastNotificationTimestamp", ServerValue.TIMESTAMP);
- update.put("/user-posts/" + uid + "/" + postId + "/lastNotificationTimestamp", ServerValue.TIMESTAMP);
-
- FirebaseDatabase.getInstance().getReference().updateChildren(update);
- // [END write_fan_out]
- }
-
- public static void sendWeeklyEmail(Map users, List topPosts) {
- // TODO(developer): send email to each user notifying them about the current top posts
- System.out.println("sendWeeklyEmail: MOCK IMPLEMENTATION");
- System.out.println("sendWeeklyEmail: there are " + users.size() + " total users.");
- System.out.println("sendWeeklyEmail: the top post is " + topPosts.get(0).title + " by " + topPosts.get(0).author);
-
- for (String userId : users.keySet()) {
- // Mark the last time the weekly email was sent out
- // [START basic_write]
- DatabaseReference userRef = FirebaseDatabase.getInstance().getReference()
- .child("users").child(userId).child("lastSentWeeklyTimestamp");
- userRef.setValue(ServerValue.TIMESTAMP);
- // [END basic_write]
- }
- }
-
-}
diff --git a/database/src/main/java/com/google/firebase/quickstart/email/WeeklyEmailJob.java b/database/src/main/java/com/google/firebase/quickstart/email/WeeklyEmailJob.java
deleted file mode 100644
index 40e063c..0000000
--- a/database/src/main/java/com/google/firebase/quickstart/email/WeeklyEmailJob.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * Copyright Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.google.firebase.quickstart.email;
-
-import com.google.firebase.database.*;
-import com.google.firebase.quickstart.model.Post;
-import com.google.firebase.quickstart.model.User;
-import org.knowm.sundial.Job;
-import org.knowm.sundial.annotations.CronTrigger;
-import org.knowm.sundial.exceptions.JobInterruptException;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Cron job to send weekly emails (Sundays at 2:30pm)
- */
-@CronTrigger(cron = "0 30 14 ? * SUN *")
-public class WeeklyEmailJob extends Job {
-
- public void doRun() throws JobInterruptException {
- DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
-
- // Top 5 Posts in the database, ordered by stars
- // [START top_posts_query]
- Query topPostsQuery = ref.child("posts").orderByChild("starCount").limitToLast(5);
- // [END top_posts_query]
-
- // All Users
- final DatabaseReference allUsersRef = ref.child("users");
-
- topPostsQuery.addListenerForSingleValueEvent(new ValueEventListener() {
- public void onDataChange(final DataSnapshot topPostsSnapshot) {
- allUsersRef.addListenerForSingleValueEvent(new ValueEventListener() {
- public void onDataChange(DataSnapshot allUsersSnapshot) {
- // Get users and posts as lists
- Map users = allUsersSnapshot.getValue(new GenericTypeIndicator