From 42b7438f6fd7dc675d98c3e20d63a44e7a0a16b4 Mon Sep 17 00:00:00 2001
From: Timm Fitschen <timm.fitschen@ds.mpg.de>
Date: Wed, 27 Mar 2019 11:09:03 +0100
Subject: [PATCH] EHN: set timezone with various methods

---
 conf/core/server.conf                         |  3 +-
 src/main/java/caosdb/server/CaosDBServer.java | 61 +++++++++++++++++--
 .../java/caosdb/server/ServerProperties.java  |  1 +
 .../caosdb/server/utils/FileUtilsTest.java    | 20 +++---
 4 files changed, 70 insertions(+), 15 deletions(-)

diff --git a/conf/core/server.conf b/conf/core/server.conf
index 78a7605b..d67e6988 100644
--- a/conf/core/server.conf
+++ b/conf/core/server.conf
@@ -1,3 +1,4 @@
+TIMEZONE=
 SERVER_OWNER=
 SERVER_NAME=CaosDB Server
 SERVER_SIDE_SCRIPTING_BIN_DIR=./scripting/bin/
@@ -16,7 +17,7 @@ MYSQL_DATABASE_NAME=caosdb
 MYSQL_USER_NAME=caosdb
 MYSQL_USER_PASSWORD=caosdb
 
-MYSQL_SCHEMA_VERSION=v2.1.0
+MYSQL_SCHEMA_VERSION=v2.1.1
 
 CONTEXT_ROOT=
 
diff --git a/src/main/java/caosdb/server/CaosDBServer.java b/src/main/java/caosdb/server/CaosDBServer.java
index ce4d2362..078e73ff 100644
--- a/src/main/java/caosdb/server/CaosDBServer.java
+++ b/src/main/java/caosdb/server/CaosDBServer.java
@@ -64,6 +64,7 @@ import caosdb.server.utils.FileUtils;
 import caosdb.server.utils.Initialization;
 import caosdb.server.utils.NullPrintStream;
 import caosdb.server.utils.Utils;
+import com.ibm.icu.util.TimeZone;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -101,8 +102,6 @@ import org.restlet.routing.TemplateRoute;
 import org.restlet.routing.Variable;
 import org.restlet.util.Series;
 
