Made SQL Servers generic.

Added MySQL Server and test.
Added partial H2 Server code.
Bulletin-Board-Client-phase_1
Arbel Deutsch Peled 2015-12-09 14:47:18 +02:00
parent 3f21f30f35
commit 76c5e6681f
16 changed files with 900 additions and 693 deletions

View File

@ -45,7 +45,11 @@ dependencies {
// Jersey for RESTful API
compile 'org.glassfish.jersey.containers:jersey-container-servlet:2.22.+'
// JDBC connections
compile 'org.xerial:sqlite-jdbc:3.7.+'
compile 'mysql:mysql-connector-java:5.1.+'
compile 'com.h2database:h2:1.0.+'
// Servlets
compile 'javax.servlet:javax.servlet-api:3.0.+'

View File

@ -1,103 +0,0 @@
package meerkat.bulletinboard.httpserver;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import meerkat.bulletinboard.BulletinBoardServer;
import meerkat.bulletinboard.sqlserver.SQLiteBulletinBoardServer;
import meerkat.comm.CommunicationException;
import meerkat.protobuf.BulletinBoardAPI.*;
public class BulletinBoardHttpServer extends HttpServlet {
public final static String DEFAULT_MEERKAT_DB = "local-instances/meerkat.db";
/**
* Auto-generated UID.
*/
private static final long serialVersionUID = -1263665607729456165L;
BulletinBoardServer bbs;
@Override
public void init(ServletConfig config) throws ServletException {
//TODO: Make this generic
bbs = new SQLiteBulletinBoardServer();
try {
bbs.init(DEFAULT_MEERKAT_DB);
} catch (CommunicationException e) {
// TODO Log error
throw new ServletException("Servlet failed to initialize: " + e.getMessage());
}
}
/**
* This procedure handles (POST) requests to post messages to the Bulletin Board.
*/
@Override
protected void doPost( HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
BulletinBoardMessage message;
try{
message = BulletinBoardMessage.newBuilder()
.mergeFrom(request.getInputStream())
.build();
} catch(Exception e){
//TODO: Log invalid request
return;
}
try {
bbs.postMessage(message);
} catch (CommunicationException e) {
// TODO Log DB communication error
}
}
/**
* This procedure handles (GET) requests which request data from the Bulletin Board.
*/
@Override
protected void doGet( HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
BulletinBoardMessage message;
try{
message = BulletinBoardMessage.newBuilder()
.mergeFrom(request.getInputStream())
.build();
} catch(Exception e){
//TODO: Log invalid request
return;
}
try {
bbs.postMessage(message);
} catch (CommunicationException e) {
// TODO Log DB communication error
}
}
@Override
public void destroy() {
try {
bbs.close();
} catch (CommunicationException e) {
// TODO Log DB communication error
}
}
}

View File

@ -1,16 +1,11 @@
package meerkat.bulletinboard.sqlserver;
import java.util.Arrays;
import java.util.List;
import java.sql.*;
import java.util.*;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.ProtocolStringList;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import meerkat.bulletinboard.BulletinBoardServer;
import meerkat.comm.CommunicationException;
import meerkat.protobuf.BulletinBoardAPI.*;
@ -19,8 +14,77 @@ import meerkat.protobuf.Crypto.SignatureVerificationKey;
import meerkat.crypto.Digest;
import meerkat.crypto.concrete.SHA256Digest;
public abstract class BulletinBoardSQLServer implements BulletinBoardServer{
/**
* This is a generic SQL implementation of the BulletinBoardServer API.
*/
public class BulletinBoardSQLServer implements BulletinBoardServer{
/**
* This interface provides the required implementation-specific data to enable an access to an actual SQL server.
* It accounts for differences in languages between SQL DB types and for the different addresses needed to access them.
*/
public interface SQLQueryProvider {
/**
* Allowed query types.
* Note that each query returned has to comply with the placeholder ("?") requirements written in its comment.
*/
public static enum QueryType {
FIND_MSG_ID, // Placeholders for: MsgId
INSERT_MSG, // Placeholders for: MsgId, Msg
INSERT_NEW_TAG, // Placeholders for: Tag
CONNECT_TAG, // Placeholders for: EntryNum, Tag
ADD_SIGNATURE, // Placeholders for: EntryNum, SignerId, Signature
GET_SIGNATURES, // Placeholders for: EntryNum
GET_MESSAGES // Placeholders for: N/A
}
/**
* This function translates a QueryType into an actual SQL query.
* @param queryType is the type of query requested
* @return a string representation of the query for the specific type of SQL database implemented.
*/
public String getSQLString(QueryType queryType) throws IllegalArgumentException;
public String getCondition(FilterType filterType) throws IllegalArgumentException;
/**
* @return the string needed in order to connect to the DB.
*/
public String getConnectionString();
/**
* This is used to get a list of queries that together create the schema needed for the DB.
* Note that these queries should not assume anything about the current state of the DB.
* In particular: they should not erase any existing tables and/or entries.
* @return The list of queries.
*/
public List<String> getSchemaCreationCommands();
/**
* This is used to get a list of queries that together delete the schema needed for the DB.
* This is useful primarily for tests, in which we want to make sure we start with a clean DB.
* @return The list of queries.
*/
public List<String> getSchemaDeletionCommands();
}
/**
* This class implements a comparator for the MessageFilter class
* The comparison is done solely by comparing the type of the filter
* This is used to sort the filters by type
*/
public class FilterTypeComparator implements Comparator<MessageFilter> {
@Override
public int compare(MessageFilter filter1, MessageFilter filter2) {
return filter1.getTypeValue() - filter2.getTypeValue();
}
}
protected SQLQueryProvider sqlQueryProvider;
protected Connection connection;
protected Digest digest;
@ -30,18 +94,52 @@ public abstract class BulletinBoardSQLServer implements BulletinBoardServer{
protected List<List<SignatureVerificationKey>> pollingCommitteeSignatureVerificationKeyArray;
protected int minCommiteeSignatures;
/**
* This method initializes the signatures but does not implement the DB connection.
* Any full (non-abstract) extension of this class should
* 1. Establish a DB connection, and
* 2. Call this procedure
* This constructor sets the type of SQL language in use.
* @param sqlQueryProvider is the provider of the SQL query strings required for actual operation of the server.
*/
public BulletinBoardSQLServer(SQLQueryProvider sqlQueryProvider) {
this.sqlQueryProvider = sqlQueryProvider;
}
private void createSchema() throws SQLException {
final int TIMEOUT = 20;
Statement statement = connection.createStatement();
statement.setQueryTimeout(TIMEOUT);
for (String command : sqlQueryProvider.getSchemaCreationCommands()) {
statement.executeUpdate(command);
}
statement.close();
}
/**
* This method initializes the signatures, connects to the DB and creates the schema (if required).
*/
@Override
public void init(String meerkatDB) throws CommunicationException {
// TODO write signature reading part.
digest = new SHA256Digest();
try{
String dbString = sqlQueryProvider.getConnectionString();
connection = DriverManager.getConnection(dbString);
} catch (SQLException e) {
throw new CommunicationException("Couldn't form a connection with the database " + e.getMessage());
}
try {
createSchema();
} catch (SQLException e) {
throw new CommunicationException("Couldn't create schema " + e.getMessage());
}
}
/**
@ -61,7 +159,29 @@ public abstract class BulletinBoardSQLServer implements BulletinBoardServer{
* This procedure makes sure that all tags in the given list have an entry in the tags table.
* @param tags
*/
protected abstract void insertNewTags(String[] tags) throws SQLException;
protected void insertNewTags(String[] tags) throws SQLException {
PreparedStatement pstmt;
String sql;
try {
sql = sqlQueryProvider.getSQLString(SQLQueryProvider.QueryType.INSERT_NEW_TAG);
pstmt = connection.prepareStatement(sql);
for (String tag : tags){
pstmt.setString(1, tag);
pstmt.addBatch();
}
pstmt.executeBatch();
pstmt.close();
} catch (SQLException e){
throw new SQLException("Error adding new tags to table: " + e.getMessage());
}
}
/**
* This procedure is used to convert a boolean to a BoolMsg.
@ -73,7 +193,7 @@ public abstract class BulletinBoardSQLServer implements BulletinBoardServer{
.setValue(b)
.build();
}
@Override
public BoolMsg postMessage(BulletinBoardMessage msg) throws CommunicationException {
@ -104,7 +224,7 @@ public abstract class BulletinBoardSQLServer implements BulletinBoardServer{
try {
sql = "SELECT EntryNum From MsgTable WHERE MsgId = ?";
sql = sqlQueryProvider.getSQLString(SQLQueryProvider.QueryType.FIND_MSG_ID);
pstmt = connection.prepareStatement(sql);
pstmt.setBytes(1, msgID);
rs = pstmt.executeQuery();
@ -115,8 +235,8 @@ public abstract class BulletinBoardSQLServer implements BulletinBoardServer{
} else{
sql = "INSERT INTO MsgTable (MsgId, Msg) VALUES(?,?)";
pstmt = connection.prepareStatement(sql);
sql = sqlQueryProvider.getSQLString(SQLQueryProvider.QueryType.INSERT_MSG);
pstmt = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
pstmt.setBytes(1, msgID);
pstmt.setBytes(2, msg.getMsg().toByteArray());
pstmt.executeUpdate();
@ -150,7 +270,7 @@ public abstract class BulletinBoardSQLServer implements BulletinBoardServer{
// Connect message to tags.
try{
sql = "INSERT OR IGNORE INTO MsgTagTable (TagId, EntryNum) SELECT TagTable.TagId, ? AS EntryNum FROM TagTable WHERE Tag = ?";
sql = sqlQueryProvider.getSQLString(SQLQueryProvider.QueryType.CONNECT_TAG);
pstmt = connection.prepareStatement(sql);
pstmt.setLong(1, entryNum);
@ -176,7 +296,7 @@ public abstract class BulletinBoardSQLServer implements BulletinBoardServer{
// Connect message to signatures.
try{
sql = "INSERT OR IGNORE INTO SignatureTable (EntryNum, SignerId, Signature) VALUES (?,?,?)";
sql = sqlQueryProvider.getSQLString(SQLQueryProvider.QueryType.ADD_SIGNATURE);
pstmt = connection.prepareStatement(sql);
pstmt.setLong(1, entryNum);
@ -197,41 +317,147 @@ public abstract class BulletinBoardSQLServer implements BulletinBoardServer{
return boolToBoolMsg(true);
}
public String testPrint(){
String s = "";
try {
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery("select * from MsgTable");
while (rs.next()) {
// read the result set
s += "entry = " + rs.getInt("EntryNum") + " \n";
s += "id = " + Arrays.toString(rs.getBytes("MsgId")) + " \n";
s += "msg = " + Arrays.toString(rs.getBytes("Msg")) + " \n";
s += "signer ID = " + Arrays.toString(rs.getBytes("SignerId")) + "\t\n<BR>";
@Override
public BulletinBoardMessageList readMessages(MessageFilterList filterList) throws CommunicationException {
PreparedStatement pstmt;
ResultSet messages, signatures;
long entryNum;
BulletinBoardMessageList.Builder resultListBuilder = BulletinBoardMessageList.newBuilder();
BulletinBoardMessage.Builder messageBuilder;
String sql;
List<MessageFilter> filters = new ArrayList<MessageFilter>(filterList.getFilterList());
int i;
boolean tagsRequired = false;
boolean signaturesRequired = false;
boolean isFirstFilter = true;
Collections.sort(filters, new FilterTypeComparator());
// Check if Tag/Signature tables are required for filtering purposes.
sql = sqlQueryProvider.getSQLString(SQLQueryProvider.QueryType.GET_MESSAGES);
// Add conditions.
if (!filters.isEmpty()){
sql += " WHERE ";
for (MessageFilter filter : filters){
if (filter.getType().getNumber() != FilterType.MAX_MESSAGES_VALUE){
if (isFirstFilter){
isFirstFilter = false;
} else{
sql += " AND ";
}
}
sql += sqlQueryProvider.getCondition(filter.getType());
}
rs = statement.executeQuery("select * from TagTable");
while (rs.next()) {
// read the result set
s += "Tag = " + rs.getString("Tag") + " \n";
s += "TagId = " + rs.getInt("TagId") + "\t\n<BR>";
}
rs = statement.executeQuery("select * from MsgTagTable");
while (rs.next()) {
// read the result set
s += "MsgId = " + Arrays.toString(rs.getBytes("MsgId")) + " \n";
s += "TagId = " + rs.getInt("TagId") + "\t\n<BR>";
}
} catch(SQLException e){
s += "Error reading from DB";
}
return s;
// Make query.
try {
pstmt = connection.prepareStatement(sql);
// Specify values for filters.
i = 1;
for (MessageFilter filter : filters){
switch (filter.getType().getNumber()){
case FilterType.EXACT_ENTRY_VALUE: // Go through.
case FilterType.MAX_ENTRY_VALUE:
pstmt.setLong(i, filter.getEntry());
i++;
break;
case FilterType.MSG_ID_VALUE: // Go through.
case FilterType.SIGNER_ID_VALUE:
pstmt.setBytes(i, filter.getId().toByteArray());
i++;
break;
case FilterType.TAG_VALUE:
pstmt.setString(i, filter.getTag());
i++;
break;
// The max-messages condition is applied as a suffix. Therefore, it is treated differently.
case FilterType.MAX_MESSAGES_VALUE:
pstmt.setLong(filters.size(), filter.getMaxMessages());
i++;
break;
}
}
// Run query.
messages = pstmt.executeQuery();
// Compile list of messages.
sql = sqlQueryProvider.getSQLString(SQLQueryProvider.QueryType.GET_SIGNATURES);
pstmt = connection.prepareStatement(sql);
while (messages.next()){
// Get entry number and retrieve signatures.
entryNum = messages.getLong(1);
pstmt.setLong(1, entryNum);
signatures = pstmt.executeQuery();
// Create message and append signatures.
messageBuilder = BulletinBoardMessage.newBuilder()
.setEntryNum(entryNum)
.setMsg(UnsignedBulletinBoardMessage.parseFrom(messages.getBytes(2)));
while (signatures.next()){
messageBuilder.addSig(Signature.parseFrom(signatures.getBytes(1)));
}
// Finalize message and add to message list.
resultListBuilder.addMessage(messageBuilder.build());
}
pstmt.close();
} catch (SQLException e){
throw new CommunicationException("Error reading messages from DB: " + e.getMessage());
} catch (InvalidProtocolBufferException e) {
throw new CommunicationException("Invalid data from DB: " + e.getMessage());
}
//Combine results and return.
return resultListBuilder.build();
}
@Override
public void close() throws CommunicationException {
try{
connection.close();
} catch (SQLException e) {
throw new CommunicationException("Couldn't close connection to the database");
}
}
}

View File

@ -1,190 +0,0 @@
package meerkat.bulletinboard.sqlserver;
import com.google.protobuf.InvalidProtocolBufferException;
import meerkat.comm.CommunicationException;
import meerkat.protobuf.BulletinBoardAPI;
import meerkat.protobuf.BulletinBoardAPI.*;
import meerkat.protobuf.Crypto.*;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* Created by Arbel Deutsch Peled on 07-Dec-15.
* This server version allows for reading of messages with several tags and/or signatures
* The superclass only allows one constraint per type.
*/
public class EnhancedSQLiteBulletinBoardServer extends SQLiteBulletinBoardServer {
/**
* This class implements a comparator for the MessageFilter class
* The comparison is done solely by comparing the type of the filter
* This is used to sort the filters by type
*/
public class FilterTypeComparator implements Comparator<MessageFilter>{
@Override
public int compare(MessageFilter filter1, MessageFilter filter2) {
return filter1.getTypeValue() - filter2.getTypeValue();
}
}
@Override
public BulletinBoardMessageList readMessages(MessageFilterList filterList) throws CommunicationException {
PreparedStatement pstmt;
ResultSet messages, signatures;
long entryNum;
BulletinBoardMessageList.Builder resultListBuilder = BulletinBoardMessageList.newBuilder();
BulletinBoardMessage.Builder messageBuilder;
String sql;
String sqlSuffix = "";
List<MessageFilter> filters = new ArrayList<MessageFilter>(filterList.getFilterList());
int i;
boolean tagsRequired = false;
boolean signaturesRequired = false;
boolean isFirstFilter = true;
Collections.sort(filters, new FilterTypeComparator());
// Check if Tag/Signature tables are required for filtering purposes.
sql = "SELECT MsgTable.EntryNum, MsgTable.Msg FROM MsgTable";
// Add conditions.
if (!filters.isEmpty()){
sql += " WHERE";
for (MessageFilter filter : filters){
if (filter.getType().getNumber() != FilterType.MAX_MESSAGES_VALUE){
if (isFirstFilter){
isFirstFilter = false;
} else{
sql += " AND";
}
}
switch (filter.getType().getNumber()){
case FilterType.EXACT_ENTRY_VALUE:
sql += " MsgTable.EntryNum = ?";
break;
case FilterType.MAX_ENTRY_VALUE:
sql += " MsgTable.EntryNum <= ?";
break;
case FilterType.MAX_MESSAGES_VALUE:
sqlSuffix += " LIMIT = ?";
break;
case FilterType.MSG_ID_VALUE:
sql += " MsgTable.MsgId = ?";
break;
case FilterType.SIGNER_ID_VALUE:
sql += " EXISTS (SELECT 1 FROM SignatureTable"
+ " WHERE SignatureTable.SignerId = ? AND SignatureTable.EntryNum = MsgTable.EntryNum)";
break;
case FilterType.TAG_VALUE:
sql += " EXISTS (SELECT 1 FROM TagTable"
+ " INNER JOIN MsgTagTable ON TagTable.TagId = MsgTagTable.TagId"
+ " WHERE TagTable.Tag = ? AND MsgTagTable.EntryNum = MsgTable.EntryNum)";
break;
}
}
sql += sqlSuffix;
}
// Make query.
try {
pstmt = connection.prepareStatement(sql);
// Specify values for filters.
i = 1;
for (MessageFilter filter : filters){
switch (filter.getType().getNumber()){
case FilterType.EXACT_ENTRY_VALUE: // Go through.
case FilterType.MAX_ENTRY_VALUE:
pstmt.setLong(i, filter.getEntry());
i++;
break;
case FilterType.MSG_ID_VALUE: // Go through.
case FilterType.SIGNER_ID_VALUE:
pstmt.setBytes(i, filter.getId().toByteArray());
i++;
break;
case FilterType.TAG_VALUE:
pstmt.setString(i, filter.getTag());
i++;
break;
// The max-messages condition is applied as a suffix. Therefore, it is treated differently.
case FilterType.MAX_MESSAGES_VALUE:
pstmt.setLong(filters.size(), filter.getMaxMessages());
i++;
break;
}
}
// Run query.
messages = pstmt.executeQuery();
// Compile list of messages.
sql = "SELECT Signature FROM SignatureTable WHERE EntryNum = ?";
pstmt = connection.prepareStatement(sql);
while (messages.next()){
// Get entry number and retrieve signatures.
entryNum = messages.getLong(1);
pstmt.setLong(1, entryNum);
signatures = pstmt.executeQuery();
// Create message and append signatures.
messageBuilder = BulletinBoardMessage.newBuilder()
.setEntryNum(entryNum)
.setMsg(UnsignedBulletinBoardMessage.parseFrom(messages.getBytes(2)));
while (signatures.next()){
messageBuilder.addSig(Signature.parseFrom(signatures.getBytes(1)));
}
// Finalize message and add to message list.
resultListBuilder.addMessage(messageBuilder.build());
}
pstmt.close();
} catch (SQLException e){
throw new CommunicationException("Error reading messages from DB: " + e.getMessage());
} catch (InvalidProtocolBufferException e) {
throw new CommunicationException("Invalid data from DB: " + e.getMessage());
}
//Combine results and return.
return resultListBuilder.build();
}
}

View File

@ -0,0 +1,111 @@
package meerkat.bulletinboard.sqlserver;
import meerkat.protobuf.BulletinBoardAPI.FilterType;
import java.util.LinkedList;
import java.util.List;
/**
* Created by Arbel Deutsch Peled on 09-Dec-15.
*/
public class H2QueryProvider implements BulletinBoardSQLServer.SQLQueryProvider {
private String dbConnectionString;
public H2QueryProvider(String dbAddress) {
dbConnectionString = "jdbc:h2:" + dbAddress + ";MODE=MYSQL";
}
@Override
public String getSQLString(QueryType queryType) throws IllegalArgumentException{
switch(queryType) {
case ADD_SIGNATURE:
return "INSERT IGNORE INTO SignatureTable (EntryNum, SignerId, Signature) VALUES (?,?,?)";
case CONNECT_TAG:
return "INSERT IGNORE INTO MsgTagTable (TagId, EntryNum)"
+ " SELECT TagTable.TagId, ? AS EntryNum FROM TagTable WHERE Tag = ?";
case FIND_MSG_ID:
return "SELECT EntryNum From MsgTable WHERE MsgId = ?";
case GET_MESSAGES:
return "SELECT MsgTable.EntryNum, MsgTable.Msg FROM MsgTable";
case GET_SIGNATURES:
return "SELECT Signature FROM SignatureTable WHERE EntryNum = ?";
case INSERT_MSG:
return "INSERT INTO MsgTable (MsgId, Msg) VALUES(?,?)";
case INSERT_NEW_TAG:
return "INSERT IGNORE INTO TagTable(Tag) VALUES (?)";
default:
throw new IllegalArgumentException("Cannot serve a query of type " + queryType);
}
}
@Override
public String getCondition(FilterType filterType) throws IllegalArgumentException {
switch(filterType) {
case EXACT_ENTRY:
return "MsgTable.EntryNum = ?";
case MAX_ENTRY:
return "MsgTable.EntryNum <= ?";
case MAX_MESSAGES:
return "LIMIT ?";
case MSG_ID:
return "MsgTable.MsgId = ?";
case SIGNER_ID:
return "EXISTS (SELECT 1 FROM SignatureTable"
+ " WHERE SignatureTable.SignerId = ? AND SignatureTable.EntryNum = MsgTable.EntryNum)";
case TAG:
return "EXISTS (SELECT 1 FROM TagTable"
+ " INNER JOIN MsgTagTable ON TagTable.TagId = MsgTagTable.TagId"
+ " WHERE TagTable.Tag = ? AND MsgTagTable.EntryNum = MsgTable.EntryNum)";
default:
throw new IllegalArgumentException("Cannot serve a filter of type " + filterType);
}
}
@Override
public String getConnectionString() {
return dbConnectionString;
}
@Override
public List<String> getSchemaCreationCommands() {
List<String> list = new LinkedList<String>();
list.add("CREATE TABLE IF NOT EXISTS MsgTable (EntryNum INT NOT NULL AUTO_INCREMENT PRIMARY KEY, MsgId TINYBLOB UNIQUE, Msg BLOB)");
list.add("CREATE TABLE IF NOT EXISTS TagTable (TagId INT NOT NULL AUTO_INCREMENT PRIMARY KEY, Tag varchar(50) UNIQUE)");
list.add("CREATE TABLE IF NOT EXISTS MsgTagTable (EntryNum INT, TagId INT,"
+ " FOREIGN KEY (EntryNum) REFERENCES MsgTable(EntryNum),"
+ " FOREIGN KEY (TagId) REFERENCES TagTable(TagId),"
+ " UNIQUE (EntryNum, TagID))");
list.add("CREATE TABLE IF NOT EXISTS SignatureTable (EntryNum INT, SignerId TINYBLOB, Signature TINYBLOB UNIQUE,"
+ " FOREIGN KEY (EntryNum) REFERENCES MsgTable(EntryNum))");
list.add("CREATE UNIQUE INDEX IF NOT EXISTS SignerIdIndex ON SignatureTable(SignerId)");
return list;
}
@Override
public List<String> getSchemaDeletionCommands() {
List<String> list = new LinkedList<String>();
list.add("DROP INDEX IF EXISTS SignerIdIndex");
list.add("DROP TABLE IF EXISTS MsgTagTable");
list.add("DROP TABLE IF EXISTS SignatureTable");
list.add("DROP TABLE IF EXISTS TagTable");
list.add("DROP TABLE IF EXISTS MsgTable");
return list;
}
}

View File

@ -0,0 +1,106 @@
package meerkat.bulletinboard.sqlserver;
import meerkat.protobuf.BulletinBoardAPI.FilterType;
import java.util.LinkedList;
import java.util.List;
/**
* Created by Arbel Deutsch Peled on 09-Dec-15.
*/
public class MySQLQueryProvider implements BulletinBoardSQLServer.SQLQueryProvider {
String dbConnectionString;
public MySQLQueryProvider(String dbAddress, String username, String password) {
dbConnectionString = "jdbc:mysql:" + dbAddress + "?user=" + username + "&password=" + password;
}
@Override
public String getSQLString(QueryType queryType) throws IllegalArgumentException{
switch(queryType) {
case ADD_SIGNATURE:
return "INSERT IGNORE INTO SignatureTable (EntryNum, SignerId, Signature) VALUES (?,?,?)";
case CONNECT_TAG:
return "INSERT IGNORE INTO MsgTagTable (TagId, EntryNum)"
+ " SELECT TagTable.TagId, ? AS EntryNum FROM TagTable WHERE Tag = ?";
case FIND_MSG_ID:
return "SELECT EntryNum From MsgTable WHERE MsgId = ?";
case GET_MESSAGES:
return "SELECT MsgTable.EntryNum, MsgTable.Msg FROM MsgTable";
case GET_SIGNATURES:
return "SELECT Signature FROM SignatureTable WHERE EntryNum = ?";
case INSERT_MSG:
return "INSERT INTO MsgTable (MsgId, Msg) VALUES(?,?)";
case INSERT_NEW_TAG:
return "INSERT IGNORE INTO TagTable(Tag) VALUES (?)";
default:
throw new IllegalArgumentException("Cannot serve a query of type " + queryType);
}
}
@Override
public String getCondition(FilterType filterType) throws IllegalArgumentException {
switch(filterType) {
case EXACT_ENTRY:
return "MsgTable.EntryNum = ?";
case MAX_ENTRY:
return "MsgTable.EntryNum <= ?";
case MAX_MESSAGES:
return "LIMIT ?";
case MSG_ID:
return "MsgTable.MsgId = ?";
case SIGNER_ID:
return "EXISTS (SELECT 1 FROM SignatureTable"
+ " WHERE SignatureTable.SignerId = ? AND SignatureTable.EntryNum = MsgTable.EntryNum)";
case TAG:
return "EXISTS (SELECT 1 FROM TagTable"
+ " INNER JOIN MsgTagTable ON TagTable.TagId = MsgTagTable.TagId"
+ " WHERE TagTable.Tag = ? AND MsgTagTable.EntryNum = MsgTable.EntryNum)";
default:
throw new IllegalArgumentException("Cannot serve a filter of type " + filterType);
}
}
@Override
public String getConnectionString() {
return dbConnectionString;
}
@Override
public List<String> getSchemaCreationCommands() {
List<String> list = new LinkedList<String>();
list.add("CREATE TABLE IF NOT EXISTS MsgTable (EntryNum INT NOT NULL AUTO_INCREMENT PRIMARY KEY, MsgId TINYBLOB, Msg BLOB, UNIQUE(MsgId(50)))");
list.add("CREATE TABLE IF NOT EXISTS TagTable (TagId INT NOT NULL AUTO_INCREMENT PRIMARY KEY, Tag varchar(50), UNIQUE(Tag))");
list.add("CREATE TABLE IF NOT EXISTS MsgTagTable (EntryNum INT, TagId INT,"
+ " CONSTRAINT FOREIGN KEY (EntryNum) REFERENCES MsgTable(EntryNum),"
+ " CONSTRAINT FOREIGN KEY (TagId) REFERENCES TagTable(TagId),"
+ " CONSTRAINT UNIQUE (EntryNum, TagID))");
list.add("CREATE TABLE IF NOT EXISTS SignatureTable (EntryNum INT, SignerId TINYBLOB, Signature TINYBLOB, UNIQUE(Signature(150)),"
+ " INDEX(SignerId(50)), CONSTRAINT FOREIGN KEY (EntryNum) REFERENCES MsgTable(EntryNum))");
return list;
}
@Override
public List<String> getSchemaDeletionCommands() {
List<String> list = new LinkedList<String>();
list.add("DROP TABLE IF EXISTS MsgTagTable");
list.add("DROP TABLE IF EXISTS SignatureTable");
list.add("DROP TABLE IF EXISTS TagTable");
list.add("DROP TABLE IF EXISTS MsgTable");
return list;
}
}

View File

@ -1,266 +0,0 @@
package meerkat.bulletinboard.sqlserver;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import com.google.protobuf.InvalidProtocolBufferException;
import meerkat.protobuf.BulletinBoardAPI.*;
import meerkat.protobuf.Crypto.Signature;
import meerkat.bulletinboard.sqlserver.BulletinBoardSQLServer;
import meerkat.comm.CommunicationException;
public class SQLiteBulletinBoardServer extends BulletinBoardSQLServer {
protected static final int TIMEOUT = 20;
/**
* This procedure initializes:
* 1. The database connection
* 2. The database tables (if they do not yet exist).
*/
private void createSchema() throws SQLException {
Statement statement = connection.createStatement();
statement.setQueryTimeout(TIMEOUT);
statement.executeUpdate("CREATE TABLE IF NOT EXISTS MsgTable (EntryNum INTEGER PRIMARY KEY, MsgId BLOB UNIQUE, Msg BLOB)");
statement.executeUpdate("CREATE TABLE IF NOT EXISTS TagTable (TagId INTEGER PRIMARY KEY, Tag varchar(50) UNIQUE)");
statement.executeUpdate("CREATE TABLE IF NOT EXISTS MsgTagTable (EntryNum BLOB, TagId INTEGER, FOREIGN KEY (EntryNum) REFERENCES MsgTable(EntryNum), FOREIGN KEY (TagId) REFERENCES TagTable(TagId), UNIQUE (EntryNum, TagID))");
statement.executeUpdate("CREATE TABLE IF NOT EXISTS SignatureTable (EntryNum BLOB, SignerId BLOB, Signature BLOB UNIQUE, FOREIGN KEY (EntryNum) REFERENCES MsgTable(EntryNum))");
statement.executeUpdate("CREATE INDEX IF NOT EXISTS SignerIndex ON SignatureTable(SignerId)");
statement.close();
}
@Override
public void init(String meerkatDB) throws CommunicationException {
try{
String dbString = "jdbc:sqlite:" + meerkatDB;
connection = DriverManager.getConnection(dbString);
createSchema();
super.init(meerkatDB);
} catch (SQLException e) {
throw new CommunicationException("Couldn't form a connection with the database" + e.getMessage());
}
}
public void close() throws CommunicationException{
try{
connection.close();
} catch (SQLException e) {
throw new CommunicationException("Couldn't close connection to the database");
}
}
@Override
protected void insertNewTags(String[] tags) throws SQLException {
PreparedStatement pstmt;
String sql;
try {
sql = "INSERT OR IGNORE INTO TagTable(Tag) VALUES (?)";
pstmt = connection.prepareStatement(sql);
for (String tag : tags){
pstmt.setString(1, tag);
pstmt.addBatch();
}
pstmt.executeBatch();
pstmt.close();
} catch (SQLException e){
throw new SQLException("Error adding new tags to table: " + e.getMessage());
}
}
@Override
public BoolMsg postMessage(BulletinBoardMessage msg) throws CommunicationException {
return super.postMessage(msg);
}
@Override
public BulletinBoardMessageList readMessages(MessageFilterList filterList) throws CommunicationException{
PreparedStatement pstmt;
ResultSet messages, signatures;
long entryNum;
BulletinBoardMessageList.Builder resultListBuilder = BulletinBoardMessageList.newBuilder();
BulletinBoardMessage.Builder messageBuilder;
String sql;
String sqlSuffix = "";
List<MessageFilter> filters = filterList.getFilterList();
int i;
boolean tagsRequired = false;
boolean signaturesRequired = false;
boolean isFirstFilter = true;
// Check if Tag/Signature tables are required for filtering purposes.
for (MessageFilter filter : filters){
if (filter.getType() == FilterType.TAG){
tagsRequired = true;
} else if (filter.getType() == FilterType.SIGNER_ID){
signaturesRequired = true;
}
}
sql = "SELECT MsgTable.EntryNum, MsgTable.Msg FROM MsgTable";
if (tagsRequired){
sql += " INNER JOIN MsgTagTable ON MsgTable.EntryNum = MsgTagTable.EntryNum";
sql += " INNER JOIN TagTable ON TagTable.TagId = MsgTagTable.TagId";
}
if (signaturesRequired){
sql += " INNER JOIN SignatureTable ON SignatureTable.EntryNum = MsgTable.EntryNum";
}
// Add conditions.
if (!filters.isEmpty()){
sql += " WHERE";
for (MessageFilter filter : filters){
if (filter.getType().getNumber() != FilterType.MAX_MESSAGES_VALUE){
if (isFirstFilter){
isFirstFilter = false;
} else{
sql += " AND";
}
}
switch (filter.getType().getNumber()){
case FilterType.EXACT_ENTRY_VALUE:
sql += " MsgTable.EntryNum = ?";
break;
case FilterType.MAX_ENTRY_VALUE:
sql += " MsgTable.EntryNum <= ?";
break;
case FilterType.MAX_MESSAGES_VALUE:
sqlSuffix += " LIMIT = ?";
break;
case FilterType.MSG_ID_VALUE:
sql += " MsgTable.MsgId = ?";
break;
case FilterType.SIGNER_ID_VALUE:
sql += " SignatureTable.SignerId = ?";
break;
case FilterType.TAG_VALUE:
sql += " TagTable.Tag = ?";
break;
}
}
sql += sqlSuffix;
}
// Make query.
try {
pstmt = connection.prepareStatement(sql);
// Specify values for filters.
i = 1;
for (MessageFilter filter : filters){
switch (filter.getType().getNumber()){
case FilterType.EXACT_ENTRY_VALUE: // Go through.
case FilterType.MAX_ENTRY_VALUE:
pstmt.setLong(i, filter.getEntry());
i++;
break;
case FilterType.MSG_ID_VALUE: // Go through.
case FilterType.SIGNER_ID_VALUE:
pstmt.setBytes(i, filter.getId().toByteArray());
i++;
break;
case FilterType.TAG_VALUE:
pstmt.setString(i, filter.getTag());
break;
// The max-messages condition is applied as a suffix. Therefore, it is treated differently.
case FilterType.MAX_MESSAGES_VALUE:
pstmt.setLong(filters.size(), filter.getMaxMessages());
break;
}
}
// Run query.
messages = pstmt.executeQuery();
// Compile list of messages.
sql = "SELECT Signature FROM SignatureTable WHERE EntryNum = ?";
pstmt = connection.prepareStatement(sql);
while (messages.next()){
// Get entry number and retrieve signatures.
entryNum = messages.getLong(1);
pstmt.setLong(1, entryNum);
signatures = pstmt.executeQuery();
// Create message and append signatures.
messageBuilder = BulletinBoardMessage.newBuilder()
.setEntryNum(entryNum)
.setMsg(UnsignedBulletinBoardMessage.parseFrom(messages.getBytes(2)));
while (signatures.next()){
messageBuilder.addSig(Signature.parseFrom(signatures.getBytes(1)));
}
// Finalize message and add to message list.
resultListBuilder.addMessage(messageBuilder.build());
}
pstmt.close();
} catch (SQLException e){
throw new CommunicationException("Error reading messages from DB: " + e.getMessage());
} catch (InvalidProtocolBufferException e) {
throw new CommunicationException("Invalid data from DB: " + e.getMessage());
}
//Combine results and return.
return resultListBuilder.build();
}
}

View File

@ -0,0 +1,109 @@
package meerkat.bulletinboard.sqlserver;
import meerkat.protobuf.BulletinBoardAPI.*;
import java.util.LinkedList;
import java.util.List;
import static meerkat.protobuf.BulletinBoardAPI.FilterType;
/**
* Created by Arbel Deutsch Peled on 09-Dec-15.
*/
public class SQLiteQueryProvider implements BulletinBoardSQLServer.SQLQueryProvider {
String dbConnectionString;
public SQLiteQueryProvider(String dbAddress) {
dbConnectionString = "jdbc:sqlite:" + dbAddress;
}
@Override
public String getSQLString(QueryType queryType) throws IllegalArgumentException{
switch(queryType) {
case ADD_SIGNATURE:
return "INSERT OR IGNORE INTO SignatureTable (EntryNum, SignerId, Signature) VALUES (?,?,?)";
case CONNECT_TAG:
return "INSERT OR IGNORE INTO MsgTagTable (TagId, EntryNum)"
+ " SELECT TagTable.TagId, ? AS EntryNum FROM TagTable WHERE Tag = ?";
case FIND_MSG_ID:
return "SELECT EntryNum From MsgTable WHERE MsgId = ?";
case GET_MESSAGES:
return "SELECT MsgTable.EntryNum, MsgTable.Msg FROM MsgTable";
case GET_SIGNATURES:
return "SELECT Signature FROM SignatureTable WHERE EntryNum = ?";
case INSERT_MSG:
return "INSERT INTO MsgTable (MsgId, Msg) VALUES(?,?)";
case INSERT_NEW_TAG:
return "INSERT OR IGNORE INTO TagTable(Tag) VALUES (?)";
default:
throw new IllegalArgumentException("Cannot serve a query of type " + queryType);
}
}
@Override
public String getCondition(FilterType filterType) throws IllegalArgumentException {
switch(filterType) {
case EXACT_ENTRY:
return "MsgTable.EntryNum = ?";
case MAX_ENTRY:
return "MsgTable.EntryNum <= ?";
case MAX_MESSAGES:
return "LIMIT = ?";
case MSG_ID:
return "MsgTable.MsgId = ?";
case SIGNER_ID:
return "EXISTS (SELECT 1 FROM SignatureTable"
+ " WHERE SignatureTable.SignerId = ? AND SignatureTable.EntryNum = MsgTable.EntryNum)";
case TAG:
return "EXISTS (SELECT 1 FROM TagTable"
+ " INNER JOIN MsgTagTable ON TagTable.TagId = MsgTagTable.TagId"
+ " WHERE TagTable.Tag = ? AND MsgTagTable.EntryNum = MsgTable.EntryNum)";
default:
throw new IllegalArgumentException("Cannot serve a filter of type " + filterType);
}
}
@Override
public String getConnectionString() {
return dbConnectionString;
}
@Override
public List<String> getSchemaCreationCommands() {
List<String> list = new LinkedList<String>();
list.add("CREATE TABLE IF NOT EXISTS MsgTable (EntryNum INTEGER PRIMARY KEY, MsgId BLOB UNIQUE, Msg BLOB)");
list.add("CREATE TABLE IF NOT EXISTS TagTable (TagId INTEGER PRIMARY KEY, Tag varchar(50) UNIQUE)");
list.add("CREATE TABLE IF NOT EXISTS MsgTagTable (EntryNum BLOB, TagId INTEGER, FOREIGN KEY (EntryNum)"
+ " REFERENCES MsgTable(EntryNum), FOREIGN KEY (TagId) REFERENCES TagTable(TagId), UNIQUE (EntryNum, TagID))");
list.add("CREATE TABLE IF NOT EXISTS SignatureTable (EntryNum BLOB, SignerId BLOB, Signature BLOB UNIQUE,"
+ " FOREIGN KEY (EntryNum) REFERENCES MsgTable(EntryNum))");
list.add("CREATE INDEX IF NOT EXISTS SignerIndex ON SignatureTable(SignerId)");
return list;
}
@Override
public List<String> getSchemaDeletionCommands() {
List<String> list = new LinkedList<String>();
list.add("DROP TABLE IF EXISTS MsgTagTable");
list.add("DROP INDEX IF EXISTS SignerIndex");
list.add("DROP TABLE IF EXISTS SignatureTable");
list.add("DROP TABLE IF EXISTS TagTable");
list.add("DROP TABLE IF EXISTS MsgTable");
return list;
}
}

View File

@ -12,7 +12,8 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import meerkat.bulletinboard.BulletinBoardServer;
import meerkat.bulletinboard.sqlserver.SQLiteBulletinBoardServer;
import meerkat.bulletinboard.sqlserver.BulletinBoardSQLServer;
import meerkat.bulletinboard.sqlserver.SQLiteQueryProvider;
import meerkat.comm.CommunicationException;
import meerkat.protobuf.BulletinBoardAPI.BoolMsg;
import meerkat.protobuf.BulletinBoardAPI.BulletinBoardMessage;
@ -51,7 +52,7 @@ public class BulletinBoardWebApp implements BulletinBoardServer, ServletContextL
String dbType = servletContext.getInitParameter("dbtype");
if (dbType.compareTo("SQLite") == 0){
bulletinBoard = new SQLiteBulletinBoardServer();
bulletinBoard = new BulletinBoardSQLServer(new SQLiteQueryProvider(meerkatDB));
}
try {

View File

@ -1,54 +0,0 @@
package meerkat.bulletinboard;
import meerkat.bulletinboard.sqlserver.EnhancedSQLiteBulletinBoardServer;
import meerkat.comm.CommunicationException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import static org.junit.Assert.fail;
/**
* Created by Arbel Deutsch Peled on 07-Dec-15.
*/
public class EnhancedSQLiteBulletinBoardServerTest{
private String testFilename = "EnhancedSQLiteDBTest.db";
private GenericBulletinBoardServerTest serverTest;
@Before
public void init(){
File old = new File(testFilename);
old.delete();
BulletinBoardServer bulletinBoardServer = new EnhancedSQLiteBulletinBoardServer();
try {
bulletinBoardServer.init(testFilename);
} catch (CommunicationException e) {
System.err.println("Failed to initialize server " + e.getMessage());
fail("Failed to initialize server " + e.getMessage());
return;
}
serverTest = new GenericBulletinBoardServerTest();
serverTest.init(bulletinBoardServer);
}
@Test
public void bulkTest() {
System.err.println("Testing Enhanced SQLite Server");
serverTest.testInsert();
serverTest.testSimpleTagAndSignature();
}
@After
public void close() {
serverTest.close();
}
}

View File

@ -32,6 +32,7 @@ public class GenericBulletinBoardServerTest {
protected BulletinBoardServer bulletinBoardServer;
private ECDSASignature signers[];
private ByteString[] signerIDs;
private Random random;
@ -71,6 +72,7 @@ public class GenericBulletinBoardServerTest {
this.bulletinBoardServer = bulletinBoardServer;
signers = new ECDSASignature[2];
signerIDs = new ByteString[signers.length];
signers[0] = new ECDSASignature();
signers[1] = new ECDSASignature();
@ -81,17 +83,21 @@ public class GenericBulletinBoardServerTest {
try {
keyStoreBuilder = signers[0].getPKCS12KeyStoreBuilder(keyStream, password);
signers[0].loadSigningCertificate(keyStoreBuilder);
signers[0].loadVerificationCertificates(getClass().getResourceAsStream(CERT1_PEM_EXAMPLE));
keyStream = getClass().getResourceAsStream(KEYFILE_EXAMPLE3);
password = KEYFILE_PASSWORD3.toCharArray();
keyStoreBuilder = signers[1].getPKCS12KeyStoreBuilder(keyStream, password);
signers[1].loadSigningCertificate(keyStoreBuilder);
signers[1].loadVerificationCertificates(getClass().getResourceAsStream(CERT3_PEM_EXAMPLE));
signers[0].loadSigningCertificate(keyStoreBuilder);
signers[0].loadVerificationCertificates(getClass().getResourceAsStream(CERT1_PEM_EXAMPLE));
keyStream = getClass().getResourceAsStream(KEYFILE_EXAMPLE3);
password = KEYFILE_PASSWORD3.toCharArray();
keyStoreBuilder = signers[1].getPKCS12KeyStoreBuilder(keyStream, password);
signers[1].loadSigningCertificate(keyStoreBuilder);
signers[1].loadVerificationCertificates(getClass().getResourceAsStream(CERT3_PEM_EXAMPLE));
for (int i = 0 ; i < signers.length ; i++) {
signerIDs[i] = signers[i].getSignerID();
}
} catch (IOException e) {
System.err.println("Failed reading from signature file " + e.getMessage());
@ -334,7 +340,7 @@ public class GenericBulletinBoardServerTest {
assertThat(messages.size(), is(expectedMsgCount));
for (BulletinBoardMessage msg : messages) {
for (int j = 0 ; j < i ; j++) {
for (int j = 0 ; j <= i ; j++) {
assertThat((msg.getEntryNum() >>> j) % 2, is((long) 1));
}
}
@ -345,11 +351,11 @@ public class GenericBulletinBoardServerTest {
filterListBuilder = MessageFilterList.newBuilder()
.addFilter(MessageFilter.newBuilder()
.setType(FilterType.SIGNER_ID)
.setId(signers[0].getSignerID())
.setId(signerIDs[0])
.build())
.addFilter(MessageFilter.newBuilder()
.setType(FilterType.SIGNER_ID)
.setId(signers[1].getSignerID())
.setId(signerIDs[1])
.build()
);

View File

@ -0,0 +1,122 @@
package meerkat.bulletinboard;
import meerkat.bulletinboard.sqlserver.BulletinBoardSQLServer;
import meerkat.bulletinboard.sqlserver.BulletinBoardSQLServer.SQLQueryProvider;
import meerkat.bulletinboard.sqlserver.H2QueryProvider;
import meerkat.comm.CommunicationException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import static org.junit.Assert.fail;
/**
* Created by Arbel Deutsch Peled on 07-Dec-15.
*/
public class H2BulletinBoardServerTest {
private final String dbAddress = "~/meerkatTest";
private GenericBulletinBoardServerTest serverTest;
private final ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); // Used to time the tests
// @Before
public void init(){
System.err.println("Starting to initialize H2BulletinBoardServerTest");
long start = threadBean.getCurrentThreadCpuTime();
SQLQueryProvider queryProvider = new H2QueryProvider(dbAddress);
try {
Connection conn = DriverManager.getConnection(queryProvider.getConnectionString());
Statement stmt = conn.createStatement();
List<String> deletionQueries = queryProvider.getSchemaDeletionCommands();
for (String deletionQuery : deletionQueries) {
stmt.execute(deletionQuery);
}
} catch (SQLException e) {
System.err.println(e.getMessage());
fail(e.getMessage());
}
BulletinBoardServer bulletinBoardServer = new BulletinBoardSQLServer(queryProvider);
try {
bulletinBoardServer.init("");
} catch (CommunicationException e) {
System.err.println(e.getMessage());
fail(e.getMessage());
return;
}
serverTest = new GenericBulletinBoardServerTest();
try {
serverTest.init(bulletinBoardServer);
} catch (Exception e) {
System.err.println(e.getMessage());
fail(e.getMessage());
}
long end = threadBean.getCurrentThreadCpuTime();
System.err.println("Finished initializing H2BulletinBoardServerTest");
System.err.println("Time of operation: " + (end - start));
}
// @Test
public void bulkTest() {
System.err.println("Starting bulkTest of H2BulletinBoardServerTest");
long start = threadBean.getCurrentThreadCpuTime();
try {
serverTest.testInsert();
} catch (Exception e) {
System.err.println(e.getMessage());
fail(e.getMessage());
}
try{
serverTest.testSimpleTagAndSignature();
} catch (Exception e) {
System.err.println(e.getMessage());
fail(e.getMessage());
}
try{
serverTest.testEnhancedTagsAndSignatures();
} catch (Exception e) {
System.err.println(e.getMessage());
fail(e.getMessage());
}
long end = threadBean.getCurrentThreadCpuTime();
System.err.println("Finished bulkTest of H2BulletinBoardServerTest");
System.err.println("Time of operation: " + (end - start));
}
// @After
public void close() {
System.err.println("Starting to close H2BulletinBoardServerTest");
long start = threadBean.getCurrentThreadCpuTime();
serverTest.close();
long end = threadBean.getCurrentThreadCpuTime();
System.err.println("Finished closing H2BulletinBoardServerTest");
System.err.println("Time of operation: " + (end - start));
}
}

View File

@ -0,0 +1,127 @@
package meerkat.bulletinboard;
import meerkat.bulletinboard.sqlserver.BulletinBoardSQLServer;
import meerkat.bulletinboard.sqlserver.BulletinBoardSQLServer.SQLQueryProvider;
import meerkat.bulletinboard.sqlserver.MySQLQueryProvider;
import meerkat.bulletinboard.sqlserver.SQLiteQueryProvider;
import meerkat.comm.CommunicationException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedList;
import java.util.List;
import static org.junit.Assert.fail;
/**
* Created by Arbel Deutsch Peled on 07-Dec-15.
*/
public class MySQLBulletinBoardServerTest {
private final String dbAddress = "//localhost:3306/meerkat";
private final String username = "arbel";
private final String password = "mypass";
private GenericBulletinBoardServerTest serverTest;
private final ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); // Used to time the tests
@Before
public void init(){
System.err.println("Starting to initialize MySQLBulletinBoardServerTest");
long start = threadBean.getCurrentThreadCpuTime();
SQLQueryProvider queryProvider = new MySQLQueryProvider(dbAddress,username,password);
try {
Connection conn = DriverManager.getConnection(queryProvider.getConnectionString());
Statement stmt = conn.createStatement();
List<String> deletionQueries = queryProvider.getSchemaDeletionCommands();
for (String deletionQuery : deletionQueries) {
stmt.execute(deletionQuery);
}
} catch (SQLException e) {
System.err.println(e.getMessage());
fail(e.getMessage());
}
BulletinBoardServer bulletinBoardServer = new BulletinBoardSQLServer(queryProvider);
try {
bulletinBoardServer.init("");
} catch (CommunicationException e) {
System.err.println(e.getMessage());
fail(e.getMessage());
return;
}
serverTest = new GenericBulletinBoardServerTest();
try {
serverTest.init(bulletinBoardServer);
} catch (Exception e) {
System.err.println(e.getMessage());
fail(e.getMessage());
}
long end = threadBean.getCurrentThreadCpuTime();
System.err.println("Finished initializing MySQLBulletinBoardServerTest");
System.err.println("Time of operation: " + (end - start));
}
@Test
public void bulkTest() {
System.err.println("Starting bulkTest of MySQLBulletinBoardServerTest");
long start = threadBean.getCurrentThreadCpuTime();
try {
serverTest.testInsert();
} catch (Exception e) {
System.err.println(e.getMessage());
fail(e.getMessage());
}
try{
serverTest.testSimpleTagAndSignature();
} catch (Exception e) {
System.err.println(e.getMessage());
fail(e.getMessage());
}
try{
serverTest.testEnhancedTagsAndSignatures();
} catch (Exception e) {
System.err.println(e.getMessage());
fail(e.getMessage());
}
long end = threadBean.getCurrentThreadCpuTime();
System.err.println("Finished bulkTest of MySQLBulletinBoardServerTest");
System.err.println("Time of operation: " + (end - start));
}
@After
public void close() {
System.err.println("Starting to close MySQLBulletinBoardServerTest");
long start = threadBean.getCurrentThreadCpuTime();
serverTest.close();
long end = threadBean.getCurrentThreadCpuTime();
System.err.println("Finished closing MySQLBulletinBoardServerTest");
System.err.println("Time of operation: " + (end - start));
}
}

View File

@ -1,6 +1,7 @@
package meerkat.bulletinboard;
import meerkat.bulletinboard.sqlserver.SQLiteBulletinBoardServer;
import meerkat.bulletinboard.sqlserver.BulletinBoardSQLServer;
import meerkat.bulletinboard.sqlserver.SQLiteQueryProvider;
import meerkat.comm.CommunicationException;
import meerkat.protobuf.*;
import org.junit.After;
@ -36,9 +37,9 @@ public class SQLiteBulletinBoardServerTest{
File old = new File(testFilename);
old.delete();
BulletinBoardServer bulletinBoardServer = new SQLiteBulletinBoardServer();
BulletinBoardServer bulletinBoardServer = new BulletinBoardSQLServer(new SQLiteQueryProvider(testFilename));
try {
bulletinBoardServer.init(testFilename);
bulletinBoardServer.init("");
} catch (CommunicationException e) {
System.err.println(e.getMessage());
@ -66,12 +67,25 @@ public class SQLiteBulletinBoardServerTest{
try {
serverTest.testInsert();
} catch (Exception e) {
System.err.println(e.getMessage());
fail(e.getMessage());
}
try{
serverTest.testSimpleTagAndSignature();
} catch (Exception e) {
System.err.println(e.getMessage());
fail(e.getMessage());
}
try{
serverTest.testEnhancedTagsAndSignatures();
} catch (Exception e) {
System.err.println(e.getMessage());
fail(e.getMessage());
}
long end = threadBean.getCurrentThreadCpuTime();
System.err.println("Finished bulkTest of SQLiteBulletinBoardServerTest");
System.err.println("Time of operation: " + (end - start));

Binary file not shown.

View File

@ -1,6 +0,0 @@
#Mon Oct 26 15:30:44 IST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.9-bin.zip