diff --git a/.classpath b/.classpath
index 5f9bb89..56f0fa7 100644
--- a/.classpath
+++ b/.classpath
@@ -10,7 +10,6 @@
-
@@ -29,5 +28,9 @@
+
+
+
+
diff --git a/README.md b/README.md
index 5147189..f39b2f9 100644
--- a/README.md
+++ b/README.md
@@ -127,55 +127,6 @@ Create a cron file to update the metric file everyday:
Warning: in previous day mode, the metrics generated are overwrited for the last month, the last week and the last day. So, six weeks in logs are required.
-### Web metrics
-
-Configuration template:
-
-```
-conf.probe.types=HttpAccessLog, HttpErrorLog
-conf.probe.httpaccesslog.file=/var/log/apache2/foo.bar.org-access.log*
-conf.probe.httperrorlog.file=/var/log/apache2/foo.bar.org-error.log*
-conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
-
-# Custom access log pattern with Java regex.
-# Default: "^(?[a-zA-F0-9\\\\:\\\\.]+) - (?[^\\[]+) \\[(?[^\\]]+)\\] \"(?.*)\" (?\\d+) (?\\d+) \"(?.*)\" \"(?[^\"]*)\".*$"
-conf.probe.httpaccesslog.pattern=
-```
-
-### Minetest metrics
-
-Configuration template:
-
-```
-conf.probe.types=Minetest
-conf.probe.minetest.logs=/home/cpm/Projets/StatoolInfos/EnvTest/minetest/minetest.log*
-conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
-
-```
-
-### Mumble metrics
-
-Configuration template:
-
-```
-conf.probe.types=Mumble
-conf.probe.mumble.logs=/var/log/mumble-server/mumble-server.log*
-conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
-```
-
-### PrivateBin metrics (experimental)
-
-Warning: works fine if database, image and comment options are disabled.
-
-Configuration template:
-
-```
-conf.probe.types=PrivateBin
-conf.probe.httpaccesslog.file=/var/log/apache2/foo.bar.org-access.log*
-conf.probe.httpaccesslog.pattern=
-conf.probe.privatebin.data=/var/www/paste.libre-service.eu/data/
-conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
-```
### Framdadate metrics (coming soon)
@@ -197,6 +148,13 @@ conf.probe.httpaccesslog.pattern=
conf.probe.gitea.data=/opt/gitea/data
conf.probe.gitea.api.url=https://forge.libre-service.eu/
conf.probe.gitea.token=b6598c616b1cd350b834258205da4e5e8b951005
+# jdbc:mariadb://localhost:1234/databasename
+# jdbc:mysql://localhost:1234/databasename
+# jdbc:postgresql://localhost:1234/databasename
+# jdbc:sqlite:/foo/bar/databasename.sqlite
+conf.probe.gitea.database.url=
+conf.probe.gitea.database.user=
+conf.probe.gitea.database.password=
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
```
@@ -208,7 +166,37 @@ Configuration template:
conf.probe.types=LibreQR
conf.probe.httpaccesslog.file=/var/log/apache2/foo.bar.org-access.log*
conf.probe.httpaccesslog.pattern=
-conf.probe.libreqr.data=/var/www/qrcode.libre-service.eu/data/
+conf.probe.libreqr.datafiles=/var/www/foo.bar.org/temp/
+conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
+```
+
+### Minetest metrics
+
+Configuration template:
+
+```
+conf.probe.types=Minetest
+conf.probe.minetest.logs=/home/cpm/Projets/StatoolInfos/EnvTest/minetest/minetest.log*
+
+conf.probe.minetest.players.database.url=jdbc:postgresql://localhost:5432/minetestdb
+conf.probe.minetest.players.database.user=minetestdba
+conf.probe.minetest.players.database.password=XXXXXXXXXXX
+
+conf.probe.minetest.worlds.database.url=jdbc:postgresql://localhost:5432/minetestdb
+conf.probe.minetest.worlds.database.user=minetestdba
+conf.probe.minetest.worlds.database.password=XXXXXXXXXXX
+
+conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
+
+```
+
+### Mumble metrics
+
+Configuration template:
+
+```
+conf.probe.types=Mumble
+conf.probe.mumble.logs=/var/log/mumble-server/mumble-server.log*
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
```
@@ -223,3 +211,31 @@ conf.probe.httpaccesslog.pattern=
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
```
+### PrivateBin metrics (experimental)
+
+Warning: works fine if database, image and comment options are disabled.
+
+Configuration template:
+
+```
+conf.probe.types=PrivateBin
+conf.probe.httpaccesslog.file=/var/log/apache2/foo.bar.org-access.log*
+conf.probe.httpaccesslog.pattern=
+conf.probe.privatebin.data=/var/www/paste.libre-service.eu/data/
+conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
+```
+
+### Web metrics
+
+Configuration template:
+
+```
+conf.probe.types=HttpAccessLog, HttpErrorLog
+conf.probe.httpaccesslog.file=/var/log/apache2/foo.bar.org-access.log*
+conf.probe.httperrorlog.file=/var/log/apache2/foo.bar.org-error.log*
+conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
+
+# Custom access log pattern with Java regex.
+# Default: "^(?[a-zA-F0-9\\\\:\\\\.]+) - (?[^\\[]+) \\[(?[^\\]]+)\\] \"(?.*)\" (?\\d+) (?\\d+) \"(?.*)\" \"(?[^\"]*)\".*$"
+conf.probe.httpaccesslog.pattern=
+```
\ No newline at end of file
diff --git a/lib/mariadb-java-client-3.0.3.jar b/lib/mariadb-java-client-3.0.3.jar
new file mode 100644
index 0000000..e034291
Binary files /dev/null and b/lib/mariadb-java-client-3.0.3.jar differ
diff --git a/lib/postgresql-42.3.3.jar b/lib/postgresql-42.3.3.jar
new file mode 100644
index 0000000..6a5116b
Binary files /dev/null and b/lib/postgresql-42.3.3.jar differ
diff --git a/lib/sqlite-jdbc-3.36.0.3.jar b/lib/sqlite-jdbc-3.36.0.3.jar
new file mode 100644
index 0000000..5cc7c44
Binary files /dev/null and b/lib/sqlite-jdbc-3.36.0.3.jar differ
diff --git a/src/fr/devinsy/statoolinfos/core/Configuration.java b/src/fr/devinsy/statoolinfos/core/Configuration.java
index 087e228..7a0295c 100644
--- a/src/fr/devinsy/statoolinfos/core/Configuration.java
+++ b/src/fr/devinsy/statoolinfos/core/Configuration.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020-2021 Christian Pierre MOMON
+ * Copyright (C) 2020-2022 Christian Pierre MOMON
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@@ -266,11 +266,9 @@ public class Configuration extends PathPropertyList
result = new DatabaseConfig();
- result.setHost(get(prefix + ".db.host"));
- result.setPort(get(prefix + ".db.port"));
- result.setName(get(prefix + ".db.name"));
- result.setUser(get(prefix + ".db.user"));
- result.setPassword(get(prefix + ".db.password"));
+ result.setUrl(get(prefix + ".database.url"));
+ result.setUser(get(prefix + ".database.user"));
+ result.setPassword(get(prefix + ".database.password"));
//
return result;
diff --git a/src/fr/devinsy/statoolinfos/core/DatabaseConfig.java b/src/fr/devinsy/statoolinfos/core/DatabaseConfig.java
index 504bba3..6276611 100644
--- a/src/fr/devinsy/statoolinfos/core/DatabaseConfig.java
+++ b/src/fr/devinsy/statoolinfos/core/DatabaseConfig.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 Christian Pierre MOMON
+ * Copyright (C) 2021-2022 Christian Pierre MOMON
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@@ -18,14 +18,14 @@
*/
package fr.devinsy.statoolinfos.core;
+import org.apache.commons.lang3.StringUtils;
+
/**
* The Class DatabaseConfig.
*/
public class DatabaseConfig
{
- private String host;
- private String port;
- private String name;
+ private String url;
private String user;
private String password;
@@ -34,31 +34,19 @@ public class DatabaseConfig
*/
public DatabaseConfig()
{
- this.host = null;
- this.port = null;
- this.name = null;
+ this.url = null;
this.user = null;
this.password = null;
}
- public String getHost()
- {
- return this.host;
- }
-
- public String getName()
- {
- return this.name;
- }
-
public String getPassword()
{
return this.password;
}
- public String getPort()
+ public String getUrl()
{
- return this.port;
+ return this.url;
}
public String getUser()
@@ -66,14 +54,26 @@ public class DatabaseConfig
return this.user;
}
- public void setHost(final String host)
+ /**
+ * Checks if is sets the.
+ *
+ * @return true, if is sets the
+ */
+ public boolean isSet()
{
- this.host = host;
- }
+ boolean result;
- public void setName(final String name)
- {
- this.name = name;
+ if (StringUtils.isAnyBlank(this.url, this.user))
+ {
+ result = false;
+ }
+ else
+ {
+ result = true;
+ }
+
+ //
+ return result;
}
public void setPassword(final String password)
@@ -81,13 +81,37 @@ public class DatabaseConfig
this.password = password;
}
- public void setPort(final String port)
+ public void setUrl(final String url)
{
- this.port = port;
+ this.url = url;
}
public void setUser(final String user)
{
this.user = user;
}
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString()
+ {
+ String result;
+
+ String password;
+ if (StringUtils.isBlank(this.password))
+ {
+ password = "";
+ }
+ else
+ {
+ password = "**********";
+ }
+
+ result = String.format("[%s,%s,%s]", this.url, this.user, password);
+
+ //
+ return result;
+ }
}
diff --git a/src/fr/devinsy/statoolinfos/metrics/Prober.java b/src/fr/devinsy/statoolinfos/metrics/Prober.java
index d74a6f8..51e8afd 100644
--- a/src/fr/devinsy/statoolinfos/metrics/Prober.java
+++ b/src/fr/devinsy/statoolinfos/metrics/Prober.java
@@ -159,8 +159,10 @@ public class Prober
logger.info("apiURL=[{}]", apiURL);
String apiToken = configuration.get("conf.probe.gitea.api.token");
logger.info("apiToken=[{}]", apiToken == null ? "null" : "************************");
+ DatabaseConfig database = configuration.getDatabaseConfig("conf.probe.gitea");
+ logger.info("database={}", database.toString());
- PathCounters metrics = GiteaProber.probe(FilesUtils.searchByWildcard(httpLogs), httpAccessLogRegex, apiURL, apiToken, dataDirectory);
+ PathCounters metrics = GiteaProber.probe(FilesUtils.searchByWildcard(httpLogs), httpAccessLogRegex, apiURL, apiToken, dataDirectory, database);
counters.putAll(metrics);
}
@@ -187,9 +189,13 @@ public class Prober
{
logger.info("== Probing Minetest.");
String source = configuration.get("conf.probe.minetest.logs");
- DatabaseConfig database = configuration.getDatabaseConfig("conf.probe.minetest.players");
+ logger.info("source=[{}]", source);
+ DatabaseConfig playerDatabase = configuration.getDatabaseConfig("conf.probe.minetest.players");
+ logger.info("players database={}", playerDatabase.toString());
+ DatabaseConfig worldDatabase = configuration.getDatabaseConfig("conf.probe.minetest.worlds");
+ logger.info("wordls database={}", worldDatabase.toString());
- PathCounters data = MinetestProber.probe(source, database);
+ PathCounters data = MinetestProber.probe(source, playerDatabase, worldDatabase);
counters.putAll(data);
}
diff --git a/src/fr/devinsy/statoolinfos/metrics/gitea/GiteaProber.java b/src/fr/devinsy/statoolinfos/metrics/gitea/GiteaProber.java
index 8b5c13d..fbfae97 100644
--- a/src/fr/devinsy/statoolinfos/metrics/gitea/GiteaProber.java
+++ b/src/fr/devinsy/statoolinfos/metrics/gitea/GiteaProber.java
@@ -20,6 +20,7 @@ package fr.devinsy.statoolinfos.metrics.gitea;
import java.io.File;
import java.io.IOException;
+import java.sql.SQLException;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
@@ -27,6 +28,7 @@ import org.json.simple.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import fr.devinsy.statoolinfos.core.DatabaseConfig;
import fr.devinsy.statoolinfos.core.StatoolInfosException;
import fr.devinsy.statoolinfos.metrics.PathCounters;
import fr.devinsy.statoolinfos.metrics.UserCounters;
@@ -36,6 +38,7 @@ import fr.devinsy.statoolinfos.metrics.http.HttpStatusCategory;
import fr.devinsy.statoolinfos.metrics.util.DatabaseProber;
import fr.devinsy.statoolinfos.metrics.util.DatafilesProber;
import fr.devinsy.statoolinfos.util.Files;
+import fr.devinsy.statoolinfos.util.sql.SQLDatabase;
import fr.devinsy.strings.StringList;
/**
@@ -67,7 +70,8 @@ public class GiteaProber
* @throws StatoolInfosException
* the statool infos exception
*/
- public static PathCounters probe(final Files httpLogs, final String httpLogRegex, final String apiURL, final String apiToken, final File dataPath) throws IOException, StatoolInfosException
+ public static PathCounters probe(final Files httpLogs, final String httpLogRegex, final String apiURL, final String apiToken, final File dataPath, final DatabaseConfig databaseConfig)
+ throws IOException, StatoolInfosException
{
PathCounters result;
@@ -77,7 +81,23 @@ public class GiteaProber
result = probeHttpAccessLog(httpLogs, httpLogRegex);
// metrics.service.database.bytes
- result.putAll(DatabaseProber.probe(null));
+ try
+ {
+ if (databaseConfig.isSet())
+ {
+ SQLDatabase database = new SQLDatabase(databaseConfig.getUrl(), databaseConfig.getUser(), databaseConfig.getPassword());
+ database.open();
+ result.putAll(DatabaseProber.probe(database));
+ }
+ else
+ {
+ System.out.println("GITEA Database undefined.");
+ }
+ }
+ catch (SQLException exception)
+ {
+ logger.error("ERROR with database.", exception);
+ }
// metrics.service.files.bytes
// metrics.service.files.count
diff --git a/src/fr/devinsy/statoolinfos/metrics/minetest/MinetestProber.java b/src/fr/devinsy/statoolinfos/metrics/minetest/MinetestProber.java
index 184f0c9..70e67f8 100644
--- a/src/fr/devinsy/statoolinfos/metrics/minetest/MinetestProber.java
+++ b/src/fr/devinsy/statoolinfos/metrics/minetest/MinetestProber.java
@@ -19,13 +19,17 @@
package fr.devinsy.statoolinfos.metrics.minetest;
import java.io.IOException;
+import java.sql.SQLException;
+import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.statoolinfos.core.DatabaseConfig;
import fr.devinsy.statoolinfos.core.StatoolInfosException;
import fr.devinsy.statoolinfos.metrics.PathCounters;
+import fr.devinsy.statoolinfos.util.sql.SQLDatabase;
+import fr.devinsy.strings.StringList;
/**
* The Class MinetestProber.
@@ -51,7 +55,7 @@ public class MinetestProber
* @throws StatoolInfosException
* @throws IOException
*/
- public static PathCounters probe(final String logs, final DatabaseConfig databaseConfig) throws IOException, StatoolInfosException
+ public static PathCounters probe(final String logs, final DatabaseConfig playerDatabaseConfig, final DatabaseConfig worldDatabaseConfig) throws IOException, StatoolInfosException
{
PathCounters result;
@@ -68,6 +72,52 @@ public class MinetestProber
// metrics.metaverse.logs.unknown
result = MinetestLogAnalyzer.probe(logs);
+ // metrics.service.database.bytes
+ long databaseSize = 0;
+ try
+ {
+ System.out.println("Probing database [" + playerDatabaseConfig.getUrl() + "]");
+ if (playerDatabaseConfig.isSet())
+ {
+ SQLDatabase database = new SQLDatabase(playerDatabaseConfig.getUrl(), playerDatabaseConfig.getUser(), playerDatabaseConfig.getPassword());
+ database.open();
+ databaseSize += database.getDatabaseSize();
+ }
+ else
+ {
+ System.out.println("Minetest Players Database undefined.");
+ }
+ }
+ catch (SQLException exception)
+ {
+ logger.error("ERROR with database.", exception);
+ }
+
+ if (!StringUtils.equals(playerDatabaseConfig.getUrl(), worldDatabaseConfig.getUrl()))
+ {
+ try
+ {
+ System.out.println("Probing database [" + worldDatabaseConfig.getUrl() + "]");
+ if (worldDatabaseConfig.isSet())
+ {
+ SQLDatabase database = new SQLDatabase(worldDatabaseConfig.getUrl(), worldDatabaseConfig.getUser(), worldDatabaseConfig.getPassword());
+ database.open();
+ databaseSize += database.getDatabaseSize();
+ }
+ else
+ {
+ System.out.println("Minetest Worlds Database undefined.");
+ }
+ }
+ catch (SQLException exception)
+ {
+ logger.error("ERROR with database.", exception);
+ }
+ }
+
+ StringList timemarks = result.getNowTimeMarks();
+ result.set(databaseSize, "metrics.service.database.bytes", timemarks);
+
// result.putAll(MumbleDatabaseAnalyzer.probe());
// metrics.service.accounts
// metrics.service.database.bytes
diff --git a/src/fr/devinsy/statoolinfos/metrics/util/DatabaseProber.java b/src/fr/devinsy/statoolinfos/metrics/util/DatabaseProber.java
index 001e404..ad4a0eb 100644
--- a/src/fr/devinsy/statoolinfos/metrics/util/DatabaseProber.java
+++ b/src/fr/devinsy/statoolinfos/metrics/util/DatabaseProber.java
@@ -23,8 +23,9 @@ import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import fr.devinsy.statoolinfos.core.DatabaseConfig;
import fr.devinsy.statoolinfos.metrics.PathCounters;
+import fr.devinsy.statoolinfos.util.sql.SQLDatabase;
+import fr.devinsy.strings.StringList;
/**
* The Class DatabaseProber.
@@ -49,30 +50,21 @@ public class DatabaseProber
* @throws IOException
* Signals that an I/O exception has occurred.
*/
- public static PathCounters probe(final DatabaseConfig config) throws IOException
+ public static PathCounters probe(final SQLDatabase database) throws IOException
{
PathCounters result;
result = new PathCounters();
- if (config != null)
+ if ((database != null) && (database.isOpened()))
{
- System.out.println("Probing directory [" + config.getName() + "]");
- }
+ System.out.println("Probing database [" + database.getUrl() + "]");
- // if ((directory != null) && (directory.exists()) &&
- // (directory.isDirectory()))
- // {
- // StringList timemarks = result.getNowTimeMarks();
- //
- // // metrics.service.database.bytes
- // long size = FileUtils.sizeOfDirectory(directory);
- // result.set(size, prefix + ".files.bytes", timemarks);
- // }
- // else
- // {
- // System.out.println("WARNING: datafile path not valid.");
- // }
+ // metrics.service.database.bytes
+ long bytes = database.getDatabaseSize();
+ StringList timemarks = result.getNowTimeMarks();
+ result.set(bytes, "metrics.service.database.bytes", timemarks);
+ }
//
return result;
diff --git a/src/fr/devinsy/statoolinfos/util/sql/ClosedDatabaseException.java b/src/fr/devinsy/statoolinfos/util/sql/ClosedDatabaseException.java
new file mode 100644
index 0000000..c03b62a
--- /dev/null
+++ b/src/fr/devinsy/statoolinfos/util/sql/ClosedDatabaseException.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018-2022 Christian Pierre MOMON
+ *
+ * This file is part of StatoolInfos, simple service statistics tool.
+ *
+ * StatoolInfos is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * StatoolInfos is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with StatoolInfos. If not, see .
+ */
+package fr.devinsy.statoolinfos.util.sql;
+
+import java.sql.SQLException;
+
+/**
+ * The Class ClosedDatabaseException.
+ */
+public class ClosedDatabaseException extends SQLException
+{
+ private static final long serialVersionUID = 9220220563426218282L;
+
+ /**
+ * Instantiates a new closed database exception.
+ */
+ public ClosedDatabaseException()
+ {
+ super("Invalid database status for this operation: closed.");
+ }
+
+ /**
+ * Instantiates a new closed database exception.
+ *
+ * @param message
+ * the message
+ */
+ public ClosedDatabaseException(final String message)
+ {
+ super(message);
+ }
+
+ /**
+ * Instantiates a new closed database exception.
+ *
+ * @param message
+ * the message
+ * @param cause
+ * the cause
+ */
+ public ClosedDatabaseException(final String message, final Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ /**
+ * Instantiates a new closed database exception.
+ *
+ * @param cause
+ * the cause
+ */
+ public ClosedDatabaseException(final Throwable cause)
+ {
+ super(cause);
+ }
+}
diff --git a/src/fr/devinsy/statoolinfos/util/sql/OpenedDatabaseException.java b/src/fr/devinsy/statoolinfos/util/sql/OpenedDatabaseException.java
new file mode 100644
index 0000000..d0739d6
--- /dev/null
+++ b/src/fr/devinsy/statoolinfos/util/sql/OpenedDatabaseException.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018-2022 Christian Pierre MOMON
+ *
+ * This file is part of StatoolInfos, simple service statistics tool.
+ *
+ * StatoolInfos is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * StatoolInfos is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with StatoolInfos. If not, see .
+ */
+package fr.devinsy.statoolinfos.util.sql;
+
+import java.sql.SQLException;
+
+/**
+ * The Class OpenedDatabaseException.
+ */
+public class OpenedDatabaseException extends SQLException
+{
+ private static final long serialVersionUID = -8218498455798186368L;
+
+ /**
+ * Instantiates a new opened database exception.
+ */
+ public OpenedDatabaseException()
+ {
+ super("Invalid database status for this operation: opened.");
+ }
+
+ /**
+ * Instantiates a new opened database exception.
+ *
+ * @param message
+ * the message
+ */
+ public OpenedDatabaseException(final String message)
+ {
+ super(message);
+ }
+
+ /**
+ * Instantiates a new opened database exception.
+ *
+ * @param message
+ * the message
+ * @param cause
+ * the cause
+ */
+ public OpenedDatabaseException(final String message, final Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ /**
+ * Instantiates a new opened database exception.
+ *
+ * @param cause
+ * the cause
+ */
+ public OpenedDatabaseException(final Throwable cause)
+ {
+ super(cause);
+ }
+}
diff --git a/src/fr/devinsy/statoolinfos/util/sql/SQLDatabase.java b/src/fr/devinsy/statoolinfos/util/sql/SQLDatabase.java
new file mode 100644
index 0000000..1787b24
--- /dev/null
+++ b/src/fr/devinsy/statoolinfos/util/sql/SQLDatabase.java
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 2013-2022 Christian Pierre MOMON
+ *
+ * This file is part of StatoolInfos, simple service statistics tool.
+ *
+ * StatoolInfos is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * StatoolInfos is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with StatoolInfos. If not, see .
+ */
+package fr.devinsy.statoolinfos.util.sql;
+
+import java.io.File;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The Class SQLDatabase.
+ */
+public class SQLDatabase
+{
+ private static final Logger logger = LoggerFactory.getLogger(SQLDatabase.class);;
+
+ public enum Driver
+ {
+ HSQL,
+ MARIADB,
+ MYSQL,
+ NONE,
+ POSTGRES,
+ SQLITE
+ };
+
+ public enum Status
+ {
+ OPENED,
+ CLOSED
+ };
+
+ private Status status;
+ private Driver driver;
+ private String url;
+ private String login;
+ private String password;
+ private Connection connection;
+
+ /**
+ * This method opens a database session.
+ *
+ * @param driverClassName
+ * the driver class name
+ * @param url
+ * the url
+ * @param login
+ * the login
+ * @param password
+ * the password
+ */
+ public SQLDatabase(final String url, final String login, final String password)
+ {
+ if (StringUtils.isBlank(url))
+ {
+ throw new IllegalArgumentException("url is null.");
+ }
+ else if (StringUtils.isBlank(login))
+ {
+ throw new IllegalArgumentException("login is null.");
+ }
+ else
+ {
+ this.status = Status.CLOSED;
+ this.driver = Driver.NONE;
+ this.url = url;
+ this.login = login;
+ this.password = password;
+ this.connection = null;
+ }
+ }
+
+ /**
+ * Close.
+ */
+ public void close()
+ {
+ if (this.connection != null)
+ {
+ try
+ {
+ this.connection.close();
+ }
+ catch (SQLException exception)
+ {
+ logger.error("Error closing database.", exception);
+ }
+ finally
+ {
+ this.connection = null;
+ }
+ }
+
+ this.status = Status.CLOSED;
+ }
+
+ /**
+ * Gets the connection.
+ *
+ * @return the connection
+ * @throws SQLException
+ * the SQL exception
+ */
+ public Connection getConnection() throws SQLException
+ {
+ Connection result;
+
+ if (isClosed())
+ {
+ throw new SQLException("Database not opened.");
+ }
+ else
+ {
+ if (this.connection != null)
+ {
+ result = this.connection;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Connection not initialized.");
+ }
+ }
+
+ //
+ return result;
+
+ }
+
+ /**
+ * Gets the database size.
+ *
+ * @return the database size
+ */
+ public long getDatabaseSize()
+ {
+ long result;
+
+ try
+ {
+ if (isOpened())
+ {
+ switch (this.driver)
+ {
+ case HSQL:
+ {
+ result = 0;
+ }
+ break;
+
+ case MARIADB:
+ case MYSQL:
+ {
+ String sql = "SELECT SUM(data_length + index_length) FROM information_schema.tables where table_schema = (select database());";
+ result = queryNumber(sql);
+ }
+ break;
+
+ case POSTGRES:
+ {
+ String sql = "SELECT pg_database_size(pg_database.datname) FROM pg_database WHERE pg_database.datname = (select current_catalog);";
+ result = queryNumber(sql);
+ }
+ break;
+
+ case SQLITE:
+ {
+ File file = new File(this.url.replace("jdbc:sqlite:", ""));
+ result = file.length();
+ }
+ break;
+
+ case NONE:
+ default:
+ result = 0;
+ }
+ }
+ else
+ {
+ result = 0;
+ }
+ }
+ catch (SQLException exception)
+ {
+ logger.error("ERROR querying database size.", exception);
+ result = 0;
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ * Gets the driver.
+ *
+ * @return the driver
+ */
+ public Driver getDriver()
+ {
+ Driver result;
+
+ result = this.driver;
+
+ //
+ return result;
+ }
+
+ /**
+ * Gets the login.
+ *
+ * @return the login
+ */
+ public String getLogin()
+ {
+ String result;
+
+ result = this.login;
+
+ //
+ return result;
+ }
+
+ /**
+ * Gets the password.
+ *
+ * @return the password
+ */
+ public String getPassword()
+ {
+ String result;
+
+ result = this.password;
+
+ //
+ return result;
+ }
+
+ /**
+ * Gets the url.
+ *
+ * @return the url
+ */
+ public String getUrl()
+ {
+ String result;
+
+ result = this.url;
+
+ //
+ return result;
+ }
+
+ /**
+ * Checks if is closed.
+ *
+ * @return true, if is closed
+ */
+ public boolean isClosed()
+ {
+ boolean result;
+
+ if (this.status == Status.CLOSED)
+ {
+ result = true;
+ }
+ else
+ {
+ result = false;
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ * Checks if is opened.
+ *
+ * @return true, if is opened
+ */
+ public boolean isOpened()
+ {
+ boolean result;
+
+ result = !isClosed();
+
+ //
+ return result;
+ }
+
+ /**
+ * Open.
+ *
+ * @throws SQLException
+ * the SQL exception
+ */
+ public void open() throws SQLException
+ {
+ try
+ {
+ //
+ close();
+
+ //
+ if (this.url == null)
+ {
+ throw new IllegalArgumentException("Undefined source.");
+ }
+ else
+ {
+ if (this.url.startsWith("jdbc:sqlite:"))
+ {
+ this.driver = Driver.SQLITE;
+ Class.forName("org.sqlite.JDBC");
+ }
+ else if (this.url.startsWith("jdbc:postgresql:"))
+ {
+ Class.forName("org.postgresql.Driver");
+ this.driver = Driver.POSTGRES;
+ }
+ else if (this.url.startsWith("jdbc:mysql:"))
+ {
+ Class.forName("com.mysql.jdbc.Driver");
+ this.driver = Driver.MYSQL;
+ }
+ else if (this.url.startsWith("jdbc:mariadb:"))
+ {
+ Class.forName("org.mariadb.jdbc.Driver");
+ this.driver = Driver.MARIADB;
+ }
+ else
+ {
+ throw new SQLException("Unknown database type.");
+ }
+
+ this.connection = DriverManager.getConnection(this.url, this.login, this.password);
+ this.status = Status.OPENED;
+ logger.info("Single connection opened with [{}].", this.url);
+ }
+ }
+ catch (ClassNotFoundException exception)
+ {
+ throw new SQLException("ERROR with driver name.", exception);
+ }
+ }
+
+ /**
+ * Query number.
+ *
+ * @param sql
+ * the sql
+ * @return the long
+ * @throws SQLException
+ * the SQL exception
+ */
+ public long queryNumber(final String sql) throws SQLException
+ {
+ long result;
+
+ if (isClosed())
+ {
+ throw new ClosedDatabaseException();
+ }
+ else
+ {
+ Connection connection = null;
+ Statement statement = null;
+ ResultSet resultSet = null;
+ try
+ {
+ connection = getConnection();
+ connection.setAutoCommit(true);
+ statement = connection.createStatement();
+ resultSet = statement.executeQuery(sql);
+
+ resultSet.next();
+ result = resultSet.getLong(1);
+ }
+ finally
+ {
+ SQLUtils.closeQuietly(statement, resultSet);
+ }
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ * Sets the login.
+ *
+ * @param login
+ * the new login
+ */
+ public void setLogin(final String login)
+ {
+ this.login = login;
+ }
+
+ /**
+ * Sets the password.
+ *
+ * @param password
+ * the new password
+ */
+ public void setPassword(final String password)
+ {
+ this.password = password;
+ }
+
+ /**
+ * Sets the url.
+ *
+ * @param url
+ * the new url
+ */
+ public void setUrl(final String url)
+ {
+ this.url = url;
+ }
+}
diff --git a/src/fr/devinsy/statoolinfos/util/SQLUtils.java b/src/fr/devinsy/statoolinfos/util/sql/SQLUtils.java
similarity index 79%
rename from src/fr/devinsy/statoolinfos/util/SQLUtils.java
rename to src/fr/devinsy/statoolinfos/util/sql/SQLUtils.java
index fcc550e..10ada04 100644
--- a/src/fr/devinsy/statoolinfos/util/SQLUtils.java
+++ b/src/fr/devinsy/statoolinfos/util/sql/SQLUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 Christian Pierre MOMON
+ * Copyright (C) 2020-2022 Christian Pierre MOMON
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with StatoolInfos. If not, see .
*/
-package fr.devinsy.statoolinfos.util;
+package fr.devinsy.statoolinfos.util.sql;
import java.sql.Connection;
import java.sql.DriverManager;
@@ -25,6 +25,7 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
+import java.util.Date;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
@@ -244,6 +245,32 @@ public final class SQLUtils
return result;
}
+ /**
+ * To date time.
+ *
+ * @param source
+ * the source
+ * @return the date time
+ */
+ public static LocalDateTime toDateTime(final java.sql.Timestamp source)
+ {
+ LocalDateTime result;
+
+ if (source == null)
+ {
+ result = null;
+ }
+ else
+ {
+ long seconds = source.getTime() / 1000;
+ long nanos = (source.getTime() - seconds * 1000) * 1000000;
+ result = LocalDateTime.ofEpochSecond(seconds, (int) nanos, ZoneOffset.UTC);
+ }
+
+ //
+ return result;
+ }
+
/**
* To date time.
*
@@ -269,4 +296,54 @@ public final class SQLUtils
//
return result;
}
+
+ /**
+ * To timestamp.
+ *
+ * @param source
+ * the source
+ * @return the java.sql. timestamp
+ */
+ public static java.sql.Timestamp toTimestamp(final Date source)
+ {
+ java.sql.Timestamp result;
+
+ if (source == null)
+ {
+ result = null;
+ }
+ else
+ {
+ result = new java.sql.Timestamp(source.getTime() * 1000);
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ * To timestamp.
+ *
+ * @param source
+ * the source
+ * @return the java.sql. timestamp
+ */
+ public static java.sql.Timestamp toTimestamp(final LocalDateTime source)
+ {
+ java.sql.Timestamp result;
+
+ if (source == null)
+ {
+ result = null;
+ }
+ else
+ {
+ long seconds = source.toEpochSecond(ZoneOffset.UTC);
+ long milliseconds = source.getNano() / 1000000;
+ result = new java.sql.Timestamp(seconds * 1000 + milliseconds);
+ }
+
+ //
+ return result;
+ }
}