public void ConvertFromDictionaryParametersToSchedulerPluginConfigurationBaseSucceeds()
        {
            var uri = new Uri("http://www.example.com/");
            var credentials = CredentialCache.DefaultNetworkCredentials;
            var appclusiveEndpoints = new AppclusiveEndpoints(uri, credentials);

            var sut = new DictionaryParameters();
            sut.Add(typeof(AppclusiveEndpoints).ToString(), appclusiveEndpoints);

            // Act
            var result = SchedulerPluginConfigurationBase.Convert<SchedulerPluginConfigurationBase>(sut);

            // Assert
            Assert.IsTrue(result.IsValid());
            Assert.IsNotNull(result.Endpoints);
        }
        public List<ScheduledJob> GetJobs(AppclusiveEndpoints endpoints)
        {
            Contract.Requires(null != endpoints);
            Contract.Ensures(null != Contract.Result<List<ScheduledJob>>());

            try
            {
                var scheduledJobs = new List<ScheduledJob>();

                var entities = endpoints.Core.ScheduledJobs.Execute() as QueryOperationResponse<ScheduledJob>;
                while(null != entities)
                {
                    foreach (var entity in entities)
                    {
                        scheduledJobs.Add(entity);
                        Contract.Assert(ScheduledJobsWorker.SCHEDULED_JOBS_WORKER_JOBS_PER_INSTANCE_MAX >= scheduledJobs.Count);
                    }

                    var dataServiceQueryContinuation = entities.GetContinuation();
                    if (null != dataServiceQueryContinuation)
                    {
                        entities = endpoints.Core.Execute(dataServiceQueryContinuation);
                    }
                    else
                    {
                        entities = null;
                    }
                }
                
                return scheduledJobs;
            }
            catch (DataServiceQueryException ex)
            {
                if(null == ex.InnerException || !(ex.InnerException is DataServiceClientException))
                {
                    throw;
                }

                var exInner = (DataServiceClientException) ex.InnerException;
                var message = string.Format("Loading ScheduledJobs from '{0}' FAILED with DataServiceClientException. The StatusCode was {1}. '{2}'", endpoints.Core.BaseUri.AbsoluteUri, exInner.StatusCode, exInner.Message);
                Trace.WriteException(message, ex);
                throw;
            }
        }
        public void ConvertToDictionaryParametersFromSchedulerPluginConfigurationBaseSucceeds()
        {
            var uri = new Uri("http://www.example.com/");
            var credentials = CredentialCache.DefaultNetworkCredentials;
            var appclusiveEndpoints = new AppclusiveEndpoints(uri, credentials);
            var keyName = appclusiveEndpoints.GetType().FullName;

            var sut = new SchedulerPluginConfigurationBase()
            {
                Endpoints = appclusiveEndpoints
            };
            Assert.IsTrue(sut.IsValid());

            // Act
            var result = sut.Convert();

            // Assert
            Assert.IsTrue(result.ContainsKey(keyName));
            Assert.AreEqual(appclusiveEndpoints, result.Get(keyName));
        }
        public ScheduledJobsWorker(ScheduledJobsWorkerConfiguration configuration)
        {
            Contract.Requires(configuration.IsValid());

            this.configuration = configuration;

            Trace.WriteLine(Method.fn());

            var result = false;

            try
            {
                Trace.WriteLine("Uri: '{0}'", configuration.Uri.AbsoluteUri, "");

                // connect to Appclusive server
                var baseUri = new Uri(string.Format("{0}api", configuration.Uri.AbsoluteUri));
                endpoints = new AppclusiveEndpoints(baseUri, configuration.Credential);

                // initialise each plugin
                foreach (var plugin in configuration.Plugins)
                {
                    try
                    {
                        Trace.WriteLine("Initialising plugin '{0}' [{1}, {2}] ...", plugin.Metadata.Type, plugin.Metadata.Role, plugin.Metadata.Priority);

                        var pluginParameters = new DictionaryParameters
                        {
                            {typeof(AppclusiveEndpoints).ToString(), endpoints}
                        };
                        plugin.Value.Initialise(pluginParameters, configuration.Logger, true);

                        Trace.WriteLine
                        (
                            "Initialising plugin '{0}' [{1}, {2}] COMPLETED. IsInitialised {3}. IsActive {4}."
                            , 
                            plugin.Metadata.Type, plugin.Metadata.Role, plugin.Metadata.Priority
                            ,
                            plugin.Value.IsInitialised, plugin.Value.IsActive
                        );
                    }
                    catch (Exception ex)
                    {
                        var message = string.Format("Initialising plugin '{0}' [{1}, {2}] FAILED.", plugin.Metadata.Type, plugin.Metadata.Role, plugin.Metadata.Priority);
                        Trace.WriteException(message, ex);
                    }
                }

                // get all defined scheduled jobs for all tenants (based on credentials)
                result = GetScheduledJobs();

                // create the timer to process all scheduled jobs periodically
                stateTimer = new ScheduledJobsWorkerTimerFactory().CreateTimer(new TimerCallback(RunJobs), null, 1000, 1000 * 60);
            }
            catch (Exception ex)
            {
                Trace.WriteException(ex.Message, ex);
                throw;
            }

            this.isInitialised = result;
            this.IsActive = result;
        
            return;
        }
        public bool GetScheduledJobs()
        {
            var result = false;

            if (isInitialised && !IsActive)
            {
                configuration.Logger.Warn("Scheduler is not initialised [{0}] or not active [{1}]. Skip loading of ScheduledJobs.", isInitialised, IsActive);
                goto Success;
            }
            
            // load ScheduledJob entities
            try
            {
                // connect to Appclusive server
                var baseUri = new Uri(string.Format("{0}api", configuration.Uri.AbsoluteUri));
                endpoints = new AppclusiveEndpoints(baseUri, configuration.Credential);

                configuration.Logger.Info("Loading ScheduledJobs from '{0}' ...", endpoints.Core.BaseUri.AbsoluteUri);
                var scheduledJobsManager = new ScheduledJobsManager(endpoints);

                var allScheduledJobs = scheduledJobsManager.GetJobs();
                var validScheduledJobs = scheduledJobsManager.GetValidJobs(allScheduledJobs);
                Contract.Assert(SCHEDULED_JOBS_WORKER_JOBS_PER_INSTANCE_MAX >= validScheduledJobs.Count);

                lock (_lock)
                {
                    foreach (var job in validScheduledJobs)
                    {
                        var existingJob = _scheduledJobs.FirstOrDefault(e => e.Id == job.Id);
                        if (null == existingJob)
                        {
                            Trace.WriteLine("Added  : Id {0} ('{1}'): '{2}'.", job.Id, job.Crontab, job.Modified.ToString("yyyy-MM-dd HH:mm:sszzz"));
                            continue;
                        }
                        
                        if (!existingJob.Crontab.Equals(job.Crontab))
                        {
                            Trace.WriteLine("Updated: Id {0} ('{1}'): '{2}'.", job.Id, job.Crontab, job.Modified.ToString("yyyy-MM-dd HH:mm:sszzz"));
                        }
                    }

                    _scheduledJobs = validScheduledJobs.ToList();
                }
            
                configuration.Logger.Info("Loading ScheduledJobs from '{0}' SUCCEEDED. [{1}]", endpoints.Core.BaseUri.AbsoluteUri, allScheduledJobs.Count);

                result = true;
            }
            catch(InvalidOperationException ex)
            {
                var message = string.Format("Loading ScheduledJobs from '{0}' FAILED with InvalidOperationException. Check the specified credentials.", endpoints.Core.BaseUri.AbsoluteUri);
                Trace.WriteException(message, ex);

                result = false;
            }
            catch (Exception ex)
            {
                Trace.WriteException(ex.Message, ex);
                
                throw;
            }

Success:
            lastUpdated = DateTimeOffset.Now;
            return result;
        }
        public PowerShellScriptPluginConfigurationManager(AppclusiveEndpoints endpoints)
        {
            Contract.Requires(null != endpoints);

            appclusiveEndpoints = endpoints;
        }