From f0ea06df7e0f8476296d4fa30ef9212172a997aa Mon Sep 17 00:00:00 2001
From: Robert Goldmann <deadlocker@gmx.de>
Date: Sat, 13 May 2017 17:13:21 +0200
Subject: [PATCH] Fixed #90 - better connection error handling (improve
 messages)

---
 .../budgetmaster/logic/ExceptionHandler.java  |  35 +++++
 .../budgetmaster/logic/ServerConnection.java  | 148 +++++++++++++-----
 .../logic/ServerConnectionException.java      |  31 ++++
 .../budgetmaster/ui/CategoryController.java   |   3 +-
 .../budgetmaster/ui/Controller.java           |   5 +-
 .../ui/NewCategoryController.java             |   3 +-
 .../budgetmaster/ui/NewPaymentController.java |   5 +-
 .../budgetmaster/ui/PaymentController.java    |   7 +-
 .../budgetmaster/ui/SettingsController.java   |  19 ++-
 9 files changed, 205 insertions(+), 51 deletions(-)
 create mode 100644 src/de/deadlocker8/budgetmaster/logic/ExceptionHandler.java
 create mode 100644 src/de/deadlocker8/budgetmaster/logic/ServerConnectionException.java

diff --git a/src/de/deadlocker8/budgetmaster/logic/ExceptionHandler.java b/src/de/deadlocker8/budgetmaster/logic/ExceptionHandler.java
new file mode 100644
index 000000000..65c70667a
--- /dev/null
+++ b/src/de/deadlocker8/budgetmaster/logic/ExceptionHandler.java
@@ -0,0 +1,35 @@
+package de.deadlocker8.budgetmaster.logic;
+
+public class ExceptionHandler
+{
+	public static String getMessageForException(Exception e)
+	{
+		if(e instanceof ServerConnectionException)
+		{
+			return handleServerConnectionException(e);
+		}		
+		
+		if(e.getMessage().contains("Connection refused"))
+		{
+			return "Server nicht erreichbar.";
+		}
+		else if(e.getMessage().contains("HTTPS hostname wrong"))
+		{
+			return "Der Server verwendet ein selbst signiertes Zertifkat für die Verschlüsselung. "
+					+ "Aus Sicherheitsgründen werden diese Zertifikate standardmäßig blockiert. "
+					+ "Wenn du dem Zertifikat trotzdem vertrauen möchtest, dann füge den Hostnamen des Servers zur Liste der vertrauenswürdigen Hosts in den Einstellungen hinzu.";
+		}
+		return e.getMessage();
+	}
+	
+	private static String handleServerConnectionException(Exception e)
+	{
+		switch(e.getMessage())
+		{
+			case "400": return "Der Server erhielt eine fehlerhafte Anfrage oder ungültige Parameter.";
+			case "401": return "Ungültiges Passwort.";
+			case "500": return "Beim Ausführen der Anfrage ist ein interner Serverfehler ist aufgetreten.";
+			default: return e.getMessage();
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/de/deadlocker8/budgetmaster/logic/ServerConnection.java b/src/de/deadlocker8/budgetmaster/logic/ServerConnection.java
index a603722b4..ed2c7b145 100644
--- a/src/de/deadlocker8/budgetmaster/logic/ServerConnection.java
+++ b/src/de/deadlocker8/budgetmaster/logic/ServerConnection.java
@@ -76,7 +76,7 @@ public class ServerConnection
 		}
 		else
 		{
-			return null;
+			return new ArrayList<>();
 		}
 	}
 
@@ -104,9 +104,16 @@ public class ServerConnection
 		HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection();
 		httpsCon.setRequestMethod("POST");
 		httpsCon.setDoInput(true);
-		InputStream stream = httpsCon.getInputStream();
-		BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
-		reader.close();
+		if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK)
+		{
+			InputStream stream = httpsCon.getInputStream();
+			BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
+			reader.close();
+		}
+		else
+		{
+			throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode()));
+		}		
 	}
 
 	public void updateCategory(Category category) throws Exception
@@ -115,9 +122,16 @@ public class ServerConnection
 		HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection();
 		httpsCon.setRequestMethod("PUT");
 		httpsCon.setDoInput(true);
-		InputStream stream = httpsCon.getInputStream();
-		BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
-		reader.close();
+		if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK)
+		{
+			InputStream stream = httpsCon.getInputStream();
+			BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
+			reader.close();
+		}
+		else
+		{
+			throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode()));
+		}	
 	}
 
 	public void deleteCategory(int ID) throws Exception
@@ -126,9 +140,16 @@ public class ServerConnection
 		HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection();
 		httpsCon.setRequestMethod("DELETE");
 		httpsCon.setDoInput(true);
