Beispiel #1
0
        private void ParsePathItemForMetadata(JsonPathFinder pathItem, Dictionary <string, RuntimeTypeData> definitionsCache, Dictionary <string, Dictionary <string, ParameterData> > parameterCache, JsonPathFinder rootDoc)
        {
            // Parse path item level parameters first
            JsonPathFinder pathLevelParameters = pathItem.Find(new JsonQueryBuilder().Property("parameters")).SingleOrDefault();
            List <Dictionary <string, ParameterData> > pathLevelParameterList = new List <Dictionary <string, ParameterData> >();

            if (pathLevelParameters != null)
            {
                foreach (JsonPathFinder parameterNode in pathLevelParameters.Children())
                {
                    Dictionary <string, ParameterData> parameters = GetParameterMetadata(parameterNode.Path, parameterNode, definitionsCache, parameterCache, rootDoc);
                    pathLevelParameterList.Add(parameters);
                }
            }

            // Parse each path (all children that are not keyed by "$ref" or "parameters")
            foreach (JsonPathFinder operationContainerNode in pathItem.Children().Where(n => String.IsNullOrEmpty(n.Key) || (!n.Key.Equals("parameters") && !n.Key.Equals("$ref"))))
            {
                // Get parameter metadata from the operation
                OperationData operationData = ParseOperationForMetadata(operationContainerNode.OpenContainer(), definitionsCache, parameterCache, rootDoc);
                // Apply the path item level parameter data to this operation
                if (operationData != null)
                {
                    Log(String.Format(CultureInfo.InvariantCulture, "Applying path level parameters to operation '{0}'", operationData.OperationId));
                    foreach (Dictionary <string, ParameterData> parametersSet in pathLevelParameterList)
                    {
                        foreach (string parameterName in parametersSet.Keys)
                        {
                            if (operationData.Parameters.ContainsKey(parameterName.ToLowerInvariant()))
                            {
                                Log(String.Format(CultureInfo.InvariantCulture, "Found parameter with name '{0}' and JSON name '{1}'", parameterName, parametersSet[parameterName].JsonName));
                                operationData.Parameters[parameterName.ToLowerInvariant()].MergeWith(parametersSet[parameterName]);
                            }
                        }
                    }
                }
            }

            // TODO: Currently no support for path item using $ref
        }
Beispiel #2
0
        public virtual CommandExecutionResult ProcessRequest(LiveTestRequest request, LiveTestCredentialFactory credentialsFactory)
        {
            if (this.Logger != null)
            {
                this.Logger.LogAsync("Translating credentials...");
            }
            credentialsFactory.TranslateCredentialsObjects(request);
            CommandExecutionResult result = null;
            string operationId            = request.OperationId == null ? null : request.OperationId.ToLowerInvariant();

            if (this.Logger != null)
            {
                this.Logger.LogAsync("Operation ID of message: " + operationId);
            }
            if (!String.IsNullOrEmpty(operationId) && this.Operations.ContainsKey(operationId))
            {
                if (this.Logger != null)
                {
                    this.Logger.LogAsync("Processing operation...");
                }
                OperationData op = this.Operations[operationId];
                // Create the command
                ICommandBuilder command = this.runspace.CreateCommand();
                command.Command = op.Command;
                foreach (string parameterName in op.Parameters.Keys)
                {
                    if (request.Params != null && request.Params.ContainsKey(parameterName.ToLowerInvariant()))
                    {
                        command.AddParameter(parameterName, request.Params[parameterName.ToLowerInvariant()]);
                    }
                    else
                    {
                        this.Logger.LogAsync("Request missing parameter: " + parameterName);
                    }
                }

                // Process credentials
                IEnumerable <ICredentialProvider> credProviders = credentialsFactory.Create(request, this.Logger);
                foreach (ICredentialProvider credProvider in credProviders)
                {
                    credProvider.Process(command);
                }

                // Run the command
                result = command.Invoke();

                // Run post processors, if any
                foreach (ICommandPostProcessor postProcessor in op.PostProcessors)
                {
                    result = postProcessor.Process(result);
                }
            }
            else
            {
                // error
                if (this.Logger != null)
                {
                    this.Logger.LogError("Operation ID was not found in module under test.");
                }
            }

            return(result);
        }
