@@ -24,7 +24,8 @@ public abstract class RefreshableTokenSource implements TokenSource {
24
24
25
25
/**
26
26
* Enum representing the state of the token. FRESH: Token is valid and not close to expiry. STALE:
27
- * Token is valid but will expire soon. EXPIRED: Token has expired and must be refreshed.
27
+ * Token is valid but will expire soon - an async refresh will be triggered if enabled. EXPIRED:
28
+ * Token has expired and must be refreshed using a blocking call.
28
29
*/
29
30
private enum TokenState {
30
31
FRESH ,
@@ -70,63 +71,21 @@ public RefreshableTokenSource enableAsyncRefresh(boolean enabled) {
70
71
}
71
72
72
73
/**
73
- * Helper method implementing OAuth token refresh .
74
+ * Refresh the OAuth token. Subclasses must implement this to define how the token is refreshed .
74
75
*
75
- * @param hc The HTTP client to use for the request.
76
- * @param clientId The client ID to authenticate with.
77
- * @param clientSecret The client secret to authenticate with.
78
- * @param tokenUrl The authorization URL for fetching tokens.
79
- * @param params Additional request parameters.
80
- * @param headers Additional headers.
81
- * @param position The position of the authentication parameters in the request.
82
- * @return The newly fetched Token.
83
- * @throws DatabricksException if the refresh fails
76
+ * <p>This method may throw an exception if the token cannot be refreshed. The specific exception
77
+ * type depends on the implementation.
78
+ *
79
+ * @return The newly refreshed Token.
84
80
*/
85
- protected static Token retrieveToken (
86
- HttpClient hc ,
87
- String clientId ,
88
- String clientSecret ,
89
- String tokenUrl ,
90
- Map <String , String > params ,
91
- Map <String , String > headers ,
92
- AuthParameterPosition position ) {
93
- switch (position ) {
94
- case BODY :
95
- if (clientId != null ) {
96
- params .put ("client_id" , clientId );
97
- }
98
- if (clientSecret != null ) {
99
- params .put ("client_secret" , clientSecret );
100
- }
101
- break ;
102
- case HEADER :
103
- String authHeaderValue =
104
- "Basic "
105
- + Base64 .getEncoder ().encodeToString ((clientId + ":" + clientSecret ).getBytes ());
106
- headers .put (HttpHeaders .AUTHORIZATION , authHeaderValue );
107
- break ;
108
- }
109
- headers .put ("Content-Type" , "application/x-www-form-urlencoded" );
110
- Request req = new Request ("POST" , tokenUrl , FormRequest .wrapValuesInList (params ));
111
- req .withHeaders (headers );
112
- try {
113
- ApiClient apiClient = new ApiClient .Builder ().withHttpClient (hc ).build ();
114
- OAuthResponse resp = apiClient .execute (req , OAuthResponse .class );
115
- if (resp .getErrorCode () != null ) {
116
- throw new IllegalArgumentException (resp .getErrorCode () + ": " + resp .getErrorSummary ());
117
- }
118
- LocalDateTime expiry = LocalDateTime .now ().plus (resp .getExpiresIn (), ChronoUnit .SECONDS );
119
- return new Token (resp .getAccessToken (), resp .getTokenType (), resp .getRefreshToken (), expiry );
120
- } catch (Exception e ) {
121
- throw new DatabricksException ("Failed to refresh credentials: " + e .getMessage (), e );
122
- }
123
- }
124
-
125
81
protected abstract Token refresh ();
126
82
127
83
/**
128
- * Get the current token, refreshing if necessary. If async refresh is enabled, may return a stale
129
- * token while a refresh is in progress.
84
+ * Gets the current token, refreshing if necessary. If async refresh is enabled, may return a
85
+ * stale token while a refresh is in progress.
86
+ *
87
+ * <p>This method may throw an exception if the token cannot be refreshed, depending on the
88
+ * implementation of {@link #refresh()}.
130
89
*
131
90
* @return The current valid token
132
91
*/
@@ -159,6 +118,9 @@ protected TokenState getTokenState() {
159
118
/**
160
119
* Get the current token, blocking to refresh if expired.
161
120
*
121
+ * <p>This method may throw an exception if the token cannot be refreshed, depending on the
122
+ * implementation of {@link #refresh()}.
123
+ *
162
124
* @return The current valid token
163
125
*/
164
126
protected synchronized Token getTokenBlocking () {
@@ -182,6 +144,9 @@ protected synchronized Token getTokenBlocking() {
182
144
* Get the current token, possibly triggering an async refresh if stale. If the token is expired,
183
145
* blocks to refresh.
184
146
*
147
+ * <p>This method may throw an exception if the token cannot be refreshed, depending on the
148
+ * implementation of {@link #refresh()}.
149
+ *
185
150
* @return The current valid or stale token
186
151
*/
187
152
protected Token getTokenAsync () {
@@ -229,4 +194,58 @@ protected synchronized void triggerAsyncRefresh() {
229
194
});
230
195
}
231
196
}
197
+
198
+ /**
199
+ * Helper method implementing OAuth token refresh.
200
+ *
201
+ * @param hc The HTTP client to use for the request.
202
+ * @param clientId The client ID to authenticate with.
203
+ * @param clientSecret The client secret to authenticate with.
204
+ * @param tokenUrl The authorization URL for fetching tokens.
205
+ * @param params Additional request parameters.
206
+ * @param headers Additional headers.
207
+ * @param position The position of the authentication parameters in the request.
208
+ * @return The newly fetched Token.
209
+ * @throws DatabricksException if the refresh fails
210
+ * @throws IllegalArgumentException if the OAuth response contains an error
211
+ */
212
+ protected static Token retrieveToken (
213
+ HttpClient hc ,
214
+ String clientId ,
215
+ String clientSecret ,
216
+ String tokenUrl ,
217
+ Map <String , String > params ,
218
+ Map <String , String > headers ,
219
+ AuthParameterPosition position ) {
220
+ switch (position ) {
221
+ case BODY :
222
+ if (clientId != null ) {
223
+ params .put ("client_id" , clientId );
224
+ }
225
+ if (clientSecret != null ) {
226
+ params .put ("client_secret" , clientSecret );
227
+ }
228
+ break ;
229
+ case HEADER :
230
+ String authHeaderValue =
231
+ "Basic "
232
+ + Base64 .getEncoder ().encodeToString ((clientId + ":" + clientSecret ).getBytes ());
233
+ headers .put (HttpHeaders .AUTHORIZATION , authHeaderValue );
234
+ break ;
235
+ }
236
+ headers .put ("Content-Type" , "application/x-www-form-urlencoded" );
237
+ Request req = new Request ("POST" , tokenUrl , FormRequest .wrapValuesInList (params ));
238
+ req .withHeaders (headers );
239
+ try {
240
+ ApiClient apiClient = new ApiClient .Builder ().withHttpClient (hc ).build ();
241
+ OAuthResponse resp = apiClient .execute (req , OAuthResponse .class );
242
+ if (resp .getErrorCode () != null ) {
243
+ throw new IllegalArgumentException (resp .getErrorCode () + ": " + resp .getErrorSummary ());
244
+ }
245
+ LocalDateTime expiry = LocalDateTime .now ().plus (resp .getExpiresIn (), ChronoUnit .SECONDS );
246
+ return new Token (resp .getAccessToken (), resp .getTokenType (), resp .getRefreshToken (), expiry );
247
+ } catch (Exception e ) {
248
+ throw new DatabricksException ("Failed to refresh credentials: " + e .getMessage (), e );
249
+ }
250
+ }
232
251
}
0 commit comments