Beispiel #1
0
 public override ExprNode Validate(ExprValidationContext validationContext)
 {
     evaluator = ChildNodes[0].Forge.ExprEvaluator;
     // always valid
     return null;
 }
Beispiel #2
0
 public override ExprNode Validate(ExprValidationContext validationContext)
 {
     return null;
 }
Beispiel #3
0
 public abstract ExprNode Validate(ExprValidationContext validationContext);
Beispiel #4
0
        public static object CoerceProperty(
            string propertyName,
            Type containingType,
            object value,
            Type type,
            ExprNodeOrigin exprNodeOrigin,
            ExprValidationContext exprValidationContext,
            bool forceNumeric,
            bool includeClassNameInEx)
        {
            // handle system-property exception
            if (value is ExprNode) {
                if (value is ExprIdentNode) {
                    var identNode = (ExprIdentNode) value;
                    Property prop;
                    try {
                        prop = PropertyParser.ParseAndWalkLaxToSimple(identNode.FullUnresolvedName);
                    }
                    catch (Exception) {
                        throw new ExprValidationException(
                            "Failed to parse property '" + identNode.FullUnresolvedName + "'");
                    }

                    if (!(prop is MappedProperty)) {
                        throw new ExprValidationException(
                            "Unrecognized property '" + identNode.FullUnresolvedName + "'");
                    }

                    var mappedProperty = (MappedProperty) prop;
                    if (string.Equals(
                        mappedProperty.PropertyNameAtomic,
                        ExprEvalSystemProperty.SYSTEM_PROPETIES_NAME,
                        StringComparison.InvariantCultureIgnoreCase)) {
                        if (type == typeof(ExprNode)) {
                            return new ExprEvalSystemProperty(mappedProperty.Key);
                        }

                        return Environment.GetEnvironmentVariable(mappedProperty.Key);
                    }
                }
                else {
                    var exprNode = (ExprNode) value;
                    if (type == typeof(ExprNode)) {
                        return exprNode;
                    }

                    if (!exprNode.Forge.ForgeConstantType.IsCompileTimeConstant) {
                        throw new ExprValidationException(
                            "Failed to determine parameter for property '" +
                            propertyName +
                            "' as the parameter is not a compile-time constant expression");
                    }

                    value = exprNode.Forge.ExprEvaluator.Evaluate(null, true, null);
                }
            }

            if (value == null) {
                return null;
            }

            var valueType = value.GetType();
            if (valueType == type) {
                return value;
            }

            
            var typeUnboxed = type.GetUnboxedType();
            if (valueType.GetUnboxedType().IsAssignmentCompatible(typeUnboxed)) {
                if (forceNumeric &&
                    value.GetType().GetBoxedType() != type.GetBoxedType() &&
                    type.IsNumeric() &&
                    value.GetType().IsNumeric()) {
                    value = TypeHelper.CoerceBoxed(value, type.GetBoxedType());
                }

                return value;
            }

            if (TypeHelper.IsSubclassOrImplementsInterface(value.GetType(), type)) {
                return value;
            }

            if (type.IsArray) {
                if (!value.GetType().IsGenericCollection()) {
                    var detail = "expects an array but receives a value of type " + value.GetType().Name;
                    throw new ExprValidationException(
                        GetExceptionText(propertyName, containingType, includeClassNameInEx, detail));
                }

                var items = value.UnwrapIntoArray<object>();
                var coercedArray = Arrays.CreateInstanceChecked(type.GetElementType(), items.Length);
                for (var i = 0; i < items.Length; i++) {
                    var coercedValue = CoerceProperty(
                        propertyName + " (array element)",
                        type,
                        items[i],
                        type.GetElementType(),
                        exprNodeOrigin,
                        exprValidationContext,
                        false,
                        includeClassNameInEx);
                    coercedArray.SetValue(coercedValue, i);
                }

                return coercedArray;
            }

            if (!(value is IDictionary<string, object>)) {
                var detail = "expects an " +
                             type.CleanName() +
                             " but receives a value of type " +
                             value.GetType().CleanName();
                throw new ExprValidationException(
                    GetExceptionText(propertyName, containingType, includeClassNameInEx, detail));
            }

            var props = (IDictionary<string, object>) value;
            return InstantiatePopulateObject(props, type, exprNodeOrigin, exprValidationContext);
        }
