Winston Li 12 жил өмнө
parent
commit
071e0a87cc

+ 0 - 1
services/git-bridge/src/uk/ac/ic/wlgitbridge/Main.java

@@ -9,7 +9,6 @@ public class Main {
 
     public static void main(String[] args) {
         new WLGitBridgeApplication(args).run();
-
     }
 
 }

+ 14 - 2
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/node/AttachmentNode.java

@@ -3,6 +3,7 @@ package uk.ac.ic.wlgitbridge.writelatex.filestore.node;
 import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
 import uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion.SnapshotAttachment;
 import uk.ac.ic.wlgitbridge.writelatex.filestore.blob.AttachmentBlob;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.blob.ByteBlob;
 import uk.ac.ic.wlgitbridge.writelatex.filestore.store.FileIndexStore;
 import uk.ac.ic.wlgitbridge.writelatex.filestore.blob.Blob;
 import uk.ac.ic.wlgitbridge.writelatex.filestore.blob.ExternalBlob;
@@ -23,13 +24,24 @@ public class AttachmentNode extends FileNode {
         initBlob(fileIndexes);
     }
 
+    public AttachmentNode(String filePath, boolean changed, String url) {
+        super(filePath, changed);
+        this.url = url;
+    }
+
+    public AttachmentNode(String url, byte[] blob) {
+        super();
+        this.url = url;
+        this.blob = new ByteBlob(blob);
+    }
+
     @Override
