Added Agent locator to locate file agents for specific folders
[pithos-ms-client] / trunk / Pithos.Client.WPF / ShellViewModel.cs
index bde305a..801aba9 100644 (file)
@@ -1,7 +1,9 @@
 using System.Collections.Concurrent;
 using System.ComponentModel.Composition;
 using System.Diagnostics;
+using System.Diagnostics.Contracts;
 using System.IO;
+using System.Net;
 using System.Runtime.InteropServices;
 using System.ServiceModel;
 using System.ServiceModel.Description;
@@ -52,9 +54,7 @@ namespace Pithos.Client.WPF {
             _statusChecker = statusChecker;
             _events = events;            
             Settings = settings;
-            
-            
-
+                                   
             UsageMessage = "Using 15% of 50 GB";
             StatusMessage = "In Synch";
 
@@ -77,7 +77,7 @@ namespace Pithos.Client.WPF {
             if (_monitors.TryGetValue(accountName,out monitor))
             {
                 //If the account is active
-                if (account.IsActive)
+                if (account.IsActive)                    
                     //Start the monitor. It's OK to start an already started monitor,
                     //it will just ignore the call
                     monitor.Start();
@@ -268,7 +268,7 @@ namespace Pithos.Client.WPF {
 
 
        
-        private Task StartMonitor(PithosMonitor monitor)
+        private Task StartMonitor(PithosMonitor monitor,int retries=0)
         {
             return Task.Factory.StartNew(() =>
             {
@@ -277,20 +277,94 @@ namespace Pithos.Client.WPF {
                     try
                     {
                         Log.InfoFormat("Start Monitoring {0}", monitor.UserName);
+
                         monitor.Start();
                     }
+                    catch (WebException exc)
+                    {
+                        if (AbandonRetry(monitor, retries))
+                            return;
+
+                        if (IsUnauthorized(exc))
+                        {
+                            var message = String.Format("API Key Expired for {0}. Starting Renewal",monitor.UserName);                            
+                            Log.Error(message,exc);
+                            TryAuthorize(monitor,retries);
+                        }
+                        else
+                        {
+                            TryLater(monitor, exc,retries);
+                        }
+                    }
                     catch (Exception exc)
                     {
-                        var message =
-                            String.Format("An exception occured. Can't start monitoring\nWill retry in 10 seconds");
-                        Task.Factory.StartNewDelayed(10000, () => StartMonitor(monitor));
-                        _events.Publish(new Notification {Title = "Error", Message = message, Level = TraceLevel.Error});
-                        Log.Error(message, exc);
+                        if (AbandonRetry(monitor, retries)) 
+                            return;
+
+                        TryLater(monitor,exc,retries);
                     }
                 }
             });
         }
 
+        private bool AbandonRetry(PithosMonitor monitor, int retries)
+        {
+            if (retries > 1)
+            {
+                var message = String.Format("Monitoring of account {0} has failed too many times. Will not retry",
+                                            monitor.UserName);
+                _events.Publish(new Notification
+                                    {Title = "Account monitoring failed", Message = message, Level = TraceLevel.Error});
+                return true;
+            }
+            return false;
+        }
+
+
+        private Task TryAuthorize(PithosMonitor monitor,int retries)
+        {
+            _events.Publish(new Notification { Title = "Authorization failed", Message = "Your API Key has probably expired. You will be directed to a page where you can renew it", Level = TraceLevel.Error });
+
+            var authorize= PithosAccount.RetrieveCredentialsAsync(Settings.PithosSite);
+
+            return authorize.ContinueWith(t =>
+            {
+                if (t.IsFaulted)
+                {                    
+                    string message = String.Format("API Key retrieval for {0} failed", monitor.UserName);
+                    Log.Error(message,t.Exception.InnerException);
+                    _events.Publish(new Notification { Title = "Authorization failed", Message = message, Level = TraceLevel.Error });
+                    return;
+                }
+                var credentials = t.Result;
+                var account =Settings.Accounts.FirstOrDefault(act => act.AccountName == credentials.UserName);
+                account.ApiKey = credentials.Password;
+                monitor.ApiKey = credentials.Password;
+                Task.Factory.StartNewDelayed(10000, () => StartMonitor(monitor,retries+1));
+            });
+        }
+
+        private static bool IsUnauthorized(WebException exc)
+        {
+            if (exc==null)
+                throw new ArgumentNullException("exc");
+            Contract.EndContractBlock();
+
+            var response = exc.Response as HttpWebResponse;
+            if (response == null)
+                return false;
+            return (response.StatusCode == HttpStatusCode.Unauthorized);
+        }
+
+        private void TryLater(PithosMonitor monitor, Exception exc,int retries)
+        {
+            var message = String.Format("An exception occured. Can't start monitoring\nWill retry in 10 seconds");
+            Task.Factory.StartNewDelayed(10000, () => StartMonitor(monitor,retries+1));
+            _events.Publish(new Notification
+                                {Title = "Error", Message = message, Level = TraceLevel.Error});
+            Log.Error(message, exc);
+        }
+
 
         public void NotifyChange(string status, TraceLevel level=TraceLevel.Info)
         {