77import com .google .api .client .http .HttpTransport ;
88import com .google .api .client .json .JsonFactory ;
99import com .google .common .annotations .VisibleForTesting ;
10+ import com .google .common .collect .ImmutableList ;
11+ import com .google .common .io .CharStreams ;
1012import com .google .firebase .internal .NonNull ;
1113import com .google .firebase .tasks .Continuation ;
1214import com .google .firebase .tasks .Task ;
1618import java .io .IOException ;
1719import java .io .InputStream ;
1820import java .io .InputStreamReader ;
19- import java .io .Reader ;
2021import java .nio .charset .StandardCharsets ;
21- import java .util .Arrays ;
2222import java .util .List ;
2323import java .util .concurrent .Callable ;
2424
3232public class FirebaseCredentials {
3333
3434 private static final List <String > FIREBASE_SCOPES =
35- Arrays . asList (
35+ ImmutableList . of (
3636 "https://www.googleapis.com/auth/firebase.database" ,
3737 "https://www.googleapis.com/auth/userinfo.email" );
3838
39- private static String streamToString (InputStream inputStream ) throws IOException {
40- StringBuilder stringBuilder = new StringBuilder ();
41- Reader reader = new InputStreamReader (inputStream , StandardCharsets .UTF_8 );
42- char [] buffer = new char [256 ];
43- int length ;
39+ private FirebaseCredentials () {
40+ }
4441
45- while ((length = reader .read (buffer )) != -1 ) {
46- stringBuilder .append (buffer , 0 , length );
47- }
48- inputStream .close ();
49- return stringBuilder .toString ();
42+ private static String streamToString (InputStream inputStream ) throws IOException {
43+ InputStreamReader reader = new InputStreamReader (inputStream , StandardCharsets .UTF_8 );
44+ return CharStreams .toString (reader );
5045 }
5146
5247 /**
@@ -84,16 +79,17 @@ static FirebaseCredential applicationDefault(HttpTransport transport, JsonFactor
8479 * service account certificate.
8580 * @return A {@link FirebaseCredential} generated from the provided service account certificate
8681 * which can be used to authenticate the SDK.
82+ * @throws IOException If an error occurs while parsing the service account certificate.
8783 */
8884 @ NonNull
89- public static FirebaseCredential fromCertificate (InputStream serviceAccount ) {
90- return fromCertificate (serviceAccount ,
91- Utils .getDefaultTransport (), Utils . getDefaultJsonFactory ());
85+ public static FirebaseCredential fromCertificate (InputStream serviceAccount ) throws IOException {
86+ return fromCertificate (serviceAccount , Utils . getDefaultTransport (),
87+ Utils .getDefaultJsonFactory ());
9288 }
9389
9490 @ VisibleForTesting
95- static FirebaseCredential fromCertificate (
96- InputStream serviceAccount , HttpTransport transport , JsonFactory jsonFactory ) {
91+ static FirebaseCredential fromCertificate (InputStream serviceAccount , HttpTransport transport ,
92+ JsonFactory jsonFactory ) throws IOException {
9793 return new CertCredential (serviceAccount , transport , jsonFactory );
9894 }
9995
@@ -108,16 +104,17 @@ static FirebaseCredential fromCertificate(
108104 * token.
109105 * @return A {@link FirebaseCredential} generated from the provided service account credential
110106 * which can be used to authenticate the SDK.
107+ * @throws IOException If an error occurs while parsing the refresh token.
111108 */
112109 @ NonNull
113- public static FirebaseCredential fromRefreshToken (InputStream refreshToken ) {
110+ public static FirebaseCredential fromRefreshToken (InputStream refreshToken ) throws IOException {
114111 return fromRefreshToken (
115112 refreshToken , Utils .getDefaultTransport (), Utils .getDefaultJsonFactory ());
116113 }
117114
118115 @ VisibleForTesting
119- static FirebaseCredential fromRefreshToken (
120- final InputStream refreshToken , HttpTransport transport , JsonFactory jsonFactory ) {
116+ static FirebaseCredential fromRefreshToken (final InputStream refreshToken ,
117+ HttpTransport transport , JsonFactory jsonFactory ) throws IOException {
121118 return new RefreshTokenCredential (refreshToken , transport , jsonFactory );
122119 }
123120
@@ -145,10 +142,10 @@ abstract static class BaseCredential implements FirebaseCredential {
145142 }
146143
147144 /** Retrieves a GoogleCredential. Should not use caching. */
148- abstract GoogleCredential fetchCredential () throws Exception ;
145+ abstract GoogleCredential fetchCredential () throws IOException ;
149146
150147 /** Retrieves an access token from a GoogleCredential. Should not use caching. */
151- abstract FirebaseAccessToken fetchToken (GoogleCredential credential ) throws Exception ;
148+ abstract FirebaseAccessToken fetchToken (GoogleCredential credential ) throws IOException ;
152149
153150 /**
154151 * Returns the associated GoogleCredential for this class. This implementation is cached by
@@ -223,30 +220,23 @@ public String then(@NonNull Task<FirebaseAccessToken> task) throws Exception {
223220
224221 static class CertCredential extends BaseCredential {
225222
226- private String jsonData ;
227- private String projectId ;
228- private Exception streamException ;
223+ private final String jsonData ;
224+ private final String projectId ;
229225
230- CertCredential (InputStream inputStream , HttpTransport transport , JsonFactory jsonFactory ) {
226+ CertCredential (InputStream inputStream , HttpTransport transport ,
227+ JsonFactory jsonFactory ) throws IOException {
231228 super (transport , jsonFactory );
229+ jsonData = streamToString (checkNotNull (inputStream ));
230+ JSONObject jsonObject = new JSONObject (jsonData );
232231 try {
233- jsonData = streamToString (checkNotNull (inputStream ));
234- JSONObject jsonObject = new JSONObject (jsonData );
235232 projectId = jsonObject .getString ("project_id" );
236- } catch (IOException e ) {
237- streamException = new IOException ("Failed to read service account" , e );
238233 } catch (JSONException e ) {
239- streamException =
240- new JSONException ("Failed to parse service account: 'project_id' must be set" );
234+ throw new IOException ("Failed to parse service account: 'project_id' must be set" , e );
241235 }
242236 }
243237
244238 @ Override
245- GoogleCredential fetchCredential () throws Exception {
246- if (streamException != null ) {
247- throw streamException ;
248- }
249-
239+ GoogleCredential fetchCredential () throws IOException {
250240 GoogleCredential firebaseCredential =
251241 GoogleCredential .fromStream (
252242 new ByteArrayInputStream (jsonData .getBytes ("UTF-8" )), transport , jsonFactory );
@@ -261,20 +251,12 @@ GoogleCredential fetchCredential() throws Exception {
261251 }
262252
263253 @ Override
264- FirebaseAccessToken fetchToken (GoogleCredential credential ) throws Exception {
265- if (streamException != null ) {
266- throw streamException ;
267- }
268-
254+ FirebaseAccessToken fetchToken (GoogleCredential credential ) throws IOException {
269255 credential .refreshToken ();
270256 return new FirebaseAccessToken (credential , clock );
271257 }
272258
273- Task <String > getProjectId (boolean forceRefresh ) {
274- if (streamException != null ) {
275- return Tasks .forException (streamException );
276- }
277-
259+ Task <String > getProjectId () {
278260 return Tasks .forResult (projectId );
279261 }
280262 }
@@ -286,39 +268,30 @@ static class ApplicationDefaultCredential extends BaseCredential {
286268 }
287269
288270 @ Override
289- GoogleCredential fetchCredential () throws Exception {
271+ GoogleCredential fetchCredential () throws IOException {
290272 return GoogleCredential .getApplicationDefault (transport , jsonFactory )
291273 .createScoped (FIREBASE_SCOPES );
292274 }
293275
294276 @ Override
295- FirebaseAccessToken fetchToken (GoogleCredential credential ) throws Exception {
277+ FirebaseAccessToken fetchToken (GoogleCredential credential ) throws IOException {
296278 credential .refreshToken ();
297279 return new FirebaseAccessToken (credential , clock );
298280 }
299281 }
300282
301283 static class RefreshTokenCredential extends BaseCredential {
302284
303- private String jsonData ;
304- private Exception streamException ;
285+ private final String jsonData ;
305286
306- RefreshTokenCredential (
307- InputStream inputStream , HttpTransport transport , JsonFactory jsonFactory ) {
287+ RefreshTokenCredential (InputStream inputStream , HttpTransport transport ,
288+ JsonFactory jsonFactory ) throws IOException {
308289 super (transport , jsonFactory );
309- try {
310- jsonData = streamToString (checkNotNull (inputStream ));
311- } catch (IOException e ) {
312- streamException = new IOException ("Failed to read refresh token" , e );
313- }
290+ jsonData = streamToString (checkNotNull (inputStream ));
314291 }
315292
316293 @ Override
317- GoogleCredential fetchCredential () throws Exception {
318- if (streamException != null ) {
319- throw streamException ;
320- }
321-
294+ GoogleCredential fetchCredential () throws IOException {
322295 GoogleCredential credential =
323296 GoogleCredential .fromStream (
324297 new ByteArrayInputStream (jsonData .getBytes ("UTF-8" )), transport , jsonFactory );
@@ -333,11 +306,7 @@ GoogleCredential fetchCredential() throws Exception {
333306 }
334307
335308 @ Override
336- FirebaseAccessToken fetchToken (GoogleCredential credential ) throws Exception {
337- if (streamException != null ) {
338- throw streamException ;
339- }
340-
309+ FirebaseAccessToken fetchToken (GoogleCredential credential ) throws IOException {
341310 credential .refreshToken ();
342311 return new FirebaseAccessToken (credential , clock );
343312 }
0 commit comments