15
15
import java .security .SecureRandom ;
16
16
import java .security .cert .X509Certificate ;
17
17
import java .util .*;
18
+ import java .util .regex .Pattern ;
18
19
19
20
import javax .net .ssl .HostnameVerifier ;
20
21
import javax .net .ssl .HttpsURLConnection ;
38
39
public class JsonClientCaller {
39
40
40
41
public final URL serviceUrl ;
41
- private ObjectMapper mapper ;
42
+ private static final ObjectMapper mapper = new ObjectMapper ().registerModule (
43
+ new JacksonTupleModule ());;
42
44
private String user = null ;
43
45
private char [] password = null ;
44
46
private AuthToken accessToken = null ;
@@ -47,6 +49,8 @@ public class JsonClientCaller {
47
49
private boolean streamRequest = false ;
48
50
private Integer connectionReadTimeOut = 30 * 60 * 1000 ;
49
51
private File fileForNextRpcResponse = null ;
52
+ private boolean isDynamic = false ;
53
+
50
54
private final URL authServiceUrl ;
51
55
52
56
private static TrustManager [] GULLIBLE_TRUST_MGR = new TrustManager [] {
@@ -74,7 +78,6 @@ public JsonClientCaller(URL url) {
74
78
75
79
public JsonClientCaller (URL url , URL authServiceUrl ) {
76
80
serviceUrl = url ;
77
- mapper = new ObjectMapper ().registerModule (new JacksonTupleModule ());
78
81
this .authServiceUrl = authServiceUrl ;
79
82
}
80
83
@@ -187,33 +190,44 @@ public void setConnectionReadTimeOut(Integer connectionReadTimeOut) {
187
190
this .connectionReadTimeOut = connectionReadTimeOut ;
188
191
}
189
192
190
- private HttpURLConnection setupCall (boolean authRequired ) throws IOException , JsonClientException {
193
+ public boolean isDynamic () {
194
+ return isDynamic ;
195
+ }
196
+
197
+ public void setDynamic (boolean isDynamic ) {
198
+ this .isDynamic = isDynamic ;
199
+ }
200
+
201
+ private static HttpURLConnection setupCall (URL serviceUrl , boolean authRequired ,
202
+ Integer connectionReadTimeOut , JsonClientCaller accessTokenHolder ,
203
+ boolean allowInsecureHttp , String user , char [] password , URL authServiceUrl ,
204
+ boolean trustAllCerts ) throws IOException , JsonClientException {
191
205
HttpURLConnection conn = (HttpURLConnection ) serviceUrl .openConnection ();
192
206
conn .setConnectTimeout (10000 );
193
207
if (connectionReadTimeOut != null ) {
194
208
conn .setReadTimeout (connectionReadTimeOut );
195
209
}
196
210
conn .setDoOutput (true );
197
211
conn .setRequestMethod ("POST" );
198
- if (authRequired || accessToken != null ) {
212
+ if (authRequired || accessTokenHolder . accessToken != null ) {
199
213
if (!(conn instanceof HttpsURLConnection || allowInsecureHttp )) {
200
214
throw new UnauthorizedException ("RPC method required authentication shouldn't " +
201
215
"be called through unsecured http, use https instead or call " +
202
216
"setAuthAllowedForHttp(true) for your client" );
203
217
}
204
- if (accessToken == null || accessToken .isExpired ()) {
218
+ if (accessTokenHolder . accessToken == null || accessTokenHolder . accessToken .isExpired ()) {
205
219
if (user == null ) {
206
- if (accessToken == null ) {
220
+ if (accessTokenHolder . accessToken == null ) {
207
221
throw new UnauthorizedException ("RPC method requires authentication but neither " +
208
222
"user nor token was set" );
209
223
} else {
210
224
throw new UnauthorizedException ("Token is expired and can not be reloaded " +
211
225
"because user wasn't set" );
212
226
}
213
227
}
214
- accessToken = requestTokenFromKBase (user , password , authServiceUrl );
228
+ accessTokenHolder . accessToken = requestTokenFromKBase (user , password , authServiceUrl );
215
229
}
216
- conn .setRequestProperty ("Authorization" , accessToken .toString ());
230
+ conn .setRequestProperty ("Authorization" , accessTokenHolder . accessToken .toString ());
217
231
}
218
232
if (conn instanceof HttpsURLConnection && trustAllCerts ) {
219
233
final HttpsURLConnection hc = (HttpsURLConnection ) conn ;
@@ -270,14 +284,62 @@ public <ARG, RET> RET jsonrpcCall(String method, ARG arg, TypeReference<RET> cls
270
284
public <ARG , RET > RET jsonrpcCall (String method , ARG arg , TypeReference <RET > cls ,
271
285
boolean ret , boolean authRequired , RpcContext [] context )
272
286
throws IOException , JsonClientException {
287
+ return jsonrpcCall (method , arg , cls , ret , authRequired , context , null );
288
+ }
289
+
290
+ public <ARG , RET > RET jsonrpcCall (String method , ARG arg , TypeReference <RET > cls ,
291
+ boolean ret , boolean authRequired , RpcContext [] context , String serviceVersion )
292
+ throws IOException , JsonClientException {
273
293
return jsonrpcCall (method , arg , cls , ret , authRequired ,
274
- context != null && context .length == 1 ? context [0 ] : null );
294
+ context != null && context .length == 1 ? context [0 ] : null , serviceVersion );
295
+ }
296
+
297
+ public <ARG , RET > RET jsonrpcCall (String method , ARG arg , TypeReference <RET > cls ,
298
+ boolean ret , boolean authRequired , RpcContext context )
299
+ throws IOException , JsonClientException {
300
+ return jsonrpcCall (method , arg , cls , ret , authRequired , context , null );
275
301
}
276
302
277
303
public <ARG , RET > RET jsonrpcCall (String method , ARG arg , TypeReference <RET > cls ,
278
- boolean ret , boolean authRequired , RpcContext context )
304
+ boolean ret , boolean authRequired , RpcContext context , String serviceVersion )
279
305
throws IOException , JsonClientException {
280
- HttpURLConnection conn = setupCall (authRequired );
306
+ URL url ;
307
+ if (isDynamic ) {
308
+ String serviceModuleName = method .split (Pattern .quote ("." ))[0 ];
309
+ List <Object > serviceStatusArgs = new ArrayList <Object >();
310
+ Map <String , String > serviceStruct = new LinkedHashMap <String , String >();
311
+ serviceStruct .put ("module_name" , serviceModuleName );
312
+ serviceStruct .put ("version" , serviceVersion );
313
+ serviceStatusArgs .add (serviceStruct );
314
+ List <Map <String , Object >> serviceState = jsonrpcCallStatic (serviceUrl ,
315
+ "ServiceWizard.get_service_status" , serviceStatusArgs ,
316
+ new TypeReference <List <Map <String , Object >>>() {}, ret ,
317
+ false , null , streamRequest , connectionReadTimeOut ,
318
+ this , allowInsecureHttp , user , password , authServiceUrl ,
319
+ trustAllCerts , null );
320
+ url = new URL ((String )serviceState .get (0 ).get ("url" ));
321
+ } else {
322
+ url = serviceUrl ;
323
+ }
324
+ try {
325
+ return jsonrpcCallStatic (url , method , arg , cls , ret , authRequired ,
326
+ context , streamRequest , connectionReadTimeOut ,
327
+ this , allowInsecureHttp , user , password , authServiceUrl ,
328
+ trustAllCerts , fileForNextRpcResponse );
329
+ } finally {
330
+ fileForNextRpcResponse = null ;
331
+ }
332
+ }
333
+
334
+ private static <ARG , RET > RET jsonrpcCallStatic (URL serviceUrl , String method , ARG arg ,
335
+ TypeReference <RET > cls , boolean ret , boolean authRequired , RpcContext context ,
336
+ boolean streamRequest , Integer connectionReadTimeOut ,
337
+ JsonClientCaller accessTokenHolder , boolean allowInsecureHttp , String user ,
338
+ char [] password , URL authServiceUrl , boolean trustAllCerts ,
339
+ File fileForNextRpcResponse ) throws IOException , JsonClientException {
340
+ HttpURLConnection conn = setupCall (serviceUrl , authRequired , connectionReadTimeOut ,
341
+ accessTokenHolder , allowInsecureHttp , user , password , authServiceUrl ,
342
+ trustAllCerts );
281
343
String id = ("" + Math .random ()).replace ("." , "" );
282
344
if (streamRequest ) {
283
345
// Calculate content-length before
@@ -286,7 +348,7 @@ public <ARG, RET> RET jsonrpcCall(String method, ARG arg, TypeReference<RET> cls
286
348
conn .setFixedLengthStreamingMode (size );
287
349
}
288
350
// Write real data into http output stream
289
- writeRequestData (method , arg , conn .getOutputStream (), id , context );
351
+ writeRequestDataStatic (method , arg , conn .getOutputStream (), id , context );
290
352
// Read response
291
353
int code = conn .getResponseCode ();
292
354
conn .getResponseMessage ();
@@ -380,7 +442,6 @@ public <ARG, RET> RET jsonrpcCall(String method, ARG arg, TypeReference<RET> cls
380
442
throw new ServerException ("An unknown server error occured" , 0 , "Unknown" , null );
381
443
}
382
444
} finally {
383
- fileForNextRpcResponse = null ;
384
445
if (fos != null )
385
446
try {
386
447
fos .close ();
@@ -389,7 +450,7 @@ public <ARG, RET> RET jsonrpcCall(String method, ARG arg, TypeReference<RET> cls
389
450
}
390
451
}
391
452
392
- private <ARG > long calculateResponseLength (String method , ARG arg ,
453
+ private static <ARG > long calculateResponseLength (String method , ARG arg ,
393
454
String id , RpcContext context ) throws IOException {
394
455
final long [] sizeWrapper = new long [] {0 };
395
456
OutputStream os = new OutputStream () {
@@ -400,7 +461,7 @@ private <ARG> long calculateResponseLength(String method, ARG arg,
400
461
@ Override
401
462
public void write (byte [] b , int o , int l ) {sizeWrapper [0 ] += l ;}
402
463
};
403
- writeRequestData (method , arg , os , id , context );
464
+ writeRequestDataStatic (method , arg , os , id , context );
404
465
return sizeWrapper [0 ];
405
466
}
406
467
@@ -422,6 +483,11 @@ private static void checkToken(JsonToken expected, JsonToken actual) throws Json
422
483
423
484
public void writeRequestData (String method , Object arg , OutputStream os , String id , RpcContext context )
424
485
throws IOException {
486
+ writeRequestDataStatic (method , arg , os , id , context );
487
+ }
488
+
489
+ private static void writeRequestDataStatic (String method , Object arg , OutputStream os , String id ,
490
+ RpcContext context ) throws IOException {
425
491
JsonGenerator g = mapper .getFactory ().createGenerator (os , JsonEncoding .UTF8 );
426
492
g .writeStartObject ();
427
493
g .writeObjectField ("params" , arg );
0 commit comments