Read external gitblit.properties from $GERRIT_SITE/etc

Allows GitBlit plugin to read an external configuration
file to override the one internally stored in the jar.
Simplifies the management of Gerrit+GitBlit setup
by using an external file without having to extract,
modify and then repackage the GitBlit plguin.

gitblit.properties documentation can be found
at the GitBlit project URL http://gitblit.com/properties.html
and should be stored under $GERRIT_SITE/etc.

Without external gitblit.properties configuration
the existing one stored in the GitBlit plugin will
be used as default.

Change-Id: I974c491487eeb6ef8d4b10c3201a575d5b3598d0
diff --git a/src/main/java/com/googlesource/gerrit/plugins/gitblit/GerritWicketFilter.java b/src/main/java/com/googlesource/gerrit/plugins/gitblit/GerritWicketFilter.java
index d2d557f..a9d0601 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/gitblit/GerritWicketFilter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/gitblit/GerritWicketFilter.java
@@ -14,11 +14,9 @@
 package com.googlesource.gerrit.plugins.gitblit;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Iterator;
-import java.util.Properties;
 import java.util.Vector;
 
 import javax.servlet.FilterChain;
@@ -30,17 +28,12 @@
 import javax.servlet.ServletResponse;
 
 import org.apache.wicket.protocol.http.WicketFilter;
-import org.eclipse.jgit.lib.Config;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.gitblit.Constants;
 import com.gitblit.GitBlit;
-import com.gitblit.IStoredSettings;
-import com.google.gerrit.common.data.GerritConfig;
 import com.google.gerrit.httpd.WebSession;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.git.LocalDiskRepositoryManager;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
@@ -48,33 +41,27 @@
 import com.googlesource.gerrit.plugins.gitblit.app.GerritToGitBlitWebApp;
 import com.googlesource.gerrit.plugins.gitblit.app.GitBlitSettings;
 import com.googlesource.gerrit.plugins.gitblit.auth.GerritAuthFilter;
