diff --git a/.gitignore b/.gitignore
index 92322c4..f3adb52 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
.idea/
target/
+run/
+*.ignore
diff --git a/pom.xml b/pom.xml
index bfd99ad..7cd7ea1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
net.mindoverflow.webmarker
WebMarker
- 1.0-SNAPSHOT
+ 0.0.1-alpha
jar
@@ -16,12 +16,27 @@
1.13.1
pom
-
ro.pippo
pippo-controller
1.13.1
+
+ org.slf4j
+ slf4j-simple
+ 2.0.0-alpha1
+
+
+ org.xerial
+ sqlite-jdbc
+ 3.32.3.2
+
+
+
+ org.yaml
+ snakeyaml
+ 1.21
+
diff --git a/src/main/java/net/mindoverflow/webmarker/WebMarker.java b/src/main/java/net/mindoverflow/webmarker/WebMarker.java
index 590a597..be10a16 100644
--- a/src/main/java/net/mindoverflow/webmarker/WebMarker.java
+++ b/src/main/java/net/mindoverflow/webmarker/WebMarker.java
@@ -1,13 +1,39 @@
package net.mindoverflow.webmarker;
-import net.mindoverflow.webmarker.server.WebApplication;
+import net.mindoverflow.webmarker.runnables.StatsRunnable;
+import net.mindoverflow.webmarker.utils.Cached;
+import net.mindoverflow.webmarker.utils.sql.SQLiteManager;
+import net.mindoverflow.webmarker.webserver.WebApplication;
+import net.mindoverflow.webmarker.utils.config.ConfigEntries;
+import net.mindoverflow.webmarker.utils.config.ConfigManager;
+import net.mindoverflow.webmarker.utils.messaging.Messenger;
import ro.pippo.core.Pippo;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
public class WebMarker {
+ private static final Messenger msg = new Messenger();
+
public static void main(String[] args)
{
+ ConfigManager.checkFiles();
+ ConfigManager.loadFiles();
+ Cached.sqlManager = new SQLiteManager();
+ Cached.sqlManager.initialize();
+
+ msg.info("Loading Pippo framework...");
final Pippo pippo = new Pippo(new WebApplication());
- pippo.start();
+ msg.info("Loaded Pippo framework.");
+
+ msg.info("Starting webserver...");
+ int port = (int) ConfigEntries.WEBSERVER_PORT.getValue();
+ pippo.start(port);
+ msg.info("Started webserver.");
+
+ ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
+ exec.scheduleAtFixedRate(new StatsRunnable(), 0, 5, TimeUnit.SECONDS);
}
}
diff --git a/src/main/java/net/mindoverflow/webmarker/runnables/StatsRunnable.java b/src/main/java/net/mindoverflow/webmarker/runnables/StatsRunnable.java
new file mode 100644
index 0000000..822ab5e
--- /dev/null
+++ b/src/main/java/net/mindoverflow/webmarker/runnables/StatsRunnable.java
@@ -0,0 +1,16 @@
+package net.mindoverflow.webmarker.runnables;
+
+import net.mindoverflow.webmarker.utils.messaging.Messenger;
+
+public class StatsRunnable implements Runnable {
+
+ Messenger msg = new Messenger();
+
+ @Override
+ public void run()
+ {
+ double usedRam = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1000000.0;
+ msg.info("Used RAM: " + usedRam + "MB");
+
+ }
+}
diff --git a/src/main/java/net/mindoverflow/webmarker/utils/Cached.java b/src/main/java/net/mindoverflow/webmarker/utils/Cached.java
new file mode 100644
index 0000000..82d3611
--- /dev/null
+++ b/src/main/java/net/mindoverflow/webmarker/utils/Cached.java
@@ -0,0 +1,8 @@
+package net.mindoverflow.webmarker.utils;
+
+import net.mindoverflow.webmarker.utils.sql.SQLiteManager;
+
+public class Cached {
+
+ public static SQLiteManager sqlManager;
+}
diff --git a/src/main/java/net/mindoverflow/webmarker/utils/config/ConfigEntries.java b/src/main/java/net/mindoverflow/webmarker/utils/config/ConfigEntries.java
new file mode 100644
index 0000000..7a7346f
--- /dev/null
+++ b/src/main/java/net/mindoverflow/webmarker/utils/config/ConfigEntries.java
@@ -0,0 +1,27 @@
+package net.mindoverflow.webmarker.utils.config;
+
+public enum ConfigEntries
+{
+ WEBSERVER_PORT("port", 7344);
+
+ private final String path;
+ private Object value;
+
+ ConfigEntries(String path, Object value)
+ {
+ this.path = path;
+ this.value = value;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public void setValue(Object value) {
+ this.value = value;
+ }
+}
diff --git a/src/main/java/net/mindoverflow/webmarker/utils/config/ConfigManager.java b/src/main/java/net/mindoverflow/webmarker/utils/config/ConfigManager.java
new file mode 100644
index 0000000..2850968
--- /dev/null
+++ b/src/main/java/net/mindoverflow/webmarker/utils/config/ConfigManager.java
@@ -0,0 +1,90 @@
+package net.mindoverflow.webmarker.utils.config;
+
+import net.mindoverflow.webmarker.utils.messaging.MessageLevel;
+import net.mindoverflow.webmarker.utils.messaging.Messenger;
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+
+public class ConfigManager
+{
+
+ private static final Messenger msg = new Messenger();
+
+ public static void checkFiles()
+ {
+ msg.send(MessageLevel.INFO, "Checking configuration files: ");
+
+ File configFile = FileType.CONFIG_YAML.file;
+
+ if(!configFile.exists())
+ {
+ try {
+ InputStream stream = ConfigManager.class.getResourceAsStream("/" + configFile.getName());
+ Files.copy(stream, Paths.get(configFile.getAbsolutePath()));
+ stream.close();
+ }
+ catch (IOException e)
+ {
+ msg.sendLine(MessageLevel.NONE, "FATAL");
+ e.printStackTrace();
+ msg.critical("Error creating missing file!");
+ System.exit(1);
+ }
+ }
+
+ msg.sendLine(MessageLevel.NONE, "OK");
+ }
+
+ public static void loadFiles()
+ {
+ msg.send(MessageLevel.INFO, "Loading configuration files: ");
+
+ try {
+ InputStream stream = new FileInputStream(FileType.CONFIG_YAML.file);
+ Yaml yaml = new Yaml();
+ FileType.CONFIG_YAML.yaml = yaml.load(stream);
+
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ msg.critical("Error loading config file!");
+ }
+
+ for(ConfigEntries entry : ConfigEntries.values())
+ {
+ String path = entry.getPath();
+ Object value = FileType.CONFIG_YAML.yaml.get(path);
+ entry.setValue(value);
+ }
+
+ msg.sendLine(MessageLevel.NONE, "OK");
+
+ for(ConfigEntries entry : ConfigEntries.values())
+ { msg.info(entry.name() + ": " + entry.getValue()); }
+ }
+
+ public static String getJarAbsolutePath()
+ {
+
+ Path currentPath = Paths.get("");
+ return currentPath.toAbsolutePath().toString();
+ }
+
+ public enum FileType
+ {
+ DATABASE_FILE(new File(getJarAbsolutePath() + File.separator + "database.sqlite"), null),
+ CONFIG_YAML(new File(getJarAbsolutePath() + File.separator + "config.yml"), new HashMap<>());
+
+ public File file;
+ public HashMap yaml;
+ FileType(File givenFile, HashMap yamlConfig)
+ {
+ file = givenFile;
+ yaml = yamlConfig;
+ }
+ }
+}
diff --git a/src/main/java/net/mindoverflow/webmarker/utils/messaging/MessageLevel.java b/src/main/java/net/mindoverflow/webmarker/utils/messaging/MessageLevel.java
new file mode 100644
index 0000000..f5b8645
--- /dev/null
+++ b/src/main/java/net/mindoverflow/webmarker/utils/messaging/MessageLevel.java
@@ -0,0 +1,21 @@
+package net.mindoverflow.webmarker.utils.messaging;
+
+public enum MessageLevel {
+
+ INFO("[INFO] "),
+ WARNING("[WARNING] "),
+ CRITICAL("[CRITICAL] "),
+ NONE("");
+
+ private String prefix;
+
+ MessageLevel(String prefix)
+ {
+ this.prefix = prefix;
+ }
+
+ public String getPrefix()
+ {
+ return prefix;
+ }
+}
diff --git a/src/main/java/net/mindoverflow/webmarker/utils/messaging/Messenger.java b/src/main/java/net/mindoverflow/webmarker/utils/messaging/Messenger.java
new file mode 100644
index 0000000..43da264
--- /dev/null
+++ b/src/main/java/net/mindoverflow/webmarker/utils/messaging/Messenger.java
@@ -0,0 +1,19 @@
+package net.mindoverflow.webmarker.utils.messaging;
+
+public class Messenger {
+
+ public void info(String message)
+ { sendLine(MessageLevel.INFO, message); }
+
+ public void warn(String message)
+ { sendLine(MessageLevel.WARNING, message); }
+
+ public void critical(String message)
+ { sendLine(MessageLevel.CRITICAL, message); }
+
+ public void sendLine(MessageLevel level, String message)
+ { System.out.println(level.getPrefix() + message); }
+
+ public void send(MessageLevel level, String message)
+ { System.out.print(level.getPrefix() + message); }
+}
diff --git a/src/main/java/net/mindoverflow/webmarker/utils/sql/FDatabaseColumn.java b/src/main/java/net/mindoverflow/webmarker/utils/sql/FDatabaseColumn.java
new file mode 100644
index 0000000..b0fedee
--- /dev/null
+++ b/src/main/java/net/mindoverflow/webmarker/utils/sql/FDatabaseColumn.java
@@ -0,0 +1,32 @@
+package net.mindoverflow.webmarker.utils.sql;
+
+import net.mindoverflow.webmarker.utils.sql.primitives.SQLColumn;
+import net.mindoverflow.webmarker.utils.sql.primitives.SQLDataType;
+
+public enum FDatabaseColumn
+{
+
+ ALL(new SQLColumn("*"), null),
+ USERNAME(new SQLColumn("username"), SQLDataType.VARCHAR_128),
+ PASSWORD(new SQLColumn("password"), SQLDataType.VARCHAR_128),
+ USERID(new SQLColumn("userid"), SQLDataType.VARCHAR_128),
+
+
+
+ ;
+
+ private final SQLColumn column;
+ private final SQLDataType type;
+
+ FDatabaseColumn(SQLColumn column, SQLDataType type)
+ {
+ this.column = column;
+ this.type = type;
+ }
+
+ public SQLColumn getColumn()
+ { return column; }
+
+ public SQLDataType getDataType()
+ { return type; }
+}
diff --git a/src/main/java/net/mindoverflow/webmarker/utils/sql/FDatabaseTable.java b/src/main/java/net/mindoverflow/webmarker/utils/sql/FDatabaseTable.java
new file mode 100644
index 0000000..3d5b182
--- /dev/null
+++ b/src/main/java/net/mindoverflow/webmarker/utils/sql/FDatabaseTable.java
@@ -0,0 +1,26 @@
+package net.mindoverflow.webmarker.utils.sql;
+
+
+import net.mindoverflow.webmarker.utils.sql.primitives.SQLTable;
+
+import java.util.ArrayList;
+
+public enum FDatabaseTable
+{
+ USERS(new SQLTable("users", // table name
+ new ArrayList<>(){{ // columns
+ add(FDatabaseColumn.USERID);
+ add(FDatabaseColumn.USERNAME);
+ add(FDatabaseColumn.PASSWORD);
+ }})),
+
+ ;
+
+ private final SQLTable table;
+
+ FDatabaseTable(SQLTable table)
+ { this.table = table; }
+
+ public SQLTable getTable()
+ { return table; }
+}
diff --git a/src/main/java/net/mindoverflow/webmarker/utils/sql/SQLiteManager.java b/src/main/java/net/mindoverflow/webmarker/utils/sql/SQLiteManager.java
new file mode 100644
index 0000000..8dac86e
--- /dev/null
+++ b/src/main/java/net/mindoverflow/webmarker/utils/sql/SQLiteManager.java
@@ -0,0 +1,113 @@
+package net.mindoverflow.webmarker.utils.sql;
+
+import net.mindoverflow.webmarker.utils.config.ConfigManager;
+import net.mindoverflow.webmarker.utils.messaging.MessageLevel;
+import net.mindoverflow.webmarker.utils.messaging.Messenger;
+import net.mindoverflow.webmarker.utils.sql.primitives.SQLDataType;
+import net.mindoverflow.webmarker.utils.sql.primitives.SQLTable;
+
+import java.sql.*;
+import java.util.List;
+
+public class SQLiteManager {
+
+ private final Messenger msg = new Messenger();
+ private Connection connection;
+
+ public void initialize()
+ {
+ msg.send(MessageLevel.INFO, "Connecting to SQLite database: ");
+
+ String url = "jdbc:sqlite:" + ConfigManager.FileType.DATABASE_FILE.file.getAbsolutePath();
+ try {
+ connection = DriverManager.getConnection(url);
+ if(connection != null && !connection.isClosed())
+ {
+ msg.sendLine(MessageLevel.NONE, "OK");
+ doInitialSetup();
+ }
+
+ } catch (SQLException throwables) {
+ msg.sendLine(MessageLevel.NONE, "FATAL");
+ throwables.printStackTrace();
+ msg.critical("Error connecting to SQLite database!");
+ System.exit(1);
+ }
+ }
+
+ private void doInitialSetup()
+ {
+ for(FDatabaseTable currentTable : FDatabaseTable.values())
+ {
+ if(!tableExists(currentTable))
+ {
+ msg.info("Creating SQLite table `" + currentTable.getTable().getTableSQLName() + "`");
+ createTable(currentTable);
+ }
+ }
+ }
+
+ private boolean tableExists(FDatabaseTable tableEnum)
+ {
+ String name = tableEnum.getTable().getTableSQLName();
+
+ try
+ {
+ DatabaseMetaData meta = connection.getMetaData();
+ ResultSet result = meta.getTables(null, null, name, null);
+ while(result.next())
+ {
+ String tableName = result.getString("TABLE_NAME");
+ if(tableName != null && tableName.equals(name.toLowerCase())) return true;
+ }
+
+ } catch (SQLException e)
+ {
+ e.printStackTrace();
+ msg.critical("Error checking SQLite table " + name + "!");
+ System.exit(1);
+ }
+ return false;
+ }
+
+ private void createTable(FDatabaseTable tableEnum)
+ {
+ SQLTable table = tableEnum.getTable();
+ List columns = table.getColumns();
+ List dataTypes = table.getDataTypes();
+
+ StringBuilder query = new StringBuilder("CREATE TABLE IF NOT EXISTS ").append(table.getTableSQLName()).append(" (");
+
+ int pos = 0;
+ for(FDatabaseColumn column : columns)
+ {
+ query.append(column.getColumn().getColumnSQLName()).append(" ").append(dataTypes.get(pos).getSQLName());
+ pos++;
+
+ if(pos < columns.size()) // we don't want to append a colon to the last entry
+ { query.append(", "); }
+ }
+ query.append(");");
+ executeUpdate(query.toString());
+ }
+
+ private void executeUpdate(String query)
+ {
+ try
+ {
+ if(connection == null || connection.isClosed())
+ {
+ msg.critical("Lost connection to SQLite database!");
+ System.exit(1);
+ }
+
+ Statement statement = connection.createStatement();
+ statement.executeUpdate(query);
+ } catch (SQLException e)
+ {
+ e.printStackTrace();
+ msg.critical("Error executing SQLite update!");
+ System.exit(1);
+ }
+ }
+}
diff --git a/src/main/java/net/mindoverflow/webmarker/utils/sql/primitives/SQLColumn.java b/src/main/java/net/mindoverflow/webmarker/utils/sql/primitives/SQLColumn.java
new file mode 100644
index 0000000..8d6bd68
--- /dev/null
+++ b/src/main/java/net/mindoverflow/webmarker/utils/sql/primitives/SQLColumn.java
@@ -0,0 +1,12 @@
+package net.mindoverflow.webmarker.utils.sql.primitives;
+
+public class SQLColumn {
+
+ private final String columnName;
+
+ public SQLColumn(String name)
+ { columnName = name; }
+
+ public String getColumnSQLName()
+ { return columnName; }
+}
diff --git a/src/main/java/net/mindoverflow/webmarker/utils/sql/primitives/SQLDataType.java b/src/main/java/net/mindoverflow/webmarker/utils/sql/primitives/SQLDataType.java
new file mode 100644
index 0000000..bd9ad9d
--- /dev/null
+++ b/src/main/java/net/mindoverflow/webmarker/utils/sql/primitives/SQLDataType.java
@@ -0,0 +1,18 @@
+package net.mindoverflow.webmarker.utils.sql.primitives;
+
+public enum SQLDataType
+{
+ INTEGER("INTEGER NOT NULL"),
+ VARCHAR_128("VARCHAR(128)"),
+ TEXT("TEXT"),
+ DATETIME("DATETIME"),
+
+ ;
+
+ private String sqlName;
+ SQLDataType(String sqlName)
+ { this.sqlName = sqlName; }
+
+ public String getSQLName()
+ { return this.sqlName; }
+}
diff --git a/src/main/java/net/mindoverflow/webmarker/utils/sql/primitives/SQLTable.java b/src/main/java/net/mindoverflow/webmarker/utils/sql/primitives/SQLTable.java
new file mode 100644
index 0000000..aa856d7
--- /dev/null
+++ b/src/main/java/net/mindoverflow/webmarker/utils/sql/primitives/SQLTable.java
@@ -0,0 +1,31 @@
+package net.mindoverflow.webmarker.utils.sql.primitives;
+
+import net.mindoverflow.webmarker.utils.sql.FDatabaseColumn;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SQLTable
+{
+ private final String tableName;
+ private final List columns;
+ private final List columnTypes = new ArrayList<>();
+
+ public SQLTable(String tableName, List columns)
+ {
+ this.tableName = tableName;
+ this.columns = columns;
+
+ for(FDatabaseColumn column : columns)
+ { columnTypes.add(column.getDataType()); }
+ }
+
+ public String getTableSQLName()
+ { return tableName; }
+
+ public List getColumns()
+ { return columns; }
+
+ public List getDataTypes()
+ { return columnTypes; }
+}
diff --git a/src/main/java/net/mindoverflow/webmarker/server/WebApplication.java b/src/main/java/net/mindoverflow/webmarker/webserver/WebApplication.java
similarity index 84%
rename from src/main/java/net/mindoverflow/webmarker/server/WebApplication.java
rename to src/main/java/net/mindoverflow/webmarker/webserver/WebApplication.java
index a3a75c1..188975a 100644
--- a/src/main/java/net/mindoverflow/webmarker/server/WebApplication.java
+++ b/src/main/java/net/mindoverflow/webmarker/webserver/WebApplication.java
@@ -1,4 +1,4 @@
-package net.mindoverflow.webmarker.server;
+package net.mindoverflow.webmarker.webserver;
import net.mindoverflow.webmarker.utils.URLMap;
import ro.pippo.controller.ControllerApplication;
@@ -46,6 +46,13 @@ public class WebApplication extends ControllerApplication {
});
+ POST("/post", routeContext -> {
+ int userId = routeContext.getParameter("id").toInt();
+ String url = routeContext.getParameter("url").toString();
+
+ routeContext.send("AAAAAAAAAAAAA " + url);
+ });
+
ANY("/.*", new TrailingSlashHandler(false)); // remove trailing slash
}
}
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
new file mode 100644
index 0000000..20a8781
--- /dev/null
+++ b/src/main/resources/config.yml
@@ -0,0 +1 @@
+port: 7344
\ No newline at end of file