11package io .quarkus .dynamodb .deployment ;
22
33import java .net .URI ;
4+ import java .util .Arrays ;
5+ import java .util .List ;
6+ import java .util .stream .Collectors ;
47
58import org .jboss .jandex .DotName ;
69import org .jboss .jandex .Type ;
1417import io .quarkus .deployment .annotations .BuildStep ;
1518import io .quarkus .deployment .annotations .ExecutionTime ;
1619import io .quarkus .deployment .annotations .Record ;
20+ import io .quarkus .deployment .builditem .CombinedIndexBuildItem ;
1721import io .quarkus .deployment .builditem .ExtensionSslNativeSupportBuildItem ;
1822import io .quarkus .deployment .builditem .FeatureBuildItem ;
1923import io .quarkus .deployment .builditem .JniBuildItem ;
2024import io .quarkus .deployment .builditem .ShutdownContextBuildItem ;
25+ import io .quarkus .deployment .builditem .substrate .ReflectiveClassBuildItem ;
2126import io .quarkus .deployment .builditem .substrate .ServiceProviderBuildItem ;
2227import io .quarkus .deployment .builditem .substrate .SubstrateProxyDefinitionBuildItem ;
28+ import io .quarkus .deployment .builditem .substrate .SubstrateResourceBuildItem ;
2329import io .quarkus .deployment .configuration .ConfigurationError ;
24- import io .quarkus .dynamodb .runtime .AwsApacheHttpClientConfig ;
30+ import io .quarkus .dynamodb .runtime .ApacheHttpClientConfig ;
2531import io .quarkus .dynamodb .runtime .AwsCredentialsProviderType ;
26- import io .quarkus .dynamodb .runtime .AwsNettyNioAsyncHttpClientConfig ;
2732import io .quarkus .dynamodb .runtime .DynamodbClientProducer ;
2833import io .quarkus .dynamodb .runtime .DynamodbConfig ;
2934import io .quarkus .dynamodb .runtime .DynamodbRecorder ;
35+ import io .quarkus .dynamodb .runtime .NettyHttpClientConfig ;
36+ import io .quarkus .dynamodb .runtime .TlsManagersProviderConfig ;
37+ import io .quarkus .dynamodb .runtime .TlsManagersProviderType ;
38+ import software .amazon .awssdk .core .interceptor .ExecutionInterceptor ;
3039import software .amazon .awssdk .http .SdkHttpService ;
3140import software .amazon .awssdk .http .apache .ApacheSdkHttpService ;
3241import software .amazon .awssdk .http .async .SdkAsyncHttpService ;
3847public class DynamodbProcessor {
3948 public static final String AWS_SDK_APPLICATION_ARCHIVE_MARKERS = "software/amazon/awssdk" ;
4049
50+ private static final List <String > INTERCEPTOR_PATHS = Arrays .asList (
51+ "software/amazon/awssdk/global/handlers/execution.interceptors" ,
52+ "software/amazon/awssdk/services/dynamodb/execution.interceptors" );
53+
54+ private static final DotName EXECUTION_INTERCEPTOR_NAME = DotName .createSimple (ExecutionInterceptor .class .getName ());
4155 private static final DotName SYNC_CLIENT_NAME = DotName .createSimple (DynamoDbClient .class .getName ());
4256 private static final DotName ASYNC_CLIENT_NAME = DotName .createSimple (DynamoDbAsyncClient .class .getName ());
4357
@@ -49,17 +63,29 @@ JniBuildItem jni() {
4963 }
5064
5165 @ BuildStep (applicationArchiveMarkers = { AWS_SDK_APPLICATION_ARCHIVE_MARKERS })
52- void setup (BuildProducer <ExtensionSslNativeSupportBuildItem > extensionSslNativeSupport ,
53- BuildProducer <ServiceProviderBuildItem > serviceProvider ,
66+ void setup (CombinedIndexBuildItem combinedIndexBuildItem ,
67+ BuildProducer <ExtensionSslNativeSupportBuildItem > extensionSslNativeSupport ,
68+ BuildProducer <ReflectiveClassBuildItem > reflectiveClasses ,
5469 BuildProducer <FeatureBuildItem > feature ,
55- BuildProducer <AdditionalBeanBuildItem > additionalBeans ) {
70+ BuildProducer <AdditionalBeanBuildItem > additionalBeans ,
71+ BuildProducer <SubstrateResourceBuildItem > resource ) {
5672
5773 feature .produce (new FeatureBuildItem (FeatureBuildItem .DYNAMODB ));
5874
5975 // Indicates that this extension would like the SSL support to be enabled
6076 extensionSslNativeSupport .produce (new ExtensionSslNativeSupportBuildItem (FeatureBuildItem .DYNAMODB ));
6177
62- checkConfig (config );
78+ INTERCEPTOR_PATHS .stream ().forEach (path -> resource .produce (new SubstrateResourceBuildItem (path )));
79+
80+ List <String > knownInterceptorImpls = combinedIndexBuildItem .getIndex ()
81+ .getAllKnownImplementors (EXECUTION_INTERCEPTOR_NAME )
82+ .stream ()
83+ .map (c -> c .name ().toString ()).collect (Collectors .toList ());
84+
85+ checkConfig (config , knownInterceptorImpls );
86+
87+ reflectiveClasses .produce (new ReflectiveClassBuildItem (false , false ,
88+ knownInterceptorImpls .toArray (new String [knownInterceptorImpls .size ()])));
6389
6490 additionalBeans .produce (AdditionalBeanBuildItem .unremovableOf (DynamodbClientProducer .class ));
6591 }
@@ -122,30 +148,43 @@ void buildClients(DynamodbClientBuildItem clientBuildItem, DynamodbRecorder reco
122148 }
123149 }
124150
125- private static void checkConfig (DynamodbConfig config ) {
126- if (config .endpointOverride .isPresent ()) {
127- URI endpointOverride = config .endpointOverride .get ();
128- if (StringUtils .isBlank (endpointOverride .getScheme ())) {
129- throw new ConfigurationError (
130- String .format ("quarkus.dynamodb.endpoint-override (%s) - scheme must be specified" ,
131- endpointOverride .toString ()));
151+ private static void checkConfig (DynamodbConfig config , List <String > knownInterceptorImpls ) {
152+ if (config .sdk != null ) {
153+ if (config .sdk .endpointOverride .isPresent ()) {
154+ URI endpointOverride = config .sdk .endpointOverride .get ();
155+ if (StringUtils .isBlank (endpointOverride .getScheme ())) {
156+ throw new ConfigurationError (
157+ String .format ("quarkus.dynamodb.sdk.endpoint-override (%s) - scheme must be specified" ,
158+ endpointOverride .toString ()));
159+ }
132160 }
161+ config .sdk .interceptors .stream ().forEach (interceptorClass -> {
162+ if (!knownInterceptorImpls .contains (interceptorClass .getName ())) {
163+ throw new ConfigurationError (
164+ String .format (
165+ "quarkus.dynamodb.sdk.interceptors (%s) - must list only existing implementations of software.amazon.awssdk.core.interceptor.ExecutionInterceptor" ,
166+ config .sdk .interceptors .toString ()));
167+ }
168+ });
133169 }
134170
135- if (config .credentials .type == AwsCredentialsProviderType .STATIC ) {
136- if (StringUtils .isBlank (config .credentials .staticProvider .accessKeyId )
137- || StringUtils .isBlank (config .credentials .staticProvider .secretAccessKey )) {
138- throw new ConfigurationError (
139- "quarkus.dynamodb.credentials.static-provider.access-key-id and "
140- + "quarkus.dynamodb.credentials.static-provider.secret-access-key cannot be empty if STATIC credentials provider used." );
171+ if (config .aws != null ) {
172+ if (config .aws .credentials .type == AwsCredentialsProviderType .STATIC ) {
173+ if (StringUtils .isBlank (config .aws .credentials .staticProvider .accessKeyId )
174+ || StringUtils .isBlank (config .aws .credentials .staticProvider .secretAccessKey )) {
175+ throw new ConfigurationError (
176+ "quarkus.dynamodb.aws.credentials.static-provider.access-key-id and "
177+ + "quarkus.dynamodb.aws.credentials.static-provider.secret-access-key cannot be empty if STATIC credentials provider used." );
178+ }
141179 }
142- }
143- if (config .credentials .type == AwsCredentialsProviderType . PROCESS ) {
144- if ( StringUtils . isBlank ( config . credentials . processProvider . command )) {
145- throw new ConfigurationError (
146- "quarkus.dynamodb.credentials.process-provider.command cannot be empty if PROCESS credentials provider used." );
180+ if ( config . aws . credentials . type == AwsCredentialsProviderType . PROCESS ) {
181+ if (StringUtils . isBlank ( config .aws . credentials .processProvider . command ) ) {
182+ throw new ConfigurationError (
183+ "quarkus.dynamodb.aws.credentials.process-provider.command cannot be empty if PROCESS credentials provider used." );
184+ }
147185 }
148186 }
187+
149188 if (config .syncClient != null ) {
150189 checkSyncClientConfig (config .syncClient );
151190 }
@@ -154,45 +193,20 @@ private static void checkConfig(DynamodbConfig config) {
154193 }
155194 }
156195
157- private static void checkSyncClientConfig (AwsApacheHttpClientConfig syncClient ) {
196+ private static void checkSyncClientConfig (ApacheHttpClientConfig syncClient ) {
158197 if (syncClient .maxConnections .isPresent () && syncClient .maxConnections .getAsInt () <= 0 ) {
159198 throw new ConfigurationError ("quarkus.dynamodb.sync-client.max-connections may not be negative or zero." );
160199 }
161200 if (syncClient .proxy != null && syncClient .proxy .enabled ) {
162201 URI proxyEndpoint = syncClient .proxy .endpoint ;
163202 if (proxyEndpoint != null ) {
164- if (StringUtils .isBlank (proxyEndpoint .getScheme ())) {
165- throw new ConfigurationError (
166- String .format ("quarkus.dynamodb.sync-client.proxy.endpoint (%s) - scheme must be specified" ,
167- proxyEndpoint .toString ()));
168- }
169- if (StringUtils .isNotBlank (proxyEndpoint .getUserInfo ())) {
170- throw new ConfigurationError (
171- String .format (
172- "quarkus.dynamodb.sync-client.proxy.endpoint (%s) - user info is not supported." ,
173- proxyEndpoint .toString ()));
174- }
175- if (StringUtils .isNotBlank (proxyEndpoint .getPath ())) {
176- throw new ConfigurationError (
177- String .format ("quarkus.dynamodb.sync-client.proxy.endpoint (%s) - path is not supported." ,
178- proxyEndpoint .toString ()));
179- }
180- if (StringUtils .isNotBlank (proxyEndpoint .getQuery ())) {
181- throw new ConfigurationError (
182- String .format ("quarkus.dynamodb.sync-client.proxy.endpoint (%s) - query is not supported." ,
183- proxyEndpoint .toString ()));
184- }
185- if (StringUtils .isNotBlank (proxyEndpoint .getFragment ())) {
186- throw new ConfigurationError (
187- String .format (
188- "quarkus.dynamodb.sync-client.proxy.endpoint (%s) - fragment is not supported." ,
189- proxyEndpoint .toString ()));
190- }
203+ validateProxyEndpoint (proxyEndpoint , "sync" );
191204 }
192205 }
206+ validateTlsManagersProvider (syncClient .tlsManagersProvider , "sync" );
193207 }
194208
195- private static void checkAsyncClientConfig (AwsNettyNioAsyncHttpClientConfig asyncClient ) {
209+ private static void checkAsyncClientConfig (NettyHttpClientConfig asyncClient ) {
196210 if (asyncClient .maxConcurrency .isPresent () && asyncClient .maxConcurrency .get () <= 0 ) {
197211 throw new ConfigurationError ("quarkus.dynamodb.async-client.max-concurrency may not be negative or zero." );
198212 }
@@ -211,5 +225,76 @@ private static void checkAsyncClientConfig(AwsNettyNioAsyncHttpClientConfig asyn
211225 "quarkus.dynamodb.async-client.event-loop.number-of-threads may not be negative or zero." );
212226 }
213227 }
228+ if (asyncClient .proxy != null && asyncClient .proxy .enabled ) {
229+ URI proxyEndpoint = asyncClient .proxy .endpoint ;
230+ if (proxyEndpoint != null ) {
231+ validateProxyEndpoint (proxyEndpoint , "async" );
232+ }
233+ }
234+ validateTlsManagersProvider (asyncClient .tlsManagersProvider , "async" );
235+ }
236+
237+ private static void validateProxyEndpoint (URI endpoint , String clientType ) {
238+ if (StringUtils .isBlank (endpoint .getScheme ())) {
239+ throw new ConfigurationError (
240+ String .format ("quarkus.dynamodb.%s-client.proxy.endpoint (%s) - scheme must be specified" ,
241+ clientType , endpoint .toString ()));
242+ }
243+ if (StringUtils .isBlank (endpoint .getHost ())) {
244+ throw new ConfigurationError (
245+ String .format ("quarkus.dynamodb.%s-client.proxy.endpoint (%s) - host must be specified" ,
246+ clientType , endpoint .toString ()));
247+ }
248+ if (StringUtils .isNotBlank (endpoint .getUserInfo ())) {
249+ throw new ConfigurationError (
250+ String .format ("quarkus.dynamodb.%s-client.proxy.endpoint (%s) - user info is not supported." ,
251+ clientType , endpoint .toString ()));
252+ }
253+ if (StringUtils .isNotBlank (endpoint .getPath ())) {
254+ throw new ConfigurationError (
255+ String .format ("quarkus.dynamodb.%s-client.proxy.endpoint (%s) - path is not supported." ,
256+ clientType , endpoint .toString ()));
257+ }
258+ if (StringUtils .isNotBlank (endpoint .getQuery ())) {
259+ throw new ConfigurationError (
260+ String .format ("quarkus.dynamodb.%s-client.proxy.endpoint (%s) - query is not supported." ,
261+ clientType , endpoint .toString ()));
262+ }
263+ if (StringUtils .isNotBlank (endpoint .getFragment ())) {
264+ throw new ConfigurationError (
265+ String .format ("quarkus.dynamodb.%s-client.proxy.endpoint (%s) - fragment is not supported." ,
266+ clientType , endpoint .toString ()));
267+ }
268+ }
269+
270+ private static void validateTlsManagersProvider (TlsManagersProviderConfig config , String clientType ) {
271+ if (config != null && config .type .isPresent ()
272+ && config .type .get () == TlsManagersProviderType .FILE_STORE ) {
273+
274+ if (config .fileStore == null ) {
275+ throw new ConfigurationError (
276+ String .format (
277+ "quarkus.dynamodb.%s-client.tls-managers-provider.file-store must be specified if 'FILE_STORE' provider type is used" ,
278+ clientType ));
279+ }
280+ if (config .fileStore .path == null ) {
281+ throw new ConfigurationError (
282+ String .format (
283+ "quarkus.dynamodb.%s-client.tls-managers-provider.file-store.path should not be empty if 'FILE_STORE' provider is used." ,
284+ clientType ));
285+ }
286+ if (StringUtils .isBlank (config .fileStore .type )) {
287+ throw new ConfigurationError (
288+ String .format (
289+ "quarkus.dynamodb.%s-client.tls-managers-provider.file-store.type should not be empty if 'FILE_STORE' provider is used." ,
290+ clientType ));
291+ }
292+ if (StringUtils .isBlank (config .fileStore .password )) {
293+ throw new ConfigurationError (
294+ String .format (
295+ "quarkus.dynamodb.%s-client.tls-managers-provider.file-store.password should not be empty if 'FILE_STORE' provider is used." ,
296+ clientType ));
297+ }
298+ }
214299 }
215300}
0 commit comments