Beispiel #5
0
        public static void PopulateObject(
            IDictionary<string, object> objectProperties,
            object top,
            ExprNodeOrigin exprNodeOrigin,
            ExprValidationContext exprValidationContext)
        {
            var applicableClass = top.GetType();
            var writables = PropertyHelper.GetWritableProperties(applicableClass);
            var annotatedFields = TypeHelper.FindAnnotatedFields(top.GetType(), typeof(DataFlowOpParameterAttribute));
            var annotatedMethods = TypeHelper.FindAnnotatedMethods(top.GetType(), typeof(DataFlowOpParameterAttribute));

            // find catch-all methods
            ISet<MethodInfo> catchAllMethods = new LinkedHashSet<MethodInfo>();
            if (annotatedMethods != null) {
                foreach (var method in annotatedMethods) {
                    var anno = (DataFlowOpParameterAttribute) TypeHelper
                        .GetAnnotations<DataFlowOpParameterAttribute>(method.UnwrapAttributes())[0];
                    if (anno.IsAll) {
                        var parameters = method.GetParameters();
                        if (parameters.Length == 2 &&
                            (parameters[0].ParameterType == typeof(string)) &&
                            (parameters[1].ParameterType == typeof(object))) {
                            catchAllMethods.Add(method);
                            continue;
                        }

                        throw new ExprValidationException("Invalid annotation for catch-call");
                    }
                }
            }

            // map provided values
            foreach (var property in objectProperties) {
                var found = false;
                var propertyName = property.Key;

                // invoke catch-all setters
                foreach (var method in catchAllMethods) {
                    try {
                        method.Invoke(top, new[] {propertyName, property.Value});
                    }
                    catch (MemberAccessException e) {
                        throw new ExprValidationException(
                            "Illegal access invoking method for property '" +
                            propertyName +
                            "' for class " +
                            applicableClass.Name +
                            " method " +
                            method.Name,
                            e);
                    }
                    catch (TargetException e) {
                        throw new ExprValidationException(
                            "Exception invoking method for property '" +
                            propertyName +
                            "' for class " +
                            applicableClass.Name +
                            " method " +
                            method.Name +
                            ": " +
                            e.InnerException.Message,
                            e);
                    }

                    found = true;
                }

                if (propertyName.ToLowerInvariant().Equals(CLASS_PROPERTY_NAME)) {
                    continue;
                }

                // use the writeable property descriptor (appropriate setter method) from writing the property
                var descriptor = FindDescriptor(applicableClass, propertyName, writables);
                if (descriptor != null) {
                    var coerceProperty = CoerceProperty(
                        propertyName,
                        applicableClass,
                        property.Value,
                        descriptor.PropertyType,
                        exprNodeOrigin,
                        exprValidationContext,
                        false,
                        true);

                    try {
                        var writeMember = descriptor.WriteMember;
                        if (writeMember is MethodInfo writeMethod) {
                            writeMethod.Invoke(top, new[] {coerceProperty});
                        }
                        else if (writeMember is PropertyInfo writeProperty) {
                            writeProperty.SetValue(top, coerceProperty);
                        }
                        else {
                            throw new IllegalStateException("writeMember of invalid type");
                        }
                    }
                    catch (ArgumentException e) {
                        throw new ExprValidationException(
                            "Illegal argument invoking setter method for property '" +
                            propertyName +
                            "' for class " +
                            applicableClass.Name +
                            " method " +
                            descriptor.WriteMember.Name +
                            " provided value " +
                            coerceProperty,
                            e);
                    }
                    catch (MemberAccessException e) {
                        throw new ExprValidationException(
                            "Illegal access invoking setter method for property '" +
                            propertyName +
                            "' for class " +
                            applicableClass.Name +
                            " method " +
                            descriptor.WriteMember.Name,
                            e);
                    }
                    catch (TargetException e) {
                        throw new ExprValidationException(
                            "Exception invoking setter method for property '" +
                            propertyName +
                            "' for class " +
                            applicableClass.Name +
                            " method " +
                            descriptor.WriteMember.Name +
                            ": " +
                            e.InnerException.Message,
                            e);
                    }

                    continue;
                }

                // find the field annotated with {@link @GraphOpProperty}
                foreach (var annotatedField in annotatedFields) {
                    var anno = (DataFlowOpParameterAttribute) TypeHelper.GetAnnotations(
                        typeof(DataFlowOpParameterAttribute),
                        annotatedField.UnwrapAttributes())[0];
                    if (anno.Name.Equals(propertyName) || annotatedField.Name.Equals(propertyName)) {
                        var coerceProperty = CoerceProperty(
                            propertyName,
                            applicableClass,
                            property.Value,
                            annotatedField.FieldType,
                            exprNodeOrigin,
                            exprValidationContext,
                            true,
                            true);
                        try {
                            annotatedField.SetValue(top, coerceProperty);
                        }
                        catch (Exception e) {
                            throw new ExprValidationException(
                                "Failed to set field '" + annotatedField.Name + "': " + e.Message,
                                e);
                        }

                        found = true;
                        break;
                    }
                }

                if (found) {
                    continue;
                }

                throw new ExprValidationException(
                    "Failed to find writable property '" + propertyName + "' for class " + applicableClass.Name);
            }
        }
