Skip to content

Commit d87f364

Browse files
committed
Merge branch 'master' into hkj-firestore-java
2 parents d64b4f6 + fb78501 commit d87f364

File tree

5 files changed

+86
-74
lines changed

5 files changed

+86
-74
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ target/
66
.project
77
.checkstyle
88
release.properties
9+
integration_cert.json
10+
integration_apikey.txt

CONTRIBUTING.md

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -130,21 +130,20 @@ Integration tests are also written using Junit4. They coexist with the unit test
130130
subdirectory. Integration tests follow the naming convention `*IT.java` (e.g. `DataTestIT.java`),
131131
which enables the Maven Surefire and Failsafe plugins to differentiate between the two types of
132132
tests. Integration tests are executed against a real life Firebase project, and therefore
133-
requires an Internet connection. Create a new project in the
134-
[Firebase console](https://console.firebase.google.com/) if you do not already have one. Use a
135-
separate, dedicated project for integration tests since the test suite makes a large number of
136-
writes to the Firebase realtime database. Download the service account private key from the
137-
"Settings > Service Accounts" page of the project. Also obtain the web API key of the project
138-
from the "Settings > General" page. Now run the following command to invoke the integration
139-
test suite:
133+
requires an Internet connection.
134+
135+
Create a new project in the [Firebase console](https://console.firebase.google.com/) if you do
136+
not already have one. Use a separate, dedicated project for integration tests since the test suite
137+
makes a large number of writes to the Firebase realtime database. Download the service account
138+
private key from the "Settings > Service Accounts" page of the project, and save it as
139+
`integration_cert.json` at the root of the codebase. Also obtain the web API key of the project
140+
from the "Settings > General" page, and save it as `integration_apikey.txt` at the root of the
141+
codebase. Now run the following command to invoke the integration test suite:
140142

141143
```
142-
mvn verify -Dfirebase.it.certificate=path/to/serviceAccount.json -Dfirebase.it.apikey=API-Key
144+
mvn verify
143145
```
144146

145-
Make sure to specify the correct path to your downloaded service account key file as the
146-
`firebase.it.certificate` system property.
147-
148147
The above command invokes both unit and integration test suites. To execute only the integration
149148
tests, specify the `-DskipUTs` flag.
150149

src/main/java/com/google/firebase/ThreadManager.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232
*
3333
* <p>Multiple app instances may use the same <code>ThreadManager</code> instance.
3434
* Methods in this interface may get invoked multiple times by the same
35-
* app, during its lifetime. Apps may also invoke methods of this interface concurrently, and
36-
* therefore implementations should provide any synchronization necessary.
35+
* app, during its lifetime. Apps may also invoke methods of this interface concurrently and
36+
* so implementations should provide any synchronization necessary.
3737
*/
3838
public abstract class ThreadManager {
3939

@@ -76,11 +76,11 @@ protected abstract void releaseExecutor(
7676
* Returns the <code>ThreadFactory</code> to be used for creating long-lived threads. This is
7777
* used mainly to create the long-lived worker threads for the Realtime Database client, and
7878
* other scheduled (periodic) tasks started by the SDK. The SDK guarantees
79-
* clean termination of all threads started via this <code>ThreadFactory</code>, upon
80-
* calling {@link FirebaseApp#delete()}.
79+
* clean termination of all threads started via this <code>ThreadFactory</code>, when the user
80+
* calls {@link FirebaseApp#delete()}.
8181
*
8282
* <p>If long-lived threads cannot be supported in the current runtime, this method may
83-
* throw a RuntimeException.
83+
* throw a {@code RuntimeException}.
8484
*
8585
* @return A non-null <code>ThreadFactory</code>.
8686
*/

src/main/java/com/google/firebase/auth/FirebaseAuth.java

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public static synchronized FirebaseAuth getInstance(FirebaseApp app) {
111111
}
112112

113113
/**
114-
* Similar to {@link #createCustomTokenAsync(String)}, but returns a Task.
114+
* Similar to {@link #createCustomTokenAsync(String)}, but returns a {@link Task}.
115115
*
116116
* @param uid The UID to store in the token. This identifies the user to other Firebase services
117117
* (Firebase Database, Firebase Auth, etc.)
@@ -124,7 +124,7 @@ public Task<String> createCustomToken(String uid) {
124124
}
125125

126126
/**
127-
* Similar to {@link #createCustomTokenAsync(String, Map)}, but returns a Task.
127+
* Similar to {@link #createCustomTokenAsync(String, Map)}, but returns a {@link Task}.
128128
*
129129
* @param uid The UID to store in the token. This identifies the user to other Firebase services
130130
* (Realtime Database, Storage, etc.). Should be less than 128 characters.
@@ -158,12 +158,14 @@ public String call() throws Exception {
158158

159159
/**
160160
* Creates a Firebase Custom Token associated with the given UID. This token can then be provided
161-
* back to a client application for use with the signInWithCustomToken authentication API.
161+
* back to a client application for use with the
162+
* <a href="/docs/auth/admin/create-custom-tokens#sign_in_using_custom_tokens_on_clients">signInWithCustomToken</a>
163+
* authentication API.
162164
*
163165
* @param uid The UID to store in the token. This identifies the user to other Firebase services
164-
* (Firebase Database, Firebase Auth, etc.)
165-
* @return An ApiFuture which will complete successfully with the created Firebase Custom Token,
166-
* or unsuccessfully with the failure Exception.
166+
* (Firebase Realtime Database, Firebase Auth, etc.)
167+
* @return An {@code ApiFuture} which will complete successfully with the created Firebase Custom
168+
* Token, or unsuccessfully with the failure Exception.
167169
*/
168170
public ApiFuture<String> createCustomTokenAsync(String uid) {
169171
return new TaskToApiFuture<>(createCustomToken(uid));
@@ -179,16 +181,16 @@ public ApiFuture<String> createCustomTokenAsync(String uid) {
179181
* @param developerClaims Additional claims to be stored in the token (and made available to
180182
* security rules in Database, Storage, etc.). These must be able to be serialized to JSON
181183
* (e.g. contain only Maps, Arrays, Strings, Booleans, Numbers, etc.)
182-
* @return An ApiFuture which will complete successfully with the created Firebase Custom Token,
183-
* or unsuccessfully with the failure Exception.
184+
* @return An {@code ApiFuture} which will complete successfully with the created Firebase Custom
185+
* Token, or unsuccessfully with the failure Exception.
184186
*/
185187
public ApiFuture<String> createCustomTokenAsync(
186188
final String uid, final Map<String, Object> developerClaims) {
187189
return new TaskToApiFuture<>(createCustomToken(uid, developerClaims));
188190
}
189191

190192
/**
191-
* Similar to {@link #verifyIdTokenAsync(String)}, but returns a Task.
193+
* Similar to {@link #verifyIdTokenAsync(String)}, but returns a {@link Task}.
192194
*
193195
* @param token A Firebase ID Token to verify and parse.
194196
* @return A {@link Task} which will complete successfully with the parsed token, or
@@ -235,20 +237,20 @@ public FirebaseToken call() throws Exception {
235237
* If the token is invalid, the future throws an exception indicating the failure.
236238
*
237239
* @param token A Firebase ID Token to verify and parse.
238-
* @return An ApiFuture which will complete successfully with the parsed token, or
240+
* @return An {@code ApiFuture} which will complete successfully with the parsed token, or
239241
* unsuccessfully with the failure Exception.
240242
*/
241243
public ApiFuture<FirebaseToken> verifyIdTokenAsync(final String token) {
242244
return new TaskToApiFuture<>(verifyIdToken(token));
243245
}
244246

245247
/**
246-
* Similar to {@link #getUserAsync(String)}, but returns a Task.
248+
* Similar to {@link #getUserAsync(String)}, but returns a {@link Task}.
247249
*
248250
* @param uid A user ID string.
249251
* @return A {@link Task} which will complete successfully with a {@link UserRecord} instance.
250252
* If an error occurs while retrieving user data or if the specified user ID does not exist,
251-
* the task fails with a FirebaseAuthException.
253+
* the task fails with a {@link FirebaseAuthException}.
252254
* @throws IllegalArgumentException If the user ID string is null or empty.
253255
* @deprecated Use {@link #getUserAsync(String)}
254256
*/
@@ -267,22 +269,22 @@ public UserRecord call() throws Exception {
267269
* Gets the user data corresponding to the specified user ID.
268270
*
269271
* @param uid A user ID string.
270-
* @return An ApiFuture which will complete successfully with a {@link UserRecord} instance.
271-
* If an error occurs while retrieving user data or if the specified user ID does not exist,
272-
* the future throws a FirebaseAuthException.
272+
* @return An {@code ApiFuture} which will complete successfully with a {@link UserRecord}
273+
* instance. If an error occurs while retrieving user data or if the specified user ID does
274+
* not exist, the future throws a {@link FirebaseAuthException}.
273275
* @throws IllegalArgumentException If the user ID string is null or empty.
274276
*/
275277
public ApiFuture<UserRecord> getUserAsync(final String uid) {
276278
return new TaskToApiFuture<>(getUser(uid));
277279
}
278280

279281
/**
280-
* Similar to {@link #getUserByEmailAsync(String)}, but returns a Task.
282+
* Similar to {@link #getUserByEmailAsync(String)}, but returns a {@link Task}.
281283
*
282284
* @param email A user email address string.
283285
* @return A {@link Task} which will complete successfully with a {@link UserRecord} instance.
284286
* If an error occurs while retrieving user data or if the email address does not correspond
285-
* to a user, the task fails with a FirebaseAuthException.
287+
* to a user, the task fails with a {@link FirebaseAuthException}.
286288
* @throws IllegalArgumentException If the email is null or empty.
287289
* @deprecated Use {@link #getUserByEmailAsync(String)}
288290
*/
@@ -301,22 +303,22 @@ public UserRecord call() throws Exception {
301303
* Gets the user data corresponding to the specified user email.
302304
*
303305
* @param email A user email address string.
304-
* @return An ApiFuture which will complete successfully with a {@link UserRecord} instance.
305-
* If an error occurs while retrieving user data or if the email address does not correspond
306-
* to a user, the future throws a FirebaseAuthException.
306+
* @return An {@code ApiFuture} which will complete successfully with a {@link UserRecord}
307+
* instance. If an error occurs while retrieving user data or if the email address does not
308+
* correspond to a user, the future throws a {@link FirebaseAuthException}.
307309
* @throws IllegalArgumentException If the email is null or empty.
308310
*/
309311
public ApiFuture<UserRecord> getUserByEmailAsync(final String email) {
310312
return new TaskToApiFuture<>(getUserByEmail(email));
311313
}
312314

313315
/**
314-
* Similar to {@link #getUserByPhoneNumberAsync(String)}, but returns a Task.
316+
* Similar to {@link #getUserByPhoneNumberAsync(String)}, but returns a {@link Task}.
315317
*
316318
* @param phoneNumber A user phone number string.
317319
* @return A {@link Task} which will complete successfully with a {@link UserRecord} instance.
318320
* If an error occurs while retrieving user data or if the phone number does not
319-
* correspond to a user, the task fails with a FirebaseAuthException.
321+
* correspond to a user, the task fails with a {@link FirebaseAuthException}.
320322
* @throws IllegalArgumentException If the phone number is null or empty.
321323
* @deprecated Use {@link #getUserByPhoneNumberAsync(String)}
322324
*/
@@ -335,22 +337,22 @@ public UserRecord call() throws Exception {
335337
* Gets the user data corresponding to the specified user phone number.
336338
*
337339
* @param phoneNumber A user phone number string.
338-
* @return An ApiFuture which will complete successfully with a {@link UserRecord} instance.
339-
* If an error occurs while retrieving user data or if the phone number does not
340-
* correspond to a user, the future throws a FirebaseAuthException.
340+
* @return An {@code ApiFuture} which will complete successfully with a {@link UserRecord}
341+
* instance. If an error occurs while retrieving user data or if the phone number does not
342+
* correspond to a user, the future throws a {@link FirebaseAuthException}.
341343
* @throws IllegalArgumentException If the phone number is null or empty.
342344
*/
343345
public ApiFuture<UserRecord> getUserByPhoneNumberAsync(final String phoneNumber) {
344346
return new TaskToApiFuture<>(getUserByPhoneNumber(phoneNumber));
345347
}
346348

347349
/**
348-
* Similar to {@link #createUserAsync(CreateRequest)}, but returns a Task.
350+
* Similar to {@link #createUserAsync(CreateRequest)}, but returns a {@link Task}.
349351
*
350352
* @param request A non-null {@link CreateRequest} instance.
351353
* @return A {@link Task} which will complete successfully with a {@link UserRecord} instance
352354
* corresponding to the newly created account. If an error occurs while creating the user
353-
* account, the task fails with a FirebaseAuthException.
355+
* account, the task fails with a {@link FirebaseAuthException}.
354356
* @throws NullPointerException if the provided request is null.
355357
* @deprecated Use {@link #createUserAsync(CreateRequest)}
356358
*/
@@ -371,22 +373,22 @@ public UserRecord call() throws Exception {
371373
* {@link CreateRequest}.
372374
*
373375
* @param request A non-null {@link CreateRequest} instance.
374-
* @return An ApiFuture which will complete successfully with a {@link UserRecord} instance
375-
* corresponding to the newly created account. If an error occurs while creating the user
376-
* account, the future throws a FirebaseAuthException.
376+
* @return An {@code ApiFuture} which will complete successfully with a {@link UserRecord}
377+
* instance corresponding to the newly created account. If an error occurs while creating the
378+
* user account, the future throws a {@link FirebaseAuthException}.
377379
* @throws NullPointerException if the provided request is null.
378380
*/
379381
public ApiFuture<UserRecord> createUserAsync(final CreateRequest request) {
380382
return new TaskToApiFuture<>(createUser(request));
381383
}
382384

383385
/**
384-
* Similar to {@link #updateUserAsync(UpdateRequest)}, but returns a Task.
386+
* Similar to {@link #updateUserAsync(UpdateRequest)}, but returns a {@link Task}.
385387
*
386388
* @param request A non-null {@link UpdateRequest} instance.
387389
* @return A {@link Task} which will complete successfully with a {@link UserRecord} instance
388390
* corresponding to the updated user account. If an error occurs while updating the user
389-
* account, the task fails with a FirebaseAuthException.
391+
* account, the task fails with a {@link FirebaseAuthException}.
390392
* @throws NullPointerException if the provided update request is null.
391393
* @deprecated Use {@link #updateUserAsync(UpdateRequest)}
392394
*/
@@ -407,22 +409,22 @@ public UserRecord call() throws Exception {
407409
* {@link UpdateRequest}.
408410
*
409411
* @param request A non-null {@link UpdateRequest} instance.
410-
* @return An ApiFuture which will complete successfully with a {@link UserRecord} instance
411-
* corresponding to the updated user account. If an error occurs while updating the user
412-
* account, the future throws a FirebaseAuthException.
412+
* @return An {@code ApiFuture} which will complete successfully with a {@link UserRecord}
413+
* instance corresponding to the updated user account. If an error occurs while updating the
414+
* user account, the future throws a {@link FirebaseAuthException}.
413415
* @throws NullPointerException if the provided update request is null.
414416
*/
415417
public ApiFuture<UserRecord> updateUserAsync(final UpdateRequest request) {
416418
return new TaskToApiFuture<>(updateUser(request));
417419
}
418420

419421
/**
420-
* Similar to {@link #deleteUserAsync(String)}, but returns a Task.
422+
* Similar to {@link #deleteUserAsync(String)}, but returns a {@link Task}.
421423
*
422424
* @param uid A user ID string.
423425
* @return A {@link Task} which will complete successfully when the specified user account has
424426
* been deleted. If an error occurs while deleting the user account, the task fails with a
425-
* FirebaseAuthException.
427+
* {@link FirebaseAuthException}.
426428
* @throws IllegalArgumentException If the user ID string is null or empty.
427429
* @deprecated Use {@link #deleteUserAsync(String)}
428430
*/
@@ -455,9 +457,9 @@ private void destroy() {
455457
* Deletes the user identified by the specified user ID.
456458
*
457459
* @param uid A user ID string.
458-
* @return An ApiFuture which will complete successfully when the specified user account has
459-
* been deleted. If an error occurs while deleting the user account, the future throws a
460-
* FirebaseAuthException.
460+
* @return An {@code ApiFuture} which will complete successfully when the specified user account
461+
* has been deleted. If an error occurs while deleting the user account, the future throws a
462+
* {@link FirebaseAuthException}.
461463
* @throws IllegalArgumentException If the user ID string is null or empty.
462464
*/
463465
public ApiFuture<Void> deleteUserAsync(final String uid) {

src/test/java/com/google/firebase/testing/IntegrationTestUtils.java

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616

1717
package com.google.firebase.testing;
1818

19-
import static com.google.common.base.Preconditions.checkArgument;
2019
import static com.google.common.base.Preconditions.checkNotNull;
2120

22-
import com.google.common.base.Strings;
21+
import com.google.api.client.googleapis.util.Utils;
22+
import com.google.api.client.json.GenericJson;
2323
import com.google.common.collect.ImmutableList;
2424
import com.google.common.io.CharStreams;
2525
import com.google.firebase.FirebaseApp;
@@ -40,26 +40,28 @@
4040
import org.apache.http.entity.StringEntity;
4141
import org.apache.http.impl.client.DefaultHttpClient;
4242
import org.apache.http.util.EntityUtils;
43-
import org.json.JSONObject;
4443

4544
public class IntegrationTestUtils {
4645

47-
private static JSONObject IT_SERVICE_ACCOUNT;
46+
private static final String IT_SERVICE_ACCOUNT_PATH = "integration_cert.json";
47+
private static final String IT_API_KEY_PATH = "integration_apikey.txt";
48+
49+
private static GenericJson serviceAccount;
50+
private static String apiKey;
4851
private static FirebaseApp masterApp;
4952

50-
private static synchronized JSONObject ensureServiceAccount() {
51-
if (IT_SERVICE_ACCOUNT == null) {
52-
String certificatePath = System.getProperty("firebase.it.certificate");
53-
checkArgument(!Strings.isNullOrEmpty(certificatePath),
54-
"Service account certificate path not set. Set the "
55-
+ "firebase.it.certificate system property and try again.");
56-
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(certificatePath))) {
57-
IT_SERVICE_ACCOUNT = new JSONObject(CharStreams.toString(reader));
53+
private static synchronized GenericJson ensureServiceAccount() {
54+
if (serviceAccount == null) {
55+
try (InputStream stream = new FileInputStream(IT_SERVICE_ACCOUNT_PATH)) {
56+
serviceAccount = Utils.getDefaultJsonFactory().fromInputStream(stream, GenericJson.class);
5857
} catch (IOException e) {
59-
throw new RuntimeException("Failed to read service account certificate", e);
58+
String msg = String.format("Failed to read service account certificate from %s. "
59+
+ "Integration tests require a service account credential obtained from a Firebase "
60+
+ "project. See CONTRIBUTING.md for more details.", IT_SERVICE_ACCOUNT_PATH);
61+
throw new RuntimeException(msg, e);
6062
}
6163
}
62-
return IT_SERVICE_ACCOUNT;
64+
return serviceAccount;
6365
}
6466

6567
public static InputStream getServiceAccountCertificate() {
@@ -78,10 +80,17 @@ public static String getStorageBucket() {
7880
return getProjectId() + ".appspot.com";
7981
}
8082

81-
public static String getApiKey() {
82-
String apiKey = System.getProperty("firebase.it.apikey");
83-
checkArgument(!Strings.isNullOrEmpty(apiKey), "API key not specified. Set the "
84-
+ "firebase.it.apikey system property and try again.");
83+
public static synchronized String getApiKey() {
84+
if (apiKey == null) {
85+
try (InputStream stream = new FileInputStream(IT_API_KEY_PATH)) {
86+
apiKey = CharStreams.toString(new InputStreamReader(stream)).trim();
87+
} catch (IOException e) {
88+
String msg = String.format("Failed to read API key from %s. "
89+
+ "Integration tests require an API key obtained from a Firebase "
90+
+ "project. See CONTRIBUTING.md for more details.", IT_API_KEY_PATH);
91+
throw new RuntimeException(msg, e);
92+
}
93+
}
8594
return apiKey;
8695
}
8796

0 commit comments

Comments
 (0)