Implemented mock snapshot server.

This commit is contained in:
Winston Li 2015-01-10 08:41:14 +00:00
parent 2310aa124f
commit 26e2b1262d
51 changed files with 1109 additions and 159 deletions

View file

@ -1,9 +1,9 @@
{ {
"port": 80, "port": 80,
"rootGitDirectory": "/var/wlgb/git", "rootGitDirectory": "/var/wlgb/git",
"apiBaseUrl": "https://www.overleaf.com/api/v0", "apiBaseUrl": "http://127.0.0.1:60000/api/v0",
"username": "REDACTED", "username": "REDACTED",
"password": "REDACTED", "password": "REDACTED",
"postbackBaseUrl": "http://your-server-name-for-postbacks", "postbackBaseUrl": "http://127.0.0.1",
"serviceName": "Overleaf" "serviceName": "Overleaf"
} }

View file

@ -25,25 +25,24 @@ public class AttsResourceHandler extends ResourceHandler {
@Override @Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
HttpURI uri = baseRequest.getUri(); String method = baseRequest.getMethod();
System.out.println(baseRequest.getMethod() + " " + uri); if (method.equals("GET")) {
MultiMap<String> multimap = new MultiMap<String>(); HttpURI uri = baseRequest.getUri();
uri.decodeQueryTo(multimap); System.out.println(method + " " + uri);
String[] pathSections = uri.getPath().split("/"); MultiMap<String> multimap = new MultiMap<String>();
String key = multimap.getString("key"); uri.decodeQueryTo(multimap);
if (key == null || pathSections.length < 2) { String[] pathSections = uri.getPath().split("/");
throw new ServletException(); 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);
} }
} }

View file

@ -1,5 +1,7 @@
package uk.ac.ic.wlgitbridge.application; 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.Request;
import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.AbstractHandler;
import uk.ac.ic.wlgitbridge.bridge.WriteLatexDataSource; import uk.ac.ic.wlgitbridge.bridge.WriteLatexDataSource;
@ -24,22 +26,45 @@ public class SnapshotPushPostbackHandler extends AbstractHandler {
@Override @Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { 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()); try {
String[] parts = request.getRequestURI().split("/"); if (request.getMethod().equals("POST") && target.endsWith("postback")) {
if (parts.length < 4) { response.setContentType("application/json");
throw new ServletException(); 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]; } catch (IOException e) {
String postbackKey = parts[2]; e.printStackTrace();
System.out.println("Postback received for project: " + projectName); throw e;
SnapshotPushPostbackContents postbackContents = new SnapshotPushPostbackContents(writeLatexDataSource, projectName, postbackKey, contents); } catch (ServletException e) {
try { e.printStackTrace();
postbackContents.processPostback(); throw e;
} catch (UnexpectedPostbackException e) { } catch (RuntimeException e) {
throw new ServletException(); e.printStackTrace();
} throw e;
baseRequest.setHandled(true);
} }
} }

View file

@ -2,8 +2,7 @@ package uk.ac.ic.wlgitbridge.bridge;
import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; import org.eclipse.jgit.transport.ServiceMayNotContinueException;
import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
import java.io.File; import java.io.File;
@ -12,6 +11,6 @@ import java.io.File;
*/ */
public interface RepositorySource { public interface RepositorySource {
public Repository getRepositoryWithNameAtRootDirectory(String name, File rootDirectory) throws RepositoryNotFoundException, ServiceNotEnabledException; public Repository getRepositoryWithNameAtRootDirectory(String name, File rootDirectory) throws RepositoryNotFoundException, ServiceMayNotContinueException;
} }

View file