Beispiel #3
0
        private OperationData ParseOperationForMetadata(JsonPathFinder path, Dictionary <string, RuntimeTypeData> definitionsCache, Dictionary <string, Dictionary <string, ParameterData> > parameterCache, JsonPathFinder rootDoc)
        {
            JsonPathFinder parametersNode  = path.Find(new JsonQueryBuilder().Property("parameters")).SingleOrDefault();
            JsonPathFinder operationIdNode = path.Find(new JsonQueryBuilder().Property("operationId")).SingleOrDefault();

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

            string operationId = operationIdNode.GetValue <string>();

            if (!this.Operations.ContainsKey(operationId.ToLowerInvariant()))
            {
                Log(String.Format(CultureInfo.InvariantCulture, "Skipping operation '{0}' because no matching command was found.", operationId));
                return(null);
            }

            OperationData operationData = this.Operations[operationId.ToLowerInvariant()];

            Log(String.Format(CultureInfo.InvariantCulture, "Loading metadata for operation '{0}' and command '{1}'", operationId, operationData.Command));

            if (parametersNode != null)
            {
                foreach (JsonPathFinder parameterNode in parametersNode.Children())
                {
                    Dictionary <string, ParameterData> parameters = GetParameterMetadata(parameterNode.Path, parameterNode, definitionsCache, parameterCache, rootDoc);
                    foreach (string parameterName in parameters.Keys)
                    {
                        if (operationData.Parameters.ContainsKey(parameterName.ToLowerInvariant()))
                        {
                            Log(String.Format(CultureInfo.InvariantCulture, "Found parameter with name '{0}' and JSON name '{1}'", parameterName, parameters[parameterName].JsonName));
                            operationData.Parameters[parameterName.ToLowerInvariant()].MergeWith(parameters[parameterName]);
                        }
                    }
                }
            }

            // Find the first response in the [200-299] range, as that's all PSSwagger supports right now
            JsonPathFinder responsesNode          = path.Find(new JsonQueryBuilder().Property("responses")).SingleOrDefault();
            string         responseDefinitionPath = null;

            if (responsesNode != null && operationData.ResponseType != null)
            {
                foreach (JsonPathFinder response in responsesNode.Children())
                {
                    int statusCode;
                    if (Int32.TryParse(response.Key, out statusCode) && statusCode >= 200 && statusCode <= 299)
                    {
                        // For now we only support ref'd schema - need to fix that
                        JsonPathFinder schemaRefNode = response.Find(new JsonQueryBuilder().RecursiveDescent().Property("$ref")).SingleOrDefault();
                        if (schemaRefNode != null)
                        {
                            responseDefinitionPath = schemaRefNode.GetValue <string>();
                            string definitionPathCaseInsensitive = responseDefinitionPath.ToLowerInvariant();
                            if (definitionsCache.ContainsKey(definitionPathCaseInsensitive))
                            {
                                operationData.ResponseType.SpecificationData.Add(definitionsCache[definitionPathCaseInsensitive]);
                                break;
                            }
                        }
                    }
                }
            }

            // Check for x-ms-pageable and set the page type if a response type exists
            JsonPathFinder pageableExtension = path.Find(new JsonQueryBuilder().Property("x-ms-pageable")).SingleOrDefault();

            if (pageableExtension != null && operationData.ResponseType != null)
            {
                string         nextLinkJsonName = "nextLink";
                string         itemsJsonName    = "value";
                JsonPathFinder nextLinkName     = pageableExtension.Find(new JsonQueryBuilder().RecursiveDescent().Property("nextLinkName")).SingleOrDefault();
                JsonPathFinder itemName         = pageableExtension.Find(new JsonQueryBuilder().RecursiveDescent().Property("itemName")).SingleOrDefault();
                if (nextLinkName != null)
                {
                    nextLinkJsonName = nextLinkName.GetValue <string>();
                }

                if (itemName != null)
                {
                    itemsJsonName = itemName.GetValue <string>();
                }

                // Assuming the module is already loaded, find the correct .NET type for the Page
                foreach (Type candidateType in AppDomain.CurrentDomain.GetAssemblies().SelectMany(asm => asm.GetTypes()))
                {
                    PropertyInfo itemsProperty        = candidateType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Where(pi => pi.Name.Equals("Items")).FirstOrDefault();
                    PropertyInfo nextPageLinkProperty = candidateType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Where(pi => pi.Name.Equals("NextPageLink")).FirstOrDefault();
                    bool         candidate            = true;
                    if (itemsProperty != null)
                    {
                        JsonPropertyAttribute jsonPropertyAttribute = (JsonPropertyAttribute)itemsProperty.GetCustomAttribute(typeof(JsonPropertyAttribute));
                        if (jsonPropertyAttribute == null || !jsonPropertyAttribute.PropertyName.Equals(itemsJsonName, StringComparison.OrdinalIgnoreCase))
                        {
                            candidate = false;
                        }
                    }
                    else
                    {
                        candidate = false;
                    }

                    if (candidate && nextPageLinkProperty != null)
                    {
                        JsonPropertyAttribute jsonPropertyAttribute = (JsonPropertyAttribute)nextPageLinkProperty.GetCustomAttribute(typeof(JsonPropertyAttribute));
                        if (jsonPropertyAttribute == null || !jsonPropertyAttribute.PropertyName.Equals(nextLinkJsonName, StringComparison.OrdinalIgnoreCase))
                        {
                            candidate = false;
                        }
                    }
                    else
                    {
                        candidate = false;
                    }

                    if (candidate)
                    {
                        operationData.ResponseType.PageType = candidateType;
                    }
                }

                // Find the correct specification data. If x-ms-pageable is used, the referenced output type is probably an array of items
                // And PSSwagger will output the individual item type rather than the array type
                // Set the output type of the individual item type
                if (!String.IsNullOrEmpty(responseDefinitionPath))
                {
                    JsonPathFinder responseDefinitionNode = rootDoc.Find(new JsonQueryBuilder(responseDefinitionPath)).SingleOrDefault();
                    if (responseDefinitionNode != null)
                    {
                        JsonPathFinder itemType = responseDefinitionNode.Find(new JsonQueryBuilder().RecursiveDescent().Property("$ref")).FirstOrDefault();
                        if (itemType != null)
                        {
                            operationData.ResponseType.SpecificationData.Add(definitionsCache[itemType.GetValue <string>().ToLowerInvariant()]);
                        }
                    }
                }
            }

            return(operationData);
        }