-		InputStream stream = httpsCon.getInputStream();
-		BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
-		reader.close();
+		if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK)
+		{
+			InputStream stream = httpsCon.getInputStream();
+			BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
+			reader.close();
+		}
+		else
+		{
+			throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode()));
+		}
 	}
 
 	/*
@@ -140,7 +161,7 @@ public class ServerConnection
 		HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection();
 		httpsCon.setDoOutput(true);
 		httpsCon.setRequestMethod("GET");
-
+			
 		if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK)
 		{
 			String result = Read.getStringFromInputStream(httpsCon.getInputStream());
@@ -152,7 +173,7 @@ public class ServerConnection
 		}
 		else
 		{
-			return null;
+			throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode()));
 		}
 	}
 
@@ -174,7 +195,7 @@ public class ServerConnection
 		}
 		else
 		{
-			return null;
+			throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode()));
 		}
 	}
 
@@ -192,7 +213,7 @@ public class ServerConnection
 		}
 		else
 		{
-			return null;
+			throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode()));
 		}
 	}
 
@@ -203,9 +224,16 @@ public class ServerConnection
 		HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection();
 		httpsCon.setRequestMethod("POST");
 		httpsCon.setDoInput(true);
-		InputStream stream = httpsCon.getInputStream();
-		BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
-		reader.close();
+		if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK)
+		{
+			InputStream stream = httpsCon.getInputStream();
+			BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
+			reader.close();
+		}
+		else
+		{
+			throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode()));
+		}
 	}
 
 	public void updateNormalPayment(NormalPayment payment) throws Exception
@@ -215,9 +243,16 @@ public class ServerConnection
 		HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection();
 		httpsCon.setRequestMethod("PUT");
 		httpsCon.setDoInput(true);
-		InputStream stream = httpsCon.getInputStream();
-		BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
-		reader.close();
+		if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK)
+		{
+			InputStream stream = httpsCon.getInputStream();
+			BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
+			reader.close();
+		}
+		else
+		{
+			throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode()));
+		}
 	}
 
 	public void addRepeatingPayment(RepeatingPayment payment) throws Exception
@@ -234,9 +269,16 @@ public class ServerConnection
 		HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection();
 		httpsCon.setRequestMethod("POST");
 		httpsCon.setDoInput(true);
-		InputStream stream = httpsCon.getInputStream();
-		BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
-		reader.close();
+		if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK)
+		{
+			InputStream stream = httpsCon.getInputStream();
+			BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
+			reader.close();
+		}
+		else
+		{
+			throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode()));
+		}
 	}
 
 	public void deleteNormalPayment(NormalPayment payment) throws Exception
@@ -245,9 +287,16 @@ public class ServerConnection
 		HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection();
 		httpsCon.setRequestMethod("DELETE");
 		httpsCon.setDoInput(true);
-		InputStream stream = httpsCon.getInputStream();
-		BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
-		reader.close();
+		if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK)
+		{
+			InputStream stream = httpsCon.getInputStream();
+			BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
+			reader.close();
+		}
+		else
+		{
+			throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode()));
+		}
 	}
 
 	public void deleteRepeatingPayment(RepeatingPaymentEntry payment) throws Exception
@@ -256,9 +305,16 @@ public class ServerConnection
 		HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection();
 		httpsCon.setRequestMethod("DELETE");
 		httpsCon.setDoInput(true);
-		InputStream stream = httpsCon.getInputStream();
-		BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
-		reader.close();
+		if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK)
+		{
+			InputStream stream = httpsCon.getInputStream();
+			BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
+			reader.close();
+		}
+		else
+		{
+			throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode()));
+		}
 	}
 
 	/*
@@ -282,7 +338,7 @@ public class ServerConnection
 		}
 		else
 		{
-			return null;
+			throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode()));
 		}
 	}
 
@@ -303,7 +359,7 @@ public class ServerConnection
 		}
 		else
 		{
-			return 0;
+			throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode()));
 		}
 	}
 
@@ -316,9 +372,16 @@ public class ServerConnection
 		HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection();
 		httpsCon.setRequestMethod("DELETE");
 		httpsCon.setDoInput(true);
-		InputStream stream = httpsCon.getInputStream();
-		BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
-		reader.close();
+		if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK)
+		{
+			InputStream stream = httpsCon.getInputStream();
+			BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
+			reader.close();
+		}
+		else
+		{
+			throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode()));
+		}		
 	}
 
 	public String exportDatabase() throws Exception
@@ -334,7 +397,7 @@ public class ServerConnection
 		}
 		else
 		{
-			return null;
+			throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode()));
 		}
 	}
 
@@ -346,9 +409,16 @@ public class ServerConnection
 //		URL url = new URL(settings.getUrl() + "/database?secret=" + Helpers.getURLEncodedString(settings.getSecret()));
 //		HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection();
 //		httpsCon.setRequestMethod("POST");
-//		httpsCon.setDoInput(true);		
-//		InputStream stream = httpsCon.getInputStream();
-//		BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
-//		reader.close();
+//		httpsCon.setDoInput(true);	
+//		if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK)
+//		{
+//			InputStream stream = httpsCon.getInputStream();
+//			BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
+//			reader.close();
+//		}
+//		else
+//		{
+//			throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode()));
+//		}
 	}
 }
\ No newline at end of file
diff --git a/src/de/deadlocker8/budgetmaster/logic/ServerConnectionException.java b/src/de/deadlocker8/budgetmaster/logic/ServerConnectionException.java
new file mode 100644
index 000000000..c18a1663b
--- /dev/null
+++ b/src/de/deadlocker8/budgetmaster/logic/ServerConnectionException.java
@@ -0,0 +1,31 @@
+package de.deadlocker8.budgetmaster.logic;
+
+public class ServerConnectionException extends Exception
+{
+	private static final long serialVersionUID = 2784475774757068549L;
+
+	public ServerConnectionException()
+	{
+		super();	
+	}
+
+	public ServerConnectionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace)
+	{
+		super(message, cause, enableSuppression, writableStackTrace);		
+	}
+
+	public ServerConnectionException(String message, Throwable cause)
+	{
+		super(message, cause);
+	}
+
+	public ServerConnectionException(String message)
+	{
+		super(message);
+	}
+
+	public ServerConnectionException(Throwable cause)
+	{
+		super(cause);
+	}
+}
\ No newline at end of file
diff --git a/src/de/deadlocker8/budgetmaster/ui/CategoryController.java b/src/de/deadlocker8/budgetmaster/ui/CategoryController.java
index 33cbba28c..52e908a7f 100644
--- a/src/de/deadlocker8/budgetmaster/ui/CategoryController.java
+++ b/src/de/deadlocker8/budgetmaster/ui/CategoryController.java
@@ -5,6 +5,7 @@ import java.io.IOException;
 import java.util.ArrayList;
 
 import de.deadlocker8.budgetmaster.logic.Category;
+import de.deadlocker8.budgetmaster.logic.ExceptionHandler;
 import de.deadlocker8.budgetmaster.logic.ServerConnection;
 import de.deadlocker8.budgetmaster.ui.cells.CategoryCell;
 import fontAwesome.FontIcon;
@@ -162,7 +163,7 @@ public class CategoryController implements Refreshable
 		catch(Exception e)
 		{
 			e.printStackTrace();
-			controller.showConnectionErrorAlert(e.getMessage());
+			controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e));
 		}
 	}
 	
diff --git a/src/de/deadlocker8/budgetmaster/ui/Controller.java b/src/de/deadlocker8/budgetmaster/ui/Controller.java
index 0e4f6d278..98ce6f6c0 100644
--- a/src/de/deadlocker8/budgetmaster/ui/Controller.java
+++ b/src/de/deadlocker8/budgetmaster/ui/Controller.java
@@ -9,6 +9,7 @@ import org.joda.time.DateTime;
 
 import de.deadlocker8.budgetmaster.logic.CategoryBudget;
 import de.deadlocker8.budgetmaster.logic.CategoryHandler;
+import de.deadlocker8.budgetmaster.logic.ExceptionHandler;
 import de.deadlocker8.budgetmaster.logic.FilterSettings;
 import de.deadlocker8.budgetmaster.logic.NormalPayment;
 import de.deadlocker8.budgetmaster.logic.PaymentHandler;
@@ -333,8 +334,8 @@ public class Controller
 		catch(Exception e)
 		{
 			Logger.error(e);
-			categoryHandler = new CategoryHandler(null);					
-			showConnectionErrorAlert(e.getMessage());
+			categoryHandler = new CategoryHandler(null);	
+			showConnectionErrorAlert(ExceptionHandler.getMessageForException(e));
 		}
 
 		refreshAllTabs();		
diff --git a/src/de/deadlocker8/budgetmaster/ui/NewCategoryController.java b/src/de/deadlocker8/budgetmaster/ui/NewCategoryController.java
index b38c067cb..d0ab8dd13 100644
--- a/src/de/deadlocker8/budgetmaster/ui/NewCategoryController.java
+++ b/src/de/deadlocker8/budgetmaster/ui/NewCategoryController.java
@@ -6,6 +6,7 @@ import org.controlsfx.control.PopOver;
 import org.controlsfx.control.PopOver.ArrowLocation;
 
 import de.deadlocker8.budgetmaster.logic.Category;
+import de.deadlocker8.budgetmaster.logic.ExceptionHandler;
 import de.deadlocker8.budgetmaster.logic.ServerConnection;
 import fontAwesome.FontIcon;
 import fontAwesome.FontIconType;
@@ -153,7 +154,7 @@ public class NewCategoryController
 			}
 			catch(Exception e)
 			{
-				controller.showConnectionErrorAlert(e.getMessage());
+				controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e));
 			}			
 		}
 		else
diff --git a/src/de/deadlocker8/budgetmaster/ui/NewPaymentController.java b/src/de/deadlocker8/budgetmaster/ui/NewPaymentController.java
index fb605bc18..99218826d 100644
--- a/src/de/deadlocker8/budgetmaster/ui/NewPaymentController.java
+++ b/src/de/deadlocker8/budgetmaster/ui/NewPaymentController.java
@@ -6,6 +6,7 @@ import java.util.ArrayList;
 import org.joda.time.DateTime;
 
 import de.deadlocker8.budgetmaster.logic.Category;
+import de.deadlocker8.budgetmaster.logic.ExceptionHandler;
 import de.deadlocker8.budgetmaster.logic.Helpers;
 import de.deadlocker8.budgetmaster.logic.NormalPayment;
 import de.deadlocker8.budgetmaster.logic.Payment;
@@ -139,7 +140,7 @@ public class NewPaymentController
 		}
 		catch(Exception e)
 		{
-			controller.showConnectionErrorAlert(e.getMessage());
+			controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e));
 			stage.close();
 			return;
 		}
@@ -315,7 +316,7 @@ public class NewPaymentController
 				catch(Exception e)
 				{
 					Logger.error(e);
-					controller.showConnectionErrorAlert(e.getMessage());
+					controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e));
 				}
 			}
 			else
diff --git a/src/de/deadlocker8/budgetmaster/ui/PaymentController.java b/src/de/deadlocker8/budgetmaster/ui/PaymentController.java
index af23540c6..c4b7cc52c 100644
--- a/src/de/deadlocker8/budgetmaster/ui/PaymentController.java
+++ b/src/de/deadlocker8/budgetmaster/ui/PaymentController.java
@@ -4,6 +4,7 @@ import java.io.IOException;
 import java.util.ArrayList;
 
 import de.deadlocker8.budgetmaster.logic.Budget;
+import de.deadlocker8.budgetmaster.logic.ExceptionHandler;
 import de.deadlocker8.budgetmaster.logic.FilterSettings;
 import de.deadlocker8.budgetmaster.logic.Helpers;
 import de.deadlocker8.budgetmaster.logic.NormalPayment;
@@ -205,7 +206,7 @@ public class PaymentController implements Refreshable
 		catch(Exception e)
 		{
 			e.printStackTrace();
-			controller.showConnectionErrorAlert(e.getMessage());
+			controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e));
 		}
 	}
 
@@ -220,7 +221,7 @@ public class PaymentController implements Refreshable
 		catch(Exception e)
 		{
 			e.printStackTrace();
-			controller.showConnectionErrorAlert(e.getMessage());
+			controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e));
 		}
 	}
 
@@ -239,7 +240,7 @@ public class PaymentController implements Refreshable
 		catch(Exception e)
 		{
 			e.printStackTrace();
-			controller.showConnectionErrorAlert(e.getMessage());
+			controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e));
 		}
 	}
 	
diff --git a/src/de/deadlocker8/budgetmaster/ui/SettingsController.java b/src/de/deadlocker8/budgetmaster/ui/SettingsController.java
index c66d001ae..c96a8494d 100644
--- a/src/de/deadlocker8/budgetmaster/ui/SettingsController.java
+++ b/src/de/deadlocker8/budgetmaster/ui/SettingsController.java
@@ -5,6 +5,7 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Optional;
 
+import de.deadlocker8.budgetmaster.logic.ExceptionHandler;
 import de.deadlocker8.budgetmaster.logic.Helpers;
 import de.deadlocker8.budgetmaster.logic.ServerConnection;
 import de.deadlocker8.budgetmaster.logic.Settings;
@@ -215,7 +216,11 @@ public class SettingsController
 				{
 					Logger.error(e);
 					Platform.runLater(() -> {
-						controller.showConnectionErrorAlert(e.getMessage());
+						if(modalStage != null)
+						{
+							modalStage.close();
+						}
+						controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e));						
 					});
 				}
 			});
@@ -268,7 +273,11 @@ public class SettingsController
 				{
 					Logger.error(e);
 					Platform.runLater(() -> {
-						controller.showConnectionErrorAlert(e.getMessage());
+						if(modalStage != null)
+						{
+							modalStage.close();
+						}
+						controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e));
 					});
 				}
 			});
@@ -345,7 +354,11 @@ public class SettingsController
 					{
 						Logger.error(e);
 						Platform.runLater(() -> {
-							controller.showConnectionErrorAlert(e.getMessage());
+							if(modalStage != null)
+							{
+								modalStage.close();
+							}
+							controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e));
 						});
 					}
 				});
-- 
GitLab