Improve logging.

- Add sanitised Config and test
- Fix issue with file permissions
This commit is contained in:
Winston Li 2016-03-31 06:35:09 +01:00
parent 559b32a22f
commit a4df78c73d
11 changed files with 163 additions and 31 deletions

View file

@ -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);
}
}
}

View file

@ -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);

View file

@ -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,
"<password>",
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;
}

View file

@ -27,4 +27,12 @@ public class Oauth2 {
return oauth2Server;
}
public static Oauth2 asSanitised(Oauth2 oauth2) {
return new Oauth2(
"<oauth2ClientID>",
"<oauth2ClientSecret>",
oauth2.oauth2Server
);
}
}

View file

@ -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();

View file

@ -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<T extends Result> {
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<T extends Result> {
}
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<T extends Result> {
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<T extends Result> {
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();

View file

@ -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);
}
}

View file

@ -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();
}

View file

@ -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);
}

View file

@ -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) {

View file

@ -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\": \"<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\": \"<oauth2ClientID>\",\n" +
" \"oauth2ClientSecret\": \"<oauth2ClientSecret>\",\n" +
" \"oauth2Server\": \"https://www.overleaf.com\"\n" +
" }\n" +
"}";
assertEquals(
"sanitised config did not hide sensitive fields",
expected,
config.getSanitisedString()
);
}
}