All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.amazonaws.mobileconnectors.lambdainvoker.LambdaInvocationHandler Maven / Gradle / Ivy

Go to download

The AWS Android SDK for AWS Lambda module holds the client classes that are used for communicating with AWS Lambda Service

There is a newer version: 2.8.4
Show newest version

package com.amazonaws.mobileconnectors.lambdainvoker;

import android.util.Log;

import com.amazonaws.mobileconnectors.util.ClientContext;
import com.amazonaws.services.lambda.AWSLambda;
import com.amazonaws.services.lambda.model.InvocationType;
import com.amazonaws.services.lambda.model.InvokeRequest;
import com.amazonaws.services.lambda.model.InvokeResult;
import com.amazonaws.services.lambda.model.LogType;
import com.amazonaws.util.Base64;
import com.amazonaws.util.StringUtils;

import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.nio.ByteBuffer;

/**
 * Invocation handler for Lambda.
 */
class LambdaInvocationHandler implements InvocationHandler {

    private static final String TAG = "LambdaInvocationHandler";

    // -------------------------------------------------------------
    // Variables - Private
    // -------------------------------------------------------------
    private final AWSLambda lambda;
    private final LambdaDataBinder binder;
    private final ClientContext clientContext;

    // -------------------------------------------------------------
    // Constructors
    // -------------------------------------------------------------
    /**
     * @param lambda lambda client
     * @param binder data binder
     * @param clientContext client context, null if unavailable
     */
    public LambdaInvocationHandler(AWSLambda lambda, LambdaDataBinder binder,
            ClientContext clientContext) {
        this.lambda = lambda;
        this.binder = binder;
        this.clientContext = clientContext;
    }

    // -------------------------------------------------------------
    // Implementation - InvocationHandler
    // -------------------------------------------------------------
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        validateInterfaceMethod(method, args);

        // With Android version before Lollipop (API level 22), args can be an
        // empty array when the method takes no arguments.
        final Object buildArg = (args == null || args.length == 0) ? null : args[0];
        InvokeRequest invokeRequest = buildInvokeRequest(method, buildArg);
        InvokeResult invokeResult = lambda.invoke(invokeRequest);

        return processInvokeResult(method, invokeResult);
    }

    // -------------------------------------------------------------
    // Methods - Private
    // -------------------------------------------------------------
    void validateInterfaceMethod(Method method, Object[] args) {
        if (method.getAnnotation(LambdaFunction.class) == null) {
            throw new UnsupportedOperationException("No LambdaFunction annotation for method "
                    + method.getName());
        }

        if (args != null && args.length > 1) {
            throw new UnsupportedOperationException(
                    "LambdaFunctions take either 0 or 1 arguments.");
        }
    }

    InvokeRequest buildInvokeRequest(Method method, Object object) throws IOException {
        LambdaFunction lambdaFunction = method.getAnnotation(LambdaFunction.class);

        InvokeRequest invokeRequest = new InvokeRequest();

        if (lambdaFunction.functionName().isEmpty()) {
            invokeRequest.setFunctionName(method.getName());
        } else {
            invokeRequest.setFunctionName(lambdaFunction.functionName());
        }

        invokeRequest.setLogType(lambdaFunction.logType());

        // If the log type is other than 'None', force to be RequestResponse.
        if (!LogType.None.equals(lambdaFunction.logType())) {
            invokeRequest.setInvocationType(InvocationType.RequestResponse);
        } else {
            invokeRequest.setInvocationType(lambdaFunction.invocationType());
        }

        if (!lambdaFunction.qualifier().isEmpty()) {
            invokeRequest.setQualifier(lambdaFunction.qualifier());
        }

        // set base64 encoded client context string
        if (clientContext != null) {
            invokeRequest.setClientContext(clientContext.toBase64String());
        }

        invokeRequest.setPayload(ByteBuffer.wrap(binder.serialize(object)));

        return invokeRequest;
    }

    Object processInvokeResult(Method method, InvokeResult invokeResult)
            throws IOException {
        if (invokeResult.getLogResult() != null) {
            Log.d(TAG, method.getName() + " log: "
                    + new String(Base64.decode(invokeResult.getLogResult()), StringUtils.UTF8));
        }

        if (invokeResult.getFunctionError() != null) {
            throw new LambdaFunctionException(invokeResult.getFunctionError(),
                    new String(invokeResult.getPayload().array(), StringUtils.UTF8));
        }

        // deserialize payload
        if (invokeResult.getStatusCode() == HttpURLConnection.HTTP_NO_CONTENT
                || method.getReturnType().equals(void.class)) {
            return null;
        }

        return binder.deserialize(invokeResult.getPayload().array(),
                method.getReturnType());
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy