Skip to content

Commit 4bc8ef1

Browse files
author
BitsAdmin
committed
Merge branch 'feature/p0' into 'integration_2025-04-24_877340287234'
feat: [development task] core-p0 (1181096) See merge request iaasng/volcengine-java-sdk!456
2 parents cc0df65 + 98f57cb commit 4bc8ef1

23 files changed

Lines changed: 1826 additions & 60 deletions

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
* Note
99

1010
### Requirements ###
11-
12-
运行 SDK需要jdk **Java 1.7+**. 你可以下载最新的版本: http://developers.sun.com/downloads/.
11+
运行 SDK需要jdk **Java 1.8.0_131+**. 你可以下载最新的版本: http://developers.sun.com/downloads/.
1312
如果 SDK版本 高于或者等于 **Java 9** 请依赖javax.annotation-api
1413
由于在高于或者等于 **Java 9** 中 javax.annotation-api 被移除
1514

volcengine-java-sdk-core/src/main/java/com/volcengine/ApiClient.java

Lines changed: 158 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
import com.squareup.okhttp.logging.HttpLoggingInterceptor;
2020
import com.squareup.okhttp.logging.HttpLoggingInterceptor.Level;
2121
import com.volcengine.auth.Authentication;
22+
import com.volcengine.auth.CredentialProvider;
23+
import com.volcengine.endpoint.DefaultEndpointProvider;
24+
import com.volcengine.endpoint.EndpointResolver;
25+
import com.volcengine.interceptor.*;
2226
import com.volcengine.model.AbstractResponse;
2327
import com.volcengine.model.ResponseMetadata;
2428
import com.volcengine.sign.Credentials;
@@ -84,14 +88,27 @@ public class ApiClient {
8488

8589
private Credentials credentials;
8690
private String region;
87-
private String endpoint = "open.volcengineapi.com";
91+
private String endpoint;
8892
private boolean disableSSL = false;
8993

94+
private InterceptorChain interceptorChain = new InterceptorChain();
95+
96+
private EndpointResolver endpointResolver;
97+
98+
private CredentialProvider credentialProvider;
99+
100+
private Integer maxIdleConns = 5;
101+
102+
private Integer keepAliveDurationMs = 5 * 60 * 1000;
103+
104+
90105
/*
91106
* Constructor for ApiClient
92107
*/
93108
public ApiClient() {
109+
ConnectionPool connectionPool=new ConnectionPool(maxIdleConns,keepAliveDurationMs);
94110
httpClient = new OkHttpClient();
111+
httpClient.setConnectionPool(connectionPool);
95112

96113

97114
verifyingSsl = true;
@@ -106,6 +123,13 @@ public ApiClient() {
106123
authentications.put(DefaultAuthentication, new VolcstackSign());
107124
// Prevent the authentications from being modified.
108125
authentications = Collections.unmodifiableMap(authentications);
126+
endpointResolver = new DefaultEndpointProvider();
127+
128+
interceptorChain.appendRequestInterceptor(new ResolveEndpointInterceptor());
129+
interceptorChain.appendRequestInterceptor(new BuildRequestInterceptor());
130+
interceptorChain.appendRequestInterceptor(new SignRequestInterceptor());
131+
132+
interceptorChain.appendResponseInterceptor(new DeserializedResponseInterceptor());
109133
}
110134

111135
/**
@@ -891,10 +915,24 @@ public <T> ApiResponse<T> execute(Call call) throws ApiException {
891915
* @throws ApiException If fail to execute the call
892916
*/
893917
public <T> ApiResponse<T> execute(Call call, final Type returnType, boolean... isCommon) throws ApiException {
918+
if (!(call instanceof InterceptorContext)) {
919+
throw new ApiException("not support custom context class");
920+
}
921+
InterceptorContext context = (InterceptorContext) call;
922+
ResponseInterceptorContext responseInterceptorContext = new ResponseInterceptorContext();
923+
responseInterceptorContext.setCommon(isCommon.length > 0 && isCommon[0]);
924+
responseInterceptorContext.setReturnType(returnType);
925+
context.setResponseContext(responseInterceptorContext);
926+
927+
context.setApiClient(this);
928+
894929
try {
895-
Response response = call.execute();
896-
T data = handleResponse(response, returnType, isCommon);
897-
return new ApiResponse<T>(response.code(), response.headers().toMultimap(), data);
930+
this.interceptorChain.executeRequest(context);
931+
Call finalCall = context.requestContext.getCall();
932+
Response response = finalCall.execute();
933+
context.getResponseContext().setOriginalResponse(response);
934+
this.interceptorChain.executeResponse(context);
935+
return new ApiResponse<T>(response.code(), response.headers().toMultimap(), (T) context.getResponseContext().getData());
898936
} catch (IOException e) {
899937
throw new ApiException(e);
900938
}
@@ -922,7 +960,23 @@ public <T> void executeAsync(Call call, ApiCallback<T> callback) {
922960
*/
923961
@SuppressWarnings("unchecked")
924962
public <T> void executeAsync(Call call, final Type returnType, final ApiCallback<T> callback) {
925-
call.enqueue(new Callback() {
963+
if (!(call instanceof InterceptorContext)) {
964+
callback.onFailure(new ApiException("not support custom context class"), 0, null);
965+
return;
966+
}
967+
final InterceptorContext context = (InterceptorContext) call;
968+
ResponseInterceptorContext responseInterceptorContext = new ResponseInterceptorContext();
969+
responseInterceptorContext.setReturnType(returnType);
970+
context.setResponseContext(responseInterceptorContext);
971+
972+
context.setApiClient(this);
973+
try {
974+
this.interceptorChain.executeRequest(context);
975+
} catch (ApiException e) {
976+
callback.onFailure(e, 0, null);
977+
return;
978+
}
979+
Callback okHttpCallBack = new Callback() {
926980
@Override
927981
public void onFailure(Request request, IOException e) {
928982
callback.onFailure(new ApiException(e), 0, null);
@@ -932,14 +986,18 @@ public void onFailure(Request request, IOException e) {
932986
public void onResponse(Response response) throws IOException {
933987
T result;
934988
try {
935-
result = (T) handleResponse(response, returnType);
989+
context.getResponseContext().setOriginalResponse(response);
990+
context.getApiClient().interceptorChain.executeResponse(context);
991+
result = (T) context.responseContext.getData();
936992
} catch (ApiException e) {
937993
callback.onFailure(e, response.code(), response.headers().toMultimap());
938994
return;
939995
}
940996
callback.onSuccess(result, response.code(), response.headers().toMultimap());
941997
}
942-
});
998+
};
999+
1000+
((InterceptorContext) call).getRequestContext().getCall().enqueue(okHttpCallBack);
9431001
}
9441002

9451003
/**
@@ -998,20 +1056,33 @@ public <T> T handleResponse(Response response, Type returnType, boolean... isCom
9981056
* @return The HTTP call
9991057
* @throws ApiException If fail to serialize the request body object
10001058
*/
1001-
public Call buildCall(String path, String method, List<Pair> queryParams, List<Pair> collectionQueryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String[] authNames, ProgressRequestBody.ProgressRequestListener progressRequestListener, boolean... isCommon) throws ApiException {
1002-
Request request = buildRequest(path, method, queryParams, collectionQueryParams, body, headerParams, formParams, authNames, progressRequestListener, isCommon);
1003-
1004-
return httpClient.newCall(request);
1005-
}
1006-
1007-
private void getDefaultContentType(Map<String, String> headerParams) {
1059+
public InterceptorContext buildCall(String path, String method, List<Pair> queryParams, List<Pair> collectionQueryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String[] authNames, ProgressRequestBody.ProgressRequestListener progressRequestListener, boolean... isCommon) throws ApiException {
1060+
InterceptorContext interceptorContext = new InterceptorContext(this.httpClient, null);
1061+
InitInterceptorContext requestInterceptorContext = new InitInterceptorContext.Builder()
1062+
.path(path)
1063+
.method(method)
1064+
.queryParams(queryParams)
1065+
.collectionQueryParams(collectionQueryParams)
1066+
.body(body)
1067+
.headerParams(headerParams)
1068+
.formParams(formParams)
1069+
.authNames(authNames)
1070+
.progressRequestListener(progressRequestListener)
1071+
.isCommon(isCommon.length > 0 && isCommon[0])
1072+
.build();
1073+
interceptorContext.setInitInterceptorContext(requestInterceptorContext);
1074+
interceptorContext.setApiClient(this);
1075+
return interceptorContext;
1076+
}
1077+
1078+
public void getDefaultContentType(Map<String, String> headerParams) {
10081079
String contentType = headerParams.get("Content-Type");
10091080
if (contentType == null) {
10101081
headerParams.put("Content-Type", "text/plain");
10111082
}
10121083
}
10131084

1014-
private boolean isApplicationJsonBody(Map<String, String> headerParams) {
1085+
public boolean isApplicationJsonBody(Map<String, String> headerParams) {
10151086
String contentType = headerParams.get("Content-Type");
10161087
if (contentType == null) {
10171088
return false;
@@ -1022,7 +1093,7 @@ private boolean isApplicationJsonBody(Map<String, String> headerParams) {
10221093
return false;
10231094
}
10241095

1025-
private boolean isPostBody(Map<String, String> headerParams) {
1096+
public boolean isPostBody(Map<String, String> headerParams) {
10261097
String contentType = headerParams.get("Content-Type");
10271098
if (contentType == null) {
10281099
return false;
@@ -1033,12 +1104,12 @@ private boolean isPostBody(Map<String, String> headerParams) {
10331104
return false;
10341105
}
10351106

1036-
private void updateQueryParams(List<Pair> queryParams, String[] param) {
1107+
public void updateQueryParams(List<Pair> queryParams, String[] param) {
10371108
queryParams.add(new Pair("Action", param[1]));
10381109
queryParams.add(new Pair("Version", param[2]));
10391110
}
10401111

1041-
private ServiceInfo addPairAndGetServiceInfo(String path, List<Pair> queryParams, Map<String, String> headerParams) {
1112+
public ServiceInfo addPairAndGetServiceInfo(String path, List<Pair> queryParams, Map<String, String> headerParams) {
10421113
String[] param = path.split("/");
10431114

10441115
if (param.length >= 6) {
@@ -1053,7 +1124,7 @@ private ServiceInfo addPairAndGetServiceInfo(String path, List<Pair> queryParams
10531124

10541125
}
10551126

1056-
private String getTruePath(String path, Map<String, String> headerParams) {
1127+
public String getTruePath(String path, Map<String, String> headerParams) {
10571128
if (isApplicationJsonBody(headerParams) || isPostBody(headerParams)) {
10581129
String[] param = path.split("/");
10591130
return "/?Action=" + param[1] + "&Version=" + param[2];
@@ -1088,7 +1159,7 @@ private boolean convertResponseBody(String source, StringBuilder stringBuilder,
10881159
return false;
10891160
}
10901161

1091-
private void buildSimpleRequest(Object body, List<Pair> queryParams, Map<String, String> headerParams, StringBuilder builder, FormEncodingBuilder formBuilder, String chain, boolean... isCommon) throws Exception {
1162+
public void buildSimpleRequest(Object body, List<Pair> queryParams, Map<String, String> headerParams, StringBuilder builder, FormEncodingBuilder formBuilder, String chain, boolean... isCommon) throws Exception {
10921163
if (body == null) {
10931164
return;
10941165
}
@@ -1352,6 +1423,25 @@ public String buildUrl(String path, List<Pair> queryParams, List<Pair> collectio
13521423
return url.toString();
13531424
}
13541425

1426+
public void buildQueryParams(String path, StringBuilder url, List<Pair> queryParams) {
1427+
if (queryParams != null && !queryParams.isEmpty()) {
1428+
// support (constant) query string in `path`, e.g. "/posts?draft=1"
1429+
String prefix = path.contains("?") ? "&" : "?";
1430+
for (Pair param : queryParams) {
1431+
if (param.getValue() != null) {
1432+
if (prefix != null) {
1433+
url.append(prefix);
1434+
prefix = null;
1435+
} else {
1436+
url.append("&");
1437+
}
1438+
String value = parameterToString(param.getValue());
1439+
url.append(escapeString(param.getName())).append("=").append(escapeString(value));
1440+
}
1441+
}
1442+
}
1443+
}
1444+
13551445
/**
13561446
* Set header parameters to the request builder, including default headers.
13571447
*
@@ -1369,6 +1459,14 @@ public void processHeaderParams(Map<String, String> headerParams, Request.Builde
13691459
}
13701460
}
13711461

1462+
public void processDefaultHeader(Map<String, String> headerParams) {
1463+
for (Entry<String, String> header : defaultHeaderMap.entrySet()) {
1464+
if (!headerParams.containsKey(header.getKey())) {
1465+
headerParams.put(header.getKey(), parameterToString(header.getValue()));
1466+
}
1467+
}
1468+
}
1469+
13721470
/**
13731471
* Update query and header parameters based on authentication settings.
13741472
*
@@ -1522,6 +1620,7 @@ public boolean verify(String hostname, SSLSession session) {
15221620
}
15231621
}
15241622

1623+
15251624
private KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException {
15261625
try {
15271626
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
@@ -1531,4 +1630,43 @@ private KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityExcepti
15311630
throw new AssertionError(e);
15321631
}
15331632
}
1633+
1634+
public CredentialProvider getCredentialProvider() {
1635+
return credentialProvider;
1636+
}
1637+
1638+
public ApiClient setCredentialProvider(CredentialProvider credentialProvider) {
1639+
this.credentialProvider = credentialProvider;
1640+
return this;
1641+
}
1642+
1643+
public EndpointResolver getEndpointResolver() {
1644+
return endpointResolver;
1645+
}
1646+
1647+
public ApiClient setEndpointResolver(EndpointResolver endpointResolver) {
1648+
this.endpointResolver = endpointResolver;
1649+
return this;
1650+
}
1651+
1652+
1653+
public Integer getMaxIdleConns() {
1654+
return maxIdleConns;
1655+
}
1656+
1657+
public ApiClient setMaxIdleConns(Integer maxIdleConns) {
1658+
this.maxIdleConns = maxIdleConns;
1659+
this.httpClient.setConnectionPool(new ConnectionPool(maxIdleConns,keepAliveDurationMs));
1660+
return this;
1661+
}
1662+
1663+
public Integer getKeepAliveDurationMs() {
1664+
return keepAliveDurationMs;
1665+
}
1666+
1667+
public ApiClient setKeepAliveDurationMs(Integer keepAliveDurationMs) {
1668+
this.keepAliveDurationMs = keepAliveDurationMs;
1669+
this.httpClient.setConnectionPool(new ConnectionPool(maxIdleConns,keepAliveDurationMs));
1670+
return this;
1671+
}
15341672
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.volcengine.auth;
2+
3+
import com.volcengine.ApiException;
4+
5+
import java.util.concurrent.locks.Lock;
6+
import java.util.concurrent.locks.ReadWriteLock;
7+
import java.util.concurrent.locks.ReentrantReadWriteLock;
8+
9+
public class CredentialProvider {
10+
private Provider provider;
11+
12+
private ReadWriteLock readWriteLock;
13+
14+
public CredentialProvider(Provider provider) {
15+
this.provider = provider;
16+
readWriteLock = new ReentrantReadWriteLock();
17+
}
18+
19+
public CredentialValue get() throws ApiException {
20+
try {
21+
readWriteLock.readLock().lock();
22+
if (!provider.isExpired()) {
23+
return provider.retrieve();
24+
}
25+
} finally {
26+
readWriteLock.readLock().unlock();
27+
}
28+
29+
try {
30+
readWriteLock.writeLock().lock();
31+
if (provider.isExpired()) {
32+
provider.refresh();
33+
}
34+
return provider.retrieve();
35+
36+
} finally {
37+
readWriteLock.writeLock().unlock();
38+
}
39+
}
40+
}

0 commit comments

Comments
 (0)