Beispiel #6
0
        public static void PopulateObject(
            string operatorName,
            int operatorNum,
            string dataFlowName,
            IDictionary<string, object> objectProperties,
            object top,
            ExprNodeOrigin exprNodeOrigin,
            ExprValidationContext exprValidationContext,
            EPDataFlowOperatorParameterProvider optionalParameterProvider,
            IDictionary<string, object> optionalParameterURIs)
        {
            var applicableClass = top.GetType();
            var writables = PropertyHelper.GetWritableProperties(applicableClass);
            var annotatedFields =
                TypeHelper.FindAnnotatedFields(top.GetType(), typeof(DataFlowOpParameterAttribute));
            var annotatedMethods =
                TypeHelper.FindAnnotatedMethods(top.GetType(), typeof(DataFlowOpParameterAttribute));

            // find catch-all methods
            ISet<MethodInfo> catchAllMethods = new LinkedHashSet<MethodInfo>();
            if (annotatedMethods != null) {
                foreach (var method in annotatedMethods) {
                    var anno = (DataFlowOpParameterAttribute) TypeHelper.GetAnnotations(
                        typeof(DataFlowOpParameterAttribute),
                        method.UnwrapAttributes())[0];
                    if (anno.IsAll) {
                        var parameterTypes = method.GetParameterTypes();
                        if (parameterTypes.Length == 2 &&
                            parameterTypes[0] == typeof(string) &&
                            parameterTypes[1] == typeof(ExprNode)) {
                            catchAllMethods.Add(method);
                            continue;
                        }

                        throw new ExprValidationException("Invalid annotation for catch-call");
                    }
                }
            }

            // map provided values
            foreach (var property in objectProperties) {
                var found = false;
                var propertyName = property.Key;

                // invoke catch-all setters
                foreach (var method in catchAllMethods) {
                    try {
                        method.Invoke(top, new[] {propertyName, property.Value});
                    }
                    catch (MemberAccessException e) {
                        throw new ExprValidationException(
                            "Illegal access invoking method for property '" +
                            propertyName +
                            "' for class " +
                            applicableClass.Name +
                            " method " +
                            method.Name,
                            e);
                    }
                    catch (TargetException e) {
                        throw new ExprValidationException(
                            "Exception invoking method for property '" +
                            propertyName +
                            "' for class " +
                            applicableClass.Name +
                            " method " +
                            method.Name +
                            ": " +
                            e.InnerException.Message,
                            e);
                    }

                    found = true;
                }

                if (propertyName.ToLowerInvariant().Equals(CLASS_PROPERTY_NAME)) {
                    continue;
                }

                // use the writeable property descriptor (appropriate setter method) from writing the property
                var descriptor = FindDescriptor(applicableClass, propertyName, writables);
                if (descriptor != null) {
                    var coerceProperty = CoerceProperty(
                        propertyName,
                        applicableClass,
                        property.Value,
                        descriptor.PropertyType,
                        exprNodeOrigin,
                        exprValidationContext,
                        false,
                        true);

                    try {
                        var writeMember = descriptor.WriteMember;
                        if (writeMember is MethodInfo writeMethod) {
                            writeMethod.Invoke(top, new[] {coerceProperty});
                        }
                        else if (writeMember is PropertyInfo writeProperty) {
                            writeProperty.SetValue(top, coerceProperty);
                        }
                        else {
                            throw new IllegalStateException("writeMember of invalid type");
                        }
                    }
                    catch (ArgumentException e) {
                        throw new ExprValidationException(
                            "Illegal argument invoking setter method for property '" +
                            propertyName +
                            "' for class " +
                            applicableClass.Name +
                            " method " +
                            descriptor.WriteMember.Name +
                            " provided value " +
                            coerceProperty,
                            e);
                    }
                    catch (MemberAccessException e) {
                        throw new ExprValidationException(
                            "Illegal access invoking setter method for property '" +
                            propertyName +
                            "' for class " +
                            applicableClass.Name +
                            " method " +
                            descriptor.WriteMember.Name,
                            e);
                    }
                    catch (TargetException e) {
                        throw new ExprValidationException(
                            "Exception invoking setter method for property '" +
                            propertyName +
                            "' for class " +
                            applicableClass.Name +
                            " method " +
                            descriptor.WriteMember.Name +
                            ": " +
                            e.InnerException.Message,
                            e);
                    }

                    continue;
                }

                // find the field annotated with {@link @GraphOpProperty}
                foreach (var annotatedField in annotatedFields) {
                    var anno = (DataFlowOpParameterAttribute) TypeHelper.GetAnnotations<DataFlowOpParameterAttribute>(
                        annotatedField.UnwrapAttributes())[0];
                    if (anno.Name.Equals(propertyName) || annotatedField.Name.Equals(propertyName)) {
                        var coerceProperty = CoerceProperty(
                            propertyName,
                            applicableClass,
                            property.Value,
                            annotatedField.FieldType,
                            exprNodeOrigin,
                            exprValidationContext,
                            true,
                            true);
                        try {
                            annotatedField.SetValue(top, coerceProperty);
                        }
                        catch (Exception e) {
                            throw new ExprValidationException(
                                "Failed to set field '" + annotatedField.Name + "': " + e.Message,
                                e);
                        }

                        found = true;
                        break;
                    }
                }

                if (found) {
                    continue;
                }

                throw new ExprValidationException(
                    "Failed to find writable property '" + propertyName + "' for class " + applicableClass.Name);
            }

            // second pass: if a parameter URI - value pairs were provided, check that
            if (optionalParameterURIs != null) {
                foreach (var annotatedField in annotatedFields) {
                    try {
                        var uri = operatorName + "/" + annotatedField.Name;
                        if (optionalParameterURIs.ContainsKey(uri)) {
                            var value = optionalParameterURIs.Get(uri);
                            annotatedField.SetValue(top, value);
                            if (Log.IsDebugEnabled) {
                                Log.Debug(
                                    "Found parameter '" +
                                    uri +
                                    "' for data flow " +
                                    dataFlowName +
                                    " setting " +
                                    value);
                            }
                        }
                        else {
                            if (Log.IsDebugEnabled) {
                                Log.Debug("Not found parameter '" + uri + "' for data flow " + dataFlowName);
                            }
                        }
                    }
                    catch (Exception e) {
                        throw new ExprValidationException(
                            "Failed to set field '" + annotatedField.Name + "': " + e.Message,
                            e);
                    }
                }

                foreach (var method in annotatedMethods) {
                    var anno = (DataFlowOpParameterAttribute) TypeHelper.GetAnnotations(
                        typeof(DataFlowOpParameterAttribute),
                        method.UnwrapAttributes())[0];
                    if (anno.IsAll) {
                        var parameters = method.GetParameters();

                        var parameterTypes = method.GetParameterTypes();
                        if (parameterTypes.Length == 2 &&
                            parameterTypes[0] == typeof(string) &&
                            parameterTypes[1] == typeof(object)) {
                            foreach (var entry in optionalParameterURIs) {
                                var elements = URIUtil.ParsePathElements(new Uri(entry.Key));
                                if (elements.Length < 2) {
                                    throw new ExprValidationException(
                                        "Failed to parse URI '" +
                                        entry.Key +
                                        "', expected " +
                                        "'operator_name/property_name' format");
                                }

                                if (elements[0].Equals(operatorName)) {
                                    try {
                                        method.Invoke(top, new[] {elements[1], entry.Value});
                                    }
                                    catch (MemberAccessException e) {
                                        throw new ExprValidationException(
                                            "Illegal access invoking method for property '" +
                                            entry.Key +
                                            "' for class " +
                                            applicableClass.Name +
                                            " method " +
                                            method.Name,
                                            e);
                                    }
                                    catch (TargetException e) {
                                        throw new ExprValidationException(
                                            "Exception invoking method for property '" +
                                            entry.Key +
                                            "' for class " +
                                            applicableClass.Name +
                                            " method " +
                                            method.Name +
                                            ": " +
                                            e.InnerException.Message,
                                            e);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Beispiel #7
0
        // Since static method calls such as "Class.method('a')" and mapped properties "Stream.property('key')"
        // look the same, however as the validation could not resolve "Stream.property('key')" before calling this method,
        // this method tries to resolve the mapped property as a static method.
        // Assumes that this is an ExprIdentNode.
        private static ExprNode ResolveStaticMethodOrField(
            ExprIdentNode identNode,
            ExprValidationException propertyException,
            ExprValidationContext validationContext)
        {
            // Reconstruct the original string
            StringBuilder mappedProperty = new StringBuilder(identNode.UnresolvedPropertyName);
            if (identNode.StreamOrPropertyName != null) {
                mappedProperty.Insert(0, identNode.StreamOrPropertyName + '.');
            }

            // Parse the mapped property format into a class name, method and single string parameter
            MappedPropertyParseResult parse = ParseMappedProperty(mappedProperty.ToString());
            if (parse == null) {
                ExprConstantNode constNode = ResolveIdentAsEnumConst(
                    mappedProperty.ToString(),
                    validationContext.ImportService);
                if (constNode == null) {
                    throw propertyException;
                }
                else {
                    return constNode;
                }
            }

            // If there is a class name, assume a static method is possible.
            if (parse.ClassName != null) {
                IList<ExprNode> parameters =
                    Collections.SingletonList((ExprNode) new ExprConstantNodeImpl(parse.ArgString));
                IList<ExprChainedSpec> chain = new List<ExprChainedSpec>();
                chain.Add(new ExprChainedSpec(parse.ClassName, Collections.GetEmptyList<ExprNode>(), false));
                chain.Add(new ExprChainedSpec(parse.MethodName, parameters, false));
                ConfigurationCompilerExpression exprConfig =
                    validationContext.StatementCompileTimeService.Configuration.Compiler.Expression;
                ExprNode result = new ExprDotNodeImpl(chain, exprConfig.IsDuckTyping, exprConfig.IsUdfCache);

                // Validate
                try {
                    result.Validate(validationContext);
                }
                catch (ExprValidationException e) {
                    throw new ExprValidationException(
                        $"Failed to resolve enumeration method, date-time method or mapped property '{mappedProperty}': {e.Message}",
                        e);
                }

                return result;
            }

            // There is no class name, try a single-row function
            string functionName = parse.MethodName;
            try {
                Pair<Type, ImportSingleRowDesc> classMethodPair =
                    validationContext.ImportService.ResolveSingleRow(functionName);
                IList<ExprNode> parameters =
                    Collections.SingletonList((ExprNode) new ExprConstantNodeImpl(parse.ArgString));
                IList<ExprChainedSpec> chain = Collections.SingletonList(
                    new ExprChainedSpec(classMethodPair.Second.MethodName, parameters, false));
                ExprNode result = new ExprPlugInSingleRowNode(
                    functionName,
                    classMethodPair.First,
                    chain,
                    classMethodPair.Second);

                // Validate
                try {
                    result.Validate(validationContext);
                }
                catch (EPException) {
                    throw;
                }
                catch (Exception ex) {
                    throw new ExprValidationException(
                        "Plug-in aggregation function '" + parse.MethodName + "' failed validation: " + ex.Message);
                }

                return result;
            }
            catch (ImportUndefinedException) {
                // Not an single-row function
            }
            catch (ImportException e) {
                throw new IllegalStateException("Error resolving single-row function: " + e.Message, e);
            }

            // Try an aggregation function factory
            try {
                AggregationFunctionForge aggregationForge =
                    validationContext.ImportService.ResolveAggregationFunction(parse.MethodName);
                ExprNode result = new ExprPlugInAggNode(false, aggregationForge, parse.MethodName);
                result.AddChildNode(new ExprConstantNodeImpl(parse.ArgString));

                // Validate
                try {
                    result.Validate(validationContext);
                }
                catch (EPException) {
                    throw;
                }
                catch (Exception e) {
                    throw new ExprValidationException(
                        "Plug-in aggregation function '" + parse.MethodName + "' failed validation: " + e.Message);
                }

                return result;
            }
            catch (ImportUndefinedException) {
                // Not an aggregation function
            }
            catch (ImportException e) {
                throw new IllegalStateException("Error resolving aggregation: " + e.Message, e);
            }

            // absolutely cannot be resolved
            throw propertyException;
        }
Beispiel #8
0
        private static ExprNode GetValidatedSubtreeInternal(
            ExprNode exprNode,
            ExprValidationContext validationContext,
            bool isTopLevel)
        {
            ExprNode result = exprNode;
            if (exprNode is ExprLambdaGoesNode) {
                return exprNode;
            }

            for (int i = 0; i < exprNode.ChildNodes.Length; i++) {
                ExprNode childNode = exprNode.ChildNodes[i];
                if (childNode is ExprDeclaredOrLambdaNode node) {
                    if (node.IsValidated) {
                        continue;
                    }
                }

                ExprNode childNodeValidated = GetValidatedSubtreeInternal(childNode, validationContext, false);
                exprNode.SetChildNode(i, childNodeValidated);
            }

            try {
                ExprNode optionalReplacement = exprNode.Validate(validationContext);
                if (optionalReplacement != null) {
                    return GetValidatedSubtreeInternal(optionalReplacement, validationContext, isTopLevel);
                }
            }
            catch (ExprValidationException e) {
                if (exprNode is ExprIdentNode identNode) {
                    try {
                        result = ResolveStaticMethodOrField(identNode, e, validationContext);
                    }
                    catch (ExprValidationException) {
                        var resolutionStream = ResolveAsStreamName(identNode, validationContext);
                        if (resolutionStream.First == false) {
                            throw;
                        }

                        result = resolutionStream.Second;
                    }
                }
                else {
                    throw;
                }
            }

            // For top-level expressions check if we perform audit
            if (isTopLevel) {
                if (validationContext.IsExpressionAudit) {
                    return (ExprNode) ExprNodeProxy.NewInstance(result);
                }
            }
            else {
                if (validationContext.IsExpressionNestedAudit &&
                    !(result is ExprIdentNode) &&
                    !(ExprNodeUtilityQuery.IsConstant(result))) {
                    return (ExprNode) ExprNodeProxy.NewInstance(result);
                }
            }

            return result;
        }