@ -5,8 +5,7 @@ import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; import org.eclipse.jgit.transport.ServiceMayNotContinueException;
import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
import uk.ac.ic.wlgitbridge.writelatex.api.request.getdoc.exception.InvalidProjectException; import uk.ac.ic.wlgitbridge.writelatex.api.request.getdoc.exception.InvalidProjectException;
import uk.ac.ic.wlgitbridge.writelatex.filestore.store.WLFileStore; import uk.ac.ic.wlgitbridge.writelatex.filestore.store.WLFileStore;
@ -29,7 +28,7 @@ public class WLBridgedProject {
this.writeLatexDataSource = writeLatexDataSource; this.writeLatexDataSource = writeLatexDataSource;
} }
public void buildRepository() throws RepositoryNotFoundException, ServiceNotEnabledException, FailedConnectionException { public void buildRepository() throws RepositoryNotFoundException, ServiceMayNotContinueException {
writeLatexDataSource.lockForProject(name); writeLatexDataSource.lockForProject(name);
if (repository.getObjectDatabase().exists()) { if (repository.getObjectDatabase().exists()) {
updateRepositoryFromSnapshots(repository); updateRepositoryFromSnapshots(repository);
@ -39,7 +38,7 @@ public class WLBridgedProject {
writeLatexDataSource.unlockForProject(name); writeLatexDataSource.unlockForProject(name);
} }
private void updateRepositoryFromSnapshots(Repository repository) throws ServiceNotEnabledException, RepositoryNotFoundException, FailedConnectionException { private void updateRepositoryFromSnapshots(Repository repository) throws RepositoryNotFoundException, ServiceMayNotContinueException {
List<WritableRepositoryContents> writableRepositories; List<WritableRepositoryContents> writableRepositories;
try { try {
writableRepositories = writeLatexDataSource.getWritableRepositories(name); writableRepositories = writeLatexDataSource.getWritableRepositories(name);
@ -54,24 +53,23 @@ public class WLBridgedProject {
git.commit().setAuthor(new PersonIdent(contents.getUserName(), contents.getUserEmail(), contents.getWhen(), TimeZone.getDefault())) git.commit().setAuthor(new PersonIdent(contents.getUserName(), contents.getUserEmail(), contents.getWhen(), TimeZone.getDefault()))
.setMessage(contents.getCommitMessage()) .setMessage(contents.getCommitMessage())
.call(); .call();
System.out.println(repository.getDirectory());
WLFileStore.deleteInDirectoryApartFrom(contents.getDirectory(), ".git"); WLFileStore.deleteInDirectoryApartFrom(contents.getDirectory(), ".git");
} }
} catch (GitAPIException e) { } catch (GitAPIException e) {
throw new ServiceNotEnabledException(); throw new ServiceMayNotContinueException(e);
} catch (IOException 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)) { if (!writeLatexDataSource.repositoryExists(name)) {
throw new RepositoryNotFoundException(name); throw new RepositoryNotFoundException(name);
} }
try { try {
repository.create(); repository.create();
} catch (IOException e) { } catch (IOException e) {
throw new ServiceNotEnabledException(); throw new ServiceMayNotContinueException(e);
} }
updateRepositoryFromSnapshots(repository); updateRepositoryFromSnapshots(repository);
} }

View file

@ -32,14 +32,20 @@ public class WLRepositoryResolver implements RepositoryResolver<HttpServletReque
try { try {
return repositorySource.getRepositoryWithNameAtRootDirectory(Util.removeAllSuffixes(name, "/", ".git"), rootGitDirectory); return repositorySource.getRepositoryWithNameAtRootDirectory(Util.removeAllSuffixes(name, "/", ".git"), rootGitDirectory);
} catch (RepositoryNotFoundException e) { } catch (RepositoryNotFoundException e) {
e.printStackTrace();
throw e; throw e;
/*
} catch (ServiceNotAuthorizedException e) {
cannot occur
} catch (ServiceNotEnabledException e) { } catch (ServiceNotEnabledException e) {
cannot occur
*/
} catch (ServiceMayNotContinueException e) { /* Such as FailedConnectionException */
e.printStackTrace(); e.printStackTrace();
throw e; throw e;
} catch (Throwable e) { } catch (RuntimeException e) {
e.printStackTrace(); e.printStackTrace();
System.out.println("An exception occurred"); throw new ServiceMayNotContinueException(e);
throw new ServiceNotEnabledException();
} }
} }

View file

