/// <summary>
 /// Saves the configuration root entity to the durable cache.
 /// </summary>
 /// <param name="config">The node to store</param>
 protected void SaveConfigToCache(ConfigRoot config)
 {
     IJsonEntity<ConfigRoot> configEntity = _cacheProvider.Entities.FirstOrDefault(y => y.Contents.ComponentName == _componentName);
     if (configEntity == null)
     {
         configEntity = _cacheProvider.Create();
     }
     configEntity.Contents = config;
     _cacheProvider.Update(configEntity);
     _cacheProvider.Save();
 }
        public void Put_on_empty_repo_returns_404()
        {
            var configRoot = new ConfigRoot
            {
                ComponentName = "tabouli",
                Data = new ConfigNode
                {
                    Name = "tabouli",
                    Value = "tomatoes",
                    Children =
                        new List<ConfigNode> { new ConfigNode { Name = "Side", Value = "Rice" } }
                }
            };

            IRequest request = new InMemoryRequest
            {
                HttpMethod = "PUT",
                Uri = new Uri("http://localhost/Config/tacos")
            };

            request.Headers["Content-Type"] = "application/json";

            var length = WriteConfigRootToStream(request.Entity.Stream, configRoot);
            request.Headers["Content-Length"] = length.ToString(CultureInfo.InvariantCulture);

            var response = _host.ProcessRequest(request);

            Assert.AreEqual(404, response.StatusCode);
        }
        public void Put_with_invalid_content_type_returns_415()
        {
            var entity = _repository.Create();
            entity.Contents = new ConfigRoot
            {
                ComponentName = "taboUli",
                Data = new ConfigNode { Name = "tabouli", Value = "salad" }
            };
            _repository.Add(entity);
            _repository.Save();

            var configRoot = new ConfigRoot
            {
                ComponentName = "tabouLi",
                Data = new ConfigNode
                {
                    Name = "tabouli",
                    Value = "tomatoes",
                    Children =
                        new List<ConfigNode> { new ConfigNode { Name = "Side", Value = "Rice" } }
                }
            };

            IRequest request = new InMemoryRequest
            {
                HttpMethod = "PUT",
                Uri = new Uri("http://localhost/Config/tabouli")
            };
            request.Headers["Content-Type"] = "text/plain";

            var length = WriteConfigRootToStream(request.Entity.Stream, configRoot);
            request.Headers["Content-Length"] = length.ToString(CultureInfo.InvariantCulture);

            var response = _host.ProcessRequest(request);

            Assert.AreEqual(415, response.StatusCode);
        }
        public void If_an_attempt_is_made_to_change_a_name_using_put_make_sure_it_doesnt_overwrite_something_else()
        {
            var entity = _repository.Create();
            entity.Contents = new ConfigRoot
                                  {
                                      ComponentName = "taBouli",
                                      Data = new ConfigNode {Name = "tabouli", Value = "salad"}
                                  };
            _repository.Add(entity);

            var anotherEntity = _repository.Create();
            anotherEntity.Contents = new ConfigRoot
                                         {
                                             ComponentName = "Grapes",
                                             Data = new ConfigNode {Name = "grapes", Value = "wrath"}
                                         };
            _repository.Add(anotherEntity);

            _repository.Save();

            var configRoot = new ConfigRoot
                                 {
                                     ComponentName = "grapeS",
                                     Data = new ConfigNode
                                                {
                                                    Name = "taboulI",
                                                    Value = "tomatoes",
                                                    Children =
                                                        new List<ConfigNode>
                                                            {new ConfigNode {Name = "Side", Value = "Rice"}}
                                                }
                                 };

            IRequest request = new InMemoryRequest
                                   {
                                       HttpMethod = "PUT",
                                       Uri = new Uri("http://localhost/Config/tabouli")
                                   };
            request.Headers["Content-Type"] = "application/json";

            var length = WriteConfigRootToStream(request.Entity.Stream, configRoot);
            request.Headers["Content-Length"] = length.ToString(CultureInfo.InvariantCulture);

            var response = _host.ProcessRequest(request);

            Assert.AreEqual(409, response.StatusCode);
        }
        public void Put_updates_config_root_in_repository()
        {
            var entity = _repository.Create();
            entity.Contents = new ConfigRoot
                                  {
                                      ComponentName = "taboUli",
                                      Data = new ConfigNode {Name = "tabouli", Value = "salad"}
                                  };
            _repository.Add(entity);
            _repository.Save();

            var configRoot = new ConfigRoot
                                 {
                                     ComponentName = "tabouLi",
                                     Data = new ConfigNode
                                                {
                                                    Name = "tabouli",
                                                    Value = "tomatoes",
                                                    Children =
                                                        new List<ConfigNode>
                                                            {new ConfigNode {Name = "Side", Value = "Rice"}}
                                                }
                                 };

            IRequest request = new InMemoryRequest
                                   {
                                       HttpMethod = "PUT",
                                       Uri = new Uri("http://localhost/Config/tabouli")
                                   };
            request.Headers["Content-Type"] = "application/json";

            var length = WriteConfigRootToStream(request.Entity.Stream, configRoot);
            request.Headers["Content-Length"] = length.ToString(CultureInfo.InvariantCulture);

            var response = _host.ProcessRequest(request);

            Assert.AreEqual(200, response.StatusCode);

            var configObj = GetConfigRootFromResponseStream(response.Entity.Stream);

            Assert.IsNotNull(configObj);
            Assert.AreEqual("tabouli", configObj.ComponentName.ToLower());
            Assert.AreEqual("tomatoes", configObj.Data.Value);
            Assert.AreEqual("Rice", configObj.Data.Children[0].Value);
        }
        public void Post_returns_400_if_component_name_is_null()
        {
            var configRoot = new ConfigRoot
            {
                ComponentName = null,
                Data = new ConfigNode
                {
                    Name = string.Empty,
                    Value = string.Empty
                }
            };

            IRequest request = new InMemoryRequest
            {
                HttpMethod = "POST",
                Uri = new Uri("http://localhost/Config")
            };
            request.Headers["Content-Type"] = "application/json";

            var length = WriteConfigRootToStream(request.Entity.Stream, configRoot);
            request.Headers["Content-Length"] = length.ToString(CultureInfo.InvariantCulture);

            var response = _host.ProcessRequest(request);

            Assert.AreEqual(400, response.StatusCode);
        }
 private ConfigRoot CreateCannedEnvironmentConfig()
 {
     ConfigRoot config = new ConfigRoot { ComponentName = "Environment", LastModified = TestDate };
     config.Data = new ConfigNode
                       {
                           Name = "Environment",
                           Children = new List<ConfigNode>
                                          {
                                              new ConfigNode {Name = "RestUrl", Value = _expectedConfig.RestUrl},
                                              new ConfigNode {Name = "ConnectionString", Value = _expectedConfig.ConnectionString},
                                          }
                       };
     return config;
 }
 private long WriteConfigRootToStream(Stream stream, ConfigRoot configRoot)
 {
     using (var sw = new StreamWriter(stream))
     {
         sw.Write(JsonConvert.SerializeObject(configRoot));
     }
     stream.Position = 0;
     return stream.Length;
 }
 private static HttpResponseMessage CreateGoodResponseForSaveOrGetComponent(ConfigRoot configRoot)
 {
     string jsonString = JsonConvert.SerializeObject(configRoot);
     var response = new HttpResponseMessage(HttpStatusCode.OK);
     response.Content = new StringContent(jsonString, Encoding.UTF8, JsonMediaType);
     return response;
 }
 public static ConfigRoot GetConfigRoot(string componentName)
 {
     ConfigRoot root = new ConfigRoot();
     root.ComponentName = componentName;
     root.LastModified = new DateTime(2009, 11, 14);
     var node = new ConfigNode();
     node.Name = root.ComponentName;
     node.Children = new List<ConfigNode>
                         {
                             new ConfigNode {Name = "N1", Value = "V1"},
                             new ConfigNode {Name = "N2", Value = "V2"}
                         };
     root.Data = node;
     return root;
 }
        /// <summary>
        /// Performs an update on an existing Config resource and returns a copy of the saved data if successful.
        /// </summary>
        /// <param name="componentName">The name of the resource to update.  Not case-sensitive.</param>
        /// <param name="config">The new config data to store - overwrites any exsiting data</param>
        /// <returns>
        /// 200 - If update is successful
        /// 409 - If an attempt is made to change the name of an existing resource and that name change would cause it to overwrite another resource (see remarks)
        /// 404 - If the requested resource does not exist
        /// </returns>
        /// <remarks>
        /// This operation allows resource renaming.  If you change the component name in the config JSON, when the operation completes the resource will have a 
        /// new Location returned in the headers, provided that no other resource exists with the same name.
        /// </remarks>
        public OperationResult Put(string componentName, ConfigRoot config)
        {
            _log.Debug("Entering ConfigHandler.Put()");

            try
            {
                var requestedEntity = _repository.Entities.FirstOrDefault(
                    x => x.Contents.ComponentName.ToUpper() == componentName.ToUpper());

                if (requestedEntity == null)
                {
                    _log.Debug(string.Format("Returning 404 Not Found for resource {0}", componentName));
                    return new OperationResult.NotFound();
                }

                if (config.ComponentName == null || Regex.IsMatch(config.ComponentName, @"\W"))
                {
                    return new OperationResult.BadRequest();
                }

                IJsonEntity<ConfigRoot> existingEntity =
                    _repository.Entities.FirstOrDefault(
                        x => x.Contents.ComponentName.ToUpper() == config.ComponentName.ToUpper());
                if (existingEntity != null && config.ComponentName.ToUpper() != componentName.ToUpper())
                {
                    _log.Debug(
                        string.Format(
                            "Returning 409 Conflict for resource {0} - attempted to change name to existing resource {1}",
                            componentName, config.ComponentName));
                    return new ConflictOperationResult();
                }

                requestedEntity.Contents = config;

                _repository.Update(requestedEntity);
                _repository.Save();

                var location = HttpHelper.GetLocation(_request.Uri, config.ComponentName);
                _response.Headers[HttpHelper.LocationHeader] = location.ToString();
                return new OperationResult.OK {ResponseResource = requestedEntity.Contents};
            }
            catch (Exception exception)
            {
                _log.Error(string.Format("Error in Put for component '{0}': {1}", componentName, exception));
                throw;
            }
        }
        /// <summary>
        /// Handles POST for creating new resource.
        /// </summary>
        /// <param name="config">Config root deserialized from JSON in request body</param>
        /// <returns>
        /// 409 Conflict - If config exists for component of same name already in repository
        /// 201 Created - If adding new config succeeds
        /// 500 Internal Server Error - If error occurs
        /// </returns>
        public OperationResult Post(ConfigRoot config)
        {
            _log.Debug("Entering ConfigHandler.Post()");

            try
            {
                IJsonEntity<ConfigRoot> configEntity = _repository.Entities.FirstOrDefault(
                    x => x.Contents.ComponentName.ToLower() == config.ComponentName.ToLower());

                if (configEntity != null)
                {
                    _log.Debug(string.Format("Returning 400 Bad Request for POST to component {0}", config.ComponentName));
                    return new OperationResult.BadRequest();
                }

                if (config.ComponentName == null || Regex.IsMatch(config.ComponentName, @"\W"))
                {
                    _log.Debug(string.Format("Returning 400 Bad Request for POST to component {0}", config.ComponentName));
                    return new OperationResult.BadRequest();
                }

                configEntity = _repository.Create();
                configEntity.Contents = config;

                _repository.Add(configEntity);
                _repository.Save();


                var location = HttpHelper.GetLocation(_request.Uri, config.ComponentName);
                _response.Headers[HttpHelper.LocationHeader] = location.ToString();
                return new OperationResult.Created {ResponseResource = configEntity.Contents};
            }
            catch (Exception exception)
            {
                _log.Error(string.Format("Error in Post for component '{0}': {1}", config != null ? config.ComponentName : null, exception));
                throw;
            }
        }
 private void CreateMockDurableCacheEntry(ConfigRoot configFromMockCache)
 {
     DurableMemoryRepositoryHelper.CreateMockDurableCacheEntry(configFromMockCache, _mockFileSystem, 1, TestPath);
 }
 private ConfigRoot CreateCannedApplicationConfig()
 {
     ConfigRoot config = new ConfigRoot {ComponentName = _applicationConfigProvider.ApplicationComponentName, LastModified = TestDate};
     config.Data = new ConfigNode
                       {
                           Name = _applicationConfigProvider.ApplicationComponentName,
                           Children = new List<ConfigNode>
                                          {
                                              new ConfigNode {Name = "TimeOut", Value = _expectedConfig.Timeout.ToString()},
                                              new ConfigNode
                                                  {
                                                      Name = "ConfigObject",
                                                      Children = new List<ConfigNode>
                                                                     {
                                                                         new ConfigNode {Name = "Name", Value = "Taco"},
                                                                         new ConfigNode {Name = "Number", Value = "6"}
                                                                     }
                                                  }
                                          }
                       };
     return config;
 }
        public void Ensure_that_error_handling_works_for_put()
        {
            // Override the config to give it a broken logger
            /*var mockLogger = new Mock<ILog>();
            mockLogger.Setup(s => s.Debug(It.Is<string>(m => m.Contains("Entering ConfigHandler"))))
                .Throws(new ApplicationException("ha ha!"));*/

            _mockFileSystem = (new MockFileSystemProvider()).MockFileSystem;
            _repository = new DurableMemoryRepository<ConfigRoot>(DataPath, _mockFileSystem.Object);

            var container = new Container();
            container.Configure(x =>
            {
                x.For<IRepository<IJsonEntity<ConfigRoot>>>().Singleton().Use(_repository);
                //x.For<ILog>().Singleton().Use(mockLogger.Object);
            });

            _host = new InMemoryHost(new Configuration(container));

            var configRoot = new ConfigRoot
            {
                ComponentName = "tabOuli",
                Data = new ConfigNode
                {
                    Name = "tabouli",
                    Value = "tomatoes",
                    Children =
                        new List<ConfigNode> { new ConfigNode { Name = "Side", Value = "Rice" } }
                }
            };

            IRequest request = new InMemoryRequest
            {
                HttpMethod = "PUT",
                Uri = new Uri("http://localhost/Config/tacos")
            };

            request.Headers["Content-Type"] = "application/json";
            var length = WriteConfigRootToStream(request.Entity.Stream, configRoot);
            request.Headers["Content-Length"] = length.ToString(CultureInfo.InvariantCulture);

            var response = _host.ProcessRequest(request);

            Assert.AreEqual(500, response.StatusCode);
        }
        public void Put_returns_400_if_component_name_contains_invalid_characters()
        {
            var entity = _repository.Create();
            entity.Contents = new ConfigRoot
            {
                ComponentName = "taboUli",
                Data = new ConfigNode { Name = "tabouli", Value = "salad" }
            };
            _repository.Add(entity);
            _repository.Save();

            var configRoot = new ConfigRoot
            {
                ComponentName = "jsnsadnc sd 8d8*** sad8s7sagd ^Q^ G5asds",
                Data = new ConfigNode
                {
                    Name = string.Empty,
                    Value = string.Empty
                }
            };

            IRequest request = new InMemoryRequest
            {
                HttpMethod = "PUT",
                Uri = new Uri("http://localhost/Config/tabouli")
            };
            request.Headers["Content-Type"] = "application/json";

            var length = WriteConfigRootToStream(request.Entity.Stream, configRoot);
            request.Headers["Content-Length"] = length.ToString(CultureInfo.InvariantCulture);

            var response = _host.ProcessRequest(request);

            Assert.AreEqual(400, response.StatusCode);
        }
 private static HttpResponseMessage CreateGoodResponseForAddNewComponent(ConfigRoot root)
 {
     string jsonString = JsonConvert.SerializeObject(root);
     var response = new HttpResponseMessage(HttpStatusCode.Created);
     response.Headers.Add("location", String.Format("http://config/{0}", root.ComponentName));
     response.Content = new StringContent(jsonString, Encoding.UTF8, JsonMediaType);
     return response;
 }
        public void Post_to_existing_component_config_returns_400()
        {
            // add tabouli to repo
            var entity = _repository.Create();
            entity.Contents = new ConfigRoot
                                  {
                                      ComponentName = "tabouli",
                                      Data = new ConfigNode {Name = "host", Value = "tortilla"}
                                  };
            _repository.Add(entity);
            _repository.Save();

            // create new tabouli config to POST
            var configRoot = new ConfigRoot
                                 {
                                     ComponentName = "tabouli",
                                     Data = new ConfigNode
                                                {
                                                    Name = "tabouli",
                                                    Value = "tomatoes",
                                                    Children =
                                                        new List<ConfigNode>
                                                            {new ConfigNode {Name = "Side", Value = "Rice"}}
                                                }
                                 };

            IRequest request = new InMemoryRequest
                                   {
                                       HttpMethod = "POST",
                                       Uri = new Uri("http://localhost/Config")
                                   };

            request.Headers["Content-Type"] = "application/json";

            var length = WriteConfigRootToStream(request.Entity.Stream, configRoot);
            request.Headers["Content-Length"] = length.ToString(CultureInfo.InvariantCulture);

            var response = _host.ProcessRequest(request);

            Assert.AreEqual(400, response.StatusCode);
        }
        /// <summary>
        /// Builds a factory that knows how to create a Config Provider that acts like the real thing, but doesn't use real caches or service calls.
        /// </summary>
        /// <param name="applicationConfig">The canned application configuration that the provider should use</param>
        /// <param name="environmentConfig">The canned environment configuration that the provider should use</param>
        /// <returns>A mock factory</returns>
        private Mock<IConfigProviderFactory> CreateFactory(ConfigRoot applicationConfig, ConfigRoot environmentConfig)
        {
            var mockConfigServiceProviderForApplication = new Mock<IConfigServiceProvider>(MockBehavior.Strict);
            var cannedApplicationResponse = new ConfigServiceResponse
                                                {
                                                    Config = applicationConfig,
                                                    StatusCode = HttpStatusCode.OK
                                                };
            mockConfigServiceProviderForApplication.Setup(x => x.GetConfig()).Returns(cannedApplicationResponse);
            var mockApplicationConfig = new Mock<IJsonEntity<ConfigRoot>>(MockBehavior.Strict);
            mockApplicationConfig.SetupProperty(x => x.Contents);
            mockApplicationConfig.SetupProperty(x => x.JsonData);
            mockApplicationConfig.Object.Contents = applicationConfig;


            var mockConfigServiceProviderForEnvironment = new Mock<IConfigServiceProvider>(MockBehavior.Strict);
            var cannedEnvironmentResponse = new ConfigServiceResponse
                                                {
                                                    Config = environmentConfig,
                                                    StatusCode = HttpStatusCode.OK
                                                };
            mockConfigServiceProviderForEnvironment.Setup(x => x.GetConfig()).Returns(cannedEnvironmentResponse);
            var mockEnvironmentConfig = new Mock<IJsonEntity<ConfigRoot>>(MockBehavior.Strict);
            mockEnvironmentConfig.SetupProperty(x => x.Contents);
            mockEnvironmentConfig.SetupProperty(x => x.JsonData);
            mockEnvironmentConfig.Object.Contents = environmentConfig;


            var mockFactory = new Mock<IConfigProviderFactory>(MockBehavior.Strict);

            var cacheProvider = new Mock<IRepository<IJsonEntity<ConfigRoot>>>(MockBehavior.Strict);
            cacheProvider.SetupAllProperties();
            cacheProvider.SetupGet(x => x.Entities).Returns(new[] {mockApplicationConfig.Object, mockEnvironmentConfig.Object}.AsQueryable());
            cacheProvider.Setup(x => x.Save());
            cacheProvider.Setup(x => x.Update(It.IsAny<IJsonEntity<ConfigRoot>>()));

            mockFactory.Setup(
                x => x.Create(_applicationConfigProvider.ApplicationComponentName, It.IsAny<Dictionary<string, Func<string, bool>>>()))
                .Returns<string, Dictionary<string, Func<string, bool>>>((name, validators) => { return new ConfigProvider(name, validators, mockConfigServiceProviderForApplication.Object, cacheProvider.Object); });

            mockFactory.Setup(
                x => x.Create("Environment", It.IsAny<Dictionary<string, Func<string, bool>>>()))
                .Returns<string, Dictionary<string, Func<string, bool>>>((name, validators) => { return new ConfigProvider(name, validators, mockConfigServiceProviderForEnvironment.Object, cacheProvider.Object); });


            return mockFactory;
        }