@@ -102,6 +102,42 @@ public BoxAPIConnection(String clientID, String clientSecret) {
102102 this (clientID , clientSecret , null , null );
103103 }
104104
105+ /**
106+ * Restores a BoxAPIConnection from a saved state.
107+ *
108+ * @see #save
109+ * @param state the saved state that was created with {@link #save}.
110+ * @return a restored API connection.
111+ */
112+ public static BoxAPIConnection restore (String state ) {
113+ JsonObject json = JsonObject .readFrom (state );
114+ String clientID = json .get ("clientID" ).asString ();
115+ String clientSecret = json .get ("clientSecret" ).asString ();
116+ String accessToken = json .get ("accessToken" ).asString ();
117+ String refreshToken = json .get ("refreshToken" ).asString ();
118+ long lastRefresh = json .get ("lastRefresh" ).asLong ();
119+ long expires = json .get ("expires" ).asLong ();
120+ String userAgent = json .get ("userAgent" ).asString ();
121+ String tokenURL = json .get ("tokenURL" ).asString ();
122+ String baseURL = json .get ("baseURL" ).asString ();
123+ String baseUploadURL = json .get ("baseUploadURL" ).asString ();
124+ boolean autoRefresh = json .get ("autoRefresh" ).asBoolean ();
125+ int maxRequestAttempts = json .get ("maxRequestAttempts" ).asInt ();
126+
127+ BoxAPIConnection api = new BoxAPIConnection (clientID , clientSecret , accessToken , refreshToken );
128+ api .accessToken = accessToken ;
129+ api .refreshToken = refreshToken ;
130+ api .lastRefresh = lastRefresh ;
131+ api .expires = expires ;
132+ api .userAgent = userAgent ;
133+ api .tokenURL = tokenURL ;
134+ api .baseURL = baseURL ;
135+ api .baseUploadURL = baseUploadURL ;
136+ api .autoRefresh = autoRefresh ;
137+ api .maxRequestAttempts = maxRequestAttempts ;
138+ return api ;
139+ }
140+
105141 /**
106142 * Authenticates the API connection by obtaining access and refresh tokens using the auth code that was obtained
107143 * from the first half of OAuth.
@@ -262,6 +298,27 @@ public void setRefreshToken(String refreshToken) {
262298 this .refreshToken = refreshToken ;
263299 }
264300
301+ /**
302+ * Gets the last time that the access token was refreshed.
303+ *
304+ * @return the last refresh time in milliseconds.
305+ */
306+ public long getLastRefresh () {
307+ return this .lastRefresh ;
308+ }
309+
310+ /**
311+ * Sets the last time that the access token was refreshed.
312+ *
313+ * <p>This value is used when determining if an access token needs to be auto-refreshed. If the amount of time since
314+ * the last refresh exceeds the access token's expiration time, then the access token will be refreshed.</p>
315+ *
316+ * @param lastRefresh the new last refresh time in milliseconds.
317+ */
318+ public void setLastRefresh (long lastRefresh ) {
319+ this .lastRefresh = lastRefresh ;
320+ }
321+
265322 /**
266323 * Enables or disables automatic refreshing of this connection's access token. Defaults to true.
267324 * @param autoRefresh true to enable auto token refresh; otherwise false.
@@ -354,6 +411,7 @@ public void refresh() {
354411 BoxJSONResponse response = (BoxJSONResponse ) request .send ();
355412 json = response .getJSON ();
356413 } catch (BoxAPIException e ) {
414+ this .notifyError (e );
357415 this .refreshLock .writeLock ().unlock ();
358416 throw e ;
359417 }
@@ -370,11 +428,20 @@ public void refresh() {
370428 }
371429
372430 /**
373- * Notifies refresh event to all the listeners.
431+ * Notifies a refresh event to all the listeners.
374432 */
375433 private void notifyRefresh () {
376434 for (BoxAPIConnectionListener listener : this .listeners ) {
377- listener .onRefresh ();
435+ listener .onRefresh (this );
436+ }
437+ }
438+
439+ /**
440+ * Notifies an error event to all the listeners.
441+ */
442+ private void notifyError (BoxAPIException error ) {
443+ for (BoxAPIConnectionListener listener : this .listeners ) {
444+ listener .onError (this , error );
378445 }
379446 }
380447
@@ -409,4 +476,27 @@ public RequestInterceptor getRequestInterceptor() {
409476 public void setRequestInterceptor (RequestInterceptor interceptor ) {
410477 this .interceptor = interceptor ;
411478 }
479+
480+ /**
481+ * Saves the state of this connection to a string so that it can be persisted and restored at a later time.
482+ *
483+ * @see #restore
484+ * @return the state of this connection.
485+ */
486+ public String save () {
487+ JsonObject state = new JsonObject ()
488+ .add ("clientID" , this .clientID )
489+ .add ("clientSecret" , this .clientSecret )
490+ .add ("accessToken" , this .accessToken )
491+ .add ("refreshToken" , this .refreshToken )
492+ .add ("lastRefresh" , this .lastRefresh )
493+ .add ("expires" , this .expires )
494+ .add ("userAgent" , this .userAgent )
495+ .add ("tokenURL" , this .tokenURL )
496+ .add ("baseURL" , this .baseURL )
497+ .add ("baseUploadURL" , this .baseUploadURL )
498+ .add ("autoRefresh" , this .autoRefresh )
499+ .add ("maxRequestAttempts" , this .maxRequestAttempts );
500+ return state .toString ();
501+ }
412502}
0 commit comments