@ -10,9 +10,10 @@ import uk.ac.ic.wlgitbridge.bridge.WriteLatexDataSource;
import uk.ac.ic.wlgitbridge.git.handler.hook.exception.ForcedPushException; import uk.ac.ic.wlgitbridge.git.handler.hook.exception.ForcedPushException;
import uk.ac.ic.wlgitbridge.git.handler.hook.exception.WrongBranchException; import uk.ac.ic.wlgitbridge.git.handler.hook.exception.WrongBranchException;
import uk.ac.ic.wlgitbridge.git.util.RepositoryObjectTreeWalker; import uk.ac.ic.wlgitbridge.git.util.RepositoryObjectTreeWalker;
import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
import uk.ac.ic.wlgitbridge.writelatex.api.request.push.exception.InternalErrorException;
import uk.ac.ic.wlgitbridge.writelatex.api.request.push.exception.OutOfDateException; import uk.ac.ic.wlgitbridge.writelatex.api.request.push.exception.OutOfDateException;
import uk.ac.ic.wlgitbridge.writelatex.api.request.push.exception.SnapshotPostException; import uk.ac.ic.wlgitbridge.writelatex.api.request.push.exception.SnapshotPostException;
import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
import java.io.IOException; import java.io.IOException;
import java.util.Collection; import java.util.Collection;
@ -36,26 +37,28 @@ public class WriteLatexPutHook implements PreReceiveHook {
try { try {
handleReceiveCommand(receivePack.getRepository(), receiveCommand); handleReceiveCommand(receivePack.getRepository(), receiveCommand);
} catch (IOException e) { } catch (IOException e) {
receivePack.sendError("IOException"); receivePack.sendError(e.getMessage());
receiveCommand.setResult(Result.REJECTED_OTHER_REASON, "I/O Exception"); receiveCommand.setResult(Result.REJECTED_OTHER_REASON, e.getMessage());
} catch (FailedConnectionException e) {
receivePack.sendError("failed connection");
receiveCommand.setResult(Result.REJECTED_OTHER_REASON, "failed connection");
} catch (OutOfDateException e) { } catch (OutOfDateException e) {
receiveCommand.setResult(Result.REJECTED_NONFASTFORWARD); receiveCommand.setResult(Result.REJECTED_NONFASTFORWARD);
} catch (SnapshotPostException e) { } catch (SnapshotPostException e) {
String message = e.getMessage(); handleSnapshotPostException(receivePack, receiveCommand, e);
receivePack.sendError(message);
for (String line : e.getDescriptionLines()) {
receivePack.sendMessage("hint: " + line);
}
receiveCommand.setResult(Result.REJECTED_OTHER_REASON, message);
} catch (Throwable t) { } catch (Throwable t) {
t.printStackTrace(); t.printStackTrace();
handleSnapshotPostException(receivePack, receiveCommand, new InternalErrorException());
} }
} }
} }
private void handleSnapshotPostException(ReceivePack receivePack, ReceiveCommand receiveCommand, SnapshotPostException e) {
String message = e.getMessage();
receivePack.sendError(message);
for (String line : e.getDescriptionLines()) {
receivePack.sendMessage("hint: " + line);
}
receiveCommand.setResult(Result.REJECTED_OTHER_REASON, message);
}
private void handleReceiveCommand(Repository repository, ReceiveCommand receiveCommand) throws IOException, SnapshotPostException, FailedConnectionException { private void handleReceiveCommand(Repository repository, ReceiveCommand receiveCommand) throws IOException, SnapshotPostException, FailedConnectionException {
checkBranch(receiveCommand); checkBranch(receiveCommand);
checkForcedPush(receiveCommand); checkForcedPush(receiveCommand);

View file

@ -0,0 +1,17 @@
package uk.ac.ic.wlgitbridge.test;
import uk.ac.ic.wlgitbridge.test.server.MockSnapshotServer;
import uk.ac.ic.wlgitbridge.test.state.SnapshotAPIState;
/**
* Created by Winston on 10/01/15.
*/
public class Main {
public static void main(String[] args) {
MockSnapshotServer server = new MockSnapshotServer();
server.setState(new SnapshotAPIState());
server.start();
}
}

View file

@ -1,46 +0,0 @@
package uk.ac.ic.wlgitbridge.test;
import org.eclipse.jetty.server.NetworkConnector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
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 SnapshotDummyServer {
private final Server server;
private int port;
public SnapshotDummyServer() {
server = new Server(0);
server.setHandler(new AbstractHandler() {
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
response.getWriter().println(target);
baseRequest.setHandled(true);
}
});
}
public void start() {
try {
server.start();
} catch (Exception e) {
e.printStackTrace();
}
port = ((NetworkConnector) server.getConnectors()[0]).getLocalPort();
System.out.println(port);
}
public static void main(String[] args) {
new SnapshotDummyServer().start();
}
}

View file

@ -0,0 +1,12 @@
package uk.ac.ic.wlgitbridge.test.exception;
/**
* Created by Winston on 09/01/15.
*/
public class InvalidAPICallException extends Exception {
public InvalidAPICallException(String target) {
super(target);
}
}

View file

@ -0,0 +1,14 @@
package uk.ac.ic.wlgitbridge.test.response;
/**
* Created by Winston on 09/01/15.
*/
public abstract class SnapshotResponse {
public abstract String respond();
public String postback() {
return null;
}
}

View file

@ -0,0 +1,57 @@
package uk.ac.ic.wlgitbridge.test.response;
import uk.ac.ic.wlgitbridge.test.exception.InvalidAPICallException;
import uk.ac.ic.wlgitbridge.test.response.getdoc.SnapshotGetDocResponse;
import uk.ac.ic.wlgitbridge.test.response.getforver.SnapshotGetForVerResponse;
import uk.ac.ic.wlgitbridge.test.response.getsavedver.SnapshotGetSavedVersResponse;
import uk.ac.ic.wlgitbridge.test.response.push.SnapshotPushResponse;
import uk.ac.ic.wlgitbridge.test.state.SnapshotAPIState;
/**
* Created by Winston on 09/01/15.
*/
public class SnapshotResponseBuilder {
private SnapshotAPIState state;
public SnapshotResponse buildWithTarget(String target, String method) throws InvalidAPICallException {
checkPrefix(target);
return parseTarget(target, target.split("/"), method);
}
private void checkPrefix(String target) throws InvalidAPICallException {
if (!target.startsWith("/api/v0/docs/")) {
throw new InvalidAPICallException(target);
}
}
private SnapshotResponse parseTarget(String target, String[] parts, String method) throws InvalidAPICallException {
String projectName = parts[4];
if (parts.length == 5) {
if (method.equals("GET")) {
return new SnapshotGetDocResponse(state.getStateForGetDoc(projectName));
}
} else if (parts.length == 6) {
String type = parts[5];
if (type.equals("snapshots") && method.equals("POST")) {
return new SnapshotPushResponse(state.getStateForPush(projectName), state.getStateForPostback(projectName));
} else if (type.equals("saved_vers") && method.equals("GET")) {
return new SnapshotGetSavedVersResponse(state.getStateForGetSavedVers(projectName));
}
} else if (parts.length == 7) {
if (parts[5].equals("snapshots") && method.equals("GET")) {
try {
return new SnapshotGetForVerResponse(state.getStateForGetForVers(projectName, Integer.parseInt(parts[6])));
} catch (NumberFormatException e) {
}
}
}
throw new InvalidAPICallException(target);
}
public void setState(SnapshotAPIState state) {
this.state = state;
}
}

View file

@ -0,0 +1,22 @@
package uk.ac.ic.wlgitbridge.test.response.getdoc;
import uk.ac.ic.wlgitbridge.test.response.SnapshotResponse;
import uk.ac.ic.wlgitbridge.writelatex.api.request.getdoc.SnapshotGetDocResult;
/**
* Created by Winston on 09/01/15.
*/
public class SnapshotGetDocResponse extends SnapshotResponse {
private final SnapshotGetDocResult state;
public SnapshotGetDocResponse(SnapshotGetDocResult state) {
this.state = state;
}
@Override
public String respond() {
return state.toJson().toString();
}
}

View file

@ -0,0 +1,22 @@
package uk.ac.ic.wlgitbridge.test.response.getforver;
import uk.ac.ic.wlgitbridge.test.response.SnapshotResponse;
import uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion.SnapshotGetForVersionResult;
/**
* Created by Winston on 09/01/15.
*/
public class SnapshotGetForVerResponse extends SnapshotResponse {
private final SnapshotGetForVersionResult state;
public SnapshotGetForVerResponse(SnapshotGetForVersionResult state) {
this.state = state;
}
@Override
public String respond() {
return state.toJson().toString();
}
}

View file

@ -0,0 +1,22 @@
package uk.ac.ic.wlgitbridge.test.response.getsavedver;
import uk.ac.ic.wlgitbridge.test.response.SnapshotResponse;
import uk.ac.ic.wlgitbridge.writelatex.api.request.getsavedvers.SnapshotGetSavedVersResult;
/**
* Created by Winston on 09/01/15.
*/
public class SnapshotGetSavedVersResponse extends SnapshotResponse {
private final SnapshotGetSavedVersResult state;
public SnapshotGetSavedVersResponse(SnapshotGetSavedVersResult state) {
this.state = state;
}
@Override
public String respond() {
return state.toJson().toString();
}
}

View file

@ -0,0 +1,34 @@
package uk.ac.ic.wlgitbridge.test.response.push;
import uk.ac.ic.wlgitbridge.test.response.SnapshotResponse;
import uk.ac.ic.wlgitbridge.test.response.push.postback.SnapshotPostbackRequest;
import uk.ac.ic.wlgitbridge.test.response.push.data.SnapshotPushResult;
/**
* Created by Winston on 09/01/15.
*/
public class SnapshotPushResponse extends SnapshotResponse {
private final SnapshotPushResult stateForPush;
private final SnapshotPostbackRequest stateForPostback;
public SnapshotPushResponse(SnapshotPushResult stateForPush, SnapshotPostbackRequest stateForPostback) {
this.stateForPush = stateForPush;
this.stateForPostback = stateForPostback;
}
@Override
public String respond() {
return stateForPush.toJson().toString();
}
@Override
public String postback() {
if (stateForPush.hasPostback()) {
return stateForPostback.toJson().toString();
} else {
return null;
}
}
}

View file

@ -0,0 +1,31 @@
package uk.ac.ic.wlgitbridge.test.response.push.data;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
/**
* Created by Winston on 09/01/15.
*/
public abstract class SnapshotPushResult {
private final int status;
private final String code;
private final String message;
public SnapshotPushResult(int status, String code, String message) {
this.status = status;
this.code = code;
this.message = message;
}
public JsonElement toJson() {
JsonObject jsonThis = new JsonObject();
jsonThis.addProperty("status", status);
jsonThis.addProperty("code", code);
jsonThis.addProperty("message", message);
return jsonThis;
}
public abstract boolean hasPostback();
}

View file

@ -0,0 +1,17 @@
package uk.ac.ic.wlgitbridge.test.response.push.data;
/**
* Created by Winston on 09/01/15.
*/
public class SnapshotPushResultOutOfDate extends SnapshotPushResult {
public SnapshotPushResultOutOfDate() {
super(409, "outOfDate", "Out of Date");
}
@Override
public boolean hasPostback() {
return false;
}
}

View file

@ -0,0 +1,17 @@
package uk.ac.ic.wlgitbridge.test.response.push.data;
/**
* Created by Winston on 09/01/15.
*/
public class SnapshotPushResultSuccess extends SnapshotPushResult {
public SnapshotPushResultSuccess() {
super(402, "accepted", "Accepted");
}
@Override
public boolean hasPostback() {
return true;
}
}

View file

@ -0,0 +1,22 @@
package uk.ac.ic.wlgitbridge.test.response.push.postback;
import com.google.gson.JsonObject;
/**
* Created by Winston on 09/01/15.
*/
public abstract class SnapshotPostbackRequest {
private final String code;
public SnapshotPostbackRequest(String code) {
this.code = code;
}
public JsonObject toJson() {
JsonObject jsonThis = new JsonObject();
jsonThis.addProperty("code", code);
return jsonThis;
}
}

View file

@ -0,0 +1,21 @@
package uk.ac.ic.wlgitbridge.test.response.push.postback;
import com.google.gson.JsonObject;
/**
* Created by Winston on 10/01/15.
*/
public class SnapshotPostbackRequestError extends SnapshotPostbackRequest {
public SnapshotPostbackRequestError() {
super("error");
}
@Override
public JsonObject toJson() {
JsonObject jsonThis = super.toJson();
jsonThis.addProperty("message", "Unexpected Error");
return jsonThis;
}
}

View file

@ -0,0 +1,32 @@
package uk.ac.ic.wlgitbridge.test.response.push.postback;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import uk.ac.ic.wlgitbridge.test.response.push.postback.invalidfile.InvalidFileError;
import java.util.List;
/**
* Created by Winston on 09/01/15.
*/
public class SnapshotPostbackRequestInvalidFiles extends SnapshotPostbackRequest {
private final List<InvalidFileError> errors;
public SnapshotPostbackRequestInvalidFiles(List<InvalidFileError> 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;
}
}

View file

@ -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<String> errors;
public SnapshotPostbackRequestInvalidProject(List<String> 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;
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because one or more lines are too long

View file

@ -3,11 +3,11 @@ package uk.ac.ic.wlgitbridge.writelatex;
import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder; 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.RepositorySource;
import uk.ac.ic.wlgitbridge.bridge.WLBridgedProject; import uk.ac.ic.wlgitbridge.bridge.WLBridgedProject;
import uk.ac.ic.wlgitbridge.bridge.WriteLatexDataSource; 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.File;
import java.io.IOException; import java.io.IOException;
@ -24,13 +24,9 @@ public class SnapshotRepositoryBuilder implements RepositorySource {
} }
@Override @Override
public Repository getRepositoryWithNameAtRootDirectory(String name, File rootDirectory) throws RepositoryNotFoundException, ServiceNotEnabledException { public Repository getRepositoryWithNameAtRootDirectory(String name, File rootDirectory) throws RepositoryNotFoundException, ServiceMayNotContinueException {
try { if (!writeLatexDataSource.repositoryExists(name)) {
if (!writeLatexDataSource.repositoryExists(name)) { throw new RepositoryNotFoundException(name);
throw new RepositoryNotFoundException(name);
}
} catch (FailedConnectionException e) {
throw new ServiceNotEnabledException();
} }
File repositoryDirectory = new File(rootDirectory, name); File repositoryDirectory = new File(rootDirectory, name);
@ -38,11 +34,8 @@ public class SnapshotRepositoryBuilder implements RepositorySource {
try { try {
repository = new FileRepositoryBuilder().setWorkTree(repositoryDirectory).build(); repository = new FileRepositoryBuilder().setWorkTree(repositoryDirectory).build();
new WLBridgedProject(repository, name, writeLatexDataSource).buildRepository(); new WLBridgedProject(repository, name, writeLatexDataSource).buildRepository();
} catch (FailedConnectionException e) {
e.printStackTrace();
throw new ServiceNotEnabledException();
} catch (IOException e) { } catch (IOException e) {
throw new ServiceNotEnabledException(); throw new ServiceMayNotContinueException(new InternalErrorException().getDescriptionLines().get(0));
} }
return repository; return repository;
} }

View file

@ -69,7 +69,7 @@ public class WriteLatexAPI implements WriteLatexDataSource {
} }
@Override @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); mainProjectLock.lockForProject(projectName);
try { try {
System.out.println("Pushing project: " + projectName); System.out.println("Pushing project: " + projectName);
@ -87,8 +87,6 @@ public class WriteLatexAPI implements WriteLatexDataSource {
throw e; throw e;
} catch (IOException e) { } catch (IOException e) {
throw e; throw e;
} catch (FailedConnectionException e) {
throw e;
} finally { } finally {
mainProjectLock.unlockForProject(projectName); mainProjectLock.unlockForProject(projectName);
} }

View file

@ -8,7 +8,7 @@ import com.google.gson.JsonElement;
public abstract class Result implements JSONSource { public abstract class Result implements JSONSource {
private JsonElement json; private JsonElement json;
private final Request request; private Request request;
public Result(Request request, JsonElement json) { public Result(Request request, JsonElement json) {
this.request = request; this.request = request;
@ -16,12 +16,20 @@ public abstract class Result implements JSONSource {
fromJSON(json); fromJSON(json);
} }
protected Result() {
}
public Request getRequest() { public Request getRequest() {
return request; return request;
} }
public abstract JsonElement toJson();
@Override @Override
public String toString() { public String toString() {
if (json == null) {
return "result";
}
return json.toString(); return json.toString();
} }

View file

@ -32,7 +32,7 @@ public abstract class SnapshotAPIRequest<T extends Result> extends Request<T> {
/* baseURL ends with / */ /* baseURL ends with / */
public static void setBaseURL(String baseURL) { public static void setBaseURL(String baseURL) {
BASE_URL = baseURL + "/docs/"; BASE_URL = baseURL + "docs/";
} }
} }

View file

@ -1,7 +1,15 @@
package uk.ac.ic.wlgitbridge.writelatex.api.request.exception; 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. * 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.");
}
} }