-    public void handleIndexer(FileNodeIndexer fileNodeIndexer) {
+    public void indexWith(FileNodeIndexer fileNodeIndexer) {
         fileNodeIndexer.index(this);
     }
 
     @Override
-    protected Blob getBlob() {
+    public Blob getBlob() {
         return blob;
     }
 

+ 6 - 1
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/node/BlobNode.java

@@ -28,8 +28,13 @@ public class BlobNode extends FileNode {
         writeChanged(projectAttDirectory);
     }
 
+    public BlobNode(String fileName, boolean changed, byte[] blob) {
+        super(fileName, changed);
+        this.blob = new ByteBlob(blob);
+    }
+
     @Override
-    public void handleIndexer(FileNodeIndexer fileNodeIndexer) {
+    public void indexWith(FileNodeIndexer fileNodeIndexer) {
         fileNodeIndexer.index(this);
     }
 

+ 15 - 6
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/node/FileNode.java

@@ -23,17 +23,19 @@ public abstract class FileNode {
     }
 
     public FileNode(String filePath, Map<String, FileNode> context) {
-        this.filePath = filePath;
         FileNode currentFileNode = context.get(filePath);
+        this.filePath = filePath;
         changed = currentFileNode == null || !equals(currentFileNode);
     }
 
-    public String getFilePath() {
-        return filePath;
+    protected FileNode(String filePath, boolean changed) {
+        this.filePath = filePath;
+        this.changed = changed;
     }
 
-    public boolean isChanged() {
-        return changed;
+    protected FileNode() {
+        filePath = "";
+        changed = false;
     }
 
     public byte[] getContents() throws FailedConnectionException {
@@ -49,8 +51,15 @@ public abstract class FileNode {
         out.close();
     }
 
-    public abstract void handleIndexer(FileNodeIndexer fileNodeIndexer);
+    public String getFilePath() {
+        return filePath;
+    }
+
+    public boolean isChanged() {
+        return changed;
+    }
 
+    public abstract void indexWith(FileNodeIndexer indexer);
     protected abstract Blob getBlob();
 
     @Override

+ 1 - 1
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/store/FileIndexStore.java

@@ -22,7 +22,7 @@ public class FileIndexStore implements FileNodeIndexer {
         blobHashMappings = new HashMap<BlobHash, FileNode>();
         urlMappings = new HashMap<String, FileNode>();
         for (FileNode fileNode : fileNodes) {
-            fileNode.handleIndexer(this);
+            fileNode.indexWith(this);
         }
     }
 

+ 6 - 13
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/model/WLDataModel.java

@@ -9,12 +9,11 @@ import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionExc
 import uk.ac.ic.wlgitbridge.writelatex.api.request.getdoc.exception.InvalidProjectException;
 import uk.ac.ic.wlgitbridge.writelatex.api.request.push.exception.SnapshotPostException;
 import uk.ac.ic.wlgitbridge.writelatex.filestore.store.WLFileStore;
-import uk.ac.ic.wlgitbridge.writelatex.model.db.SQLiteWLDatabase;
-import uk.ac.ic.wlgitbridge.writelatex.model.db.WLDatabase;
+import uk.ac.ic.wlgitbridge.writelatex.model.db.PersistentStoreAPI;
+import uk.ac.ic.wlgitbridge.writelatex.model.db.WLGBPersistentStore;
 
 import java.io.File;
 import java.io.IOException;
-import java.sql.SQLException;
 import java.util.List;
 
 /**
@@ -22,21 +21,15 @@ import java.util.List;
  */
 public class WLDataModel implements CandidateSnapshotCallback {
 
-    private WLDatabase db;
+    private final PersistentStoreAPI persistentStore;
     private final WLProjectStore projectStore;
     private final WLFileStore fileStore;
 
     public WLDataModel(String rootGitDirectoryPath) {
         File rootGitDirectory = initRootGitDirectory(rootGitDirectoryPath);
-        try {
-            db = new SQLiteWLDatabase(rootGitDirectory);
-        } catch (SQLException e) {
-            e.printStackTrace();
-        } catch (ClassNotFoundException e) {
-            e.printStackTrace();
-        }
-        projectStore = db.loadProjectStore();
-        fileStore = db.loadFileStore();
+        persistentStore = new WLGBPersistentStore(rootGitDirectory);
+        projectStore = persistentStore.loadProjectStore();
+        fileStore = persistentStore.loadFileStore();
     }
 
     public List<WritableRepositoryContents> updateProjectWithName(String name) throws FailedConnectionException, InvalidProjectException {

+ 2 - 3
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/model/WLProjectStore.java

@@ -1,6 +1,6 @@
 package uk.ac.ic.wlgitbridge.writelatex.model;
 
-import uk.ac.ic.wlgitbridge.writelatex.model.db.WLDatabase;
+import uk.ac.ic.wlgitbridge.writelatex.model.db.PersistentStoreAPI;
 import uk.ac.ic.wlgitbridge.writelatex.model.db.WLDatabaseSource;
 
 import java.util.HashMap;
@@ -29,8 +29,7 @@ public class WLProjectStore implements WLDatabaseSource {
     }
 
     @Override
-    public void initFromDatabase(WLDatabase database) {
+    public void initFromDatabase(PersistentStoreAPI database) {
 
     }
-
 }

+ 29 - 0
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/model/db/PersistentStoreAPI.java

@@ -0,0 +1,29 @@
+package uk.ac.ic.wlgitbridge.writelatex.model.db;
+
+import uk.ac.ic.wlgitbridge.writelatex.filestore.node.FileNode;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.store.WLFileStore;
+import uk.ac.ic.wlgitbridge.writelatex.model.WLProjectStore;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by Winston on 17/11/14.
+ */
+public interface PersistentStoreAPI {
+
+    public WLProjectStore loadProjectStore();
+    public WLFileStore loadFileStore();
+
+    public void addProject(String name);
+    public void addSnapshot(String projectName, int versionID);
+    public void addFileNodeBlob(String projectName, String fileName, int changed, byte[] blob);
+    public void addFileNodeExternal(String projectName, String fileName, int changed, String url);
+    public void addURLIndex(String projectName, String url, byte[] blob);
+
+    public List<String> getProjectNames();
+    public List<Integer> getVersionIDsForProjectName(String projectName);
+    public List<FileNode> getFileNodesForProjectName(String projectName);
+    public Map<String, FileNode> getURLIndexTableForProjectName(String projectName);
+
+}

+ 147 - 14
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/model/db/SQLiteWLDatabase.java

@@ -1,15 +1,20 @@
 package uk.ac.ic.wlgitbridge.writelatex.model.db;
 
-import uk.ac.ic.wlgitbridge.writelatex.filestore.store.WLFileStore;
-import uk.ac.ic.wlgitbridge.writelatex.model.WLProjectStore;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.node.AttachmentNode;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.node.BlobNode;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.node.FileNode;
 
 import java.io.File;
 import java.sql.*;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
 
 /**
  * Created by Winston on 17/11/14.
  */
-public class SQLiteWLDatabase implements WLDatabase {
+public class SQLiteWLDatabase {
 
     private static final String[] CREATE_TABLE_STATEMENTS = {
             "CREATE TABLE IF NOT EXISTS `projects` (\n" +
@@ -25,6 +30,7 @@ public class SQLiteWLDatabase implements WLDatabase {
             "CREATE TABLE IF NOT EXISTS `file_node_table` (\n" +
             "  `project_name` varchar(10) NOT NULL DEFAULT '',\n" +
             "  `file_name` varchar(255) NOT NULL DEFAULT '',\n" +
+            "  `changed` tinyint(1) NOT NULL,\n" +
             "  `is_blob` tinyint(1) NOT NULL,\n" +
             "  `blob` blob,\n" +
             "  `url` varchar(128) DEFAULT NULL,\n" +
@@ -40,12 +46,39 @@ public class SQLiteWLDatabase implements WLDatabase {
             ")"
     };
 
-    private static final String addProject =
+    private static final String ADD_PROJECT =
             "INSERT INTO `projects` (`name`) VALUES (?);\n";
+    private static final String ADD_SNAPSHOT =
+            "INSERT INTO `snapshots` (`project_name`, `version_id`) VALUES (?, ?);\n";
+    private static final String ADD_FILE_NODE_BLOB =
+            "INSERT INTO `file_node_table` (`project_name`, `file_name`, `changed`, `is_blob`, `blob`, `url`) VALUES (?, ?, ?, '1', ?, NULL);\n";
+    private static final String ADD_FILE_NODE_EXTERNAL =
+            "INSERT INTO `file_node_table` (`project_name`, `file_name`, `changed`, `is_blob`, `blob`, `url`) VALUES (?, ?, ?, '0', NULL, ?);\n";
+    private static final String ADD_URL_INDEX =
+            "INSERT INTO `url_index_store` (`project_name`, `url`, `blob`) VALUES (?, ?, ?);\n";
+
+    private static final String GET_PROJECT_NAMES =
+            "SELECT * FROM `projects`;\n";
+    private static final String GET_VERSION_IDS_FOR_PROJECT_NAME =
+            "SELECT `version_id` FROM `snapshots` WHERE `project_name` = ?";
+    private static final String GET_FILE_NODES_FOR_PROJECT_NAME =
+            "SELECT `file_name`, `changed`, `is_blob`, `blob`, `url` FROM `file_node_table` WHERE `project_name` = ?";
+    private static final String GET_URL_INDEXES_FOR_PROJECT_NAME =
+            "SELECT `url`, `blob` FROM `url_index_store` WHERE `project_name` = ?";
 
     private final File rootGitDirectory;
     private final Connection connection;
+
     private PreparedStatement addProjectStatement;
+    private PreparedStatement addSnapshotStatement;
+    private PreparedStatement addFileNodeBlobStatement;
+    private PreparedStatement addFileNodeExternalStatement;
+    private PreparedStatement addURLIndexStatement;
+
+    private PreparedStatement getProjectNamesStatement;
+    private PreparedStatement getVersionIDsForProjectNameStatement;
+    private PreparedStatement getFileNodesForProjectNameStatement;
+    private PreparedStatement getURLIndexesForProjectNameStatement;
 
     public SQLiteWLDatabase(File rootGitDirectory) throws SQLException, ClassNotFoundException {
         this.rootGitDirectory = rootGitDirectory;
@@ -55,7 +88,6 @@ public class SQLiteWLDatabase implements WLDatabase {
         connection = DriverManager.getConnection("jdbc:sqlite:" + databaseFile.getAbsolutePath());
         createTables();
         prepareStatements();
-        test();
     }
 
     private void createTables() throws SQLException {
@@ -66,28 +98,129 @@ public class SQLiteWLDatabase implements WLDatabase {
     }
 
     private void prepareStatements() throws SQLException {
-        addProjectStatement = connection.prepareStatement(addProject);
+        addProjectStatement = connection.prepareStatement(ADD_PROJECT);
+        addSnapshotStatement = connection.prepareStatement(ADD_SNAPSHOT);
+        addFileNodeBlobStatement = connection.prepareStatement(ADD_FILE_NODE_BLOB);
+        addFileNodeExternalStatement = connection.prepareStatement(ADD_FILE_NODE_EXTERNAL);
+        addURLIndexStatement = connection.prepareStatement(ADD_URL_INDEX);
+
+        getProjectNamesStatement = connection.prepareStatement(GET_PROJECT_NAMES);
+        getVersionIDsForProjectNameStatement = connection.prepareStatement(GET_VERSION_IDS_FOR_PROJECT_NAME);
+        getFileNodesForProjectNameStatement = connection.prepareStatement(GET_FILE_NODES_FOR_PROJECT_NAME);
+        getURLIndexesForProjectNameStatement = connection.prepareStatement(GET_URL_INDEXES_FOR_PROJECT_NAME);
     }
 
     public void addProject(String name) throws SQLException {
+        addProjectStatement.clearParameters();
         addProjectStatement.setString(1, name);
         addProjectStatement.executeUpdate();
-        addProjectStatement.clearParameters();
+    }
+
+    public void addSnapshot(String projectName, int versionID) throws SQLException {
+        addSnapshotStatement.clearParameters();
+        addSnapshotStatement.setString(1, projectName);
+        addSnapshotStatement.setInt(2, versionID);
+        addSnapshotStatement.executeUpdate();
+    }
+
+    public void addFileNodeBlob(String projectName, String fileName, int changed, byte[] blob) throws SQLException {
+        addFileNodeBlobStatement.clearParameters();
+        addFileNodeBlobStatement.setString(1, projectName);
+        addFileNodeBlobStatement.setString(2, fileName);
+        addFileNodeBlobStatement.setInt(3, changed);
+        addFileNodeBlobStatement.setBytes(4, blob);
+        addFileNodeBlobStatement.executeUpdate();
+    }
+
+    public void addFileNodeExternal(String projectName, String fileName, int changed, String url) throws SQLException {
+        addFileNodeExternalStatement.clearParameters();
+        addFileNodeExternalStatement.setString(1, projectName);
+        addFileNodeExternalStatement.setString(2, fileName);
+        addFileNodeExternalStatement.setInt(3, changed);
+        addFileNodeExternalStatement.setString(4, url);
+        addFileNodeExternalStatement.executeUpdate();
+    }
+
+    public void addURLIndex(String projectName, String url, byte[] blob) throws SQLException {
+        addURLIndexStatement.clearParameters();
+        addURLIndexStatement.setString(1, projectName);
+        addURLIndexStatement.setString(2, url);
+        addURLIndexStatement.setBytes(3, blob);
+        addURLIndexStatement.executeUpdate();
+    }
+
+    public List<String> getProjectNames() throws SQLException {
+        List<String> projectNames = new LinkedList<String>();
+        ResultSet results = getProjectNamesStatement.executeQuery();
+        while (results.next()) {
+            projectNames.add(results.getString("name"));
+        }
+        return projectNames;
+    }
+
+    public List<Integer> getVersionIDsForProjectName(String projectName) throws SQLException {
+        List<Integer> versionIDs = new LinkedList<Integer>();
+        getVersionIDsForProjectNameStatement.clearParameters();
+        getVersionIDsForProjectNameStatement.setString(1, projectName);
+        ResultSet results = getVersionIDsForProjectNameStatement.executeQuery();
+        while (results.next()) {
+            versionIDs.add(results.getInt("version_id"));
+        }
+        return versionIDs;
+    }
+
+    public List<FileNode> getFileNodesForProjectName(String projectName) throws SQLException {
+        List<FileNode> fileNodes = new LinkedList<FileNode>();
+        getFileNodesForProjectNameStatement.clearParameters();
+        getFileNodesForProjectNameStatement.setString(1, projectName);
+        ResultSet results = getFileNodesForProjectNameStatement.executeQuery();
+        while (results.next()) {
+            boolean isBlob = intToBoolean(results.getInt("is_blob"));
+            FileNode fileNode;
+            String fileName = results.getString("file_name");
+            boolean changed = intToBoolean(results.getInt("changed"));
+            if (isBlob) {
+                fileNode = new BlobNode(fileName, changed, results.getBytes("blob"));
+            } else {
+                fileNode = new AttachmentNode(fileName, changed, results.getString("url"));
+            }
+            fileNodes.add(fileNode);
+        }
+        return fileNodes;
+    }
+
+    public Map<String, FileNode> getURLIndexTableForProjectName(String projectName) throws SQLException {
+        Map<String, FileNode> urlIndexTable = new HashMap<String, FileNode>();
+        getURLIndexesForProjectNameStatement.clearParameters();
+        getURLIndexesForProjectNameStatement.setString(1, projectName);
+        ResultSet results = getURLIndexesForProjectNameStatement.executeQuery();
+        while (results.next()) {
+            String url = results.getString("url");
+            byte[] blob = results.getBytes("blob");
+            urlIndexTable.put(url, new AttachmentNode(url, blob));
+        }
+        return urlIndexTable;
     }
 
     private void test() throws SQLException {
         addProject("testproj12");
-        
+        addSnapshot("testproj12", 0);
+        addSnapshot("testproj12", 1);
+        addFileNodeBlob("testproj12", "filename.tex", 1, "hello".getBytes());
+        addFileNodeExternal("testproj12", "urlname.jpg", 1, "http://someurl.com/urlname.jpg");
+        addURLIndex("testproj12", "http://someurl.com/urlname.jpg", "thebytes".getBytes());
     }
 
-    @Override
-    public WLProjectStore loadProjectStore() {
-        return new WLProjectStore();
+    private static int booleanToInt(boolean b) {
+        if (b) {
+            return 1;
+        } else {
+            return 0;
+        }
     }
 
-    @Override
-    public WLFileStore loadFileStore() {
-        return new WLFileStore(rootGitDirectory);
+    private static boolean intToBoolean(int i) {
+        return i != 0;
     }
 
 }

+ 0 - 14
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/model/db/WLDatabase.java

@@ -1,14 +0,0 @@
-package uk.ac.ic.wlgitbridge.writelatex.model.db;
-
-import uk.ac.ic.wlgitbridge.writelatex.filestore.store.WLFileStore;
-import uk.ac.ic.wlgitbridge.writelatex.model.WLProjectStore;
-
-/**
- * Created by Winston on 17/11/14.
- */
-public interface WLDatabase {
-
-    public WLProjectStore loadProjectStore();
-    public WLFileStore loadFileStore();
-
-}

+ 1 - 1
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/model/db/WLDatabaseSource.java

@@ -5,6 +5,6 @@ package uk.ac.ic.wlgitbridge.writelatex.model.db;
  */
 public interface WLDatabaseSource {
 
-    public void initFromDatabase(WLDatabase database);
+    public void initFromDatabase(PersistentStoreAPI database);
 
 }

+ 122 - 0
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/model/db/WLGBPersistentStore.java

@@ -0,0 +1,122 @@
+package uk.ac.ic.wlgitbridge.writelatex.model.db;
+
+import uk.ac.ic.wlgitbridge.writelatex.filestore.node.FileNode;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.store.WLFileStore;
+import uk.ac.ic.wlgitbridge.writelatex.model.WLProjectStore;
+
+import java.io.File;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by Winston on 19/11/14.
+ */
+public class WLGBPersistentStore implements PersistentStoreAPI {
+
+    private final File rootGitDirectory;
+    private final SQLiteWLDatabase database;
+
+    public WLGBPersistentStore(File rootGitDirectory) {
+        this.rootGitDirectory = rootGitDirectory;
+        try {
+            database = new SQLiteWLDatabase(rootGitDirectory);
+        } catch (SQLException e) {
+            throw new RuntimeException(e);
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public WLProjectStore loadProjectStore() {
+        return new WLProjectStore();
+    }
+
+    @Override
+    public WLFileStore loadFileStore() {
+        return new WLFileStore(rootGitDirectory);
+    }
+
+    @Override
+    public void addProject(String name) {
+        try {
+            database.addProject(name);
+        } catch (SQLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public void addSnapshot(String projectName, int versionID) {
+        try {
+            database.addSnapshot(projectName, versionID);
+        } catch (SQLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public void addFileNodeBlob(String projectName, String fileName, int changed, byte[] blob) {
+        try {
+            database.addFileNodeBlob(projectName, fileName, changed, blob);
+        } catch (SQLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public void addFileNodeExternal(String projectName, String fileName, int changed, String url) {
+        try {
+            database.addFileNodeExternal(projectName, fileName, changed, url);
+        } catch (SQLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public void addURLIndex(String projectName, String url, byte[] blob) {
+        try {
+            database.addURLIndex(projectName, url, blob);
+        } catch (SQLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public List<String> getProjectNames() {
+        try {
+            return database.getProjectNames();
+        } catch (SQLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public List<Integer> getVersionIDsForProjectName(String projectName) {
+        try {
+            return database.getVersionIDsForProjectName(projectName);
+        } catch (SQLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public List<FileNode> getFileNodesForProjectName(String projectName) {
+        try {
+            return database.getFileNodesForProjectName(projectName);
+        } catch (SQLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public Map<String, FileNode> getURLIndexTableForProjectName(String projectName) {
+        try {
+            return database.getURLIndexTableForProjectName(projectName);
+        } catch (SQLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+}