-import com.ibm.icu.util.TimeZone;
-
 public class CaosDBServer extends Application {
 
   private static Logger logger = Logger.getLogger(CaosDBServer.class.getName());
@@ -123,6 +122,59 @@ public class CaosDBServer extends Application {
     SERVER_PROPERTIES = ServerProperties.initServerProperties();
   }
 
+  /**
+   * Precedence order:
+   *
+   * <p>1) ServerProperty "TIMEZONE" 2) JVM property "user.timezone" 3) Environment variable "TZ" 4)
+   * Output of posix' "date +%Z"
+   *
+   * @throws InterruptedException
+   * @throws IOException
+   */
+  public static void initTimeZone() throws InterruptedException, IOException {
+    String serverProperty = getServerProperty(ServerProperties.KEY_TIMEZONE);
+    if (serverProperty != null && !serverProperty.isEmpty()) {
+      logger.config("SET TIMEZONE = " + serverProperty);
+      TimeZone.setDefault(TimeZone.getTimeZone(serverProperty));
+      return;
+    }
+
+    String prop = System.getProperty("user.timezone");
+    if (prop != null && !prop.isEmpty()) {
+      logger.config("SET TIMEZONE = " + prop);
+      TimeZone.setDefault(TimeZone.getTimeZone(prop));
+      return;
+    }
+
+    String envVar = System.getenv("TZ");
+    if (envVar != null && !envVar.isEmpty()) {
+      logger.config("SET TIMEZONE = " + envVar);
+      TimeZone.setDefault(TimeZone.getTimeZone(envVar));
+      return;
+    }
+
+    String fromDate = getTimeZoneFromDate();
+    if (fromDate != null && fromDate.isEmpty()) {
+      logger.config("SET TIMEZONE = " + fromDate);
+      TimeZone.setDefault(TimeZone.getTimeZone(fromDate));
+      return;
+    }
+
+    logger.warning("COULD NOT SET TIMEZONE. DEFAULTS TO " + TimeZone.getDefault());
+  }
+
+  private static String getTimeZoneFromDate() throws InterruptedException, IOException {
+    final Process cmd = Runtime.getRuntime().exec(new String[] {"date", "+%Z"});
+
+    if (cmd.waitFor() == 0) {
+      return Utils.InputStream2String(cmd.getInputStream());
+    }
+    logger.warning(
+        "Could not determine time zone from `date +%Z`. The command returned with exit code "
+            + cmd.exitValue());
+    return null;
+  }
+
   /**
    * This main method starts up a web application that will listen on a port defined in the config
    * file.
@@ -138,9 +190,10 @@ public class CaosDBServer extends Application {
     logger.info("TimeZone: " + TimeZone.getDefault());
     try {
       initServerProperties();
-    } catch (IOException e1) {
+      initTimeZone();
+    } catch (IOException | InterruptedException e1) {
       e1.printStackTrace();
-      System.err.println("Could not read config files.");
+      System.err.println("Could not configure the server.");
       System.exit(1);
     }
     boolean startGui = true;
diff --git a/src/main/java/caosdb/server/ServerProperties.java b/src/main/java/caosdb/server/ServerProperties.java
index 3543d9c3..701f22c8 100644
--- a/src/main/java/caosdb/server/ServerProperties.java
+++ b/src/main/java/caosdb/server/ServerProperties.java
@@ -127,6 +127,7 @@ public class ServerProperties extends Properties {
   public static final String KEY_CHECK_ENTITY_ACL_ROLES_MODE = "CHECK_ENTITY_ACL_ROLES_MODE";
 
   public static final String KEY_GLOBAL_ENTITY_PERMISSIONS_FILE = "GLOBAL_ENTITY_PERMISSIONS_FILE";
+  public static final String KEY_TIMEZONE = "TIMEZONE";
 
   /**
    * Read the config files and initialize the server properties.
diff --git a/src/test/java/caosdb/server/utils/FileUtilsTest.java b/src/test/java/caosdb/server/utils/FileUtilsTest.java
index 7f6e0d4d..4d5262fc 100644
--- a/src/test/java/caosdb/server/utils/FileUtilsTest.java
+++ b/src/test/java/caosdb/server/utils/FileUtilsTest.java
@@ -68,16 +68,16 @@ public class FileUtilsTest {
 
   @BeforeClass
   public static void setup() throws Message, IOException {
-	Assert.assertTrue(new File(FileSystem.getBasepath()).canWrite());
-	Assert.assertTrue(new File(FileSystem.getBasepath()).canRead());
-	Assert.assertTrue(new File(FileSystem.getBasepath()).canExecute());
-	Assert.assertTrue(new File(FileSystem.getTmp()).canWrite());
-	Assert.assertTrue(new File(FileSystem.getTmp()).canRead());
-	Assert.assertTrue(new File(FileSystem.getTmp()).canExecute());
-	Assert.assertTrue(new File(FileSystem.getDropOffBox()).canWrite());
-	Assert.assertTrue(new File(FileSystem.getDropOffBox()).canRead());
-	Assert.assertTrue(new File(FileSystem.getDropOffBox()).canExecute());
-	
+    Assert.assertTrue(new File(FileSystem.getBasepath()).canWrite());
+    Assert.assertTrue(new File(FileSystem.getBasepath()).canRead());
+    Assert.assertTrue(new File(FileSystem.getBasepath()).canExecute());
+    Assert.assertTrue(new File(FileSystem.getTmp()).canWrite());
+    Assert.assertTrue(new File(FileSystem.getTmp()).canRead());
+    Assert.assertTrue(new File(FileSystem.getTmp()).canExecute());
+    Assert.assertTrue(new File(FileSystem.getDropOffBox()).canWrite());
+    Assert.assertTrue(new File(FileSystem.getDropOffBox()).canRead());
+    Assert.assertTrue(new File(FileSystem.getDropOffBox()).canExecute());
+
     deleteTmp();
     FileUtils.createFolders(testRoot);
     FileUtils.createFolders(someDir);
-- 
GitLab