diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/Main.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/Main.java index ec7596cab8..3a2fa2625f 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/Main.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/Main.java @@ -1,6 +1,7 @@ package uk.ac.ic.wlgitbridge; import uk.ac.ic.wlgitbridge.application.GitBridgeApp; +import uk.ac.ic.wlgitbridge.util.Log; /** * Created by Winston on 01/11/14. @@ -8,7 +9,13 @@ import uk.ac.ic.wlgitbridge.application.GitBridgeApp; public class Main { public static void main(String[] args) { - new GitBridgeApp(args).run(); + try { + new GitBridgeApp(args).run(); + } catch (Throwable t) { + /* So that we get a timestamp */ + Log.error("Fatal exception thrown to top level, exiting: ", t); + System.exit(1); + } } } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/GitBridgeApp.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/GitBridgeApp.java index fdb0aa44ef..6e3f049cf6 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/GitBridgeApp.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/GitBridgeApp.java @@ -36,7 +36,7 @@ public class GitBridgeApp implements Runnable { try { parseArguments(args); loadConfigFile(); - Log.info("Config file loaded"); + Log.info("Config loaded: {}", config.getSanitisedString()); } catch (ArgsException e) { printUsage(); System.exit(EXIT_CODE_FAILED); diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Config.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Config.java index 9e350b9b88..f434437606 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Config.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Config.java @@ -3,9 +3,9 @@ package uk.ac.ic.wlgitbridge.application.config; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; import uk.ac.ic.wlgitbridge.application.exception.ConfigFileException; import uk.ac.ic.wlgitbridge.snapshot.base.JSONSource; +import uk.ac.ic.wlgitbridge.util.Instance; import java.io.FileReader; import java.io.IOException; @@ -16,6 +16,19 @@ import java.io.Reader; */ public class Config implements JSONSource { + static Config asSanitised(Config config) { + return new Config( + config.port, + config.rootGitDirectory, + config.username, + "", + config.apiBaseURL, + config.postbackURL, + config.serviceName, + Oauth2.asSanitised(config.oauth2) + ); + } + private int port; private String rootGitDirectory; private String username; @@ -25,7 +38,8 @@ public class Config implements JSONSource { private String serviceName; private Oauth2 oauth2; - public Config(String configFilePath) throws ConfigFileException, IOException { + public Config(String configFilePath) throws ConfigFileException, + IOException { this(new FileReader(configFilePath)); } @@ -33,14 +47,38 @@ public class Config implements JSONSource { fromJSON(new Gson().fromJson(reader, JsonElement.class)); } + public Config(int port, + String rootGitDirectory, + String username, + String password, + String apiBaseURL, + String postbackURL, + String serviceName, + Oauth2 oauth2) { + this.port = port; + this.rootGitDirectory = rootGitDirectory; + this.username = username; + this.password = password; + this.apiBaseURL = apiBaseURL; + this.postbackURL = postbackURL; + this.serviceName = serviceName; + this.oauth2 = oauth2; + } + @Override public void fromJSON(JsonElement json) { JsonObject configObject = json.getAsJsonObject(); port = getElement(configObject, "port").getAsInt(); - rootGitDirectory = getElement(configObject, "rootGitDirectory").getAsString(); + rootGitDirectory = getElement( + configObject, + "rootGitDirectory" + ).getAsString(); username = getOptionalString(configObject, "username"); password = getOptionalString(configObject, "password"); - String apiBaseURL = getElement(configObject, "apiBaseUrl").getAsString(); + String apiBaseURL = getElement( + configObject, + "apiBaseUrl" + ).getAsString(); if (!apiBaseURL.endsWith("/")) { apiBaseURL += "/"; } @@ -53,6 +91,10 @@ public class Config implements JSONSource { oauth2 = new Gson().fromJson(configObject.get("oauth2"), Oauth2.class); } + public String getSanitisedString() { + return Instance.prettyGson.toJson(Config.asSanitised(this)); + } + public int getPort() { return port; } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Oauth2.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Oauth2.java index 11d04562b2..6edf465d60 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Oauth2.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Oauth2.java @@ -27,4 +27,12 @@ public class Oauth2 { return oauth2Server; } + public static Oauth2 asSanitised(Oauth2 oauth2) { + return new Oauth2( + "", + "", + oauth2.oauth2Server + ); + } + } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/data/model/db/sql/SQLiteWLDatabase.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/data/model/db/sql/SQLiteWLDatabase.java index b042bc4a32..af6acee858 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/data/model/db/sql/SQLiteWLDatabase.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/data/model/db/sql/SQLiteWLDatabase.java @@ -9,6 +9,7 @@ import uk.ac.ic.wlgitbridge.data.model.db.sql.update.create.CreateURLIndexStoreS import uk.ac.ic.wlgitbridge.data.model.db.sql.update.delete.DeleteFilesForProjectSQLUpdate; import uk.ac.ic.wlgitbridge.data.model.db.sql.update.insert.AddURLIndexSQLUpdate; import uk.ac.ic.wlgitbridge.data.model.db.sql.update.insert.SetProjectSQLUpdate; +import uk.ac.ic.wlgitbridge.util.Log; import java.io.File; import java.sql.*; @@ -23,7 +24,12 @@ public class SQLiteWLDatabase { public SQLiteWLDatabase(File rootGitDirectory) throws SQLException, ClassNotFoundException { File databaseFile = new File(rootGitDirectory, "/.wlgb/wlgb.db"); - databaseFile.getParentFile().mkdirs(); + File dotWlgbDir = databaseFile.getParentFile(); + if (!dotWlgbDir.exists()) { + if (!dotWlgbDir.mkdirs()) { + Log.error("{} directory didn't exist, and unable to create. Check your permissions", dotWlgbDir.getAbsolutePath()); + } + } Class.forName("org.sqlite.JDBC"); connection = DriverManager.getConnection("jdbc:sqlite:" + databaseFile.getAbsolutePath()); createTables(); diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/snapshot/base/Request.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/snapshot/base/Request.java index 9f67eb8186..2d4c7aaa35 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/snapshot/base/Request.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/snapshot/base/Request.java @@ -1,16 +1,13 @@ package uk.ac.ic.wlgitbridge.snapshot.base; import com.google.api.client.http.*; -import com.google.gson.Gson; import com.google.gson.JsonElement; -import com.ning.http.client.AsyncCompletionHandler; import com.ning.http.client.AsyncHttpClient; -import com.ning.http.client.Response; import uk.ac.ic.wlgitbridge.snapshot.exception.FailedConnectionException; import uk.ac.ic.wlgitbridge.util.Instance; +import uk.ac.ic.wlgitbridge.util.Log; import uk.ac.ic.wlgitbridge.util.Util; -import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.concurrent.ExecutionException; @@ -47,22 +44,32 @@ public abstract class Request { public T getResult() throws FailedConnectionException, ForbiddenException { try { HttpResponse response = future.get(); - Util.sout(response.getStatusCode() + " " + response.getStatusMessage() + " (" + response.getHeaders().getContentLength() + "B) -> " + url); - JsonElement json = new Gson().fromJson(response.parseAsString(), JsonElement.class); + Log.info( + "{} {} ({}B) -> " + url, + response.getStatusCode(), + response.getStatusMessage(), + response.getHeaders().getContentLength() + ); + JsonElement json = Instance.gson.fromJson( + response.parseAsString(), + JsonElement.class + ); return parseResponse(json); } catch (InterruptedException e) { throw new FailedConnectionException(); } catch (ExecutionException e) { Throwable cause = e.getCause(); - int statusCode = ((HttpResponseException) cause).getStatusCode(); - if (cause instanceof HttpResponseException && (statusCode == HttpServletResponse.SC_UNAUTHORIZED || statusCode == HttpServletResponse.SC_FORBIDDEN)) { + if (cause instanceof HttpResponseException && + (((HttpResponseException) cause).getStatusCode() == + HttpServletResponse.SC_UNAUTHORIZED || + ((HttpResponseException) cause).getStatusCode() == + HttpServletResponse.SC_FORBIDDEN)) { throw new ForbiddenException(); } else { - throw new FailedConnectionException(); + throw new FailedConnectionException(cause); } } catch (IOException e) { - Util.serr("Failed to parse JSON"); - e.printStackTrace(); + Log.error("Failed to parse JSON.", e); throw new FailedConnectionException(); } } @@ -73,7 +80,8 @@ public abstract class Request { } - protected abstract T parseResponse(JsonElement json) throws FailedConnectionException; + protected abstract + T parseResponse(JsonElement json) throws FailedConnectionException; protected String getPostBody() { return null; @@ -82,7 +90,9 @@ public abstract class Request { private void performGetRequest() { Util.sout("GET -> " + url); try { - HttpRequest request = Instance.httpRequestFactory.buildGetRequest(new GenericUrl(url)); + HttpRequest request = Instance.httpRequestFactory.buildGetRequest( + new GenericUrl(url) + ); request(request); } catch (IOException e) { e.printStackTrace(); @@ -93,7 +103,13 @@ public abstract class Request { private void performPostRequest() { Util.sout("POST -> " + url); try { - HttpRequest request = Instance.httpRequestFactory.buildPostRequest(new GenericUrl(url), new ByteArrayContent("application/json", getPostBody().getBytes())); + HttpRequest request = Instance.httpRequestFactory.buildPostRequest( + new GenericUrl(url), + new ByteArrayContent( + "application/json", + getPostBody().getBytes() + ) + ); request(request); } catch (IOException e) { e.printStackTrace(); diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/snapshot/exception/FailedConnectionException.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/snapshot/exception/FailedConnectionException.java index 770e2a129b..c81b8abade 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/snapshot/exception/FailedConnectionException.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/snapshot/exception/FailedConnectionException.java @@ -9,7 +9,12 @@ import uk.ac.ic.wlgitbridge.util.Util; public class FailedConnectionException extends ServiceMayNotContinueException { public FailedConnectionException() { - super(Util.getServiceName() + " server not available. Please try again later."); + super(Util.getServiceName() + + " server not available. Please try again later."); + } + + public FailedConnectionException(Throwable cause) { + super(cause); } } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/util/Instance.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/util/Instance.java index ef4c2d49b1..fd041eb75e 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/util/Instance.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/util/Instance.java @@ -5,14 +5,25 @@ import com.google.api.client.http.HttpTransport; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.json.JsonFactory; import com.google.api.client.json.gson.GsonFactory; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; /** * Created by winston on 25/10/15. */ public class Instance { - public static final HttpTransport httpTransport = new NetHttpTransport(); - public static final HttpRequestFactory httpRequestFactory = httpTransport.createRequestFactory(); + public static final HttpTransport httpTransport = + new NetHttpTransport(); + + public static final HttpRequestFactory httpRequestFactory = + httpTransport.createRequestFactory(); + public static final JsonFactory jsonFactory = new GsonFactory(); + public static final Gson prettyGson = + new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); + + public static final Gson gson = new Gson(); + } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/util/Log.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/util/Log.java index 3b586957fa..862d211ff3 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/util/Log.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/util/Log.java @@ -77,6 +77,10 @@ public class Log { logger.error(msg); } + public static void error(String msg, Object... args) { + logger.error(msg, args); + } + public static void error(String msg, Throwable t) { logger.error(msg, t); } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/util/Util.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/util/Util.java index b20f1e5f28..d964e93f40 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/util/Util.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/util/Util.java @@ -90,7 +90,7 @@ public class Util { } private static void println(PrintStream ps, String ln) { - ps.println(getStringBuilder().append(ln)); + Log.info(ln); } public static void sout(String ln) { @@ -108,10 +108,6 @@ public class Util { return sb; } - public static void sout() { - sout(""); - } - public static void serr() { serr(""); } @@ -121,8 +117,7 @@ public class Util { } public static void printStackTrace(Throwable t) { - serr(); - t.printStackTrace(); + Log.warn("Exception", t); } public static void deleteDirectory(File directory) { diff --git a/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/application/config/ConfigTest.java b/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/application/config/ConfigTest.java index 8719082529..98d42251f8 100644 --- a/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/application/config/ConfigTest.java +++ b/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/application/config/ConfigTest.java @@ -66,4 +66,42 @@ public class ConfigTest { config.getOauth2(); } + @Test + public void asSanitised() throws Exception { + Reader reader = new StringReader("{\n" + + " \"port\": 80,\n" + + " \"rootGitDirectory\": \"/var/wlgb/git\",\n" + + " \"apiBaseUrl\": \"http://127.0.0.1:60000/api/v0\",\n" + + " \"username\": \"username\",\n" + + " \"password\": \"my super secret password\",\n" + + " \"postbackBaseUrl\": \"http://127.0.0.1\",\n" + + " \"serviceName\": \"Overleaf\",\n" + + " \"oauth2\": {\n" + + " \"oauth2ClientID\": \"my oauth2 client id\",\n" + + " \"oauth2ClientSecret\": \"my oauth2 client secret\",\n" + + " \"oauth2Server\": \"https://www.overleaf.com\"\n" + + " }\n" + + "}\n"); + Config config = new Config(reader); + String expected = "{\n" + + " \"port\": 80,\n" + + " \"rootGitDirectory\": \"/var/wlgb/git\",\n" + + " \"username\": \"username\",\n" + + " \"password\": \"\",\n" + + " \"apiBaseURL\": \"http://127.0.0.1:60000/api/v0/\",\n" + + " \"postbackURL\": \"http://127.0.0.1/\",\n" + + " \"serviceName\": \"Overleaf\",\n" + + " \"oauth2\": {\n" + + " \"oauth2ClientID\": \"\",\n" + + " \"oauth2ClientSecret\": \"\",\n" + + " \"oauth2Server\": \"https://www.overleaf.com\"\n" + + " }\n" + + "}"; + assertEquals( + "sanitised config did not hide sensitive fields", + expected, + config.getSanitisedString() + ); + } + } \ No newline at end of file