/* * 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} . * *
* ClientConfiguration config = new ClientConfiguration();
* config.setSocketTimeout(5 * 60 * 1000); // 5 minutes
*
*
* @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} .
*
*
* ClientConfiguration config = new ClientConfiguration();
* config.setSocketTimeout(5 * 60 * 1000); // 5 minutes
* LambdaInvokerFactory factory = new LambdaInvokerFactory(context, region,
* provider, config);
*
*
* @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