/// <summary>
        /// Creates an expression to convert incoming Stream to the customer method inputs.
        /// If customer method takes no inputs or only takes ILambdaContext, return null.
        /// </summary>
        /// <param name="customerSerializerInstance">Instance of lambda input & output serializer.</param>
        /// <param name="inStreamParameter">Input stream parameter.</param>
        /// <param name="iLambdaContextType">Type of context passed for the invocation.</param>
        /// <returns>Expression that deserializes incoming stream to the customer method inputs or null if customer method takes no input.</returns>
        /// <exception cref="LambdaValidationException">Thrown when customer method inputs don't meet lambda requirements.</exception>
        private Expression BuildInputExpressionOrNull(object customerSerializerInstance, Expression inStreamParameter, out Type iLambdaContextType)
        {
            Type inputType = null;

            iLambdaContextType = null;

            // get input types
            var inputTypes = _customerMethodInfo.GetParameters().Select(pi => pi.ParameterType).ToArray();

            // check if there are too many parameters
            if (inputTypes.Length > 2)
            {
                throw LambdaExceptions.ValidationException(Errors.UserCodeLoader.MethodTooManyParams,
                                                           _customerMethodInfo.Name, _handler.TypeName);
            }

            // if two parameters, check that the second input is ILambdaContext
            if (inputTypes.Length == 2)
            {
                if (!Types.IsILambdaContext(inputTypes[1]))
                {
                    throw LambdaExceptions.ValidationException(Errors.UserCodeLoader.MethodSecondParamNotContext,
                                                               _customerMethodInfo.Name, _handler.TypeName, Types.ILambdaContextTypeName);
                }

                iLambdaContextType = inputTypes[1];
                inputType          = inputTypes[0];
            }

            // if one input, check if input is ILambdaContext
            else if (inputTypes.Length == 1)
            {
                if (Types.IsILambdaContext(inputTypes[0]))
                {
                    iLambdaContextType = inputTypes[0];
                }
                else
                {
                    inputType = inputTypes[0];
                }
            }

            if (inputType != null)
            {
                // deserializer.Deserialize(inStream)
                return(CreateDeserializeExpression(customerSerializerInstance, inputType, inStreamParameter));
            }

            if (iLambdaContextType != null)
            {
                _logger.LogDebug($"UCL : Validating iLambdaContextType");
                UserCodeValidator.ValidateILambdaContextType(iLambdaContextType);
            }

            return(null);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Constructs an instance of the customer-specified serializer
        /// </summary>
        /// <param name="serializerAttribute">Serializer attribute used to define the input/output serializer.</param>
        /// <returns></returns>
        /// <exception cref="LambdaValidationException">Thrown when serializer doesn't satisfy serializer type requirements.</exception>
        /// <exception cref="LambdaUserCodeException">Thrown when failed to instantiate serializer type.</exception>
        private object ConstructCustomSerializer(Attribute serializerAttribute)
        {
            var attributeType          = serializerAttribute.GetType();
            var serializerTypeProperty = attributeType.GetTypeInfo().GetProperty("SerializerType");

            if (serializerTypeProperty == null)
            {
                throw LambdaExceptions.ValidationException(Errors.UserCodeLoader.InvalidClassNoSerializerType, attributeType.FullName);
            }

            if (!Types.TypeType.GetTypeInfo().IsAssignableFrom(serializerTypeProperty.PropertyType))
            {
                throw LambdaExceptions.ValidationException(Errors.UserCodeLoader.InvalidClassSerializerTypeWrongType,
                                                           attributeType.FullName, Types.TypeType.FullName);
            }

            var serializerType = serializerTypeProperty.GetValue(serializerAttribute) as Type;

            if (serializerType == null)
            {
                throw LambdaExceptions.ValidationException(Errors.UserCodeLoader.SerializerTypeNotSet,
                                                           attributeType.FullName);
            }

            var serializerTypeInfo = serializerType.GetTypeInfo();

            var constructor = serializerTypeInfo.GetConstructor(Type.EmptyTypes);

            if (constructor == null)
            {
                throw LambdaExceptions.ValidationException(Errors.UserCodeLoader.SerializerMissingConstructor, serializerType.FullName);
            }

            var iLambdaSerializerType = serializerTypeInfo.GetInterface(Types.ILambdaSerializerTypeName);

            if (iLambdaSerializerType == null)
            {
                throw LambdaExceptions.ValidationException(Errors.UserCodeLoader.InvalidClassNoILambdaSerializer, serializerType.FullName);
            }

            _logger.LogDebug($"UCL : Validating type '{iLambdaSerializerType.FullName}'");
            UserCodeValidator.ValidateILambdaSerializerType(iLambdaSerializerType);

            object customSerializerInstance;

            customSerializerInstance = constructor.Invoke(null);

            return(customSerializerInstance);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Constructs an instance of the customer type, or returns null
        /// if the customer method is static and does not require an object
        /// </summary>
        /// <param name="customerType">Type of the customer handler container.</param>
        /// <returns>Instance of customer handler container type</returns>
        /// <exception cref="LambdaUserCodeException">Thrown when failed to instantiate customer type.</exception>
        private object GetCustomerObject(Type customerType)
        {
            _logger.LogDebug($"UCL : Validating type '{_handler.TypeName}'");
            UserCodeValidator.ValidateCustomerType(customerType, CustomerMethodInfo);

            var isHandlerStatic = CustomerMethodInfo.IsStatic;

            if (isHandlerStatic)
            {
                _logger.LogDebug($"UCL : Not constructing customer object, customer method is static");
                _logger.LogDebug($"UCL : Running static constructor for type '{_handler.TypeName}'");

                // Make sure the static initializer for the type runs now, during the init phase.
                RuntimeHelpers.RunClassConstructor(customerType.TypeHandle);

                return(null);
            }

            _logger.LogDebug($"UCL : Instantiating type '{_handler.TypeName}'");

            return(Activator.CreateInstance(customerType));
        }
Exemplo n.º 4
0
        /// <summary>
        /// Loads customer assembly, type, and method.
        /// After this call returns without errors, it is possible to invoke
        /// the customer method through the Invoke method.
        /// </summary>
        public void Init(Action <string> customerLoggingAction)
        {
            Assembly customerAssembly = null;

            try
            {
                _logger.LogDebug($"UCL : Parsing handler string '{_handlerString}'");
                _handler = new HandlerInfo(_handlerString);

                // Set the logging action private field on the Amazon.Lambda.Core.LambdaLogger type which is part of the
                // public Amazon.Lambda.Core package when it is loaded.
                AppDomain.CurrentDomain.AssemblyLoad += (sender, args) =>
                {
                    _logger.LogInformation($"UCL : Loaded assembly {args.LoadedAssembly.FullName} into default ALC.");
                    if (!_customerLoggerSetUpComplete && string.Equals(LambdaCoreAssemblyName, args.LoadedAssembly.GetName().Name, StringComparison.Ordinal))
                    {
                        _logger.LogDebug(
                            $"UCL : Load context loading '{LambdaCoreAssemblyName}', attempting to set {Types.LambdaLoggerTypeName}.{LambdaLoggingActionFieldName} to logging action.");
                        SetCustomerLoggerLogAction(args.LoadedAssembly, customerLoggingAction, _logger);
                        _customerLoggerSetUpComplete = true;
                    }
                };

                _logger.LogDebug($"UCL : Attempting to load assembly '{_handler.AssemblyName}'");
                customerAssembly = AssemblyLoadContext.Default.LoadFromAssemblyName(_handler.AssemblyName);
            }
            catch (FileNotFoundException fex)
            {
                _logger.LogError(fex, "An error occured on UCL Init");
                throw LambdaExceptions.ValidationException(Errors.UserCodeLoader.CouldNotFindHandlerAssembly, fex.FileName);
            }
            catch (LambdaValidationException validationException)
            {
                _logger.LogError(validationException, "An error occured on UCL Init");
                throw;
            }
            catch (Exception exception)
            {
                _logger.LogError(exception, "An error occured on UCL Init");
                throw LambdaExceptions.ValidationException(Errors.UserCodeLoader.UnableToLoadAssembly, _handler.AssemblyName);
            }

            _logger.LogDebug($"UCL : Attempting to load type '{_handler.TypeName}'");
            var customerType = customerAssembly.GetType(_handler.TypeName);

            if (customerType == null)
            {
                throw LambdaExceptions.ValidationException(Errors.UserCodeLoader.UnableToLoadType, _handler.TypeName, _handler.AssemblyName);
            }

            _logger.LogDebug($"UCL : Attempting to find method '{_handler.MethodName}' in type '{_handler.TypeName}'");
            CustomerMethodInfo = FindCustomerMethod(customerType);
            _logger.LogDebug($"UCL : Located method '{CustomerMethodInfo}'");

            _logger.LogDebug($"UCL : Validating method '{CustomerMethodInfo}'");
            UserCodeValidator.ValidateCustomerMethod(CustomerMethodInfo);

            var customerObject = GetCustomerObject(customerType);

            var customerSerializerInstance = GetSerializerObject(customerAssembly);

            _logger.LogDebug($"UCL : Constructing invoke delegate");

            var isPreJit = UserCodeInit.IsCallPreJit();
            var builder  = new InvokeDelegateBuilder(_logger, _handler, CustomerMethodInfo);

            _invokeDelegate = builder.ConstructInvokeDelegate(customerObject, customerSerializerInstance, isPreJit);
            if (isPreJit)
            {
                _logger.LogInformation("PreJit: PrepareDelegate");
                RuntimeHelpers.PrepareDelegate(_invokeDelegate);
            }
        }