View file

@ -23,6 +23,25 @@ public class SnapshotGetDocResult extends Result {
super(request, json); 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 @Override
public void fromJSON(JsonElement json) { public void fromJSON(JsonElement json) {
JsonObject jsonObject = json.getAsJsonObject(); JsonObject jsonObject = json.getAsJsonObject();

View file

@ -1,9 +1,11 @@
package uk.ac.ic.wlgitbridge.writelatex.api.request.getdoc.exception; package uk.ac.ic.wlgitbridge.writelatex.api.request.getdoc.exception;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import uk.ac.ic.wlgitbridge.writelatex.api.request.push.exception.SnapshotPostException; import uk.ac.ic.wlgitbridge.writelatex.api.request.push.exception.SnapshotPostException;
import java.util.LinkedList;
import java.util.List; import java.util.List;
/** /**
@ -11,26 +13,34 @@ import java.util.List;
*/ */
public class InvalidProjectException extends SnapshotPostException { public class InvalidProjectException extends SnapshotPostException {
private List<String> errors;
public InvalidProjectException(JsonObject json) { public InvalidProjectException(JsonObject json) {
super(json); super(json);
} }
public InvalidProjectException() { public InvalidProjectException() {
super(); super();
errors = new LinkedList<String>();
} }
@Override @Override
public String getMessage() { public String getMessage() {
return null; return "invalid project";
} }
@Override @Override
public List<String> getDescriptionLines() { public List<String> getDescriptionLines() {
return null; return errors;
} }
@Override @Override
public void fromJSON(JsonElement json) { public void fromJSON(JsonElement json) {
errors = new LinkedList<String>();
JsonArray errors = json.getAsJsonObject().get("errors").getAsJsonArray();
System.out.println(errors);
for (JsonElement error : errors) {
this.errors.add(error.getAsString());
}
} }
} }

View file

@ -2,6 +2,7 @@ package uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
/** /**
* Created by Winston on 06/11/14. * Created by Winston on 06/11/14.
@ -14,6 +15,19 @@ public class SnapshotAttachment extends SnapshotFile {
super(json); 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 @Override
public byte[] getContents() { public byte[] getContents() {
return null; return null;

View file

@ -2,6 +2,7 @@ package uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import uk.ac.ic.wlgitbridge.writelatex.api.request.base.JSONSource; import uk.ac.ic.wlgitbridge.writelatex.api.request.base.JSONSource;
import java.util.LinkedList; import java.util.LinkedList;
@ -24,6 +25,26 @@ public class SnapshotData implements JSONSource {
fromJSON(json); fromJSON(json);
} }
public SnapshotData(List<SnapshotFile> srcs, List<SnapshotAttachment> 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 @Override
public void fromJSON(JsonElement json) { public void fromJSON(JsonElement json) {
populateSrcs(json.getAsJsonObject().get(JSON_KEY_SRCS).getAsJsonArray()); populateSrcs(json.getAsJsonObject().get(JSON_KEY_SRCS).getAsJsonArray());

View file

@ -2,6 +2,7 @@ package uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import uk.ac.ic.wlgitbridge.bridge.RawFile; import uk.ac.ic.wlgitbridge.bridge.RawFile;
import uk.ac.ic.wlgitbridge.writelatex.api.request.base.JSONSource; import uk.ac.ic.wlgitbridge.writelatex.api.request.base.JSONSource;
@ -17,6 +18,20 @@ public class SnapshotFile implements JSONSource, RawFile {
fromJSON(json); 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 @Override
public String getPath() { public String getPath() {
return path; return path;

View file

@ -3,7 +3,6 @@ package uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import uk.ac.ic.wlgitbridge.writelatex.api.request.base.Request; 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.base.Result;
import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
/** /**
* Created by Winston on 06/11/14. * Created by Winston on 06/11/14.
@ -16,6 +15,15 @@ public class SnapshotGetForVersionResult extends Result {
super(request, json); super(request, json);
} }
public SnapshotGetForVersionResult(SnapshotData snapshotData) {
this.snapshotData = snapshotData;
}
@Override
public JsonElement toJson() {
return snapshotData.toJson();
}
@Override @Override
public void fromJSON(JsonElement json) { public void fromJSON(JsonElement json) {
snapshotData = new SnapshotData(json); snapshotData = new SnapshotData(json);

View file

@ -1,7 +1,9 @@
package uk.ac.ic.wlgitbridge.writelatex.api.request.getsavedvers; package uk.ac.ic.wlgitbridge.writelatex.api.request.getsavedvers;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement; 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.Request;
import uk.ac.ic.wlgitbridge.writelatex.api.request.base.Result; import uk.ac.ic.wlgitbridge.writelatex.api.request.base.Result;
import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException; import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
@ -20,6 +22,28 @@ public class SnapshotGetSavedVersResult extends Result {
super(request, json); super(request, json);
} }
public SnapshotGetSavedVersResult(List<SnapshotInfo> 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 @Override
public void fromJSON(JsonElement json) { public void fromJSON(JsonElement json) {
savedVers = new LinkedList<SnapshotInfo>(); savedVers = new LinkedList<SnapshotInfo>();

View file

@ -13,8 +13,12 @@ public class SnapshotInfo {
private String createdAt; private String createdAt;
public SnapshotInfo(int versionID, String createdAt, String name, String email) { public SnapshotInfo(int versionID, String createdAt, String name, String email) {
this.versionId = versionID; this(versionID, "Update on " + Util.getServiceName() + ".", name, email, createdAt);
comment = "Update on " + Util.getServiceName() + "."; }
public SnapshotInfo(int versionID, String comment, String email, String name, String createdAt) {
versionId = versionID;
this.comment = comment;
user = new WLUser(name, email); user = new WLUser(name, email);
this.createdAt = createdAt; this.createdAt = createdAt;
} }

View file

@ -1,14 +1,22 @@
package uk.ac.ic.wlgitbridge.writelatex.api.request.push; 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.InvalidPostbackKeyException;
import uk.ac.ic.wlgitbridge.writelatex.api.request.push.exception.PostbackTimeoutException;
import uk.ac.ic.wlgitbridge.writelatex.api.request.push.exception.SnapshotPostException; 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. * Created by Winston on 17/11/14.
*/ */
public class PostbackContents { public class PostbackContents {
private final String postbackKey; private final String postbackKey;
private final ReentrantLock lock;
private final Condition cond;
private boolean received; private boolean received;
private int versionID; private int versionID;
@ -16,37 +24,57 @@ public class PostbackContents {
public PostbackContents(String postbackKey) { public PostbackContents(String postbackKey) {
this.postbackKey = postbackKey; this.postbackKey = postbackKey;
lock = new ReentrantLock();
cond = lock.newCondition();
received = false; received = false;
exception = null; exception = null;
} }
public synchronized int waitForPostback() throws SnapshotPostException { public int waitForPostback() throws SnapshotPostException {
while (!received) { lock.lock();
try { try {
wait(); while (!received) {
} catch (InterruptedException e) { try {
e.printStackTrace(); if (!cond.await(30, TimeUnit.SECONDS)) {
throw new PostbackTimeoutException();
}
} catch (InterruptedException e) {
e.printStackTrace();
throw new InternalErrorException();
}
} }
} if (exception != null) {
if (exception != null) { throw exception;
throw exception; }
} return versionID;
return versionID; } finally {
} lock.unlock();
public synchronized void receivedVersionID(int versionID, String postbackKey) {
if (postbackKey.equals(this.postbackKey)) {
this.versionID = versionID;
received = true;
notifyAll();
} }
} }
public synchronized void receivedException(SnapshotPostException exception, String postbackKey) { public void receivedVersionID(int versionID, String postbackKey) {
if (postbackKey.equals(this.postbackKey)) { lock.lock();
this.exception = exception; try {
received = true; if (postbackKey.equals(this.postbackKey)) {
notifyAll(); 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();
} }
} }

View file

@ -23,9 +23,13 @@ public class PostbackManager {
} }
public int getVersionID(String projectName) throws SnapshotPostException { public int getVersionID(String projectName) throws SnapshotPostException {
int versionID = postbackContentsTable.get(projectName).waitForPostback(); try {
postbackContentsTable.remove(projectName); return postbackContentsTable.get(projectName).waitForPostback();
return versionID; } catch (SnapshotPostException e) {
throw e;
} finally {
postbackContentsTable.remove(projectName);
}
} }
public void postVersionIDForProject(String projectName, int versionID, String postbackKey) throws UnexpectedPostbackException { public void postVersionIDForProject(String projectName, int versionID, String postbackKey) throws UnexpectedPostbackException {

View file

@ -17,6 +17,11 @@ public class SnapshotPushRequestResult extends Result {
super(request, json); super(request, json);
} }
@Override
public JsonElement toJson() {
return null;
}
public boolean wasSuccessful() { public boolean wasSuccessful() {
return success; return success;
} }

View file

@ -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<String> getDescriptionLines() {
return Arrays.asList("There as an internal error with the Git server.",
"Please contact " + Util.getServiceName() + ".");
}
@Override
public void fromJSON(JsonElement json) {
}
}

View file

@ -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<String> getDescriptionLines() {
return Arrays.asList("The " + Util.getServiceName() + " server is currently unavailable.", "Please try again later.");
}
@Override
public void fromJSON(JsonElement json) {
}
}