From 26e2b1262df8d115daad2d5528db844500441984 Mon Sep 17 00:00:00 2001 From: Winston Li Date: Sat, 10 Jan 2015 08:41:14 +0000 Subject: [PATCH] Implemented mock snapshot server. --- services/git-bridge/bin/config.json | 4 +- .../application/AttsResourceHandler.java | 35 +++-- .../SnapshotPushPostbackHandler.java | 55 +++++--- .../wlgitbridge/bridge/RepositorySource.java | 5 +- .../wlgitbridge/bridge/WLBridgedProject.java | 16 +-- .../git/handler/WLRepositoryResolver.java | 12 +- .../git/handler/hook/WriteLatexPutHook.java | 27 ++-- .../java/uk/ac/ic/wlgitbridge/test/Main.java | 17 +++ .../wlgitbridge/test/SnapshotDummyServer.java | 46 ------- .../exception/InvalidAPICallException.java | 12 ++ .../test/response/SnapshotResponse.java | 14 ++ .../response/SnapshotResponseBuilder.java | 57 +++++++++ .../getdoc/SnapshotGetDocResponse.java | 22 ++++ .../getforver/SnapshotGetForVerResponse.java | 22 ++++ .../SnapshotGetSavedVersResponse.java | 22 ++++ .../response/push/SnapshotPushResponse.java | 34 +++++ .../push/data/SnapshotPushResult.java | 31 +++++ .../data/SnapshotPushResultOutOfDate.java | 17 +++ .../push/data/SnapshotPushResultSuccess.java | 17 +++ .../postback/SnapshotPostbackRequest.java | 22 ++++ .../SnapshotPostbackRequestError.java | 21 +++ .../SnapshotPostbackRequestInvalidFiles.java | 32 +++++ ...SnapshotPostbackRequestInvalidProject.java | 33 +++++ .../SnapshotPostbackRequestOutOfDate.java | 21 +++ .../SnapshotPostbackRequestSuccess.java | 24 ++++ .../invalidfile/InvalidFileError.java | 25 ++++ .../invalidfile/InvalidFileErrorDefault.java | 17 +++ .../InvalidFileErrorDisallowed.java | 17 +++ .../invalidfile/InvalidFileErrorUnclean.java | 29 +++++ .../server/MockSnapshotRequestHandler.java | 40 ++++++ .../test/server/MockSnapshotServer.java | 37 ++++++ .../test/server/PostbackThread.java | 45 +++++++ .../test/state/SnapshotAPIState.java | 120 ++++++++++++++++++ .../writelatex/SnapshotRepositoryBuilder.java | 19 +-- .../wlgitbridge/writelatex/WriteLatexAPI.java | 4 +- .../writelatex/api/request/base/Result.java | 10 +- .../api/request/base/SnapshotAPIRequest.java | 2 +- .../exception/FailedConnectionException.java | 10 +- .../request/getdoc/SnapshotGetDocResult.java | 19 +++ .../exception/InvalidProjectException.java | 16 ++- .../getforversion/SnapshotAttachment.java | 14 ++ .../request/getforversion/SnapshotData.java | 21 +++ .../request/getforversion/SnapshotFile.java | 15 +++ .../SnapshotGetForVersionResult.java | 10 +- .../SnapshotGetSavedVersResult.java | 24 ++++ .../request/getsavedvers/SnapshotInfo.java | 8 +- .../api/request/push/PostbackContents.java | 74 +++++++---- .../api/request/push/PostbackManager.java | 10 +- .../push/SnapshotPushRequestResult.java | 5 + .../exception/InternalErrorException.java | 30 +++++ .../exception/PostbackTimeoutException.java | 29 +++++ 51 files changed, 1109 insertions(+), 159 deletions(-) create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/Main.java delete mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/SnapshotDummyServer.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/exception/InvalidAPICallException.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/SnapshotResponse.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/SnapshotResponseBuilder.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/getdoc/SnapshotGetDocResponse.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/getforver/SnapshotGetForVerResponse.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/getsavedver/SnapshotGetSavedVersResponse.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/SnapshotPushResponse.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/data/SnapshotPushResult.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/data/SnapshotPushResultOutOfDate.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/data/SnapshotPushResultSuccess.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/SnapshotPostbackRequest.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/SnapshotPostbackRequestError.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/SnapshotPostbackRequestInvalidFiles.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/SnapshotPostbackRequestInvalidProject.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/SnapshotPostbackRequestOutOfDate.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/SnapshotPostbackRequestSuccess.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/invalidfile/InvalidFileError.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/invalidfile/InvalidFileErrorDefault.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/invalidfile/InvalidFileErrorDisallowed.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/invalidfile/InvalidFileErrorUnclean.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/server/MockSnapshotRequestHandler.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/server/MockSnapshotServer.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/server/PostbackThread.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/state/SnapshotAPIState.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/exception/InternalErrorException.java create mode 100644 services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/exception/PostbackTimeoutException.java diff --git a/services/git-bridge/bin/config.json b/services/git-bridge/bin/config.json index 7dc5cd110c..e174ed8eb9 100644 --- a/services/git-bridge/bin/config.json +++ b/services/git-bridge/bin/config.json @@ -1,9 +1,9 @@ { "port": 80, "rootGitDirectory": "/var/wlgb/git", - "apiBaseUrl": "https://www.overleaf.com/api/v0", + "apiBaseUrl": "http://127.0.0.1:60000/api/v0", "username": "REDACTED", "password": "REDACTED", - "postbackBaseUrl": "http://your-server-name-for-postbacks", + "postbackBaseUrl": "http://127.0.0.1", "serviceName": "Overleaf" } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/AttsResourceHandler.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/AttsResourceHandler.java index 821871f983..31c8029a63 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/AttsResourceHandler.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/AttsResourceHandler.java @@ -25,25 +25,24 @@ public class AttsResourceHandler extends ResourceHandler { @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { - HttpURI uri = baseRequest.getUri(); - System.out.println(baseRequest.getMethod() + " " + uri); - MultiMap multimap = new MultiMap(); - uri.decodeQueryTo(multimap); - String[] pathSections = uri.getPath().split("/"); - String key = multimap.getString("key"); - if (key == null || pathSections.length < 2) { - throw new ServletException(); + String method = baseRequest.getMethod(); + if (method.equals("GET")) { + HttpURI uri = baseRequest.getUri(); + System.out.println(method + " " + uri); + MultiMap multimap = new MultiMap(); + uri.decodeQueryTo(multimap); + String[] pathSections = uri.getPath().split("/"); + String key = multimap.getString("key"); + if (key == null || pathSections.length < 2) { + throw new ServletException(); + } + try { + writeLatexDataSource.checkPostbackKey(pathSections[1], key); + } catch (InvalidPostbackKeyException e) { + throw new ServletException(); + } + super.handle(target, baseRequest, request, response); } - try { - writeLatexDataSource.checkPostbackKey(pathSections[1], key); - } catch (InvalidPostbackKeyException e) { - throw new ServletException(); - } - - if (false) { - throw new ServletException(); - } - super.handle(target, baseRequest, request, response); } } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/SnapshotPushPostbackHandler.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/SnapshotPushPostbackHandler.java index ca1183d40e..ad1aa0715b 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/SnapshotPushPostbackHandler.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/SnapshotPushPostbackHandler.java @@ -1,5 +1,7 @@ package uk.ac.ic.wlgitbridge.application; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import uk.ac.ic.wlgitbridge.bridge.WriteLatexDataSource; @@ -24,22 +26,45 @@ public class SnapshotPushPostbackHandler extends AbstractHandler { @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { - if (request.getMethod().equals("POST") && request.getPathInfo().endsWith("postback")) { - String contents = Util.getContentsOfReader(request.getReader()); - String[] parts = request.getRequestURI().split("/"); - if (parts.length < 4) { - throw new ServletException(); + + try { + if (request.getMethod().equals("POST") && target.endsWith("postback")) { + response.setContentType("application/json"); + String contents = Util.getContentsOfReader(request.getReader()); + String[] parts = request.getRequestURI().split("/"); + if (parts.length < 4) { + System.out.println("Invalid postback url"); + throw new ServletException(); + } + String projectName = parts[1]; + String postbackKey = parts[2]; + System.out.println("Postback received for project: " + projectName); + SnapshotPushPostbackContents postbackContents = new SnapshotPushPostbackContents(writeLatexDataSource, projectName, postbackKey, contents); + JsonObject body = new JsonObject(); + + try { + postbackContents.processPostback(); + } catch (UnexpectedPostbackException e) { + response.setStatus(HttpServletResponse.SC_CONFLICT); + body.add("code", new JsonPrimitive("unexpectedPostback")); + response.getWriter().println(body); + baseRequest.setHandled(true); + return; + } + response.setStatus(HttpServletResponse.SC_OK); + body.add("code", new JsonPrimitive("success")); + response.getWriter().println(body); + baseRequest.setHandled(true); } - String projectName = parts[1]; - String postbackKey = parts[2]; - System.out.println("Postback received for project: " + projectName); - SnapshotPushPostbackContents postbackContents = new SnapshotPushPostbackContents(writeLatexDataSource, projectName, postbackKey, contents); - try { - postbackContents.processPostback(); - } catch (UnexpectedPostbackException e) { - throw new ServletException(); - } - baseRequest.setHandled(true); + } catch (IOException e) { + e.printStackTrace(); + throw e; + } catch (ServletException e) { + e.printStackTrace(); + throw e; + } catch (RuntimeException e) { + e.printStackTrace(); + throw e; } } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/RepositorySource.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/RepositorySource.java index df62ed32d8..3d43c9e8bf 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/RepositorySource.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/RepositorySource.java @@ -2,8 +2,7 @@ package uk.ac.ic.wlgitbridge.bridge; import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; -import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException; +import org.eclipse.jgit.transport.ServiceMayNotContinueException; import java.io.File; @@ -12,6 +11,6 @@ import java.io.File; */ public interface RepositorySource { - public Repository getRepositoryWithNameAtRootDirectory(String name, File rootDirectory) throws RepositoryNotFoundException, ServiceNotEnabledException; + public Repository getRepositoryWithNameAtRootDirectory(String name, File rootDirectory) throws RepositoryNotFoundException, ServiceMayNotContinueException; } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/WLBridgedProject.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/WLBridgedProject.java index bda511718b..d91af8a4fb 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/WLBridgedProject.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/WLBridgedProject.java @@ -5,8 +5,7 @@ import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; -import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException; +import org.eclipse.jgit.transport.ServiceMayNotContinueException; import uk.ac.ic.wlgitbridge.writelatex.api.request.getdoc.exception.InvalidProjectException; import uk.ac.ic.wlgitbridge.writelatex.filestore.store.WLFileStore; @@ -29,7 +28,7 @@ public class WLBridgedProject { this.writeLatexDataSource = writeLatexDataSource; } - public void buildRepository() throws RepositoryNotFoundException, ServiceNotEnabledException, FailedConnectionException { + public void buildRepository() throws RepositoryNotFoundException, ServiceMayNotContinueException { writeLatexDataSource.lockForProject(name); if (repository.getObjectDatabase().exists()) { updateRepositoryFromSnapshots(repository); @@ -39,7 +38,7 @@ public class WLBridgedProject { writeLatexDataSource.unlockForProject(name); } - private void updateRepositoryFromSnapshots(Repository repository) throws ServiceNotEnabledException, RepositoryNotFoundException, FailedConnectionException { + private void updateRepositoryFromSnapshots(Repository repository) throws RepositoryNotFoundException, ServiceMayNotContinueException { List writableRepositories; try { writableRepositories = writeLatexDataSource.getWritableRepositories(name); @@ -54,24 +53,23 @@ public class WLBridgedProject { git.commit().setAuthor(new PersonIdent(contents.getUserName(), contents.getUserEmail(), contents.getWhen(), TimeZone.getDefault())) .setMessage(contents.getCommitMessage()) .call(); - System.out.println(repository.getDirectory()); WLFileStore.deleteInDirectoryApartFrom(contents.getDirectory(), ".git"); } } catch (GitAPIException e) { - throw new ServiceNotEnabledException(); + throw new ServiceMayNotContinueException(e); } catch (IOException e) { - throw new ServiceNotEnabledException(); + throw new ServiceMayNotContinueException(e); } } - private void buildRepositoryFromScratch(Repository repository) throws RepositoryNotFoundException, ServiceNotEnabledException, FailedConnectionException { + private void buildRepositoryFromScratch(Repository repository) throws RepositoryNotFoundException, ServiceMayNotContinueException { if (!writeLatexDataSource.repositoryExists(name)) { throw new RepositoryNotFoundException(name); } try { repository.create(); } catch (IOException e) { - throw new ServiceNotEnabledException(); + throw new ServiceMayNotContinueException(e); } updateRepositoryFromSnapshots(repository); } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/handler/WLRepositoryResolver.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/handler/WLRepositoryResolver.java index 95074eccca..4e16b9d433 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/handler/WLRepositoryResolver.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/handler/WLRepositoryResolver.java @@ -32,14 +32,20 @@ public class WLRepositoryResolver implements RepositoryResolver errors; + + public SnapshotPostbackRequestInvalidFiles(List errors) { + super("invalidFiles"); + this.errors = errors; + } + + @Override + public JsonObject toJson() { + JsonObject jsonThis = super.toJson(); + JsonArray jsonErrors = new JsonArray(); + for (InvalidFileError error : errors) { + jsonErrors.add(error.toJson()); + } + jsonThis.add("errors", jsonErrors); + return jsonThis; + } + +} diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/SnapshotPostbackRequestInvalidProject.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/SnapshotPostbackRequestInvalidProject.java new file mode 100644 index 0000000000..e60368cf16 --- /dev/null +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/SnapshotPostbackRequestInvalidProject.java @@ -0,0 +1,33 @@ +package uk.ac.ic.wlgitbridge.test.response.push.postback; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +import java.util.List; + +/** + * Created by Winston on 10/01/15. + */ +public class SnapshotPostbackRequestInvalidProject extends SnapshotPostbackRequest { + + private final List errors; + + public SnapshotPostbackRequestInvalidProject(List errors) { + super("invalidProject"); + this.errors = errors; + } + + @Override + public JsonObject toJson() { + JsonObject jsonThis = super.toJson(); + jsonThis.addProperty("message", "short string message for debugging"); + JsonArray jsonErrors = new JsonArray(); + for (String error : errors) { + jsonErrors.add(new JsonPrimitive(error)); + } + jsonThis.add("errors", jsonErrors); + return jsonThis; + } + +} diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/SnapshotPostbackRequestOutOfDate.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/SnapshotPostbackRequestOutOfDate.java new file mode 100644 index 0000000000..e01645ccd6 --- /dev/null +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/SnapshotPostbackRequestOutOfDate.java @@ -0,0 +1,21 @@ +package uk.ac.ic.wlgitbridge.test.response.push.postback; + +import com.google.gson.JsonObject; + +/** + * Created by Winston on 09/01/15. + */ +public class SnapshotPostbackRequestOutOfDate extends SnapshotPostbackRequest { + + public SnapshotPostbackRequestOutOfDate() { + super("outOfDate"); + } + + @Override + public JsonObject toJson() { + JsonObject jsonThis = super.toJson(); + jsonThis.addProperty("message", "Out of Date"); + return jsonThis; + } + +} diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/SnapshotPostbackRequestSuccess.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/SnapshotPostbackRequestSuccess.java new file mode 100644 index 0000000000..28a887ab40 --- /dev/null +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/SnapshotPostbackRequestSuccess.java @@ -0,0 +1,24 @@ +package uk.ac.ic.wlgitbridge.test.response.push.postback; + +import com.google.gson.JsonObject; + +/** + * Created by Winston on 09/01/15. + */ +public class SnapshotPostbackRequestSuccess extends SnapshotPostbackRequest { + + private final int latestVerId; + + public SnapshotPostbackRequestSuccess(int latestVerId) { + super("upToDate"); + this.latestVerId = latestVerId; + } + + @Override + public JsonObject toJson() { + JsonObject jsonThis = super.toJson(); + jsonThis.addProperty("latestVerId", latestVerId); + return jsonThis; + } + +} diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/invalidfile/InvalidFileError.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/invalidfile/InvalidFileError.java new file mode 100644 index 0000000000..f8c79bbd71 --- /dev/null +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/invalidfile/InvalidFileError.java @@ -0,0 +1,25 @@ +package uk.ac.ic.wlgitbridge.test.response.push.postback.invalidfile; + +import com.google.gson.JsonObject; + +/** + * Created by Winston on 09/01/15. + */ +public abstract class InvalidFileError { + + private final String file; + + public InvalidFileError(String file) { + this.file = file; + } + + public JsonObject toJson() { + JsonObject jsonThis = new JsonObject(); + jsonThis.addProperty("file", file); + jsonThis.addProperty("state", getState()); + return jsonThis; + } + + protected abstract String getState(); + +} diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/invalidfile/InvalidFileErrorDefault.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/invalidfile/InvalidFileErrorDefault.java new file mode 100644 index 0000000000..038d98cbd2 --- /dev/null +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/invalidfile/InvalidFileErrorDefault.java @@ -0,0 +1,17 @@ +package uk.ac.ic.wlgitbridge.test.response.push.postback.invalidfile; + +/** + * Created by Winston on 09/01/15. + */ +public class InvalidFileErrorDefault extends InvalidFileError { + + public InvalidFileErrorDefault(String file) { + super(file); + } + + @Override + protected String getState() { + return "error"; + } + +} diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/invalidfile/InvalidFileErrorDisallowed.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/invalidfile/InvalidFileErrorDisallowed.java new file mode 100644 index 0000000000..bb30f550ef --- /dev/null +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/invalidfile/InvalidFileErrorDisallowed.java @@ -0,0 +1,17 @@ +package uk.ac.ic.wlgitbridge.test.response.push.postback.invalidfile; + +/** + * Created by Winston on 09/01/15. + */ +public class InvalidFileErrorDisallowed extends InvalidFileError { + + public InvalidFileErrorDisallowed(String file) { + super(file); + } + + @Override + protected String getState() { + return "disallowed"; + } + +} diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/invalidfile/InvalidFileErrorUnclean.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/invalidfile/InvalidFileErrorUnclean.java new file mode 100644 index 0000000000..694bc882e2 --- /dev/null +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/response/push/postback/invalidfile/InvalidFileErrorUnclean.java @@ -0,0 +1,29 @@ +package uk.ac.ic.wlgitbridge.test.response.push.postback.invalidfile; + +import com.google.gson.JsonObject; + +/** + * Created by Winston on 09/01/15. + */ +public class InvalidFileErrorUnclean extends InvalidFileError { + + private final String cleanFile; + + public InvalidFileErrorUnclean(String file, String cleanFile) { + super(file); + this.cleanFile = cleanFile; + } + + @Override + public JsonObject toJson() { + JsonObject jsonThis = super.toJson(); + jsonThis.addProperty("cleanFile", cleanFile); + return jsonThis; + } + + @Override + protected String getState() { + return "unclean_name"; + } + +} diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/server/MockSnapshotRequestHandler.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/server/MockSnapshotRequestHandler.java new file mode 100644 index 0000000000..2ff9bef82a --- /dev/null +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/server/MockSnapshotRequestHandler.java @@ -0,0 +1,40 @@ +package uk.ac.ic.wlgitbridge.test.server; + +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.handler.AbstractHandler; +import uk.ac.ic.wlgitbridge.test.exception.InvalidAPICallException; +import uk.ac.ic.wlgitbridge.test.response.SnapshotResponse; +import uk.ac.ic.wlgitbridge.test.response.SnapshotResponseBuilder; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * Created by Winston on 09/01/15. + */ +public class MockSnapshotRequestHandler extends AbstractHandler { + + private final SnapshotResponseBuilder responseBuilder; + + public MockSnapshotRequestHandler(SnapshotResponseBuilder responseBuilder) { + this.responseBuilder = responseBuilder; + } + + @Override + public void handle(String target, final Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + + try { + final SnapshotResponse snapshotResponse = responseBuilder.buildWithTarget(target, baseRequest.getMethod()); + response.getWriter().println(snapshotResponse.respond()); + new PostbackThread(baseRequest.getReader(), snapshotResponse.postback()).startIfNotNull(); + } catch (InvalidAPICallException e) { + e.printStackTrace(); + } catch (RuntimeException e) { + e.printStackTrace(); + } + baseRequest.setHandled(true); + } + +} diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/server/MockSnapshotServer.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/server/MockSnapshotServer.java new file mode 100644 index 0000000000..b03606c315 --- /dev/null +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/server/MockSnapshotServer.java @@ -0,0 +1,37 @@ +package uk.ac.ic.wlgitbridge.test.server; + +import org.eclipse.jetty.server.NetworkConnector; +import org.eclipse.jetty.server.Server; +import uk.ac.ic.wlgitbridge.test.response.SnapshotResponseBuilder; +import uk.ac.ic.wlgitbridge.test.state.SnapshotAPIState; + +/** + * Created by Winston on 09/01/15. + */ +public class MockSnapshotServer { + + private final Server server; + private final SnapshotResponseBuilder responseBuilder; + private int port; + + public MockSnapshotServer() { + server = new Server(60000); + responseBuilder = new SnapshotResponseBuilder(); + server.setHandler(new MockSnapshotRequestHandler(responseBuilder)); + } + + public void start() { + try { + server.start(); + } catch (Exception e) { + e.printStackTrace(); + } + port = ((NetworkConnector) server.getConnectors()[0]).getLocalPort(); + System.out.println(port); + } + + public void setState(SnapshotAPIState state) { + responseBuilder.setState(state); + } + +} diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/server/PostbackThread.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/server/PostbackThread.java new file mode 100644 index 0000000000..2085f56a49 --- /dev/null +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/server/PostbackThread.java @@ -0,0 +1,45 @@ +package uk.ac.ic.wlgitbridge.test.server; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.ning.http.client.AsyncHttpClient; + +import java.io.IOException; +import java.io.Reader; +import java.util.concurrent.ExecutionException; + +/** + * Created by Winston on 10/01/15. + */ +public class PostbackThread extends Thread { + + private String url; + private String postback; + + public PostbackThread(Reader reader, String postback) { + if (postback != null) { + url = new Gson().fromJson(reader, JsonObject.class).get("postbackUrl").getAsString(); + this.postback = postback; + } + } + + @Override + public void run() { + try { + new AsyncHttpClient().preparePost(url).setBody(postback).execute().get().getResponseBody(); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + } + + public void startIfNotNull() { + if (url != null && postback != null) { + start(); + } + } + +} diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/state/SnapshotAPIState.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/state/SnapshotAPIState.java new file mode 100644 index 0000000000..e628aec501 --- /dev/null +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/test/state/SnapshotAPIState.java @@ -0,0 +1,120 @@ +package uk.ac.ic.wlgitbridge.test.state; + +import uk.ac.ic.wlgitbridge.test.response.push.data.SnapshotPushResult; +import uk.ac.ic.wlgitbridge.test.response.push.data.SnapshotPushResultSuccess; +import uk.ac.ic.wlgitbridge.test.response.push.postback.SnapshotPostbackRequest; +import uk.ac.ic.wlgitbridge.writelatex.api.request.getdoc.SnapshotGetDocResult; +import uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion.SnapshotAttachment; +import uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion.SnapshotData; +import uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion.SnapshotFile; +import uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion.SnapshotGetForVersionResult; +import uk.ac.ic.wlgitbridge.writelatex.api.request.getsavedvers.SnapshotGetSavedVersResult; +import uk.ac.ic.wlgitbridge.writelatex.api.request.getsavedvers.SnapshotInfo; + +import java.util.*; + +/** + * Created by Winston on 09/01/15. + */ +public class SnapshotAPIState { + + private Map getDoc; + private Map getSavedVers; + private Map> getForVers; + private Map push; + private Map postback; + + public SnapshotAPIState() { + getDoc = new HashMap(); + getDoc.put("1826rqgsdb", new SnapshotGetDocResult(243, "2014-11-30T18:40:58Z", "jdleesmiller+1@gmail.com", "John+1")); + + getSavedVers = new HashMap(); + List savedVers = new LinkedList(); + savedVers.add(new SnapshotInfo(243, "added more info on doc GET and error details", "jdleesmiller+1@gmail.com", "John+1", "2014-11-30T18:47:01Z")); + savedVers.add(new SnapshotInfo(185, "with more details on POST request", "jdleesmiller+1@gmail.com", "John+1", "2014-11-11T17:18:40Z")); + savedVers.add(new SnapshotInfo(175, "with updated PUT/POST request", "jdleesmiller+1@gmail.com", "John+1", "2014-11-09T23:09:13Z")); + savedVers.add(new SnapshotInfo(146, "added PUT format", "jdleesmiller@gmail.com", "John Lees-Miller", "2014-11-07T15:11:35Z")); + savedVers.add(new SnapshotInfo(74, "with example output", "jdleesmiller@gmail.com", "John Lees-Miller", "2014-11-05T18:09:41Z")); + savedVers.add(new SnapshotInfo(39, "with more files", "jdleesmiller@gmail.com", "John Lees-Miller", "2014-11-05T18:02:19Z")); + savedVers.add(new SnapshotInfo(24, "first draft", "jdleesmiller@gmail.com", "John Lees-Miller", "2014-11-05T17:56:58Z")); + getSavedVers.put("1826rqgsdb", new SnapshotGetSavedVersResult(savedVers)); + + getForVers = new HashMap>() {{ + put("1826rqgsdb", new HashMap() {{ + put(243, new SnapshotGetForVersionResult(new SnapshotData(Arrays.asList( + new SnapshotFile("\\\\documentclass[a4paper]{article}\\n\\n\\\\usepackage[english]{babel}\\n\\\\usepackage[utf8]{inputenc}\\n\\\\usepackage{graphicx}\\n\\\\usepackage{fullpage}\\n\\\\usepackage{listings}\\n\\\\usepackage{courier}\\n\\\\usepackage{url}\\n\\n\\\\lstset{basicstyle=\\\\ttfamily,breaklines=true}\\n\\n\\\\begin{document}\\n\\\\title{API for the writeLaTeX-Git Bridge}\\n\\\\author{JLM}\\n\\\\date{\\\\today}\\n\\\\maketitle\\n\\n\\\\section{Fetching a Project from WriteLaTeX}\\n\\nThere are three API calls that will likely be of interest. You can run them against this server, \\\\url{radiant-wind-3058.herokuapp.com}, but they're not on the production server yet.\\n\\n\\\\subsection{Get Doc}\\n\\nA ``doc'' is our internal term for a ``project''. This endpoint returns the latest version id, when the latest version was created (ISO8601), and the user that last edited the project (if any, otherwise null).\\n\\n\\\\begin{lstlisting}\\nGET https://.../api/v0/docs/1826rqgsdb\\n# => {\\n \\\"latestVerId\\\": 39,\\n \\\"latestVerAt\\\": \\\"2014-11-30T18:35:27Z\\\",\\n \\\"latestVerBy\\\": {\\n \\\"email\\\": \\\"jdleesmiller@gmail.com\\\",\\n \\\"name\\\": \\\"John Lees-Miller\\\"\\n }}\\n\\\\end{lstlisting}\\n\\n\\\\subsection{Get Saved Vers}\\n\\nA ``saved ver'' is a version of a doc, saved by via the versions menu. Note that this query is not currently paginated.\\n\\n\\\\begin{lstlisting}\\nGET https://.../api/v0/docs/1826rqgsdb/saved_vers\\n# => [\\n {\\\"versionId\\\":39,\\n \\\"comment\\\":\\\"with more files\\\",\\n \\\"user\\\":{\\n \\\"email\\\":\\\"jdleesmiller@gmail.com\\\",\\n \\\"name\\\":\\\"John Lees-Miller\\\"},\\n \\\"createdAt\\\":\\\"2014-11-05T18:02:19Z\\\"},\\n {\\\"versionId\\\":24,\\n \\\"comment\\\":\\\"first draft\\\",\\n \\\"user\\\":{\\n \\\"email\\\":\\\"jdleesmiller@gmail.com\\\",\\n \\\"name\\\":\\\"John Lees-Miller\\\"},\\n \\\"createdAt\\\":\\\"2014-11-05T17:56:58Z\\\"}]\\n\\\\end{lstlisting}\\n\\n\\\\subsection{Get Snapshot for Version}\\n\\nA snapshot contains the content of a project in the given version. You can safely request a snapshot of any version that is, or was at any point in the last 24 hours, (1) a saved version, or (2) the current version. (Older versions may or may not have been moved to cold storage.)\\n\\nThe srcs array contains (content, file name) pairs; the atts array contains (URL, file name) pairs.\\n\\n\\\\begin{lstlisting}\\nGET https://.../api/v0/docs/1826rqgsdb/snapshots/39\\n# => {\\n \\\"srcs\\\":[\\n [\\\"This text is from another file.\\\",\\\"foo/bar/test.tex\\\"],\\n [\\\"\\\\\\\\documentclass[a4paper]{article}\\\\n...\\\",\\\"main.tex\\\"]],\\n \\\"atts\\\":[\\n [\\\"https://writelatex-staging.s3.amazonaws.com/filepicker/1ENnu6zJSGyslI3DuNZD_min_mean_wait_evm_7.eps.150dpi.png\\\",\\\"min_mean_wait_evm_7_eps_150dpi.png\\\"]]}\\n\\\\end{lstlisting}\\n\\n\\\\section{Pushing a Project to WriteLaTeX}\\n\\n\\\\subsection{Push a Project}\\n\\n\\\\begin{lstlisting}\\n# NB: JLM originally said PUT, but he now thinks POST is better\\n# NB: you must set a Content-Type: application/json header for this request\\n# in order to specify the data as JSON in the request body\\nPOST https://.../api/v0/docs/1826rqgsdb/snapshots\\nData:\\n{\\n latestVerId: integer,\\n files: [\\n {\\n name: string path (forward slashes, relative to root)\\n url: string (but only if the file is modified; else no url given)\\n }, ...\\n ]\\n postbackUrl: url to post result back to\\n}\\nResponse on success:\\n{\\n status: 202,\\n code: \\\"accepted\\\",\\n message: \\\"Accepted\\\"\\n}\\nResponse on out of date:\\n{\\n status: 409, # Conflict\\n code: \\\"outOfDate\\\",\\n message: \\\"Out of Date\\\"\\n}\\n\\nPostback Data (METHOD POST):\\nOn success:\\n{\\n code: \\\"upToDate\\\",\\n latestVerId: integer\\n}\\nOn out of date:\\n{\\n code: \\\"outOfDate\\\",\\n message: \\\"Out of Date\\\"\\n}\\nOn error with the files list (e.g. file extension not allowed):\\n{\\n code: \\\"invalidFiles\\\",\\n errors: [ {\\n file: the file name from the snapshot,\\n state: \\\"error\\\"|\\\"disallowed\\\"|\\\"unclean_name\\\"\\n }, ... ]\\n}\\nIf the file's error state is unclean_name, the error object will alsocontain a property cleanFile that contains the name of the file after it has been \\\"cleaned\\\" to meet our file naming requirements; for other file error states, this property is not present.\\nOn error with the project as a whole (e.g. over quota):\\n{\\n code: \\\"invalidProject\\\",\\n message: short string message for debugging\\n errors: [ array of zero or more string messages for the user ]\\n}\\nOn unexpected error (bug):\\n{\\n code: \\\"error\\\",\\n message: \\\"Unexpected Error\\\"\\n}\\n\\\\end{lstlisting}\\n\\n\\\\section{Test Data}\\n\\nYou can use this project as one of your test projects. I've added an attachment and a file in a subfolder to make it a bit more interesting.\\n\\n\\\\input{foo/bar/test}\\n\\n\\\\includegraphics[width=\\\\linewidth]{min_mean_wait_evm_7_eps_150dpi}\\n\\n\\\\end{document}", "main.tex"), + new SnapshotFile("This text is from another file.", "foo/bar/test.tex") + ), Arrays.asList( + new SnapshotAttachment("https://writelatex-staging.s3.amazonaws.com/filepicker/1ENnu6zJSGyslI3DuNZD_min_mean_wait_evm_7.eps.150dpi.png", "min_mean_wait_evm_7_eps_150dpi.png") + )))); + put(185, new SnapshotGetForVersionResult(new SnapshotData(Arrays.asList( + new SnapshotFile("\\\\documentclass[a4paper]{article}\\n\\n\\\\usepackage[english]{babel}\\n\\\\usepackage[utf8]{inputenc}\\n\\\\usepackage{graphicx}\\n\\\\usepackage{fullpage}\\n\\\\usepackage{listings}\\n\\\\usepackage{courier}\\n\\\\usepackage{url}\\n\\n\\\\lstset{basicstyle=\\\\ttfamily,breaklines=true}\\n\\n\\\\begin{document}\\n\\\\title{API for the writeLaTeX-Git Bridge}\\n\\\\author{JLM}\\n\\\\date{\\\\today}\\n\\\\maketitle\\n\\n\\\\section{Fetching a Project from WriteLaTeX}\\n\\nThere are three API calls that will likely be of interest. You can run them against this server, \\\\url{radiant-wind-3058.herokuapp.com}, but they're not on the production server yet.\\n\\n\\\\subsection{Get Doc}\\n\\nA ``doc'' is our internal term for a ``project''. At present, this just returns the latest version number.\\n\\n\\\\begin{lstlisting}\\nGET https://.../api/v0/docs/1826rqgsdb\\n# => { latestVerId: 39 }\\nTODO will also include updatedAt time and user (if it was not anonymous)\\n\\\\end{lstlisting}\\n\\n\\\\subsection{Get Saved Vers}\\n\\nA ``saved ver'' is a version of a doc, saved by via the versions menu. Note that this query is not currently paginated.\\n\\n\\\\begin{lstlisting}\\nGET https://.../api/v0/docs/1826rqgsdb/saved_vers\\n# => [\\n {\\\"versionId\\\":39,\\n \\\"comment\\\":\\\"with more files\\\",\\n \\\"user\\\":{\\n \\\"email\\\":\\\"jdleesmiller@gmail.com\\\",\\n \\\"name\\\":\\\"John Lees-Miller\\\"},\\n \\\"createdAt\\\":\\\"2014-11-05T18:02:19Z\\\"},\\n {\\\"versionId\\\":24,\\n \\\"comment\\\":\\\"first draft\\\",\\n \\\"user\\\":{\\n \\\"email\\\":\\\"jdleesmiller@gmail.com\\\",\\n \\\"name\\\":\\\"John Lees-Miller\\\"},\\n \\\"createdAt\\\":\\\"2014-11-05T17:56:58Z\\\"}]\\n\\\\end{lstlisting}\\n\\n\\\\subsection{Get Snapshot for Version}\\n\\nA snapshot contains the content of a project in the given version. You can safely request a snapshot of any version that is, or was at any point in the last 24 hours, (1) a saved version, or (2) the current version. (Older versions may or may not have been moved to cold storage.)\\n\\nThe srcs array contains (content, file name) pairs; the atts array contains (URL, file name) pairs.\\n\\n\\\\begin{lstlisting}\\nGET https://.../api/v0/docs/1826rqgsdb/snapshots/39\\n# => {\\n \\\"srcs\\\":[\\n [\\\"This text is from another file.\\\",\\\"foo/bar/test.tex\\\"],\\n [\\\"\\\\\\\\documentclass[a4paper]{article}\\\\n...\\\",\\\"main.tex\\\"]],\\n \\\"atts\\\":[\\n [\\\"https://writelatex-staging.s3.amazonaws.com/filepicker/1ENnu6zJSGyslI3DuNZD_min_mean_wait_evm_7.eps.150dpi.png\\\",\\\"min_mean_wait_evm_7_eps_150dpi.png\\\"]]}\\n\\\\end{lstlisting}\\n\\n\\\\section{Pushing a Project to WriteLaTeX}\\n\\n\\\\subsection{Push a Project}\\n\\n\\\\begin{lstlisting}\\n# NB: JLM originally said PUT, but he now thinks POST is better\\n# NB: you must set a Content-Type: application/json header for this request\\n# in order to specify the data as JSON in the request body\\nPOST https://.../api/v0/docs/1826rqgsdb/snapshots\\nData:\\n{\\n latestVerId: integer,\\n files: [\\n {\\n name: string path (forward slashes, relative to root)\\n url: string (but only if the file is modified; else no url given)\\n }, ...\\n ]\\n postbackUrl: url to post result back to\\n}\\nResponse on success:\\n{\\n status: 202,\\n code: \\\"accepted\\\",\\n message: \\\"Accepted\\\"\\n}\\nResponse on out of date:\\n{\\n status: 409, # Conflict\\n code: \\\"outOfDate\\\",\\n message: \\\"Out of Date\\\"\\n}\\n\\nPostback Data (METHOD POST):\\nOn success:\\n{\\n code: \\\"upToDate\\\",\\n latestVerId: integer\\n}\\nOn out of date:\\n{\\n code: \\\"outOfDate\\\",\\n message: \\\"Out of Date\\\"\\n}\\nOn error with the files list (e.g. file extension not allowed):\\n{\\n code: \\\"invalidFiles\\\",\\n errors: TODO\\n}\\nOn error with the project as a whole (e.g. over quota):\\n{\\n code: \\\"invalidProject\\\",\\n errors: TODO\\n}\\nOn unexpected error (bug):\\n{\\n code: \\\"error\\\",\\n message: \\\"Unexpected Error\\\"\\n}\\n\\\\end{lstlisting}\\n\\n\\\\section{Test Data}\\n\\nYou can use this project as one of your test projects. I've added an attachment and a file in a subfolder to make it a bit more interesting.\\n\\n\\\\input{foo/bar/test}\\n\\n\\\\includegraphics[width=\\\\linewidth]{min_mean_wait_evm_7_eps_150dpi}\\n\\n\\\\end{document}", "main.tex"), + new SnapshotFile("This text is from another file.", "foo/bar/test.tex") + ), Arrays.asList( + new SnapshotAttachment("https://writelatex-staging.s3.amazonaws.com/filepicker/1ENnu6zJSGyslI3DuNZD_min_mean_wait_evm_7.eps.150dpi.png", "min_mean_wait_evm_7_eps_150dpi.png") + )))); + put(175, new SnapshotGetForVersionResult(new SnapshotData(Arrays.asList( + new SnapshotFile("\\\\documentclass[a4paper]{article}\\n\\n\\\\usepackage[english]{babel}\\n\\\\usepackage[utf8]{inputenc}\\n\\\\usepackage{graphicx}\\n\\\\usepackage{fullpage}\\n\\\\usepackage{listings}\\n\\\\usepackage{courier}\\n\\\\usepackage{url}\\n\\n\\\\lstset{basicstyle=\\\\ttfamily,breaklines=true}\\n\\n\\\\begin{document}\\n\\\\title{API for the writeLaTeX-Git Bridge}\\n\\\\author{JLM}\\n\\\\date{\\\\today}\\n\\\\maketitle\\n\\n\\\\section{Fetching a Project from WriteLaTeX}\\n\\nThere are three API calls that will likely be of interest. You can run them against this server, \\\\url{radiant-wind-3058.herokuapp.com}, but they're not on the production server yet.\\n\\n\\\\subsection{Get Doc}\\n\\nA ``doc'' is our internal term for a ``project''. At present, this just returns the latest version number.\\n\\n\\\\begin{lstlisting}\\nGET https://.../api/v0/docs/1826rqgsdb\\n# => { latestVerId: 39 }\\nTODO will also include updatedAt time and user (if it was not anonymous)\\n\\\\end{lstlisting}\\n\\n\\\\subsection{Get Saved Vers}\\n\\nA ``saved ver'' is a version of a doc, saved by via the versions menu. Note that this query is not currently paginated.\\n\\n\\\\begin{lstlisting}\\nGET https://.../api/v0/docs/1826rqgsdb/saved_vers\\n# => [\\n {\\\"versionId\\\":39,\\n \\\"comment\\\":\\\"with more files\\\",\\n \\\"user\\\":{\\n \\\"email\\\":\\\"jdleesmiller@gmail.com\\\",\\n \\\"name\\\":\\\"John Lees-Miller\\\"},\\n \\\"createdAt\\\":\\\"2014-11-05T18:02:19Z\\\"},\\n {\\\"versionId\\\":24,\\n \\\"comment\\\":\\\"first draft\\\",\\n \\\"user\\\":{\\n \\\"email\\\":\\\"jdleesmiller@gmail.com\\\",\\n \\\"name\\\":\\\"John Lees-Miller\\\"},\\n \\\"createdAt\\\":\\\"2014-11-05T17:56:58Z\\\"}]\\n\\\\end{lstlisting}\\n\\n\\\\subsection{Get Snapshot for Version}\\n\\nA snapshot contains the content of a project in the given version. You can safely request a snapshot of any version that is, or was at any point in the last 24 hours, (1) a saved version, or (2) the current version. (Older versions may or may not have been moved to cold storage.)\\n\\nThe srcs array contains (content, file name) pairs; the atts array contains (URL, file name) pairs.\\n\\n\\\\begin{lstlisting}\\nGET https://.../api/v0/docs/1826rqgsdb/snapshots/39\\n# => {\\n \\\"srcs\\\":[\\n [\\\"This text is from another file.\\\",\\\"foo/bar/test.tex\\\"],\\n [\\\"\\\\\\\\documentclass[a4paper]{article}\\\\n...\\\",\\\"main.tex\\\"]],\\n \\\"atts\\\":[\\n [\\\"https://writelatex-staging.s3.amazonaws.com/filepicker/1ENnu6zJSGyslI3DuNZD_min_mean_wait_evm_7.eps.150dpi.png\\\",\\\"min_mean_wait_evm_7_eps_150dpi.png\\\"]]}\\n\\\\end{lstlisting}\\n\\n\\\\section{Pushing a Project to WriteLaTeX}\\n\\n\\\\subsection{Push a Project}\\n\\n\\\\begin{lstlisting}\\n# NB: JLM originally said PUT, but he now thinks POST is better\\n# NB: you must set a Content-Type: application/json header for this request\\n# in order to specify the data as JSON in the request body\\nPOST https://.../api/v0/docs/1826rqgsdb/snapshots\\nData:\\n{\\n latestVerId: integer,\\n files: [\\n {\\n name: string path (forward slashes, relative to root)\\n url: string (but only if the file is modified; else no url given)\\n }, ...\\n ]\\n postbackUrl: url to post result back to\\n}\\nResponse on success:\\n{\\n status: 202,\\n code: \\\"accepted\\\",\\n message: \\\"Accepted\\\"\\n}\\nResponse on out of date:\\n{\\n status: 409, # Conflict\\n code: \\\"outOfDate\\\",\\n message: \\\"Out of Date\\\"\\n}\\n\\nPostback Data (METHOD POST):\\nOn success:\\n{\\n code: \\\"upToDate\\\",\\n latestVerId: integer\\n}\\nOn out of date:\\n{\\n code: \\\"outOfDate\\\",\\n message: \\\"Out of Date\\\"\\n}\\nOn error:\\n{\\n code: \\\"invalidFile\\\",\\n TODO\\n}\\n\\\\end{lstlisting}\\n\\n\\\\section{Test Data}\\n\\nYou can use this project as one of your test projects. I've added an attachment and a file in a subfolder to make it a bit more interesting.\\n\\n\\\\input{foo/bar/test}\\n\\n\\\\includegraphics[width=\\\\linewidth]{min_mean_wait_evm_7_eps_150dpi}\\n\\n\\\\end{document}", "main.tex"), + new SnapshotFile("This text is from another file.", "foo/bar/test.tex") + ), Arrays.asList( + new SnapshotAttachment("https://writelatex-staging.s3.amazonaws.com/filepicker/1ENnu6zJSGyslI3DuNZD_min_mean_wait_evm_7.eps.150dpi.png", "min_mean_wait_evm_7_eps_150dpi.png") + )))); + put(146, new SnapshotGetForVersionResult(new SnapshotData(Arrays.asList( + new SnapshotFile("\\\\documentclass[a4paper]{article}\\n\\n\\\\usepackage[english]{babel}\\n\\\\usepackage[utf8]{inputenc}\\n\\\\usepackage{graphicx}\\n\\\\usepackage{fullpage}\\n\\\\usepackage{listings}\\n\\\\usepackage{courier}\\n\\\\usepackage{url}\\n\\n\\\\lstset{basicstyle=\\\\ttfamily,breaklines=true}\\n\\n\\\\begin{document}\\n\\\\title{API for the writeLaTeX-Git Bridge}\\n\\\\author{JLM}\\n\\\\date{\\\\today}\\n\\\\maketitle\\n\\n\\\\section{Fetching a Project from WriteLaTeX}\\n\\nThere are three API calls that will likely be of interest. You can run them against this server, \\\\url{radiant-wind-3058.herokuapp.com}, but they're not on the production server yet.\\n\\n\\\\subsection{Get Doc}\\n\\nA ``doc'' is our internal term for a ``project''. At present, this just returns the latest version number.\\n\\n\\\\begin{lstlisting}\\nGET https://.../api/v0/docs/1826rqgsdb\\n# => { latestVerId: 39 }\\n\\\\end{lstlisting}\\n\\n\\\\subsection{Get Saved Vers}\\n\\nA ``saved ver'' is a version of a doc, saved by via the versions menu. Note that this query is not currently paginated.\\n\\n\\\\begin{lstlisting}\\nGET https://.../api/v0/docs/1826rqgsdb/saved_vers\\n# => [\\n {\\\"versionId\\\":39,\\n \\\"comment\\\":\\\"with more files\\\",\\n \\\"user\\\":{\\n \\\"email\\\":\\\"jdleesmiller@gmail.com\\\",\\n \\\"name\\\":\\\"John Lees-Miller\\\"},\\n \\\"createdAt\\\":\\\"2014-11-05T18:02:19Z\\\"},\\n {\\\"versionId\\\":24,\\n \\\"comment\\\":\\\"first draft\\\",\\n \\\"user\\\":{\\n \\\"email\\\":\\\"jdleesmiller@gmail.com\\\",\\n \\\"name\\\":\\\"John Lees-Miller\\\"},\\n \\\"createdAt\\\":\\\"2014-11-05T17:56:58Z\\\"}]\\n\\\\end{lstlisting}\\n\\n\\\\subsection{Get Snapshot for Version}\\n\\nA snapshot contains the content of a project in the given version. You can safely request a snapshot of any version that is, or was at any point in the last 24 hours, (1) a saved version, or (2) the current version. (Older versions may or may not have been moved to cold storage.)\\n\\nThe srcs array contains (content, file name) pairs; the atts array contains (URL, file name) pairs.\\n\\n\\\\begin{lstlisting}\\nGET https://.../api/v0/docs/1826rqgsdb/snapshots/39\\n# => {\\n \\\"srcs\\\":[\\n [\\\"This text is from another file.\\\",\\\"foo/bar/test.tex\\\"],\\n [\\\"\\\\\\\\documentclass[a4paper]{article}\\\\n...\\\",\\\"main.tex\\\"]],\\n \\\"atts\\\":[\\n [\\\"https://writelatex-staging.s3.amazonaws.com/filepicker/1ENnu6zJSGyslI3DuNZD_min_mean_wait_evm_7.eps.150dpi.png\\\",\\\"min_mean_wait_evm_7_eps_150dpi.png\\\"]]}\\n\\\\end{lstlisting}\\n\\n\\\\section{Pushing a Project to WriteLaTeX}\\n\\n\\\\subsection{Push a Project}\\n\\n\\\\begin{lstlisting}\\nPUT https://.../api/v0/docs/1826rqgsdb/snapshots\\nData:\\n{\\n latestVerId: integer,\\n files: [\\n {\\n name: string path (forward slashes, relative to root)\\n url: string (but only if the file is modified; else no url given)\\n }, ...\\n ]\\n postbackUrl: url to post result back to\\n}\\nResponse on success:\\n{\\n status: 20x,\\n}\\nResponse on out of date:\\n{\\n status: 40x,\\n code: \\\"outOfDate\\\",\\n message: \\\"Out of Date\\\"\\n}\\n\\nPostback Data (METHOD POST):\\nOn success:\\n{\\n code: \\\"upToDate\\\",\\n latestVerId: integer\\n}\\nOn out of date:\\n{\\n code: \\\"outOfDate\\\",\\n message: \\\"Out of Date\\\"\\n}\\nOn error:\\n{\\n code: \\\"invalidFile\\\",\\n TODO\\n}\\n\\\\end{lstlisting}\\n\\n\\\\section{Test Data}\\n\\nYou can use this project as one of your test projects. I've added an attachment and a file in a subfolder to make it a bit more interesting.\\n\\n\\\\input{foo/bar/test}\\n\\n\\\\includegraphics[width=\\\\linewidth]{min_mean_wait_evm_7_eps_150dpi}\\n\\n\\\\end{document}", "main.tex"), + new SnapshotFile("This text is from another file.", "foo/bar/test.tex") + ), Arrays.asList( + new SnapshotAttachment("https://writelatex-staging.s3.amazonaws.com/filepicker/1ENnu6zJSGyslI3DuNZD_min_mean_wait_evm_7.eps.150dpi.png", "min_mean_wait_evm_7_eps_150dpi.png") + )))); + put(74, new SnapshotGetForVersionResult(new SnapshotData(Arrays.asList( + new SnapshotFile("\\\\documentclass[a4paper]{article}\\n\\n\\\\usepackage[english]{babel}\\n\\\\usepackage[utf8]{inputenc}\\n\\\\usepackage{graphicx}\\n\\\\usepackage{fullpage}\\n\\\\usepackage{listings}\\n\\\\usepackage{courier}\\n\\\\usepackage{url}\\n\\n\\\\lstset{basicstyle=\\\\ttfamily,breaklines=true}\\n\\n\\\\begin{document}\\n\\\\title{API for the writeLaTeX-Git Bridge}\\n\\\\author{JLM}\\n\\\\date{\\\\today}\\n\\\\maketitle\\n\\n\\\\section{Fetching a Project from WriteLaTeX}\\n\\nThere are three API calls that will likely be of interest. You can run them against this server, \\\\url{radiant-wind-3058.herokuapp.com}, but they're not on the production server yet.\\n\\n\\\\subsection{Get Doc}\\n\\nA ``doc'' is our internal term for a ``project''. At present, this just returns the latest version number.\\n\\n\\\\begin{lstlisting}\\nGET https://.../api/v0/docs/1826rqgsdb\\n# => { latestVerId: 39 }\\n\\\\end{lstlisting}\\n\\n\\\\subsection{Get Saved Vers}\\n\\nA ``saved ver'' is a version of a doc, saved by via the versions menu. Note that this query is not currently paginated.\\n\\n\\\\begin{lstlisting}\\nGET https://.../api/v0/docs/1826rqgsdb/saved_vers\\n# => [\\n {\\\"versionId\\\":39,\\n \\\"comment\\\":\\\"with more files\\\",\\n \\\"user\\\":{\\n \\\"email\\\":\\\"jdleesmiller@gmail.com\\\",\\n \\\"name\\\":\\\"John Lees-Miller\\\"},\\n \\\"createdAt\\\":\\\"2014-11-05T18:02:19Z\\\"},\\n {\\\"versionId\\\":24,\\n \\\"comment\\\":\\\"first draft\\\",\\n \\\"user\\\":{\\n \\\"email\\\":\\\"jdleesmiller@gmail.com\\\",\\n \\\"name\\\":\\\"John Lees-Miller\\\"},\\n \\\"createdAt\\\":\\\"2014-11-05T17:56:58Z\\\"}]\\n\\\\end{lstlisting}\\n\\n\\\\subsection{Get Snapshot for Version}\\n\\nA snapshot contains the content of a project in the given version. You can safely request a snapshot of any version that is, or was at any point in the last 24 hours, (1) a saved version, or (2) the current version. (Older versions may or may not have been moved to cold storage.)\\n\\nThe srcs array contains (content, file name) pairs; the atts array contains (URL, file name) pairs.\\n\\n\\\\begin{lstlisting}\\nGET https://.../api/v0/docs/1826rqgsdb/snapshots/39\\n# => {\\n \\\"srcs\\\":[\\n [\\\"This text is from another file.\\\",\\\"foo/bar/test.tex\\\"],\\n [\\\"\\\\\\\\documentclass[a4paper]{article}\\\\n...\\\",\\\"main.tex\\\"]],\\n \\\"atts\\\":[\\n [\\\"https://writelatex-staging.s3.amazonaws.com/filepicker/1ENnu6zJSGyslI3DuNZD_min_mean_wait_evm_7.eps.150dpi.png\\\",\\\"min_mean_wait_evm_7_eps_150dpi.png\\\"]]}\\n\\\\end{lstlisting}\\n\\n\\\\section{Pushing a Project to WriteLaTeX}\\n\\nTODO still working on this part\\n\\n\\\\section{Test Data}\\n\\nYou can use this project as a test project. I've added an attachment and a file in a subfolder to make it a bit more interesting.\\n\\n\\\\input{foo/bar/test}\\n\\n\\\\includegraphics[width=\\\\linewidth]{min_mean_wait_evm_7_eps_150dpi}\\n\\n\\\\end{document}", "main.tex"), + new SnapshotFile("This text is from another file.", "foo/bar/test.tex") + ), Arrays.asList( + new SnapshotAttachment("https://writelatex-staging.s3.amazonaws.com/filepicker/1ENnu6zJSGyslI3DuNZD_min_mean_wait_evm_7.eps.150dpi.png", "min_mean_wait_evm_7_eps_150dpi.png") + )))); + put(39, new SnapshotGetForVersionResult(new SnapshotData(Arrays.asList( + new SnapshotFile("\\\\documentclass[a4paper]{article}\\n\\n\\\\usepackage[english]{babel}\\n\\\\usepackage[utf8]{inputenc}\\n\\\\usepackage{graphicx}\\n\\\\usepackage{fullpage}\\n\\\\usepackage{listings}\\n\\\\usepackage{courier}\\n\\\\usepackage{url}\\n\\n\\\\lstset{basicstyle=\\\\ttfamily,breaklines=true}\\n\\n\\\\begin{document}\\n\\\\title{API for the writeLaTeX-Git Bridge}\\n\\\\author{JLM}\\n\\\\date{\\\\today}\\n\\\\maketitle\\n\\n\\\\section{Fetching a Project from WriteLaTeX}\\n\\nThere are three API calls that will likely be of interest. You can run them against this server, \\\\url{radiant-wind-3058.herokuapp.com}, but they're not on the production server yet.\\n\\n\\\\subsection{Get Doc}\\n\\nA ``doc'' is our internal term for a ``project''. At present, this just returns the latest version number.\\n\\n\\\\begin{lstlisting}\\nGET https://.../api/v0/docs/1826rqgsdb\\n\\\\end{lstlisting}\\n\\n\\\\subsection{Get Saved Vers}\\n\\nA ``saved ver'' is a version of a doc, saved by via the versions menu. To list saved versions for a doc:\\n\\n\\\\begin{lstlisting}\\nGET https://.../api/v0/docs/1826rqgsdb/saved_vers\\n\\\\end{lstlisting}\\n\\n\\\\subsection{Get Snapshot for Version}\\n\\nA snapshot contains the content of a project in the given version. You can safely request a snapshot of any version that is, or was at any point in the last 24 hours, (1) a saved version, or (2) the current version. (Older versions may or may not have been moved to cold storage.)\\n\\n\\\\begin{lstlisting}\\nGET https://.../api/v0/docs/1826rqgsdb/snapshots/1\\n\\\\end{lstlisting}\\n\\n\\\\section{Pushing a Project to WriteLaTeX}\\n\\nTODO still working on this part\\n\\n\\\\section{Test Data}\\n\\nYou can use this project as a test project. I've added an attachment and a file in a subfolder to make it a bit more interesting.\\n\\n\\\\input{foo/bar/test}\\n\\n\\\\includegraphics[width=\\\\linewidth]{min_mean_wait_evm_7_eps_150dpi}\\n\\n\\\\end{document}", "main.tex"), + new SnapshotFile("This text is from another file.", "foo/bar/test.tex") + ), Arrays.asList( + new SnapshotAttachment("https://writelatex-staging.s3.amazonaws.com/filepicker/1ENnu6zJSGyslI3DuNZD_min_mean_wait_evm_7.eps.150dpi.png", "min_mean_wait_evm_7_eps_150dpi.png") + )))); + put(24, new SnapshotGetForVersionResult(new SnapshotData(Arrays.asList( + new SnapshotFile("\\\\documentclass[a4paper]{article}\\n\\n\\\\usepackage[english]{babel}\\n\\\\usepackage[utf8]{inputenc}\\n\\\\usepackage{graphicx}\\n\\\\usepackage{fullpage}\\n\\\\usepackage{listings}\\n\\\\usepackage{courier}\\n\\\\usepackage{url}\\n\\n\\\\lstset{basicstyle=\\\\ttfamily,breaklines=true}\\n\\n\\\\begin{document}\\n\\\\title{API for the writeLaTeX-Git Bridge}\\n\\\\author{JLM}\\n\\\\date{\\\\today}\\n\\\\maketitle\\n\\n\\\\section{Fetching a Project from WriteLaTeX}\\n\\nThere are three API calls that will likely be of interest. You can run them against this server (radiant-wind-3058.herokuapp.com).\\n\\n\\\\subsection{Get Doc}\\n\\nA ``doc'' is our internal term for a ``project''. At present, this just returns the latest version number.\\n\\n\\\\begin{lstlisting}\\nGET https://radiant-wind.....com/api/v0/docs/1826rqgsdb\\n\\\\end{lstlisting}\\n\\n\\\\subsection{Get Saved Vers}\\n\\nA ``saved ver'' is a version of a doc, saved by via the versions menu. To list saved versions for a doc:\\n\\n\\\\begin{lstlisting}\\nGET https://radiant-wind.....com/api/v0/docs/1826rqgsdb/saved_vers\\n\\\\end{lstlisting}\\n\\n\\\\subsection{Get Snapshot for Version}\\n\\nA snapshot contains the content of a project in the given version. You can safely request a snapshot of any version that is, or was at any point in the last 24 hours, (1) a saved version, or (2) the current version. (Older versions may or may not have been moved to cold storage.)\\n\\n\\\\begin{lstlisting}\\nGET https://radiant-wind.....com/api/v0/docs/1826rqgsdb/snapshots/1\\n\\\\end{lstlisting}\\n\\n\\\\section{Pushing a Project to WriteLaTeX}\\n\\nTODO still working on this part\\n\\n\\\\section{Test Data}\\n\\nYou can use this project as a test project. Here is an extra file to make it a bit more interesting.\\n\\n\\\\includegraphics[width=\\\\linewidth]{min_mean_wait_evm_7_eps_150dpi}\\n\\n\\\\end{document}", "main.tex") + ), Arrays.asList( + new SnapshotAttachment("https://writelatex-staging.s3.amazonaws.com/filepicker/1ENnu6zJSGyslI3DuNZD_min_mean_wait_evm_7.eps.150dpi.png", "min_mean_wait_evm_7_eps_150dpi.png") + )))); + }}); + }}; + + push = new HashMap() {{ + put("1826rqgsdb", new SnapshotPushResultSuccess()); + }}; + + postback = new HashMap() {{ +// put("1826rqgsdb", new SnapshotPostbackRequestInvalidFiles(Arrays.asList(new InvalidFileErrorDefault("file1.fff"), new InvalidFileErrorDisallowed("file2.fff"), new InvalidFileErrorUnclean("unclean", "clean")))); +// put("1826rqgsdb", new SnapshotPostbackRequestOutOfDate()); +// put("1826rqgsdb", new SnapshotPostbackRequestInvalidProject(Arrays.asList("line1", "line2"))); +// put("1826rqgsdb", new SnapshotPostbackRequestError()); + }}; + } + + public SnapshotGetDocResult getStateForGetDoc(String projectName) { + return getDoc.get(projectName); + } + + public SnapshotGetSavedVersResult getStateForGetSavedVers(String projectName) { + return getSavedVers.get(projectName); + } + + public SnapshotGetForVersionResult getStateForGetForVers(String projectName, int versionID) { + return getForVers.get(projectName).get(versionID); + } + + public SnapshotPushResult getStateForPush(String projectName) { + return push.get(projectName); + } + + public SnapshotPostbackRequest getStateForPostback(String projectName) { + return postback.get(projectName); + } + +} diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/SnapshotRepositoryBuilder.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/SnapshotRepositoryBuilder.java index 2e0853f6d7..911a9c91a8 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/SnapshotRepositoryBuilder.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/SnapshotRepositoryBuilder.java @@ -3,11 +3,11 @@ package uk.ac.ic.wlgitbridge.writelatex; import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.storage.file.FileRepositoryBuilder; -import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; +import org.eclipse.jgit.transport.ServiceMayNotContinueException; import uk.ac.ic.wlgitbridge.bridge.RepositorySource; import uk.ac.ic.wlgitbridge.bridge.WLBridgedProject; import uk.ac.ic.wlgitbridge.bridge.WriteLatexDataSource; -import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException; +import uk.ac.ic.wlgitbridge.writelatex.api.request.push.exception.InternalErrorException; import java.io.File; import java.io.IOException; @@ -24,13 +24,9 @@ public class SnapshotRepositoryBuilder implements RepositorySource { } @Override - public Repository getRepositoryWithNameAtRootDirectory(String name, File rootDirectory) throws RepositoryNotFoundException, ServiceNotEnabledException { - try { - if (!writeLatexDataSource.repositoryExists(name)) { - throw new RepositoryNotFoundException(name); - } - } catch (FailedConnectionException e) { - throw new ServiceNotEnabledException(); + public Repository getRepositoryWithNameAtRootDirectory(String name, File rootDirectory) throws RepositoryNotFoundException, ServiceMayNotContinueException { + if (!writeLatexDataSource.repositoryExists(name)) { + throw new RepositoryNotFoundException(name); } File repositoryDirectory = new File(rootDirectory, name); @@ -38,11 +34,8 @@ public class SnapshotRepositoryBuilder implements RepositorySource { try { repository = new FileRepositoryBuilder().setWorkTree(repositoryDirectory).build(); new WLBridgedProject(repository, name, writeLatexDataSource).buildRepository(); - } catch (FailedConnectionException e) { - e.printStackTrace(); - throw new ServiceNotEnabledException(); } catch (IOException e) { - throw new ServiceNotEnabledException(); + throw new ServiceMayNotContinueException(new InternalErrorException().getDescriptionLines().get(0)); } return repository; } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/WriteLatexAPI.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/WriteLatexAPI.java index bbbe7fda0d..d864705e4d 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/WriteLatexAPI.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/WriteLatexAPI.java @@ -69,7 +69,7 @@ public class WriteLatexAPI implements WriteLatexDataSource { } @Override - public void putDirectoryContentsToProjectWithName(String projectName, RawDirectoryContents directoryContents, String hostname) throws SnapshotPostException, IOException, FailedConnectionException { + public void putDirectoryContentsToProjectWithName(String projectName, RawDirectoryContents directoryContents, String hostname) throws SnapshotPostException, IOException { mainProjectLock.lockForProject(projectName); try { System.out.println("Pushing project: " + projectName); @@ -87,8 +87,6 @@ public class WriteLatexAPI implements WriteLatexDataSource { throw e; } catch (IOException e) { throw e; - } catch (FailedConnectionException e) { - throw e; } finally { mainProjectLock.unlockForProject(projectName); } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/base/Result.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/base/Result.java index 0226e373b3..5b23cc978d 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/base/Result.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/base/Result.java @@ -8,7 +8,7 @@ import com.google.gson.JsonElement; public abstract class Result implements JSONSource { private JsonElement json; - private final Request request; + private Request request; public Result(Request request, JsonElement json) { this.request = request; @@ -16,12 +16,20 @@ public abstract class Result implements JSONSource { fromJSON(json); } + protected Result() { + } + public Request getRequest() { return request; } + public abstract JsonElement toJson(); + @Override public String toString() { + if (json == null) { + return "result"; + } return json.toString(); } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/base/SnapshotAPIRequest.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/base/SnapshotAPIRequest.java index 3d5d3722c5..2d96ae5ec8 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/base/SnapshotAPIRequest.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/base/SnapshotAPIRequest.java @@ -32,7 +32,7 @@ public abstract class SnapshotAPIRequest extends Request { /* baseURL ends with / */ public static void setBaseURL(String baseURL) { - BASE_URL = baseURL + "/docs/"; + BASE_URL = baseURL + "docs/"; } } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/exception/FailedConnectionException.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/exception/FailedConnectionException.java index baf3685181..2e003e29d4 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/exception/FailedConnectionException.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/exception/FailedConnectionException.java @@ -1,7 +1,15 @@ package uk.ac.ic.wlgitbridge.writelatex.api.request.exception; +import org.eclipse.jgit.transport.ServiceMayNotContinueException; +import uk.ac.ic.wlgitbridge.util.Util; + /** * Created by Winston on 08/11/14. */ -public class FailedConnectionException extends Exception { +public class FailedConnectionException extends ServiceMayNotContinueException { + + public FailedConnectionException() { + super(Util.getServiceName() + " server not available. Please try again later."); + } + } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getdoc/SnapshotGetDocResult.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getdoc/SnapshotGetDocResult.java index fbb3fe2579..93f2ce0f44 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getdoc/SnapshotGetDocResult.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getdoc/SnapshotGetDocResult.java @@ -23,6 +23,25 @@ public class SnapshotGetDocResult extends Result { super(request, json); } + public SnapshotGetDocResult(int versionID, String createdAt, String email, String name) { + this.versionID = versionID; + this.createdAt = createdAt; + this.name = name; + this.email = email; + } + + @Override + public JsonElement toJson() { + JsonObject jsonThis = new JsonObject(); + jsonThis.addProperty("latestVerId", versionID); + jsonThis.addProperty("latestVerAt", createdAt); + JsonObject latestVerBy = new JsonObject(); + latestVerBy.addProperty("email", email); + latestVerBy.addProperty("name", name); + jsonThis.add("latestVerBy", latestVerBy); + return jsonThis; + } + @Override public void fromJSON(JsonElement json) { JsonObject jsonObject = json.getAsJsonObject(); diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getdoc/exception/InvalidProjectException.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getdoc/exception/InvalidProjectException.java index 237586f26a..53d22ea829 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getdoc/exception/InvalidProjectException.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getdoc/exception/InvalidProjectException.java @@ -1,9 +1,11 @@ package uk.ac.ic.wlgitbridge.writelatex.api.request.getdoc.exception; +import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import uk.ac.ic.wlgitbridge.writelatex.api.request.push.exception.SnapshotPostException; +import java.util.LinkedList; import java.util.List; /** @@ -11,26 +13,34 @@ import java.util.List; */ public class InvalidProjectException extends SnapshotPostException { + private List errors; + public InvalidProjectException(JsonObject json) { super(json); } public InvalidProjectException() { super(); + errors = new LinkedList(); } @Override public String getMessage() { - return null; + return "invalid project"; } @Override public List getDescriptionLines() { - return null; + return errors; } @Override public void fromJSON(JsonElement json) { - + errors = new LinkedList(); + JsonArray errors = json.getAsJsonObject().get("errors").getAsJsonArray(); + System.out.println(errors); + for (JsonElement error : errors) { + this.errors.add(error.getAsString()); + } } } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotAttachment.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotAttachment.java index a6efebbede..aea8cc7287 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotAttachment.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotAttachment.java @@ -2,6 +2,7 @@ package uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion; import com.google.gson.JsonArray; import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; /** * Created by Winston on 06/11/14. @@ -14,6 +15,19 @@ public class SnapshotAttachment extends SnapshotFile { super(json); } + public SnapshotAttachment(String url, String path) { + super(null, path); + this.url = url; + } + + @Override + public JsonElement toJson() { + JsonArray jsonThis = new JsonArray(); + jsonThis.add(new JsonPrimitive(url)); + jsonThis.add(new JsonPrimitive(getPath())); + return jsonThis; + } + @Override public byte[] getContents() { return null; diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotData.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotData.java index cb42aaf23c..fcf954e396 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotData.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotData.java @@ -2,6 +2,7 @@ package uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion; import com.google.gson.JsonArray; import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import uk.ac.ic.wlgitbridge.writelatex.api.request.base.JSONSource; import java.util.LinkedList; @@ -24,6 +25,26 @@ public class SnapshotData implements JSONSource { fromJSON(json); } + public SnapshotData(List srcs, List atts) { + this.srcs = srcs; + this.atts = atts; + } + + public JsonElement toJson() { + JsonObject jsonThis = new JsonObject(); + JsonArray jsonSrcs = new JsonArray(); + for (SnapshotFile src : srcs) { + jsonSrcs.add(src.toJson()); + } + jsonThis.add("srcs", jsonSrcs); + JsonArray jsonAtts = new JsonArray(); + for (SnapshotAttachment att : atts) { + jsonAtts.add(att.toJson()); + } + jsonThis.add("atts", jsonAtts); + return jsonThis; + } + @Override public void fromJSON(JsonElement json) { populateSrcs(json.getAsJsonObject().get(JSON_KEY_SRCS).getAsJsonArray()); diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotFile.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotFile.java index 05f2dbc3ea..93b41b16c7 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotFile.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotFile.java @@ -2,6 +2,7 @@ package uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion; import com.google.gson.JsonArray; import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; import uk.ac.ic.wlgitbridge.bridge.RawFile; import uk.ac.ic.wlgitbridge.writelatex.api.request.base.JSONSource; @@ -17,6 +18,20 @@ public class SnapshotFile implements JSONSource, RawFile { fromJSON(json); } + public SnapshotFile(String contents, String path) { + this.path = path; + if (contents != null) { + this.contents = contents.getBytes(); + } + } + + public JsonElement toJson() { + JsonArray jsonThis = new JsonArray(); + jsonThis.add(new JsonPrimitive(new String(contents))); + jsonThis.add(new JsonPrimitive(path)); + return jsonThis; + } + @Override public String getPath() { return path; diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotGetForVersionResult.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotGetForVersionResult.java index 629139dd1d..27e6e595c6 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotGetForVersionResult.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotGetForVersionResult.java @@ -3,7 +3,6 @@ package uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion; import com.google.gson.JsonElement; import uk.ac.ic.wlgitbridge.writelatex.api.request.base.Request; import uk.ac.ic.wlgitbridge.writelatex.api.request.base.Result; -import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException; /** * Created by Winston on 06/11/14. @@ -16,6 +15,15 @@ public class SnapshotGetForVersionResult extends Result { super(request, json); } + public SnapshotGetForVersionResult(SnapshotData snapshotData) { + this.snapshotData = snapshotData; + } + + @Override + public JsonElement toJson() { + return snapshotData.toJson(); + } + @Override public void fromJSON(JsonElement json) { snapshotData = new SnapshotData(json); diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getsavedvers/SnapshotGetSavedVersResult.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getsavedvers/SnapshotGetSavedVersResult.java index 43993f4277..a2c5732b78 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getsavedvers/SnapshotGetSavedVersResult.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getsavedvers/SnapshotGetSavedVersResult.java @@ -1,7 +1,9 @@ package uk.ac.ic.wlgitbridge.writelatex.api.request.getsavedvers; import com.google.gson.Gson; +import com.google.gson.JsonArray; import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import uk.ac.ic.wlgitbridge.writelatex.api.request.base.Request; import uk.ac.ic.wlgitbridge.writelatex.api.request.base.Result; import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException; @@ -20,6 +22,28 @@ public class SnapshotGetSavedVersResult extends Result { super(request, json); } + public SnapshotGetSavedVersResult(List savedVers) { + this.savedVers = savedVers; + } + + @Override + public JsonElement toJson() { + JsonArray jsonThis = new JsonArray(); + for (SnapshotInfo savedVer : savedVers) { + JsonObject jsonSavedVer = new JsonObject(); + jsonSavedVer.addProperty("versionId", savedVer.getVersionId()); + jsonSavedVer.addProperty("comment", savedVer.getComment()); + WLUser user = savedVer.getUser(); + JsonObject jsonUser = new JsonObject(); + jsonUser.addProperty("email", user.getEmail()); + jsonUser.addProperty("name", user.getName()); + jsonSavedVer.add("user", jsonUser); + jsonSavedVer.addProperty("createdAt", savedVer.getCreatedAt()); + jsonThis.add(jsonSavedVer); + } + return jsonThis; + } + @Override public void fromJSON(JsonElement json) { savedVers = new LinkedList(); diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getsavedvers/SnapshotInfo.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getsavedvers/SnapshotInfo.java index f5359bbd70..9006f0deee 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getsavedvers/SnapshotInfo.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/getsavedvers/SnapshotInfo.java @@ -13,8 +13,12 @@ public class SnapshotInfo { private String createdAt; public SnapshotInfo(int versionID, String createdAt, String name, String email) { - this.versionId = versionID; - comment = "Update on " + Util.getServiceName() + "."; + this(versionID, "Update on " + Util.getServiceName() + ".", name, email, createdAt); + } + + public SnapshotInfo(int versionID, String comment, String email, String name, String createdAt) { + versionId = versionID; + this.comment = comment; user = new WLUser(name, email); this.createdAt = createdAt; } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/PostbackContents.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/PostbackContents.java index 20f854e621..f0bc388430 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/PostbackContents.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/PostbackContents.java @@ -1,14 +1,22 @@ package uk.ac.ic.wlgitbridge.writelatex.api.request.push; +import uk.ac.ic.wlgitbridge.writelatex.api.request.push.exception.InternalErrorException; import uk.ac.ic.wlgitbridge.writelatex.api.request.push.exception.InvalidPostbackKeyException; +import uk.ac.ic.wlgitbridge.writelatex.api.request.push.exception.PostbackTimeoutException; import uk.ac.ic.wlgitbridge.writelatex.api.request.push.exception.SnapshotPostException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + /** * Created by Winston on 17/11/14. */ public class PostbackContents { private final String postbackKey; + private final ReentrantLock lock; + private final Condition cond; private boolean received; private int versionID; @@ -16,37 +24,57 @@ public class PostbackContents { public PostbackContents(String postbackKey) { this.postbackKey = postbackKey; + lock = new ReentrantLock(); + cond = lock.newCondition(); received = false; exception = null; } - public synchronized int waitForPostback() throws SnapshotPostException { - while (!received) { - try { - wait(); - } catch (InterruptedException e) { - e.printStackTrace(); + public int waitForPostback() throws SnapshotPostException { + lock.lock(); + try { + while (!received) { + try { + if (!cond.await(30, TimeUnit.SECONDS)) { + throw new PostbackTimeoutException(); + } + } catch (InterruptedException e) { + e.printStackTrace(); + throw new InternalErrorException(); + } } - } - if (exception != null) { - throw exception; - } - return versionID; - } - - public synchronized void receivedVersionID(int versionID, String postbackKey) { - if (postbackKey.equals(this.postbackKey)) { - this.versionID = versionID; - received = true; - notifyAll(); + if (exception != null) { + throw exception; + } + return versionID; + } finally { + lock.unlock(); } } - public synchronized void receivedException(SnapshotPostException exception, String postbackKey) { - if (postbackKey.equals(this.postbackKey)) { - this.exception = exception; - received = true; - notifyAll(); + public void receivedVersionID(int versionID, String postbackKey) { + lock.lock(); + try { + if (postbackKey.equals(this.postbackKey)) { + this.versionID = versionID; + received = true; + cond.signalAll(); + } + } finally { + lock.unlock(); + } + } + + public void receivedException(SnapshotPostException exception, String postbackKey) { + lock.lock(); + try { + if (postbackKey.equals(this.postbackKey)) { + this.exception = exception; + received = true; + cond.signalAll(); + } + } finally { + lock.unlock(); } } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/PostbackManager.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/PostbackManager.java index 9e0fea863d..843a53e455 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/PostbackManager.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/PostbackManager.java @@ -23,9 +23,13 @@ public class PostbackManager { } public int getVersionID(String projectName) throws SnapshotPostException { - int versionID = postbackContentsTable.get(projectName).waitForPostback(); - postbackContentsTable.remove(projectName); - return versionID; + try { + return postbackContentsTable.get(projectName).waitForPostback(); + } catch (SnapshotPostException e) { + throw e; + } finally { + postbackContentsTable.remove(projectName); + } } public void postVersionIDForProject(String projectName, int versionID, String postbackKey) throws UnexpectedPostbackException { diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/SnapshotPushRequestResult.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/SnapshotPushRequestResult.java index 9d40674cd5..ec25cbea22 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/SnapshotPushRequestResult.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/SnapshotPushRequestResult.java @@ -17,6 +17,11 @@ public class SnapshotPushRequestResult extends Result { super(request, json); } + @Override + public JsonElement toJson() { + return null; + } + public boolean wasSuccessful() { return success; } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/exception/InternalErrorException.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/exception/InternalErrorException.java new file mode 100644 index 0000000000..5aa3011f2e --- /dev/null +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/exception/InternalErrorException.java @@ -0,0 +1,30 @@ +package uk.ac.ic.wlgitbridge.writelatex.api.request.push.exception; + +import com.google.gson.JsonElement; +import uk.ac.ic.wlgitbridge.util.Util; + +import java.util.Arrays; +import java.util.List; + +/** + * Created by Winston on 09/01/15. + */ +public class InternalErrorException extends SnapshotPostException { + + @Override + public String getMessage() { + return "internal error"; + } + + @Override + public List getDescriptionLines() { + return Arrays.asList("There as an internal error with the Git server.", + "Please contact " + Util.getServiceName() + "."); + } + + @Override + public void fromJSON(JsonElement json) { + + } + +} diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/exception/PostbackTimeoutException.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/exception/PostbackTimeoutException.java new file mode 100644 index 0000000000..cea41d61e1 --- /dev/null +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/api/request/push/exception/PostbackTimeoutException.java @@ -0,0 +1,29 @@ +package uk.ac.ic.wlgitbridge.writelatex.api.request.push.exception; + +import com.google.gson.JsonElement; +import uk.ac.ic.wlgitbridge.util.Util; + +import java.util.Arrays; +import java.util.List; + +/** + * Created by Winston on 09/01/15. + */ +public class PostbackTimeoutException extends SnapshotPostException { + + @Override + public String getMessage() { + return "timeout"; + } + + @Override + public List getDescriptionLines() { + return Arrays.asList("The " + Util.getServiceName() + " server is currently unavailable.", "Please try again later."); + } + + @Override + public void fromJSON(JsonElement json) { + + } + +}