This repository was archived by the owner on Aug 3, 2026. It is now read-only.
Repository navigation
Expand file tree
/
Copy pathLambdaInvokerFactory.java
More file actions
346 lines (314 loc) · 12.8 KB
/
Copy pathLambdaInvokerFactory.java
File metadata and controls
346 lines (314 loc) · 12.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
/*
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.amazonaws.mobileconnectors.lambdainvoker;
import android.content.Context;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.mobile.config.AWSConfiguration;
import com.amazonaws.mobileconnectors.util.ClientContext;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.lambda.AWSLambda;
import com.amazonaws.services.lambda.AWSLambdaClient;
import org.json.JSONObject;
import java.lang.reflect.Proxy;
/**
* A factory class that creates a dynamic proxy object backed by Lambda service.
*/
@SuppressWarnings("checkstyle:hiddenfield")
public class LambdaInvokerFactory {
// -------------------------------------------------------------
// Methods - Public - Static
// -------------------------------------------------------------
private final AWSLambda lambda;
private final ClientContext clientContext;
/**
* Builder class for LambdaInvokerFactory
*/
public static class Builder {
private Context context;
private Regions region;
private AWSCredentialsProvider provider;
private ClientConfiguration clientConfig;
private AWSConfiguration awsConfig;
private AWSLambda lambda;
private ClientContext clientContext;
protected Builder() { }
/**
*
* @param context The context.
* @return builder
*/
public Builder context(Context context) {
this.context = context;
return this;
}
/**
* This will take precedence over any region specified in {@linkAWSConfiguration
* @param region The region your lambda functions were created in.
* @return builder
*/
public Builder region(Regions region) {
this.region = region;
return this;
}
/**
*
* @param provider The credentials that have access to the functions
* @return builder
*/
public Builder credentialsProvider(AWSCredentialsProvider provider) {
this.provider = provider;
return this;
}
/**
* If your Lambda function takes a long time to finish (longer than the
* default socket timeout of 15 seconds), you can increase the timeout
* via {@link ClientConfiguration} .
*
* <pre>
* ClientConfiguration config = new ClientConfiguration();
* config.setSocketTimeout(5 * 60 * 1000); // 5 minutes
* </pre>
*
* @param clientConfig The configuration for the lambda client
* @return builder
*/
public Builder clientConfiguration(ClientConfiguration clientConfig) {
this.clientConfig = clientConfig;
return this;
}
/**
*
* @param clientContext Client context
* @return builder
*/
public Builder clientContext(ClientContext clientContext) {
this.clientContext = clientContext;
return this;
}
/**
* This will be constructed if you directly provide
* {@link #credentialsProvider(AWSCredentialsProvider)} and
* {@link #clientContext(ClientContext)} and either
* {@link #region(Regions)} or
* {@link #awsConfiguration(AWSConfiguration)}
*
* @param lambda The lambda client making the network calls
* @return builder
*/
public Builder lambdaClient(AWSLambda lambda) {
this.lambda = lambda;
return this;
}
/**
* This region will be overridden by {@link #region(Regions)}, if specified.
*
* Example awsconfiguration.json
* {
* "LambdaInvoker" : {
* "Default": {
* "Region": "ap-northeast-1"
* }
* }
* }
* @param awsConfig The configuration will override the region set in
* the lambda client.
* @return builder
*/
public Builder awsConfiguration(AWSConfiguration awsConfig) {
this.awsConfig = awsConfig;
return this;
}
/**
*
* @return the LambdaInvokerFactory created by the parts provided
*/
public LambdaInvokerFactory build() {
if (this.clientConfig == null) {
if (this.context == null) {
throw new IllegalArgumentException("Context or ClientContext are required"
+ " please set using .context(context) or .clientContext(clientContext)");
}
this.clientContext = new ClientContext(this.context);
}
if (this.lambda == null) {
if (this.provider == null) {
throw new IllegalArgumentException("AWSCredentialsProvider is required please"
+ " set using .credentialsProvider(creds)");
}
if (this.clientConfig == null) {
this.clientConfig = new ClientConfiguration();
}
}
if (this.awsConfig != null) {
try {
if (this.clientConfig != null) {
String userAgent = this.clientConfig.getUserAgent();
if (userAgent == null || userAgent.trim().isEmpty()) {
this.clientConfig.setUserAgent(this.awsConfig.getUserAgent());
} else {
this.clientConfig.setUserAgent(userAgent
+ "/" + this.awsConfig.getUserAgent());
}
}
final JSONObject lambdaConfig = this.awsConfig.optJsonObject("LambdaInvoker");
if (this.region != null) {
this.region = Regions.fromName(lambdaConfig.getString("Region"));
}
} catch (Exception e) {
throw new IllegalArgumentException("Failed to read LambdaInvoker "
+ "please check your setup or awsconfiguration.json file", e);
}
}
if (this.lambda == null) {
this.lambda = new AWSLambdaClient(this.provider, this.clientConfig);
}
if (this.region != null) {
this.lambda.setRegion(Region.getRegion(this.region));
}
return new LambdaInvokerFactory(this.lambda, this.clientContext);
}
}
/**
* Some examples:
* LambdaInvokerFactory.builder()
* .context(context)
* .region(Regions.AP_NORTHEAST_1)
* .clientConfiguration(clientConfig) // Optional
* .credentialsProvider(provider)
* .build();
*
* LambdaInvokerFactory.builder()
* .context(context)
* .awsConfiguration(awsConfig)
* .clientConfiguration(clientConfig) // Optional
* .credentialsProvider(provider)
* .build;
*
* LambdaInvokerFactory.builder()
* .lambdaClient(client)
* .clientContext(clientContext)
* .build;
* @return builder
*/
public static Builder builder() {
return new Builder();
}
/**
* Constructs a Lambda invoker factory object.
*
* @param context context of the app. A client context will be created from
* the given context.
* @param region region of Lambda service
* @param provider a AWS credentials provider
* @deprecated Please use LambdaInvokerFactory.builder()
* .context(context)
* .region(Regions.AP_NORTHEAST_1)
* .credentialsProvider(provider)
* .build();
*/
public LambdaInvokerFactory(Context context, Regions region, AWSCredentialsProvider provider) {
this(context, region, provider, new ClientConfiguration());
}
/**
* Constructs a Lambda invoker factory object. If your Lambda function takes
* a long time to finish (longer than the default socket timeout of 15
* seconds), you can increase the timeout via {@link ClientConfiguration} .
*
* <pre>
* ClientConfiguration config = new ClientConfiguration();
* config.setSocketTimeout(5 * 60 * 1000); // 5 minutes
* LambdaInvokerFactory factory = new LambdaInvokerFactory(context, region,
* provider, config);
* </pre>
*
* @param context context of the app. A client context will be created from
* the given context.
* @param region region of Lambda service
* @param provider a AWS credentials provider
* @param clientConfiguration client configuration for the factory
* @deprecated Please use LambdaInvokerFactory.builder()
* .context(context)
* .region(Regions.AP_NORTHEAST_1)
* .credentialsProvider(provider)
* .clientConfiguration(clientConfig)
* .build();
*/
public LambdaInvokerFactory(Context context, Regions region, AWSCredentialsProvider provider,
ClientConfiguration clientConfiguration) {
if (context == null) {
throw new IllegalArgumentException("context can't be null");
}
if (provider == null) {
throw new IllegalArgumentException("provider can't be null");
}
// constructs a lambda client
lambda = new AWSLambdaClient(provider, clientConfiguration);
lambda.setRegion(Region.getRegion(region));
clientContext = new ClientContext(context);
}
/**
* Constructs a Lambda invoker factory object.
*
* @param lambda a lambda client
* @param clientContext client context object
* @deprecated Please use LambdaInvokerFactory.builder()
* .lambdaClient(client)
* .clientContext(clientContext)
* .build();
*/
LambdaInvokerFactory(AWSLambda lambda, ClientContext clientContext) {
this.lambda = lambda;
this.clientContext = clientContext;
}
/**
* Contexts a dynamic proxy object of the given class with a default Json
* data binder.
*
* @param interfaceClass the class to be dynamically proxied by Lambda
* @param <T> the type for the class
* @return a dynamic proxy object of the given class
*/
public <T> T build(Class<T> interfaceClass) {
return build(interfaceClass, new LambdaJsonBinder());
}
/**
* Contexts a dynamic proxy object of the given class.
*
* @param interfaceClass the class to be dynamically proxied by Lambda
* @param binder a data binder to convert between POJO and byte stream.
* @param <T> the type of the interfaceclass.
* @return a dynamic proxy object of the given class
*/
public <T> T build(Class<T> interfaceClass, LambdaDataBinder binder) {
final Object proxy = Proxy.newProxyInstance(interfaceClass.getClassLoader(),
new Class<?>[] {
interfaceClass
},
new LambdaInvocationHandler(lambda, binder, clientContext));
return interfaceClass.cast(proxy);
}
/**
* Gets the client context associated with this factory. Changes to the
* client context will affect all proxy objects created by this factory,
* including those were created.
*
* @return client context
*/
public ClientContext getClientContext() {
return clientContext;
}
}