-import com.googlesource.gerrit.plugins.gitblit.auth.GerritToGitBlitUserService;
 
 @Singleton
 public class GerritWicketFilter extends WicketFilter {
-  private static final String GITBLIT_GERRIT_PROPERTIES = "/gitblit.properties";
   private static final Logger log = LoggerFactory
       .getLogger(GerritWicketFilter.class);
 
-  private final LocalDiskRepositoryManager repoManager;
   private final Provider<WebSession> webSession;
   @SuppressWarnings("unused")
   // We need Guice to create the GerritGitBlit instance
   private final GerritGitBlit gitBlit;
   private final GerritAuthFilter gerritAuthFilter;
-  private final GitBlitUrlsConfig config;
+  private final GitBlitSettings settings;
 
   @Inject
-  public GerritWicketFilter(final LocalDiskRepositoryManager repoManager,
+  public GerritWicketFilter(
       final Provider<WebSession> webSession, final GerritGitBlit gitBlit,
-      final GerritAuthFilter gerritAuthFilter, final @GerritServerConfig Config config,
-      final GerritConfig gerritConfig) {
-
-    this.repoManager = repoManager;
+      final GerritAuthFilter gerritAuthFilter, final GitBlitSettings settings) {
     this.webSession = webSession;
     this.gitBlit = gitBlit;
     this.gerritAuthFilter = gerritAuthFilter;
-    this.config = new GitBlitUrlsConfig(config);
+    this.settings = settings;
   }
 
   @Override
@@ -82,29 +69,7 @@
     showGitBlitBanner();
 
     try {
-      InputStream resin =
-          getClass().getResourceAsStream(GITBLIT_GERRIT_PROPERTIES);
-      Properties properties = null;
-      try {
-        properties = new Properties();
-        properties.load(resin);
-        properties.put("git.repositoriesFolder", repoManager.getBasePath()
-            .getAbsolutePath());
-        properties.put("realm.userService",
-            GerritToGitBlitUserService.class.getName());
-        if (properties.get("web.otherUrls") != null) {
-	    properties.put("web.otherUrls",
-                (config.getGitHttpUrl() + " " + config.getGitSshUrl()).trim()
-                + " " + properties.get("web.otherUrls"));
-        } else {
-            properties.put("web.otherUrls",
-                (config.getGitHttpUrl() + " " + config.getGitSshUrl()).trim());
-        }
-      } finally {
-        resin.close();
-      }
-      IStoredSettings settings = new GitBlitSettings(properties);
-      GitBlit.self().configureContext(settings, repoManager.getBasePath(),
+      GitBlit.self().configureContext(settings, settings.getBasePath(),
           false);
       GitBlit.self().contextInitialized(
           new ServletContextEvent(filterConfig.getServletContext()));
diff --git a/src/main/java/com/googlesource/gerrit/plugins/gitblit/app/GitBlitSettings.java b/src/main/java/com/googlesource/gerrit/plugins/gitblit/app/GitBlitSettings.java
index f11e715..2f93f52 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/gitblit/app/GitBlitSettings.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/gitblit/app/GitBlitSettings.java
@@ -13,17 +13,48 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.gitblit.app;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.SimpleDateFormat;
+import java.util.Date;
 import java.util.Map;
 import java.util.Properties;
 
+import org.eclipse.jgit.lib.Config;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import com.gitblit.IStoredSettings;
+import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.server.config.SitePaths;
+import com.google.gerrit.server.git.LocalDiskRepositoryManager;
+import com.google.inject.Inject;
+import com.googlesource.gerrit.plugins.gitblit.GitBlitUrlsConfig;
+import com.googlesource.gerrit.plugins.gitblit.auth.GerritToGitBlitUserService;
 
 public class GitBlitSettings extends IStoredSettings {
-  private Properties properties;
+  private static final String GITBLIT_GERRIT_PROPERTIES = "/gitblit.properties";
 
-  public GitBlitSettings(Properties properties) {
+  private final LocalDiskRepositoryManager repoManager;
+  private final GitBlitUrlsConfig config;
+  private final File etcDir;
+
+  private Properties properties;
+  private File gitblitPropertiesFile;
+
+  @Inject
+  public GitBlitSettings(final LocalDiskRepositoryManager repoManager,
+      final @GerritServerConfig Config config, final SitePaths sitePaths)
+      throws IOException {
     super(GitBlitSettings.class);
-    this.properties = properties;
+    this.properties = new Properties();
+    this.repoManager = repoManager;
+    this.config = new GitBlitUrlsConfig(config);
+    this.etcDir = sitePaths.etc_dir;
+    load();
   }
 
   @Override
@@ -36,4 +67,65 @@
     properties.putAll(updatedSettings);
     return true;
   }
+
+  private void load() throws IOException {
+    InputStream resin = openPropertiesFile();
+    try {
+      properties = new Properties();
+      properties.load(resin);
+      properties.put("git.repositoriesFolder", repoManager.getBasePath()
+          .getAbsolutePath());
+      properties.put("realm.userService",
+          GerritToGitBlitUserService.class.getName());
+      if (properties.get("web.otherUrls") != null) {
+        properties.put("web.otherUrls",
+            (config.getGitHttpUrl() + " " + config.getGitSshUrl()).trim() + " "
+                + properties.get("web.otherUrls"));
+      } else {
+        properties.put("web.otherUrls",
+            (config.getGitHttpUrl() + " " + config.getGitSshUrl()).trim());
+      }
+    } finally {
+      resin.close();
+    }
+  }
+
+  private InputStream openPropertiesFile() {
+    InputStream gitblitPropertiesIn;
+    gitblitPropertiesFile = new File(etcDir, GITBLIT_GERRIT_PROPERTIES);
+    if (gitblitPropertiesFile.exists()) {
+      try {
+        gitblitPropertiesIn = new FileInputStream(gitblitPropertiesFile);
+      } catch (FileNotFoundException e) {
+        // this would never happen as we checked for file existence before
+        throw new IllegalStateException(e);
+      }
+    } else {
+      gitblitPropertiesIn =
+          getClass().getResourceAsStream(GITBLIT_GERRIT_PROPERTIES);
+    }
+    return gitblitPropertiesIn;
+  }
+
+  public File getBasePath() {
+    return repoManager.getBasePath();
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder stringSettings = new StringBuilder();
+    if (!gitblitPropertiesFile.exists()) {
+      stringSettings.append(GITBLIT_GERRIT_PROPERTIES
+          + " from gitblit plugin jar");
+    } else {
+      stringSettings.append(gitblitPropertiesFile.getAbsolutePath()
+          + " (lastModified: "
+          + new SimpleDateFormat().format(new Date(gitblitPropertiesFile
+              .lastModified())) + ")");
+    }
+
+    stringSettings.append(" with values ");
+    stringSettings.append(properties.toString());
+    return stringSettings.toString();
+  }
 }