Compare commits

...

243 commits
0.4.0 ... main

Author SHA1 Message Date
c414a04075 Build 0.6.1 2024-09-23 04:42:38 +02:00
000d779d01 Fixed bad log init with no configuration file. 2024-09-23 03:43:04 +02:00
b092073311 Fixed StackOverflowError case in AccessLog regex. 2024-09-23 03:18:11 +02:00
c330ac064d Improved Javadoc and added test for isPage method. 2024-09-23 03:16:33 +02:00
35a90e3ff9 Fixed Java version in build script. 2024-09-23 02:12:55 +02:00
3ace8b3151 Fixed label in script build.sh. 2024-09-23 00:54:01 +02:00
0af4eafec3 Upgraded log4j libs from 1.7.32 to 2.23.1. 2024-08-21 16:22:25 +02:00
e8a96d1bcb Improved main README. 2024-08-20 23:05:50 +02:00
9662d66254 Improved main README and resources files. 2024-08-20 22:57:44 +02:00
93284171d9 Improved documentation. 2024-08-19 00:54:25 +02:00
3740992dd1 Improved build script. 2024-08-19 00:54:07 +02:00
613d3891be Build 0.6.0 2024-08-17 23:44:54 +02:00
9caa833856 Fixed infinite loop checking ApacheHttpErrorLogFiles. 2024-08-17 23:27:36 +02:00
6455fc7e90 Improved parameter documentation. 2024-08-17 22:37:28 +02:00
3fcb303a91 Fixed categories logo path. 2024-08-16 23:28:27 +02:00
856aab30c9 Improved wording. 2024-08-16 22:25:50 +02:00
0526ab46e8 Made Javadoc review. 2024-08-15 03:53:28 +02:00
790f40b9e7 Prepared next CHANGELOG. 2024-08-15 00:19:11 +02:00
4c0fc7d6a5 Deleted a no longer targeted service. 2024-08-14 23:43:11 +02:00
d960265a0b Fixed UTF-8 in project settings. 2024-08-14 23:35:03 +02:00
8ca626039a Removed useless logger variable. 2024-08-14 23:34:33 +02:00
2ab08cca77 Made Javadoc review and header review. 2024-08-14 23:01:50 +02:00
f11b3c7ec3 Upgraded class instanciate method. 2024-08-14 17:20:41 +02:00
839689e6c6 Increased version after the splitweb step. 2024-08-14 16:57:53 +02:00
b9f67d8363 Removed unuseful htmlize option in configuration file. 2024-08-14 02:46:06 +02:00
eca3d45fb6 Added tests. 2024-08-13 03:15:10 +02:00
d024d02409 Added CrawlCache expired management feature. 2024-08-12 05:46:41 +02:00
cfec6aab7c Updated the README text. 2024-08-09 01:56:32 +02:00
f98a53362e Added a category file. 2024-08-08 17:14:30 +02:00
f0f915ddc1 Refactor and improved to run with the split web app. 2024-08-08 17:13:28 +02:00
e44bda8db2 Made a huge optimization in the property check. Added test. 2024-08-02 04:55:03 +02:00
93c06e728a Removed htmlize target directory conf. 2024-07-27 04:04:23 +02:00
6bf7610328 Removed unuseful Xidyn lib. 2024-07-26 19:20:15 +02:00
b5cfdaef21 Migrated from Java 11 to Java 17. 2024-07-26 19:16:38 +02:00
be08c8c7e4 Split htmlize command code to statoolinfosweb project. 2024-07-26 02:32:50 +02:00
9227238b25 Moved (Year/Month/Week)Values classes form htmlize to properties
package.
2024-07-26 02:18:47 +02:00
78e6fda4cc Added new error log parameter description for configuration file. 2024-07-22 12:17:05 +02:00
9bd442d99f Fixed property label. 2024-07-22 11:48:39 +02:00
f32c712727 Updated main README file. 2024-07-21 02:53:43 +02:00
33455ae54f Added tests about http access logs. 2024-07-21 02:48:38 +02:00
3ca13aad0c Fixed refactor from http to httpaccess 2024-07-20 19:52:49 +02:00
b37cebb01f Added configuation file for HttpAccessLogs tests. 2024-07-20 15:57:24 +02:00
98966ee8ea Refactored HttpErrorLogs tests. 2024-07-20 15:55:42 +02:00
0f67780f1b Added tests for HttpAcessLogParser class. 2024-07-20 15:45:35 +02:00
112afd61ed Fixed parsing of \" in "" for http access logs. 2024-07-20 15:24:38 +02:00
1253e22ce1 Added new file detection in FilesLineIterator. 2024-07-20 02:59:17 +02:00
d453979eef Refactored http error log metrics. Added list errfile and list errlog
commands.
2024-07-20 02:58:27 +02:00
633246dddd Made Javadoc review. 2024-07-18 19:24:41 +02:00
f1074afe95 Clean metrics.httpaccess package. 2024-07-18 19:24:02 +02:00
70f6c9fb02 Refactored readFirstLine methods. 2024-07-18 19:23:17 +02:00
4612402014 Rename package from http to httpaccess (part 2). 2024-07-18 19:21:41 +02:00
a4f968a347 Added data for http error tests. 2024-07-18 19:16:17 +02:00
3bc224b779 Rename package from http to httpaccess. 2024-07-18 19:09:41 +02:00
cc545c217e Fixed member path use. 2023-07-20 12:08:06 +02:00
080f72a374 Commented exception print trace to avoid error cron email. 2023-07-04 15:21:45 +02:00
ed2590b88b Added configuration file for stat visitors cli command. 2023-07-04 03:20:28 +02:00
623438a218 Added configuration file for stat user agents cli command. 2023-07-04 03:14:50 +02:00
8564cef205 Added configuration file for stat ip cli command. 2023-07-03 19:15:30 +02:00
7af1766f4f Added configuration file for list visitor cli command. 2023-07-03 18:25:19 +02:00
da1af17b04 Added configuration file for list ip cli command. 2023-07-03 18:11:55 +02:00
0458382f86 Added configuration file for list ua cli command. 2023-07-03 18:02:25 +02:00
02281b1ab6 Added HttpAccessLogDateTimePattern management (#sleto). 2023-07-03 17:40:23 +02:00
8619c59a65 Improved user agent bot list. 2023-07-03 14:38:36 +02:00
c51822877f Build 0.5.1 2023-05-09 18:35:08 +02:00
00486a4710 Reviewed Javadoc. 2023-05-09 15:01:06 +02:00
5e7ec3e6f2 Reviewed Javadoc. 2023-05-09 14:34:34 +02:00
189f8471ac Added CHANGELOG file. 2023-05-09 14:21:50 +02:00
8b972d3fce Improved documentation. 2023-05-09 13:03:24 +02:00
805144c2cf Improved logging. 2023-05-09 11:57:03 +02:00
bb1820222f Updated documentation. 2023-05-09 11:26:21 +02:00
52090b3637 Added multi sources for Http log file search. 2023-05-09 10:30:36 +02:00
3565c1024b Improved XMPP probing. 2023-05-09 10:29:56 +02:00
72ea872546 Improved property stats page with only active organizations. 2023-05-07 11:55:20 +02:00
5cc3f8c634 Wording. 2023-05-07 11:22:33 +02:00
607135b72e Fixed header. 2023-05-07 10:52:00 +02:00
9d35f87009 Fixed header. 2023-05-07 10:50:57 +02:00
ea85018977 Improved User Agent Bot detection. 2023-05-07 10:46:27 +02:00
4a0ac7b2df Added wrong password metrics for Minetest. 2023-05-07 10:45:45 +02:00
c1adf8e650 Improved PropertyStats page with only active services. 2023-05-07 10:41:11 +02:00
f28e0e61aa Fixed property label in Privatebin patch probe. 2023-03-20 00:37:04 +01:00
a0ba83b885 Improved CLI commands. 2023-02-27 22:54:45 +01:00
2ec1b2e926 Improved CLI commands. 2023-02-27 20:45:36 +01:00
af0ee48e4b Improved CLI commands. 2023-02-27 18:33:03 +01:00
89bb16ea66 Made Javadoc review. 2023-02-27 18:18:12 +01:00
2b5fb4489b Improved Http Access logs reading. 2023-02-27 12:56:35 +01:00
1539872bf2 Extended user agent bot detector list. 2023-02-26 11:00:58 +01:00
8fdafcdf1d Added CLI commands to test HttpAccessLog files and lines. 2023-02-26 02:02:24 +01:00
580d2ff447 Fixed hosting properties file management. 2023-02-25 23:24:09 +01:00
ad7494c01f Added Z support in DATETIME property check. 2023-02-25 15:47:43 +01:00
ec9f8ede3c Mise à jour de 'README.md' 2023-02-24 01:14:21 +01:00
72483be914 Moved HttpErrorLog analyzer in dedicated package. 2023-02-24 00:55:06 +01:00
0555c41c10 Refactored prober call from CLI. 2023-02-24 00:46:37 +01:00
9a1b76343e Mise à jour de 'README.md' 2023-02-23 22:16:13 +01:00
96c31990d0 Mise à jour de 'README.md' 2023-02-23 20:25:47 +01:00
d7fad84d11 Merge branch 'master' of git@forge.devinsy.fr:devinsy/statoolinfos.git 2023-02-23 20:07:44 +01:00
10b284c053 Added new analyzers. 2023-02-23 19:39:57 +01:00
a1dd2ba48f Added pathFilter parameter in httpAccessLog read (#2, Sleto). 2023-02-23 19:39:16 +01:00
67445f6170 Fixed HTTP access log pattern. 2023-02-23 18:24:11 +01:00
5080c980d8 Mise à jour de 'README.md' 2023-02-21 17:43:38 +01:00
b1d46f61a6 Mise à jour de 'README.md' 2023-02-13 11:51:14 +01:00
c79e9ade15 Added optional parameter IPV6ONLY in statoolinfos.sh. 2023-02-11 08:39:59 +01:00
9d63f37e33 Mise à jour de 'README.md' 2023-02-04 18:23:50 +01:00
bb2e551196 Mise à jour de 'README.md' 2023-02-04 18:22:47 +01:00
f69847abb9 Mise à jour de 'README.md' 2023-02-04 18:22:15 +01:00
6245ef8c5a Fixed header year. 2023-02-03 14:09:26 +01:00
84d073ab8e Mise à jour de 'README.md' 2023-02-02 20:14:33 +01:00
4ec7e4de81 Mise à jour de 'README.md' 2023-02-02 18:30:38 +01:00
5521dcaec5 Mise à jour de 'README.md' 2023-02-02 18:08:18 +01:00
a977b16b3c Mise à jour de 'README.md' 2023-02-02 18:07:55 +01:00
14217d74be Mise à jour de 'README.md' 2023-02-02 18:06:51 +01:00
4c2869862f Mise à jour de 'README.md' 2023-02-02 16:30:38 +01:00
89b56c543e Fixed HTTP pattern management from metric conf file. 2023-02-02 14:19:03 +01:00
9970a85bff Added Kuma in Bot detection file. 2023-01-31 00:44:59 +01:00
dcc266a41d Added not authorized HTTP status code. 2023-01-06 23:08:10 +01:00
999b61d3be Added chat metrics for Minetest. 2023-01-06 23:07:50 +01:00
3e328d186c Changed metrics menu entry from 2020 to 2022. 2023-01-06 23:07:02 +01:00
34550c8ab4 Set 401 uptime cas as OK. 2022-11-10 22:58:53 +01:00
d309c4156a Fixed year header. 2022-11-10 21:44:52 +01:00
a6ddce2ee1 Fixed bad category list building. 2022-11-10 19:24:19 +01:00
c8b63869b2 Removed debug trace. 2022-11-10 11:01:52 +01:00
003fb306a0 Fixed categories compare. 2022-11-10 10:55:48 +01:00
a1e9949ca5 Improved bot pattern list with TinyStatus. 2022-10-06 01:00:14 +02:00
83efaf25e7 Fixed wording. 2022-09-18 16:32:03 +02:00
3cd843e1f1 Fixed separase case characters in property stats. 2022-07-25 18:32:26 +02:00
c98fc07e1b Improved federation service count. 2022-07-25 15:32:56 +02:00
92f6674bfc Improved date management. 2022-07-24 11:24:28 +02:00
04aed10a38 Improved startDate and endDate management for services. 2022-07-24 11:01:46 +02:00
8712c99894 Improved startDate and endDate management for organizations. 2022-07-24 10:55:50 +02:00
f23834d8e3 Improved Federation getStartDate management. 2022-07-24 10:49:28 +02:00
a414ba7956 Added provider hypervisor charts for service stats. 2022-07-24 01:49:07 +02:00
7b77a0ddf6 Added type chart and provider hypervisor charts for organization stats. 2022-07-24 01:34:09 +02:00
edc60840d0 Added federation organization type chart. Improved federation charts. 2022-07-23 01:24:23 +02:00
fbf6e50b49 Refactored federation stats. Added provider hypervisor chart. 2022-07-22 18:32:54 +02:00
4d6e592204 Added organization.type check entry. 2022-07-22 16:54:11 +02:00
e034f955ad Added host.provider.hypervisor check entry. 2022-07-22 16:51:43 +02:00
fa053bebad Changed color of ServiceCountYearChart. 2022-07-22 16:29:46 +02:00
371d199ee9 Fixed bad display of htmlizeHostNamePieChart. 2022-07-22 16:26:48 +02:00
b8433e84eb Swap columns in htmlizeOrganizationInOutChart. 2022-07-22 16:26:00 +02:00
62f1b7b92f Fixed colors. 2022-07-22 15:59:20 +02:00
a1833ddd0b Merge branch 'master' of forge.devinsy.fr:devinsy/statoolinfos 2022-06-27 21:50:33 +02:00
611b962171 Added metrics for GSL. 2022-06-27 21:43:41 +02:00
af44628def Hide token in exception message. 2022-06-23 02:01:11 +02:00
32972d2046 Mise à jour de 'README.md' 2022-05-26 23:50:16 +02:00
70387d3cfd Improved GiteaAPI exception message. 2022-04-27 09:58:16 +02:00
03d7661ba9 Added GSL metric generator. 2022-04-18 20:34:54 +02:00
7533d0cd43 Fixed Etherpad probing documentation. 2022-03-29 02:03:52 +02:00
c2076f15ce Extended Etherpad probing. 2022-03-29 01:58:54 +02:00
5601fe5d54 Added Etherpad probing. 2022-03-28 18:16:15 +02:00
0b44e9629e Added host server distribution stats graphics. Improved and fixed stats. 2022-03-24 02:35:44 +01:00
c858a23e0d Added check rule for host.server.distribution. 2022-03-23 16:12:19 +01:00
950d06fae7 Added Privatebin patch log probing. 2022-03-11 14:56:16 +01:00
058b902fbd Javadoc review. 2022-03-11 14:55:16 +01:00
bca355a047 Fixed uptime button color. 2022-03-11 14:48:19 +01:00
f7efce5c4f Added account metric for Minetest. 2022-03-08 13:04:38 +01:00
87a6a15f10 Added sql database probing. Gitea + Minetest. 2022-03-07 22:45:18 +01:00
b1e841c787 Added services figure view. 2022-03-05 16:19:04 +01:00
94f807dfad Added emoji, userCount, visitCount and column sorting. 2022-03-04 18:23:01 +01:00
b731b9ad90 Renamed metrics.barcodes.count to metrics.barcodes.created. 2022-03-04 00:57:09 +01:00
ab2834d597 Improved top labels. 2022-03-04 00:42:10 +01:00
2b2f444c44 Fixed URL checker with http prefix mandatory. 2022-02-28 17:30:12 +01:00
37853c40d9 Improved Gitea user metric computation. 2022-02-27 12:01:29 +01:00
f750d648fb Step in add of figures view. 2022-02-27 11:57:37 +01:00
57d7c3cc97 Improved generic metric listing. 2022-02-26 17:01:34 +01:00
8aa0a2e84b Fixed user metric computation for Minetest. 2022-02-26 17:00:51 +01:00
c267d2637a A new icon for soon figure page. 2022-02-25 18:26:02 +01:00
03b11ebe57 Fixed specific metric computation. 2022-02-25 18:25:37 +01:00
1519850ed1 Fixed label in metrics page. 2022-02-25 18:19:59 +01:00
0ae5357970 Improved install in README. 2022-02-23 02:47:47 +01:00
205bd54b01 Fixed generic metrics display. 2022-02-20 02:37:51 +01:00
380028376a Improved temporary file removing. 2022-02-20 02:16:47 +01:00
d017781858 Renamed metrics.service.files metric and added auto-fix. 2022-02-20 02:15:58 +01:00
e24c7ad2aa Improved Gitea probing parameter doc. 2022-02-19 12:18:05 +01:00
a2eee04e72 Fixed URL format in Gitea probing. 2022-02-19 12:13:27 +01:00
8f4ff59a6a Added Gitea probing parameters in README. 2022-02-19 12:02:22 +01:00
066203eae1 Improved Gitea probing. 2022-02-18 19:39:47 +01:00
0f9e3c4ae8 Improved organization list view with actives, idles and aways. 2022-02-16 19:37:31 +01:00
5bd6e2c600 Improved probing of Gitea, PrivateBin and LibreQR. Refactoring. 2022-02-15 01:45:39 +01:00
0f4b1e2c2c Improved http access log parsing. 2022-02-15 01:39:09 +01:00
e64872aa9a Improved bot detection. 2022-02-15 01:31:42 +01:00
224470e609 Fixed grammar. 2022-02-14 12:50:01 +01:00
676669260b Improved LibreQR probing. 2022-02-11 11:49:28 +01:00
067bdfe5bb Fixed ISO reference. 2022-02-10 13:31:51 +01:00
a3e3fce191 Added qrcode count metric for LibreQR. 2022-01-31 16:10:11 +01:00
71da08488b Removed bots from user in LibreQR metrics. 2022-01-31 14:42:36 +01:00
e86aeeabd5 Improved snapshot script. 2022-01-30 03:17:09 +01:00
553068713a Added LibreQR probing. Improved wildcard management. 2022-01-30 03:16:53 +01:00
d08eb7a9d7 Increased protocol version. 2022-01-24 05:39:38 +01:00
20a58e2b1d Build 0.5.0 2022-01-23 03:49:07 +01:00
d644e334a8 Added custom access log pattern config in README. 2022-01-23 03:48:29 +01:00
18c386b91c Prepared next version. 2022-01-23 03:39:43 +01:00
2ee42fd197 Improved code. 2022-01-22 19:29:44 +01:00
defa20b003 Improved http access log regex. 2022-01-22 19:29:18 +01:00
87b44605c5 Restricted federation stats to active organizations only. 2022-01-22 19:28:52 +01:00
8a106f01c7 Upgraded commons-io lib. 2022-01-22 16:54:57 +01:00
8aaf2f345c Improved access http parsing. 2022-01-22 16:54:41 +01:00
6850f3b57a Added method http metric. 2022-01-22 16:54:10 +01:00
6bf8037cc5 Improved status management in organizations and services display. 2022-01-22 13:05:28 +01:00
251d4ef761 Improved property date get. 2022-01-22 03:30:18 +01:00
a1b0c34645 Fixed emoji sorting in organization list and service list views. 2022-01-21 19:41:41 +01:00
ebff7251e8 Added Let's encrypt detection for bot filtering. 2022-01-21 00:55:08 +01:00
1c4b9cfe87 Added date tips in header column with monthly label. 2022-01-21 00:43:37 +01:00
1d36510ac3 Replaced 0 value with emoji in tables. 2022-01-21 00:31:33 +01:00
0e47ac2dae Added visits.ipv4 and visits.ipv6 management. 2022-01-20 19:25:02 +01:00
00d778c9f3 Imporved error message. 2022-01-20 16:27:25 +01:00
eee023346f Clean script file. 2022-01-20 16:26:34 +01:00
9fdb7beb46 Fixed unmanaged crawl exception. 2022-01-18 13:08:15 +01:00
35c3f91609 Improved about page. 2022-01-17 04:36:40 +01:00
4099a9a5fb Added metrics configuration templates in README. 2022-01-16 05:55:13 +01:00
2e59500d69 Added asset filter in http visit definition. 2022-01-13 17:56:21 +01:00
f1361c9d25 Fixed visit and visitor new definition. 2022-01-13 12:55:17 +01:00
f6d433de00 Fixed bug in error nginx time parsing. 2022-01-13 12:53:49 +01:00
79441007b0 Fixed label display in 2 data graph. 2022-01-13 12:52:33 +01:00
3feafb815c Improved code. 2022-01-11 16:04:15 +01:00
f02a3b7dd4 Added bot pattern for mod_jk dummy connection in http logs. 2022-01-11 16:02:24 +01:00
6c220602fd Improved code. 2022-01-11 16:01:51 +01:00
a667d59072 Removed success filter in http log visits compute. 2022-01-11 02:15:24 +01:00
88a1cd4c29 Added asterisk month in organization list view. 2022-01-11 00:29:16 +01:00
ab9e8c6b56 Added contributor. 2022-01-09 12:12:46 +01:00
b3f9d37480 Fixed DataTables path after upgrade. 2022-01-09 11:14:32 +01:00
9f7de0cde4 Fixed former member display in organization page. 2022-01-08 19:12:08 +01:00
fd19427700 Improved UserAgent analyze. 2022-01-06 10:24:55 +01:00
07de9414b9 Fixed empty log file case. 2022-01-05 14:06:47 +01:00
8f8eeb437d Fixed and added metrics in Mumble probing. 2022-01-05 02:32:20 +01:00
8f8bb0dffc Fixed Mumble probing. 2022-01-05 01:27:01 +01:00
f4338ca7b2 Fixed previous commit. 2022-01-04 14:43:50 +01:00
407f22692b Added level log4j2 configuration. 2022-01-04 14:20:09 +01:00
65354e89cc Improved log4j2 configuration and fixed build process. 2022-01-04 02:27:42 +01:00
efe5b00ae3 Upgraded Log4j lib files. 2022-01-02 18:29:09 +01:00
b34903fde2 Coded step in new specific metric probing. 2021-12-31 23:24:44 +01:00
68bfab5b26 Extended and fixed timemark code. 2021-12-31 23:23:29 +01:00
1da2b34734 Reviewed Javadoc. 2021-12-31 23:21:49 +01:00
50ec907ac8 Added PrivateBin probing. 2021-12-31 14:05:49 +01:00
5d3e05d6f1 Improved default UTF-8 charset used. 2021-12-29 15:58:04 +01:00
62815f6d1e Migrated to Log4j2. 2021-12-29 01:00:20 +01:00
d5c67afb64 Improved generic metric display. 2021-12-24 17:38:30 +01:00
88c503a812 Build 0.4.1 2021-12-23 02:00:48 +01:00
b49e2a5822 Upgraded DataTables (CVE-2021-23445). 2021-12-20 12:46:30 +01:00
5fd94e6fbd Improved wildcard feature in probe command (#1 thx Kepon). 2021-12-20 01:40:36 +01:00
94916ef5d1 Improved sample conf resources. 2021-12-20 01:38:47 +01:00
8b87eed546 Added Minetest log analyze. 2021-12-18 18:14:36 +01:00
0bed68260a Clean useful code. 2021-12-18 12:11:13 +01:00
e1cf7fd209 Improved help message. 2021-12-18 12:10:29 +01:00
93dea811f2 Improved README. 2021-12-15 17:44:04 +01:00
506 changed files with 19908 additions and 26011 deletions

View file

@ -2,7 +2,7 @@
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="test"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
<attributes>
<attribute name="module" value="true"/>
<attribute name="owner.project.facets" value="java"/>
@ -10,22 +10,36 @@
</classpathentry>
<classpathentry kind="lib" path="lib/commons-codec-1.8.jar" sourcepath="lib/commons-codec-1.8-sources.jar"/>
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
<classpathentry kind="lib" path="lib/mysql-jdbc-5.0.8.jar"/>
<classpathentry kind="lib" path="lib/Logs/log4j-1.2.17.jar" sourcepath="lib/Logs/log4j-1.2.17-source.zip"/>
<classpathentry kind="lib" path="lib/UnitTesting/hamcrest-core-1.3.jar" sourcepath="lib/UnitTesting/hamcrest-core-1.3-sources.jar"/>
<classpathentry kind="lib" path="lib/hsqldb-2.3.0.jar"/>
<classpathentry kind="lib" path="lib/Logs/slf4j-api-1.7.25.jar" sourcepath="lib/Logs/slf4j-api-1.7.25-sources.jar"/>
<classpathentry kind="lib" path="lib/Logs/slf4j-log4j12-1.7.25.jar" sourcepath="lib/Logs/slf4j-log4j12-1.7.25-sources.jar"/>
<classpathentry kind="lib" path="lib/UnitTesting/junit-4.12.jar" sourcepath="lib/UnitTesting/junit-4.12-sources.jar"/>
<classpathentry kind="lib" path="lib/commons-cli-1.4.jar" sourcepath="lib/commons-cli-1.4-sources.jar"/>
<classpathentry kind="lib" path="lib/commons-io-2.7.jar" sourcepath="lib/commons-io-2.7-sources.jar"/>
<classpathentry kind="lib" path="lib/commons-lang3-3.11.jar" sourcepath="lib/commons-lang3-3.11-sources.jar"/>
<classpathentry kind="lib" path="lib/commons-text-1.9.jar" sourcepath="lib/commons-text-1.9-sources.jar"/>
<classpathentry kind="lib" path="lib/tika-core-1.24.1.jar" sourcepath="lib/tika-core-1.24.1-sources.jar"/>
<classpathentry kind="lib" path="lib/catgenerator-core-0.1.7.jar" sourcepath="lib/catgenerator-core-0.1.7-sources.zip"/>
<classpathentry kind="lib" path="lib/xidyn-1.11.2.jar" sourcepath="lib/xidyn-1.11.2-sources.zip"/>
<classpathentry kind="lib" path="lib/jOpenDocument-1.3.jar" sourcepath="lib/jOpenDocument-src-1.3.zip"/>
<classpathentry kind="lib" path="lib/threeten-extra-1.5.0.jar" sourcepath="lib/threeten-extra-1.5.0-sources.jar"/>
<classpathentry kind="lib" path="lib/devinsy-strings-0.11.4.jar" sourcepath="lib/devinsy-strings-0.11.4-sources.zip"/>
<classpathentry kind="lib" path="lib/commons-io-2.11.0.jar" sourcepath="lib/commons-io-2.11.0-sources.jar"/>
<classpathentry kind="lib" path="lib/json-simple-1.1.1.jar" sourcepath="lib/json-simple-1.1.1-sources.jar"/>
<classpathentry kind="lib" path="lib/mariadb-java-client-3.0.3.jar"/>
<classpathentry kind="lib" path="lib/postgresql-42.3.3.jar"/>
<classpathentry kind="lib" path="lib/sqlite-jdbc-3.36.0.3.jar"/>
<classpathentry kind="lib" path="lib/mysql-jdbc-5.0.8.jar"/>
<classpathentry kind="lib" path="lib/devinsy-strings-0.17.0.jar" sourcepath="lib/devinsy-strings-0.17.0-sources.zip"/>
<classpathentry kind="con" path="org.eclipse.jst.server.core.container/org.eclipse.jst.server.tomcat.runtimeTarget/apache-tomcat-10.1.12">
<attributes>
<attribute name="owner.project.facets" value="jst.utility"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path=".apt_generated">
<attributes>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="lib/Logs/log4j-api-2.23.1.jar" sourcepath="lib/Logs/log4j-api-2.23.1-sources.jar"/>
<classpathentry kind="lib" path="lib/Logs/log4j-core-2.23.1.jar" sourcepath="lib/Logs/log4j-core-2.23.1-sources.jar"/>
<classpathentry kind="lib" path="lib/Logs/log4j-slf4j2-impl-2.23.1.jar" sourcepath="lib/Logs/log4j-slf4j2-impl-2.32.1-sources.jar"/>
<classpathentry kind="lib" path="lib/Logs/slf4j-api-2.0.16.jar" sourcepath="lib/Logs/slf4j-api-2.0.16-sources.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

1
.gitignore vendored
View file

@ -2,3 +2,4 @@
/build
/dist
*~
/.apt_generated/

View file

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View file

@ -0,0 +1,5 @@
eclipse.preferences.version=1
org.eclipse.jdt.apt.aptEnabled=true
org.eclipse.jdt.apt.genSrcDir=.apt_generated
org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
org.eclipse.jdt.apt.reconcileEnabled=true

View file

@ -11,9 +11,9 @@ org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=11
org.eclipse.jdt.core.compiler.compliance=17
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@ -21,20 +21,30 @@ org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.processAnnotations=enabled
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=11
org.eclipse.jdt.core.compiler.source=17
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
org.eclipse.jdt.core.formatter.align_selector_in_method_invocation_on_expression_first_line=false
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false
org.eclipse.jdt.core.formatter.align_with_spaces=false
org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16
org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant=49
org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field=49
org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable=49
org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method=49
org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package=49
org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter=0
org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type=49
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_assertion_message=0
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
@ -44,6 +54,8 @@ org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain=0
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=49
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_arrow=0
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_colon=0
org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16
org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
org.eclipse.jdt.core.formatter.alignment_for_module_statements=16
@ -52,6 +64,7 @@ org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16
org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_permitted_types_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_record_components=16
org.eclipse.jdt.core.formatter.alignment_for_relational_operator=0
org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
@ -62,8 +75,10 @@ org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_switch_case_with_arrow=0
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_type_annotations=0
org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0
org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0
org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
@ -112,6 +127,7 @@ org.eclipse.jdt.core.formatter.comment.indent_tag_description=false
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags=do not insert
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
org.eclipse.jdt.core.formatter.comment.javadoc_do_not_separate_block_tags=false
org.eclipse.jdt.core.formatter.comment.line_length=80
org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
@ -191,6 +207,7 @@ org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arg
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_permitted_types=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions=insert
@ -282,6 +299,7 @@ org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_ar
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_permitted_types=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions=do not insert
@ -365,6 +383,8 @@ org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false
org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false
org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=false
org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false
org.eclipse.jdt.core.formatter.keep_switch_body_block_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_switch_case_with_arrow_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.lineSplit=200
@ -395,6 +415,7 @@ org.eclipse.jdt.core.formatter.text_block_indentation=0
org.eclipse.jdt.core.formatter.use_on_off_tags=false
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true
org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator=true
org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false
org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true
org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true
@ -404,5 +425,6 @@ org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
org.eclipse.jdt.core.formatter.wrap_before_relational_operator=true
org.eclipse.jdt.core.formatter.wrap_before_shift_operator=true
org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true
org.eclipse.jdt.core.formatter.wrap_before_switch_case_arrow_operator=false
org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter

View file

@ -1,3 +1,4 @@
cleanup.add_all=false
cleanup.add_default_serial_version_id=false
cleanup.add_generated_serial_version_id=true
cleanup.add_missing_annotations=true
@ -7,34 +8,78 @@ cleanup.add_missing_nls_tags=false
cleanup.add_missing_override_annotations=true
cleanup.add_missing_override_annotations_interface_methods=true
cleanup.add_serial_version_id=true
cleanup.also_simplify_lambda=true
cleanup.always_use_blocks=true
cleanup.always_use_parentheses_in_expressions=false
cleanup.always_use_this_for_non_static_field_access=true
cleanup.always_use_this_for_non_static_method_access=false
cleanup.array_with_curly=false
cleanup.arrays_fill=false
cleanup.bitwise_conditional_expression=false
cleanup.boolean_literal=false
cleanup.boolean_value_rather_than_comparison=true
cleanup.break_loop=false
cleanup.collection_cloning=false
cleanup.comparing_on_criteria=false
cleanup.comparison_statement=false
cleanup.controlflow_merge=false
cleanup.convert_functional_interfaces=false
cleanup.convert_to_enhanced_for_loop=false
cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
cleanup.convert_to_switch_expressions=false
cleanup.correct_indentation=true
cleanup.do_while_rather_than_while=true
cleanup.double_negation=false
cleanup.else_if=false
cleanup.embedded_if=false
cleanup.evaluate_nullable=false
cleanup.extract_increment=false
cleanup.format_source_code=true
cleanup.format_source_code_changes_only=false
cleanup.hash=false
cleanup.if_condition=false
cleanup.insert_inferred_type_arguments=false
cleanup.instanceof=false
cleanup.instanceof_keyword=false
cleanup.invert_equals=false
cleanup.join=false
cleanup.lazy_logical_operator=false
cleanup.make_local_variable_final=false
cleanup.make_parameters_final=true
cleanup.make_private_fields_final=false
cleanup.make_type_abstract_if_missing_method=false
cleanup.make_variable_declarations_final=true
cleanup.map_cloning=false
cleanup.merge_conditional_blocks=false
cleanup.multi_catch=false
cleanup.never_use_blocks=false
cleanup.never_use_parentheses_in_expressions=true
cleanup.no_string_creation=false
cleanup.no_super=false
cleanup.number_suffix=false
cleanup.objects_equals=false
cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
cleanup.operand_factorization=false
cleanup.organize_imports=false
cleanup.overridden_assignment=false
cleanup.overridden_assignment_move_decl=true
cleanup.plain_replacement=false
cleanup.precompile_regex=false
cleanup.primitive_comparison=false
cleanup.primitive_parsing=false
cleanup.primitive_rather_than_wrapper=true
cleanup.primitive_serialization=false
cleanup.pull_out_if_from_if_else=false
cleanup.pull_up_assignment=false
cleanup.push_down_negation=false
cleanup.qualify_static_field_accesses_with_declaring_class=false
cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
cleanup.qualify_static_member_accesses_with_declaring_class=true
cleanup.qualify_static_method_accesses_with_declaring_class=false
cleanup.reduce_indentation=false
cleanup.redundant_comparator=false
cleanup.redundant_falling_through_block_end=false
cleanup.remove_private_constructors=true
cleanup.remove_redundant_modifiers=false
cleanup.remove_redundant_semicolons=false
@ -47,13 +92,36 @@ cleanup.remove_unnecessary_casts=true
cleanup.remove_unnecessary_nls_tags=true
cleanup.remove_unused_imports=true
cleanup.remove_unused_local_variables=false
cleanup.remove_unused_method_parameters=false
cleanup.remove_unused_private_fields=true
cleanup.remove_unused_private_members=false
cleanup.remove_unused_private_methods=true
cleanup.remove_unused_private_types=true
cleanup.return_expression=false
cleanup.simplify_lambda_expression_and_method_ref=false
cleanup.single_used_field=false
cleanup.sort_members=true
cleanup.sort_members_all=false
cleanup.standard_comparison=false
cleanup.static_inner_class=false
cleanup.strictly_equal_or_different=false
cleanup.stringbuffer_to_stringbuilder=false
cleanup.stringbuilder=false
cleanup.stringbuilder_for_local_vars=true
cleanup.stringconcat_stringbuffer_stringbuilder=false
cleanup.stringconcat_to_textblock=false
cleanup.substring=false
cleanup.switch=false
cleanup.system_property=false
cleanup.system_property_boolean=false
cleanup.system_property_file_encoding=false
cleanup.system_property_file_separator=false
cleanup.system_property_line_separator=false
cleanup.system_property_path_separator=false
cleanup.ternary_operator=false
cleanup.try_with_resource=false
cleanup.unlooped_while=false
cleanup.unreachable_block=false
cleanup.use_anonymous_class_creation=false
cleanup.use_autoboxing=false
cleanup.use_blocks=true
@ -61,18 +129,22 @@ cleanup.use_blocks_only_for_return_and_throw=false
cleanup.use_directly_map_method=false
cleanup.use_lambda=true
cleanup.use_parentheses_in_expressions=false
cleanup.use_string_is_blank=false
cleanup.use_this_for_non_static_field_access=true
cleanup.use_this_for_non_static_field_access_only_if_necessary=false
cleanup.use_this_for_non_static_method_access=false
cleanup.use_this_for_non_static_method_access_only_if_necessary=true
cleanup.use_unboxing=false
cleanup.use_var=false
cleanup_profile=_StatoolInfos
cleanup.useless_continue=false
cleanup.useless_return=false
cleanup.valueof_rather_than_instantiation=false
cleanup_profile=_StaoolInfos
cleanup_settings_version=2
eclipse.preferences.version=1
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
formatter_profile=_StatoolInfos
formatter_settings_version=19
formatter_settings_version=23
jautodoc.cleanup.add_header=false
jautodoc.cleanup.javadoc=false
jautodoc.cleanup.replace_header=false
@ -80,6 +152,8 @@ org.eclipse.jdt.ui.exception.name=exception
org.eclipse.jdt.ui.gettersetter.use.is=true
org.eclipse.jdt.ui.keywordthis=false
org.eclipse.jdt.ui.overrideannotation=true
org.eclipse.jdt.ui.text.custom_code_templates=
sp_cleanup.add_all=false
sp_cleanup.add_default_serial_version_id=true
sp_cleanup.add_generated_serial_version_id=false
sp_cleanup.add_missing_annotations=true
@ -89,35 +163,79 @@ sp_cleanup.add_missing_nls_tags=false
sp_cleanup.add_missing_override_annotations=true
sp_cleanup.add_missing_override_annotations_interface_methods=true
sp_cleanup.add_serial_version_id=false
sp_cleanup.also_simplify_lambda=false
sp_cleanup.always_use_blocks=true
sp_cleanup.always_use_parentheses_in_expressions=false
sp_cleanup.always_use_this_for_non_static_field_access=true
sp_cleanup.always_use_this_for_non_static_method_access=false
sp_cleanup.array_with_curly=false
sp_cleanup.arrays_fill=false
sp_cleanup.bitwise_conditional_expression=false
sp_cleanup.boolean_literal=false
sp_cleanup.boolean_value_rather_than_comparison=false
sp_cleanup.break_loop=false
sp_cleanup.collection_cloning=false
sp_cleanup.comparing_on_criteria=false
sp_cleanup.comparison_statement=false
sp_cleanup.controlflow_merge=false
sp_cleanup.convert_functional_interfaces=false
sp_cleanup.convert_to_enhanced_for_loop=false
sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
sp_cleanup.convert_to_switch_expressions=false
sp_cleanup.correct_indentation=true
sp_cleanup.do_while_rather_than_while=false
sp_cleanup.double_negation=false
sp_cleanup.else_if=false
sp_cleanup.embedded_if=false
sp_cleanup.evaluate_nullable=false
sp_cleanup.extract_increment=false
sp_cleanup.format_source_code=true
sp_cleanup.format_source_code_changes_only=false
sp_cleanup.hash=false
sp_cleanup.if_condition=false
sp_cleanup.insert_inferred_type_arguments=false
sp_cleanup.instanceof=false
sp_cleanup.instanceof_keyword=false
sp_cleanup.invert_equals=false
sp_cleanup.join=false
sp_cleanup.lazy_logical_operator=false
sp_cleanup.make_local_variable_final=false
sp_cleanup.make_parameters_final=true
sp_cleanup.make_private_fields_final=false
sp_cleanup.make_type_abstract_if_missing_method=false
sp_cleanup.make_variable_declarations_final=true
sp_cleanup.map_cloning=false
sp_cleanup.merge_conditional_blocks=false
sp_cleanup.multi_catch=false
sp_cleanup.never_use_blocks=false
sp_cleanup.never_use_parentheses_in_expressions=true
sp_cleanup.no_string_creation=false
sp_cleanup.no_super=false
sp_cleanup.number_suffix=false
sp_cleanup.objects_equals=false
sp_cleanup.on_save_use_additional_actions=true
sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
sp_cleanup.operand_factorization=false
sp_cleanup.organize_imports=true
sp_cleanup.overridden_assignment=false
sp_cleanup.overridden_assignment_move_decl=false
sp_cleanup.plain_replacement=false
sp_cleanup.precompile_regex=false
sp_cleanup.primitive_comparison=false
sp_cleanup.primitive_parsing=false
sp_cleanup.primitive_rather_than_wrapper=false
sp_cleanup.primitive_serialization=false
sp_cleanup.pull_out_if_from_if_else=false
sp_cleanup.pull_up_assignment=false
sp_cleanup.push_down_negation=false
sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
sp_cleanup.reduce_indentation=false
sp_cleanup.redundant_comparator=false
sp_cleanup.redundant_falling_through_block_end=false
sp_cleanup.remove_private_constructors=true
sp_cleanup.remove_redundant_modifiers=false
sp_cleanup.remove_redundant_semicolons=false
@ -130,13 +248,36 @@ sp_cleanup.remove_unnecessary_casts=true
sp_cleanup.remove_unnecessary_nls_tags=true
sp_cleanup.remove_unused_imports=true
sp_cleanup.remove_unused_local_variables=false
sp_cleanup.remove_unused_method_parameters=false
sp_cleanup.remove_unused_private_fields=true
sp_cleanup.remove_unused_private_members=false
sp_cleanup.remove_unused_private_methods=true
sp_cleanup.remove_unused_private_types=true
sp_cleanup.return_expression=false
sp_cleanup.simplify_lambda_expression_and_method_ref=false
sp_cleanup.single_used_field=false
sp_cleanup.sort_members=true
sp_cleanup.sort_members_all=false
sp_cleanup.standard_comparison=false
sp_cleanup.static_inner_class=false
sp_cleanup.strictly_equal_or_different=false
sp_cleanup.stringbuffer_to_stringbuilder=false
sp_cleanup.stringbuilder=false
sp_cleanup.stringbuilder_for_local_vars=false
sp_cleanup.stringconcat_stringbuffer_stringbuilder=false
sp_cleanup.stringconcat_to_textblock=false
sp_cleanup.substring=false
sp_cleanup.switch=false
sp_cleanup.system_property=false
sp_cleanup.system_property_boolean=false
sp_cleanup.system_property_file_encoding=false
sp_cleanup.system_property_file_separator=false
sp_cleanup.system_property_line_separator=false
sp_cleanup.system_property_path_separator=false
sp_cleanup.ternary_operator=false
sp_cleanup.try_with_resource=false
sp_cleanup.unlooped_while=false
sp_cleanup.unreachable_block=false
sp_cleanup.use_anonymous_class_creation=false
sp_cleanup.use_autoboxing=false
sp_cleanup.use_blocks=true
@ -144,12 +285,16 @@ sp_cleanup.use_blocks_only_for_return_and_throw=false
sp_cleanup.use_directly_map_method=false
sp_cleanup.use_lambda=false
sp_cleanup.use_parentheses_in_expressions=false
sp_cleanup.use_string_is_blank=false
sp_cleanup.use_this_for_non_static_field_access=true
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
sp_cleanup.use_this_for_non_static_method_access=false
sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
sp_cleanup.use_unboxing=false
sp_cleanup.use_var=false
sp_cleanup.useless_continue=false
sp_cleanup.useless_return=false
sp_cleanup.valueof_rather_than_instantiation=false
sp_jautodoc.cleanup.add_header=false
sp_jautodoc.cleanup.javadoc=false
sp_jautodoc.cleanup.replace_header=false

View file

@ -1,6 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="SikevaDB">
<wb-module deploy-name="StatooInfos">
<wb-resource deploy-path="/" source-path="/src"/>
<wb-resource deploy-path="/" source-path="/test"/>
<wb-resource deploy-path="/" source-path="/.apt_generated"/>
</wb-module>
</project-modules>

View file

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<runtime name="apache-tomcat-10.1.12"/>
<fixed facet="java"/>
<fixed facet="jst.utility"/>
<installed facet="jst.utility" version="1.0"/>
<installed facet="java" version="11"/>
<installed facet="java" version="17"/>
</faceted-project>

164
CHANGELOG.md Normal file
View file

@ -0,0 +1,164 @@
# StatoolInfos Changelog
All notable changes of StatoolInfos will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
- …
## [0.6.1] - 2024-09-23
- Fixed bad log init with no configuration file.
- Fixed StackOverflowError case in AccessLog regex.
- Improved Javadoc and added test for isPage method.
- Fixed Java version in build script.
- Fixed label in script build.sh.
- Upgraded log4j libs from 1.7.32 to 2.23.1.
- Improved main README and resources files.
- Improved documentation.
- Improved build script.
## [0.6.0] - 2024-08-17
Change major number because of split web event.
Changes for metrics:
- Deleted no longer targeted GSL service.
- Made Javadoc review and header review.
- Increased version after the splitweb step.
- Added CrawlCache expired management feature.
- Updated the README text.
- Added categories file from CHATONS stats workgroup with Angie from Framasoft, MrFlo and Cpm.
- Improved the federation time load (> x200).
- Huge optimization in the property check.
- Removed htmlize target directory conf.
- Migrated from Java 11 to Java 17.
- Split htmlize command code to statoolinfosweb project.
- Added new error log parameter description for configuration file.
- Fixed property label.
- Fixed parsing of \" in "" for http access logs. Less unrecognized http logs.
- Refactored http error log metrics.
- Added list errfile and list errlog CLI commands.
- Improved tests.
- Improved package naming.
- Added configuration file for list and stats CLI commands.
- Added HttpAccessLogDateTimePattern management (#sleto).
- Improved user agent bot list.
Changes for web building:
- SPLITWEB: no more web building! See the StatoolInfosWeb project.
## [0.5.1] 2023-05-09
Changes for metrics:
- Added multi sources for Http log file search.
- Added wrong password metrics for Minetest.
- Fixed property label in Privatebin patch probe.
- Added CLI commands to test HttpAccessLog files and lines.
- Moved HttpErrorLog analyzer in dedicated package.
- Refactored prober call from CLI.
- Added new metrics analyzers.
- Added pathFilter parameter in httpAccessLog read.
- Fixed HTTP access log pattern.
- Fixed HTTP pattern management from metric conf file.
- Added Kuma in Bot detection file.
- Added not authorized HTTP status code.
- Added chat metrics for Minetest.
- Set 401 uptime case as OK.
- Improved bot pattern list with TinyStatus.
- Added metrics for GSL.
- Improved documentation (README)
Changes for web building:
- Improved property stats page with only active organizations.
- Improved PropertyStats page with only active services.
- Fixed hosting properties file management.
- Added Z support in DATETIME property check.
- Added optional parameter IPV6ONLY in statoolinfos.sh.
- Changed metrics menu entry from 2020 to 2022.
- Fixed bad category list building.
- Removed debug trace.
- Fixed categories compare.
- Fixed wording.
- Fixed separate case characters in property stats.
- Improved federation service count.
- Improved date management.
- Improved startDate and endDate management for services.
- Improved startDate and endDate management for organizations.
- Improved Federation getStartDate management.
- Added provider hypervisor charts for service stats.
- Added type chart and provider hypervisor charts for organization stats.
- Added federation organization type chart. Improved federation charts.
- Refactored federation stats. Added provider hypervisor chart.
- Added organization.type check entry.
- Added host.provider.hypervisor check entry.
- Changed color of ServiceCountYearChart.
- Fixed bad display of htmlizeHostNamePieChart.
- Swap columns in htmlizeOrganizationInOutChart.
- Fixed colors.
## [0.5.0] 2022-01-23
This release contains many improvments:
- Extended http access log regex.
- Restricted federation stats to active organizations only.
- Improved status management in organizations and services display.
- Added Let's encrypt detection for bot filtering.
- Added date tips in header column with monthly label.
- Replaced 0 value with emoji in organizations view and services view.
- Added visits.ipv4 and visits.ipv6 management.
- Added metrics configuration templates in README.
- Changed visit and visitor definition.
- Fixed bug in error nginx time parsing.
- Fixed label display in 2 data graph.
- Added bot pattern for mod_jk dummy connection in http logs.
- Added asterisk month in organization list view.
- Added asterisk month in service list view.
- Fixed DataTables paths.
- Fixed former member display.
- Improved userAgent analyze.
- Fixed empty http log file bug.
- Added first veresion of Mumble probing (see README.md).
- Fixed bug in TimeMark code.
- Added first version of PrivateBin probing (see README.md).
- Migrated to Log4j2 (with Log4shell fix).
- Made code improvments.
Warning: visit and visitors definition has changed. Now it is more restricted: humans + method GET + page + status SUCCESS.
So some metrics have to be generate again (with -full) and some properties have to deleted:
- Added
- metrics.http.requesters : nombre de requêteurs.
- metrics.http.requesters.ipv4 : nombre de requêteurs IPv4.
- metrics.http.requesters.ipv6 : nombre de requêteurs IPv6.
- metrics.http.requesters.humans : nombre de requêteurs humains.
- metrics.http.requesters.bots : nombre de requêteurs bots.
- metrics.http.requesters.bots.walks : nombre de passages de requêteurs bots.
- metrics.http.metrics.methods.XXX : nombre de requête avec la méthode XXX.
- metrics.http.visits.ipv4 : nombre de visites en IPv4.
- metrics.http.visits.ipv6 : nombre de visites en IPv6.
- Changed
- metrics.http.visits : définition plus restrictive (humains + GET + page + SUCCESS).
- metrics.http.visitors : définition de visiteur plus restrictive.
- metrics.http.visitors.ipv4 : définition de visiteur plus restrictive.
- metrics.http.visitors.ipv6 : définition de visiteur plus restrictive.
- Removed
- metrics.http.visitors.humans : remplacé par metrics.http.visitors (nouvelle définition d'une visite).
- metrics.http.visitors.bots : supprimé (nouvelle définition d'une visite).
- metrics.https.visits.bots : supprimé (nouvelle définition d'une visite).
## [0.4.1] 2021-12-23
This release contains small improvments:
- Fixed DataTables (CVE-2021-23445).
- Improved wildcard feature in probe command (#1 thx Kepon).
- Improved sample config file.
- Added beta Minetest specific probing feature.
## [0.4.0] 2021-12-15
This release contains probe feature to generate metrics files.

View file

@ -65,8 +65,8 @@ Voici une liste de types simples :
| Type | Description | Modèle | Exemple |
| ------ | ------ | ------ | ------ |
| DATE | Une date au format ISO | ISO_DATE | 2020-07-06 |
| DATETIME | Une date horaire au format ISO | ISO_DATETIME | 2020-07-06T14:23:20 |
| DATE | Une date au format ISO | ISO_8601 | 2020-07-06 |
| DATETIME | Une date horaire au format ISO | ISO_8601 | 2020-07-06T14:23:20 |
| DAYS | Une liste de 366 valeurs numériques avec séparateurs | STU | 1;2;3;4;5;…;365 |
| EMAIL | Un courriel. | ^.+@.+$ | christian@momon.org |
| MONTHS | Une liste de 12 valeurs numériques avec séparateurs | STU | 1;2;3;4;5;6;7;9;10;11;12 |

View file

@ -9,7 +9,7 @@ Cette section regroupe des informations sur le fichier *properties*.
file.class = federation
# Version de l'ontologie utilisée utilisé (type STRING, recommandé).
file.protocol = ChatonsInfos-0.1
file.protocol = ChatonsInfos-0.5
# Date et horaire de génération du fichier (type DATETIME, recommandé).
file.datetime = 2020-07-06T14:23:20

457
README.md
View file

@ -10,6 +10,7 @@ StatoolInfos is released under the GNU AGPL+ license. Enjoy!
Authors:
* Christian Pierre MOMON <christian.momon@devinsy.fr>
Contributors : Angie, MrFlos, Quentin Duchemin, Fabrice61, Thomas TConstans, labecasse, Antoine Jaba, setop, Jérémy Collot, Pilou, Kepon, Laurent Sleto, Rodinux…
### Cat Avatar Generator images
@ -20,28 +21,16 @@ I am glad to use the beautiful artwork of David Revoy (http://www.peppercarrot.c
* Originally inspired of the code for "MonsterID" by Andreas Gohr http://www.splitbrain.org/go/monsterid.
### Cicle-icons
I am glad to use the generous artwork of ElegantThemes.com :
* https://www.elegantthemes.com/blog/freebie-of-the-week/beautiful-flat-icons-for-free
* "These icons are completely free and Open Source under the GPL".
### Logo
Author: Christian Pierre MOMON <christian.momon@devinsy.fr>
License: Creative Commons CC-BY-SA last version.
License: Creative Commons CC BY-SA last version.
### Other stuff
License of other stuff:
* csv-logo.svg, json-logo.svg, ods-icon.svg:
* Author: Christian P. Momon
* License: CC-BY-SA 3+.
* other: without any specific information, default license of images is CC-BY-SA 3+.
License of other stuff: without any specific information, default license of images is CC BY-SA 3+.
## DOCUMENTATION
@ -50,12 +39,48 @@ Read CONCEPT.md and ONTOLOGY.md files.
## Requirements
- Java 11
- Eclipse 4.16 (202006).
- Java 17
- Eclipse 4.29 (2023-09).
## INSTALL
Unzip the package and move the `statoolinfos.jar` and `statoolinfo.sh` files in `/srv/statoolinfos/bin/`.
Install Java on Debian:
```
apt-get install openjdk-17-jre-headless
```
Download the last release: `https://forge.devinsy.fr/statool/statoolinfos/releases` and unzip the package.
The `srv/` directory is a example of deployment tree:
```
srv/
srv/statoolinfos
srv/statoolinfos/bin
srv/statoolinfos/bin/refresh
srv/statoolinfos/bin/probe
srv/statoolinfos/bin/uptime
srv/statoolinfos/bin/statoolinfos.sh
srv/statoolinfos/bin/crawl
srv/statoolinfos/conf
srv/statoolinfos/conf/sample-probe-http.conf
srv/statoolinfos/conf/log4j2-default.properties
srv/statoolinfos/conf/sample-probe-minetest.conf
srv/statoolinfos/conf/sample-federation.conf
srv/statoolinfos/conf/sample-probe-qrcode.conf
srv/statoolinfos/cache
srv/statoolinfos/statoolinfos-cron.log
srv/statoolinfos/well-known
srv/statoolinfos/well-known/statoolinfos
srv/statoolinfos/well-known/statoolinfos/organization-template.properties
srv/statoolinfos/well-known/statoolinfos/services.properties
srv/statoolinfos/well-known/statoolinfos/BOM
srv/statoolinfos/well-known/statoolinfos/federation-template.properties
srv/statoolinfos/well-known/statoolinfos/service-template.properties
```
Then, move the `statoolinfos.jar` file in `/srv/statoolinfos/bin/`.
Create link:
@ -63,6 +88,15 @@ Create link:
cd /srv/statoolinfos/bin/ ; ln -s statoolinfos.sh statoolinfos
```
Edit script in `/srv/statoolinfos/bin/` to target your federation configuration file.
In case of bad language output, add these lines on top of cron file:
```
LANGUAGE=en_EN.UTF8
LC_ALL=en_EN.UTF-8
```
## Usage
@ -74,32 +108,192 @@ Usage:
statoolinfos build <configurationfile> build property files from conf and input
statoolinfos clear <configurationfile> remove property files from conf
statoolinfos crawl <configurationfile> crawl all file from conf and input
statoolinfos htmlize <configurationfile> generate web pages from conf
statoolinfos format <fileordirectory> format property files in tiny way
s̶t̶a̶t̶o̶o̶l̶i̶n̶f̶o̶s̶ ̶h̶t̶m̶l̶i̶z̶e̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶<̶c̶o̶n̶f̶i̶g̶u̶r̶a̶t̶i̶o̶n̶f̶i̶l̶e̶>̶ ̶ ̶ ̶ ̶ ̶g̶e̶n̶e̶r̶a̶t̶e̶ ̶w̶e̶b̶ ̶p̶a̶g̶e̶s̶ ̶f̶r̶o̶m̶ ̶c̶o̶n̶f̶ REMOVED since splitweb
statoolinfos probe OPTION [<directory>|<configurationfile>] generate metrics files from conf
OPTION = [-full|-today|-previousday|-NN] with NN a day count
statoolinfos tagdate <fileordirectory> update the file.datetime file
statoolinfos uptime <configurationfile> update uptime journal
statoolinfos format <fileordirectory> format property files in tiny way
statoolinfos list ip [-bot|-nobot] <fileordirectory> generate ip list from log file
statoolinfos list ua [-bot|-nobot] <fileordirectory> generate user agent list from log file
statoolinfos list visitors [-bot|-nobot] <fileordirectory> generate visitors (ip+ua) list from log file
statoolinfos stat ip [-bot|-nobot] <fileordirectory> generate stats about ip from log file
statoolinfos stat ua [-bot|-nobot] <fileordirectory> generate stats about user agent from log file
statoolinfos stat visitors [-bot|-nobot] <fileordirectory> generate stats about visitors (ip+ua) from log file
statoolinfos tagdate <fileordirectory> update the file.datetime file
statoolinfos list file <logfilesorconfigfile> display http access log files
statoolinfos list log [-bot|-nobot] <logfilesorconfigfile> display http access log lines
statoolinfos list ip [-bot|-nobot] <logfilesorconfigfile> generate ip list from http log file
statoolinfos list ua [-bot|-nobot] <logfilesorconfigfile> generate user agent list from http log file
statoolinfos list visitor [-bot|-nobot] <logfilesorconfigfile> generate visitors (ip+ua) list from http log file
statoolinfos stat ip [-bot|-nobot] <logfilesorconfigfile> generate stats about ip from http log file
statoolinfos stat ua [-bot|-nobot] <logfilesorconfigfile> generate stats about user agent from http log file
statoolinfos stat visitor [-bot|-nobot] <logfilesorconfigfile> generate stats about visitor (ip+ua) from http log file
statoolinfos list errfile <logfilesorconfigfile> display http error log files
statoolinfos list errlog <logfilesorconfigfile> display http error log lines
```
## Simple federation configuration file
Example of `libre-service.eu.conf`:
```
# [Configuration] conf + organization + services + machines + metrics
conf.class=federation
conf.protocol=StatoolInfos-0.6.0
conf.crawl.input=https://www.libre-service.eu/.well-known/statoolinfos/libre-service.eu.properties
conf.crawl.cache=/srv/statoolinfos/cache/
```
The field `input` gives the federation properties URL file. Reminder, the StatoolInfos Protocol requires that the federation properties file is exposed on the Web.
The field `cache` gives local directory used as data cache.
## Crawl
The `statoolinfos crawl` command loads the federation configuration file, then downloads the federation properties file and download all files set in.
In case of use with StatoolInfosWeb, never forget to give read permissions to Tomcat server. So, create a dedicated script would help.
Example of script `/srv/statoolinfos/bin/crawl`:
```
#!/bin/bash
echo "========== CRAWL at $(date --iso-8601=seconds)"
cd $(dirname "$0")
./statoolinfos crawl ../conf/federation.conf
chmod -R g+r /srv/statoolinfos/cache
chgrp -R tomcat /srv/statoolinfos/cache
```
Example of cron configuration `/etc/cron.d/statoolinfos`:
```
4 * * * * root /srv/statoolinfos/bin/crawl >> /srv/statoolinfos/statoolinfos-cron.log
```
Adjust your frequency according to your need. In case of large federation, once an hour is a good compromise.
## Uptime
The `statoolinfos uptime` command is very useful to collect the uptime of services. It's just to share which services are down and since how many time. It is not a monitoring feature because an one hour check is enough for this. Actually, only website are checked.
In case of use with StatoolInfosWeb, never forget to give read permissions to Tomcat server. So, create a dedicated script would help.
Example of script `/srv/statoolinfos/bin/uptime`:
```
#!/bin/bash
echo "========== UPTIME at $(date --iso-8601=seconds)"
cd $(dirname "$0")
./statoolinfos uptime ../conf/federation.conf
chmod -R g+r /srv/statoolinfos/cache
chgrp -R tomcat /srv/statoolinfos/cache
```
Example of cron configuration `/etc/cron.d/statoolinfos`:
```
4 * * * * root /srv/statoolinfos/bin/uptime >> /srv/statoolinfos/statoolinfos-cron.log
```
One check per hour is a good idea. In the uptime page, the mouse over a yellow status icon show the list of the check results.
In case of crawl, uptime and probe cron on the same computer, you can have different cron frequencies. It is better to have only script for call all them:
```
#!/bin/bash
echo "========== REFRESH at $(date --iso-8601=seconds)"
cd $(dirname "$0")
./probe
./crawl
./uptime
#./htmlize
chmod -R g+r /srv/statoolinfos/cache
chgrp -R tomcat /srv/statoolinfos/cache
```
And so your cron can be like that:
```
4 0,12,23 * * * root /srv/statoolinfos/bin/refresh >> /srv/statoolinfos/statoolinfos-cron.log
4 1-11,13-22 * * * root /srv/statoolinfos/bin/uptime >> /srv/statoolinfos/statoolinfos-cron.log
```
### Generate metrics files
## Htmlize command **removed**
The `statoolinfos htmlize` command is removed since 2024-07.
As a reminder, the htmlize command generated absolutely all the pages needed for a static website.
As the number of pages generated became too large (> 10000 with 100 organizations), the decision was made to separate the html valuation into a separate project, StatoolInfosWeb.
A dynamic web site allows to generate page only when it is necessary.
## Probe (Generate metrics files)
### Basics
The `statoolinfos probe` command computes data sources to generate metric properties files. In case of already existings file, the data are loaded before the computation to be updated.
In case of use with StatoolInfosWeb, never forget to give read permissions to Tomcat server. So, create a dedicated script would help.
Example of script `/srv/statoolinfos/bin/probe`:
```
#!/bin/bash
echo "========== PROBE at $(date --iso-8601=seconds)"
cd $(dirname "$0")
./statoolinfos probe -previousday ../conf/
chmod -R g+r /srv/statoolinfos/cache
chgrp -R tomcat /srv/statoolinfos/cache
```
Note: set a specific configuration file is not necessary, because you can have multiple service to probe. Only probe configuration files will be manage.
Example of cron configuration `/etc/cron.d/statoolinfos`:
```
4 * * * * root /srv/statoolinfos/bin/probe >> /srv/statoolinfos/statoolinfos-cron.log
```
### HTTP Server configuration
The probe feature generates properties files to expose on web. StatoolInfos protocol recommends to follow the well-known convention.
Example of `/etc/apache2/statoolinfos.conf` generic configuration file:
```
Alias "/.well-known/statoolinfos/" "/srv/statoolinfos/well-known/statoolinfos/"
<Directory "/srv/statoolinfos/well-known/statoolinfos">
Options +Indexes
Require all granted
</Directory>
```
Example of include directive in `/etc/apache2/sites-enabled/myservice.conf`:
```
<VirtualHost *:443>
[…]
Include statoolinfos.conf
[…]
</VirtualHost>
```
### Sample configuration file
Create a configuration file `/srv/statoolInfos/conf/foo.bar.org.conf`:
```
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
conf.probe.types=<metrictype1>, <metrictype2>
conf.probe.metrictype1param1.file=<value>
conf.probe.metrictype1param2.file=<value>
conf.probe.metrictype2param1.file=<value>
conf.probe.metrictype2param2.file=<value>
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
```
Generate the metric file for the first time:
@ -108,8 +302,203 @@ Generate the metric file for the first time:
/srv/statoolinfos/bin/statoolinfos probe -full /srv/statoolinfos/conf/foo.bar.org.conf
```
Create a cron file to update the metric file everyday:
Create a cron file in `/etc/cron.d/statoolinfos` to update the metric file everyday:
```
4 0,12 * * * root /srv/statoolinfos/bin/statoolinfos probe -previousday /srv/statoolinfos/conf/foo.bar.org.conf >> /srv/statoolinfos/cron.log
```
In case of several configuration files, just set the configuration directory (without wildcard):
```
1 0,12 * * * root /srv/statoolinfos/bin/statoolinfos probe -previousday /srv/statoolinfos/conf/ >> /srv/statoolinfos/cron.log
```
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**.
### Etherpad metrics
Configuration template:
```
1 * * * * root /srv/statoolinfos/bin/probe -previousday /srv/statoolinfos/conf/foo.bar.org.conf
conf.probe.types=Etherpad
conf.probe.httpaccesslog.file=/var/log/apache2/foo.bar.org-access.log*
conf.probe.httpaccesslog.pattern=
conf.probe.httpaccesslog.pathfilter=
# This parameter requires real ip proxy setting and log output setting.
conf.probe.etherpad.logs=/var/log/etherpad/output.log
# Database URL. Example of the most frequent cases:
# jdbc:mariadb://localhost:1234/databasename
# jdbc:mysql://localhost:1234/databasename
# jdbc:postgresql://localhost:1234/databasename
# jdbc:sqlite:/foo/bar/databasename.sqlite
conf.probe.etherpad.database.url=
conf.probe.etherpad.database.user=
conf.probe.etherpad.database.password=
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
```
### Framdadate metrics (coming soon)
Configuration template:
```
conf.probe.types=Framadate
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
```
### Gitea metrics
Configuration template:
```
conf.probe.types=Gitea
conf.probe.httpaccesslog.file=/var/log/apache2/foo.bar.org-access.log*
conf.probe.httpaccesslog.pattern=
conf.probe.httpaccesslog.pathfilter=
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
```
### LibreQR metrics
Configuration template:
```
conf.probe.types=LibreQR
conf.probe.httpaccesslog.file=/var/log/apache2/foo.bar.org-access.log*
conf.probe.httpaccesslog.pattern=
conf.probe.httpaccesslog.pathfilter=
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
```
### Nextcloud metrics (coming soon)
Configuration template:
```
conf.probe.types=Nextcloud
conf.probe.httpaccesslog.file=/var/log/apache2/foo.bar.org-access.log*
conf.probe.httpaccesslog.pattern=
conf.probe.httpaccesslog.pathfilter=
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
```
### PrivateBin metrics (partial)
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.httpaccesslog.pathfilter=
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*,/var/log/apache2/foo.bar.org-extraaccess.log*
conf.probe.httperrorlog.file=/var/log/apache2/foo.bar.org-error.log*,/var/log/apache2/foo.bar.org-extraerror.log*
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
# Custom access log pattern with Java regex.
# Default: ^(?<remoteAddress>[a-fA-F0-9\:\.]+) - (?<remoteUser>[^\[]+) \[(?<time>[^\]]+)\] "(?<request>([^\"]|\")*)" (?<status>\d+) (?<bodyBytesSent>\d+) "(?<referer>([^\"]|\")*)" "(?<userAgent>([^\"]|\")*)".*$
conf.probe.httpaccesslog.pattern=
# Custom datetime access log pattern (https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#patterns). The language ID is mandatory.
# Default: dd/MMM/yyyy:HH:mm:ss Z|EN
conf.prob.httpaccesslog.datetimepattern=
# Filter request with Java regex (without the initial '^' and without the final '$', see https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html).
# Example: pathfilter=/.*well-known.*
conf.probe.httpaccesslog.pathfilter=
# Custom error log pattern with Java regex. By default, automatic detection.
# Default Apache: ^\[(?<time>[^\]]+)\]\s\[(?<level>[^\]]*)\]\s(?<message>.*)$
# Default NGinx: ^(?<time>\S+\s\S+)\s\[(?<level>[^\]]*)\]\s(?<message>.*)$
conf.probe.httperrorlog.pattern=
# Custom datetime access log pattern (https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#patterns). The language ID is mandatory.
# Default: dd/MMM/yyyy:HH:mm:ss Z|EN
conf.prob.httperrorlog.datetimepattern=
```
Warning: to have month metric values, you have to set **retention log to 7 weeks or 50 days** in Nginx or Apache logrotate configuration.
For Nginx, éditer le fichier `/etc/logrotate.d/nginx` :
```
/var/log/nginx/*.log {
weekly
missingok
rotate 7
```
For Apache, éditer le fichier `/etc/logrotate.d/apache2` :
```
/var/log/apache2/*.log {
weekly
missingok
rotate 7
```
### Cron all task
A situation you will encounter is the need to do several tasks from the same machine. In this case, avoid multiple cron in the same time. Put all in Bash script and call it with only one cron.
Example:
```
4 0,12,23 * * * root /srv/statoolinfos/bin/refresh >> /srv/statoolinfos/statoolinfos-cron.log
4 1-11,13-22 * * * root /srv/statoolinfos/bin/statoolinfos uptime /srv/statoolinfos/conf/libre-service.eu.conf >> /srv/statoolinfos/statoolinfos-cron.log
```

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project default="main" name="Build-appjar">
<!--ANT 1.7 is required -->
<property name="buildjar.version" value="1.8" />
<!--ANT 1.11 is required -->
<property name="buildjar.version" value="1.11" />
<property file="build.properties" />
<property name="build.dir" value="${basedir}/build" />
<property name="build.src" value="${basedir}/src" />
@ -11,8 +11,7 @@
<property name="test.classes" value="${build.dir}/test-classes" />
<property name="debug" value="on" />
<path id="project.libs">
<fileset dir="${basedir}/lib" includes="**/*.jar" excludes="*sources* *src*" />
<!--fileset dir="${basedir}/lib/Logs" includes="**.jar" excludes="*sources* *src*" /-->
<fileset dir="${basedir}/lib" includes="**/*.jar" excludes="*sources* **/*sources* *src* **/*src*" />
</path>
<property name="classpath.absolute" value="${toString:project.libs}" />
@ -58,6 +57,8 @@
<!-- ***** JavaDoc ***** -->
<target name="javadoc" description="Javadoc construction">
<javadoc sourcepath="${build.src}" destdir="${build.javadoc}">
<arg value="-Xmaxwarns"/>
<arg value="500"/>
<classpath>
<fileset dir="lib" includes="**/*.jar" />
</classpath>
@ -95,26 +96,18 @@
<entry key="product.revision.author" value="${user.name}"/>
</propertyfile>
<!-- Build the jar file list. -->
<!-- Package jar -->
<property name="dist.jar" value="${dist.dir}/${product.name}.jar" />
<jar destfile="${dist.jar}">
<restrict>
<name regex=".*/*\.(class|gif|ico|jpg|ngp|png|pom|properties|svg@|xml|xsd)"/>
<archives>
<zips>
<fileset dir="${basedir}/lib" includes="**/*.jar" excludes="*sources* *src*" />
</zips>
</archives>
</restrict>
<fileset dir="${build.classes}" />
<zipgroupfileset dir="${basedir}/lib" includes="*.jar **/*.jar" excludes="*sources* **/*sources* *src* **/*src*" />
<manifest>
<attribute name="Built-By" value="${user.name} using ant" />
<attribute name="Built-Date" value="${dist.time}" />
<attribute name="Main-Class" value = "fr.devinsy.statoolinfos.StatoolInfosLauncher"/>
</manifest>
<fileset dir="${build.classes}" />
<!--zipfileset dir="${basedir}/lib" includes="${toString:project.libs}" /-->
<attribute name="Multi-Release" value = "true"/>
</manifest>
</jar>
<!-- Package sources -->
@ -133,16 +126,22 @@
<!-- Copy stuff -->
<echo message="==========> Copy Stuff" />
<copy file="resources/scripts/${product.name}.sh" todir="${dist.dir}/" overwrite="true" />
<chmod file="${dist.dir}/${product.name}.sh" perm="ugo+rx" />
<copy file="LICENSE" todir="${dist.dir}/" overwrite="true" failonerror="false" />
<copy file="README" todir="${dist.dir}/" overwrite="true" failonerror="false" />
<!--copy file="README" todir="${dist.dir}/" overwrite="true" failonerror="false" /-->
<copy file="README.md" todir="${dist.dir}/" overwrite="true" failonerror="false" />
<!--copy file="scripts/log4j.properties" todir="${dist.dir}/" overwrite="true" /-->
<mkdir dir="${dist.dir}/srv" />
<copy todir="${dist.dir}/srv/" overwrite="true" failonerror="false">
<fileset dir="resources/srv" includes="**" />
</copy>
<echo message="==========>ZZZZ" />
<mkdir dir="${dist.dir}/conf" />
<copy todir="${dist.dir}/conf">
<fileset dir="${basedir}/resources/conf" includes="*" />
<fileset dir="${basedir}/resources/conf" includes="**" />
</copy>
<!--
<mkdir dir="${dist.dir}/man"/>

View file

@ -1,3 +1,3 @@
#Build Number for ANT. Do not edit!
#Wed Dec 15 17:27:27 CET 2021
build.number=1
#Mon Sep 23 04:40:53 CEST 2024
build.number=2

View file

@ -1,4 +1,4 @@
product.name=statoolinfos
product.revision.major=0
product.revision.minor=4
product.revision.minor=6
product.revision.snapshot=

121
build.sh
View file

@ -5,7 +5,7 @@
#
function help
{
echo "StatoolInfos build script."
echo "Build script."
echo "Usage: build.sh [ -h | -help | --help | -snapshot | -local | -full ]"
echo " -h, -help, --help display this help."
echo " -snapshot, --snapshot build a snapshot."
@ -15,9 +15,9 @@ function help
}
#
# Build snapshot.
# Check env.
#
function build_snapshot
function check_env
{
okCount=0
@ -40,96 +40,13 @@ function build_snapshot
fi
# Java version check.
JAVA_VERSION=17;
javaVersionCheck=`javac -version 2>&1`
if [[ "$javaVersionCheck" =~ ^.*\ 11. ]]; then
echo "Java 11 version requirement..... OK"
if [[ "$javaVersionCheck" =~ ^.*\ ${JAVA_VERSION}. ]]; then
echo "Java ${JAVA_VERSION} version requirement..... OK"
let "okCount+=1"
else
echo "Java 11 version requirement..... MISSING"
fi
if [ "$okCount" == 3 ]; then
echo "Requirement OK"
ant -f build-snapshot.xml
else
echo "Requirement MISSING, build abort"
fi
}
#
# Build local.
#
function build_local
{
okCount=0
# Ant check.
antCheck=`which ant`
if [[ "$antCheck" =~ ^/.* ]]; then
echo "Ant requirement................ OK"
let "okCount+=1"
else
echo "Ant requirement................ MISSING"
fi
# Javac check.
javacCheck=`which javac`
if [[ "$javacCheck" =~ ^/.* ]]; then
echo "Javac requirement.............. OK"
let "okCount+=1"
else
echo "Javac requirement.............. MISSING"
fi
# Java version check.
javaVersionCheck=`javac -version 2>&1`
if [[ "$javaVersionCheck" =~ ^.*\ 11. ]]; then
echo "Java 11 version requirement..... OK"
let "okCount+=1"
else
echo "Java 11 version requirement..... MISSING"
fi
if [ "$okCount" == 3 ]; then
echo "Requirement OK"
ant -f build-local.xml
else
echo "Requirement MISSING, build abort"
fi
}
#
# Build tagandpush.
#
function build_tagandpush
{
okCount=0
# Ant check.
antCheck=`which ant`
if [[ "$antCheck" =~ ^/.* ]]; then
echo "Ant requirement................ OK"
let "okCount+=1"
else
echo "Ant requirement................ MISSING"
fi
# Javac check.
javacCheck=`which javac`
if [[ "$javacCheck" =~ ^/.* ]]; then
echo "Javac requirement.............. OK"
let "okCount+=1"
else
echo "Javac requirement.............. MISSING"
fi
# Java version check.
javaVersionCheck=`javac -version 2>&1`
if [[ "$javaVersionCheck" =~ ^.*\ 11. ]]; then
echo "Java 11 version requirement..... OK"
let "okCount+=1"
else
echo "Java 11 version requirement..... MISSING"
echo "Java ${JAVA_VERSION} version requirement..... MISSING"
fi
# Git check.
@ -143,26 +60,28 @@ function build_tagandpush
if [ "$okCount" == 4 ]; then
echo "Requirement OK"
ant -f build-tagandpush.xml
else
echo "Requirement MISSING, build abort"
exit -1
fi
}
#
# Main.
#
if [ "$#" -eq 0 ] || [ "$1" == "-h" ] || [ "$1" == "-help" ] || [ "$1" == "--help" ]; then
help
elif [ "$1" == "-snapshot" ] || [ "$1" == "--snapshot" ] ; then
build_snapshot
elif [ "$1" == "-local" ] || [ "$1" == "--local" ] ; then
build_local
elif [ "$1" == "-tagandpush" ] || [ "$1" == "--tagandpush" ] ; then
build_tagandpush
else
echo "Invalid parameters."
help
check_env
if [ "$1" == "-snapshot" ] || [ "$1" == "--snapshot" ] ; then
ant -f build-snapshot.xml
elif [ "$1" == "-local" ] || [ "$1" == "--local" ] ; then
ant -f build-local.xml
elif [ "$1" == "-tagandpush" ] || [ "$1" == "--tagandpush" ] ; then
ant -f build-tagandpush.xml
else
echo "Invalid parameters."
help
fi
fi

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,9 +1,10 @@
Description of used libraries:
- Logs/
- log4j log API
- log4j-api log API
- log4j-core
- log4j-slf4j-impl adaptation layer between slf4j and log4j
- slf4j-api facade log API
- slf4j-log4j12 adaptation layer between slf4j and log4j
- UnitTesting/
- hamcrest-core required by junit

Binary file not shown.

BIN
lib/commons-io-2.11.0.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
lib/json-simple-1.1.1.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
lib/postgresql-42.3.3.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,13 +0,0 @@
# Log configuration
# #################
# priority setting: DEBUG < INFO < WARN < ERROR
log4j.rootLogger = INFO, console
log4j.logger.fr.devinsy.statoolinfos = INFO
log4j.logger.fr.devinsy.xidyn = WARN
#--
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.layout = org.apache.log4j.PatternLayout
#log4j.appender.console.layout.ConversionPattern = %d{ISO8601} - StatoolInfos [%-5p] %34.34c.%25M - %m%n
log4j.appender.console.layout.ConversionPattern = %m%n

26
log4j2.properties Normal file
View file

@ -0,0 +1,26 @@
# Log configuration
# #################
# priority setting: DEBUG < INFO < WARN < ERROR
dest = err
name = Log4j2PropertiesConfig
status = ERROR
# Appenders settings.
appenders = console
appender.console.type = Console
appender.console.name = LogToConsole
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %m%n
# Logger settings.
rootLogger.level = INFO
rootLogger.appenderRefs = a
rootLogger.appenderRef.a.ref = LogToConsole
logger.statoolinfos.name = fr.devinsy.statoolinfos
logger.statoolinfos.level = INFO
logger.xidyn.name = fr.devinsy.xidyn
logger.xidyn.level = WARN

1
resources/conf/README.md Normal file
View file

@ -0,0 +1 @@
See the `srv/statoolinfos/conf` directory.

View file

@ -1,21 +0,0 @@
# Log configuration
# #################
# priority setting: DEBUG < INFO < WARN < ERROR
log4j.rootLogger = INFO, stdout, LogWriter
log4j.logger.fr.devinsy.statoolinfos = INFO
log4j.logger.fr.devinsy.xidyn = INFO
#--
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %m%n
#--
log4j.appender.LogWriter = org.apache.log4j.RollingFileAppender
log4j.appender.LogWriter.File = /srv/StatoolInfos/tatoolinfos.log
log4j.appender.LogWriter.MaxFileSize = 100000KB
log4j.appender.LogWriter.MaxBackupIndex = 5
log4j.appender.LogWriter.layout = org.apache.log4j.PatternLayout
log4j.appender.LogWriter.layout.ConversionPattern = %d{ISO8601} - InfosStatool [%-5p] %34.34c.%-25M - %m%n

View file

@ -1,10 +0,0 @@
#
# Sample StatoolInfos probe config file.
#
# Note: move this file outside the git directory.
conf.probe.types=HttpAccessLog, HttpErrorLog
conf.probe.httpaccesslog.file=/var/log/apache2/qrcode.libre-service.eu/qrcode.libre-service.eu-access.log*
conf.probe.httperrorlog.file=/var/log/apache2/qrcode.libre-service.eu/qrcode.libre-service.eu-error.log*
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/qrcode.libre-service.eu.metrics

View file

@ -1,14 +0,0 @@
#
# Sample StatoolInfos config file.
#
# Note: move this file outside the git directory.
conf.class=federation
conf.protocol=StatoolInfos-0.3.0
conf.crawl.input=https://www.libre-service.eu/.well-known/statoolinfos/libre-service.eu.properties
conf.crawl.cache=/srv/statoolinfos/cache/
conf.htmlize.categories=/srv/statoolinfos/inputs/categories/categories.properties
conf.htmlize.input=https://www.libre-service.eu/.well-known/statoolinfos/libre-service.eu.properties
conf.htmlize.directory=/srv/statoolinfos/www/

View file

@ -1,3 +0,0 @@
LANGUAGE=fr_FR.UTF8
LC_ALL=fr_FR.UTF-8
/5 * * * * root /srv/statoolinfos/bin/statoolinfo.sh >> /srv/statoolinfos/statoolinfos-cron.log

View file

@ -0,0 +1,5 @@
Alias "/.well-known/statoolinfos/" "/srv/statoolinfos/well-known/statoolinfos/"
<Directory "/srv/statoolinfos/well-known/statoolinfos">
Options +Indexes
Require all granted
</Directory>

View file

@ -0,0 +1,2 @@
4 0,12,23 * * * root /srv/statoolinfos/bin/refresh >> /srv/statoolinfos/statoolinfos-cron.log
4 1-11,13-22 * * * root /srv/statoolinfos/bin/uptime >> /srv/statoolinfos/statoolinfos-cron.log

View file

@ -1,10 +1,22 @@
#!/bin/bash
# Optional environment settings:
# export LOG4J_CONFIGURATION_FILE="toto.properties"
# export LOG4J_LEVEL=ERROR
# https://logging.apache.org/log4j/log4j-2.11.2/manual/configuration.html#System_Properties
# Java check.
javaCheck=`which java`
if [[ "$javaCheck" =~ ^/.* ]]; then
#echo "Java requirement............... OK"
java -Djava.awt.headless=true -jar "$(dirname "$0")"/statoolinfos.jar $@
#echo "Java requirement............... OK"
# Optional system properties:
# LOGFILE="-Dlog4j2.configurationFile=../../log4j2.properties"
# LOGLEVEL="-Dlog4j2.level=ERROR"
# IPV6ONLY="-Djava.net.preferIPv4Stack=false -Djava.net.preferIPv6Addresses=true"
# https://logging.apache.org/log4j/log4j-2.11.2/manual/configuration.html#System_Properties
java -Djava.awt.headless=true $IPV6ONLY $LOGFILE $LOGLEVEL -jar "$(dirname "$0")"/statoolinfos.jar $@
else
echo "Java requirement............... MISSING"
echo "Java requirement............... MISSING"
fi

View file

@ -0,0 +1,7 @@
#!/bin/bash
echo "========== CRAWL at $(date --iso-8601=seconds)"
cd $(dirname "$0")
./statoolinfos crawl ../conf/federation.conf
chmod -R g+r /srv/statoolinfos/cache
chgrp -R tomcat /srv/statoolinfos/cache

View file

@ -0,0 +1,7 @@
#!/bin/bash
echo "========== PROBE at $(date --iso-8601=seconds)"
cd $(dirname "$0")
./statoolinfos probe -previousday ../conf/
chmod -R g+r /srv/statoolinfos/cache
chgrp -R tomcat /srv/statoolinfos/cache

View file

@ -0,0 +1,10 @@
#!/bin/bash
echo "========== REFRESH at $(date --iso-8601=seconds)"
cd $(dirname "$0")
./probe
./crawl
./uptime
#./htmlize
chmod -R g+r /srv/statoolinfos/cache
chgrp -R tomcat /srv/statoolinfos/cache

View file

@ -0,0 +1,22 @@
#!/bin/bash
# Optional environment settings:
# export LOG4J_CONFIGURATION_FILE="toto.properties"
# export LOG4J_LEVEL=ERROR
# https://logging.apache.org/log4j/log4j-2.11.2/manual/configuration.html#System_Properties
# Java check.
javaCheck=`which java`
if [[ "$javaCheck" =~ ^/.* ]]; then
#echo "Java requirement............... OK"
# Optional system properties:
# LOGFILE="-Dlog4j2.configurationFile=../../log4j2.properties"
# LOGLEVEL="-Dlog4j2.level=ERROR"
# IPV6ONLY="-Djava.net.preferIPv4Stack=false -Djava.net.preferIPv6Addresses=true"
# https://logging.apache.org/log4j/log4j-2.11.2/manual/configuration.html#System_Properties
java -Djava.awt.headless=true $IPV6ONLY $LOGFILE $LOGLEVEL -jar "$(dirname "$0")"/statoolinfos.jar $@
else
echo "Java requirement............... MISSING"
fi

View file

@ -0,0 +1,7 @@
#!/bin/bash
echo "========== UPTIME at $(date --iso-8601=seconds)"
cd $(dirname "$0")
./statoolinfos uptime ../conf/federation.conf
chmod -R g+r /srv/statoolinfos/cache
chgrp -R tomcat /srv/statoolinfos/cache

View file

@ -0,0 +1,26 @@
# Log configuration
# #################
# priority setting: DEBUG < INFO < WARN < ERROR
dest = err
name = Log4j2PropertiesConfig
status = ERROR
# Appenders settings.
appenders = console
appender.console.type = Console
appender.console.name = LogToConsole
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %m%n
# Logger settings.
rootLogger.level = INFO
rootLogger.appenderRefs = a
rootLogger.appenderRef.a.ref = LogToConsole
logger.statoolinfos.name = fr.devinsy.statoolinfos
logger.statoolinfos.level = INFO
logger.xidyn.name = fr.devinsy.xidyn
logger.xidyn.level = WARN

View file

@ -0,0 +1,8 @@
# [Configuration]
conf.class=federation
conf.protocol=StatoolInfos-0.6.0
conf.crawl.input=https://www.libre-service.eu/.well-known/statoolinfos/libre-service.eu.properties
conf.crawl.cache=/srv/statoolinfos/cache/

View file

@ -0,0 +1,8 @@
# [Configuration]
conf.class=service
conf.protocol=StatoolInfos-0.6.0
conf.probe.types=HttpAccessLog, HttpErrorLog
conf.probe.httpaccesslog.file=/var/log/apache2/www.libre-service.eu/www.libre-service.eu-access.log*
conf.probe.httperrorlog.file=/var/log/apache2/www.libre-service.eu/www.libre-service.eu-error.log*
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/www.libre-service.eu-metrics.properties

View file

@ -0,0 +1,23 @@
#
# Sample StatoolInfos probe config file.
#
# Warning: move this file outside the git directory.
# List of the targets to probe.
conf.probe.types=Minetest
# Minetest log files to probe. Wildcards available.
conf.probe.minetest.logs=/var/log/minetest/minetest.log*
# Players database parameters.
conf.probe.minetest.players.db.host=
conf.probe.minetest.players.db.port=
conf.probe.minetest.players.db.name=
conf.probe.minetest.players.db.user=
conf.probe.minetest.players.db.password=
#
conf.probe.minetest.datafilepath=
# Target file to write computed metrics. If file exists then it is renamed with '.bak'.
conf.probe.target=/srv/statoolinfos/well-known/statoolinfo/www.myservice.org-metrics.properties

View file

@ -0,0 +1,24 @@
#
# Sample StatoolInfos config file to probe http.
#
# Warning: move this file outside the Git directory.
# List of the targets to probe.
conf.probe.types=HttpAccessLog, HttpErrorLog
# Access log file to probe. Wildcards available.
# Example: /tmp/*foo*.log??
conf.probe.httpaccesslog.file=/var/log/apache2/qrcode.libre-service.eu/qrcode.libre-service.eu-access.log*
# Optional. Custom access http log pattern in Java regex mode (https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html).
# Default value COMBINED: (?<remoteAddress>[a-zA-F0-9\\\\:\\\\.]+) - (?<remoteUser>[^\\[]+) \\[(?<time>[^\\]]+)\\] \"(?<request>[^\"]*)\" (?<status>\\d+) (?<bodyBytesSent>\\d+) \"(?<referer>[^\"]*)\" \"(?<userAgent>[^\"]*)\".*$");
conf.probe.httpaccesslog.pattern=
# Error log file to probe. Wildcards available.
# Example: /tmp/*foo*.log??
conf.probe.httperrorlog.file=/var/log/apache2/qrcode.libre-service.eu/qrcode.libre-service.eu-error.log*
# Target file to write computed metrics. If file exists then it is renamed with '.bak'.
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/qrcode.libre-service.eu-metrics.properties

View file

@ -0,0 +1 @@


View file

@ -0,0 +1,87 @@
# federation.properties
# [File]
# Classe du fichier (valeur parmi {Federation, Organization, Service, Device}, obligatoire).
file.class = federation
# Version de l'ontologie utilisée utilisé (type STRING, recommandé).
file.protocol = ChatonsInfos-0.5
# Date et horaire de génération du fichier (type DATETIME, recommandé, ex. 2020-07-06T14:23:20).
file.datetime =
# Nom du générateur du fichier (type STRING, recommandé).
file.generator =
# [Federation]
# Nom de la fédération (type STRING, obligatoire).
federation.name=
# Description de la fédération (type STRING, recommandé).
federation.description =
# Lien du site web de la fédération (type URL, recommandé).
federation.website =
# Lien du logo de la fédération (type URL, recommandé).
federation.logo =
# Lien de la page web de contact de la fédération (type URL, recommandé).
federation.contact.url =
# Courriel de contact de la fédération (type EMAIL, recommandé).
federation.contact.email =
# Lien du compte Twitter de la fédération (type URL, optionnel).
federation.socialnetworks.twitter =
# Lien de la page Facebook de la fédération (type URL, optionnel).
federation.socialnetworks.facebook =
# Lien du compte Mastodon de la fédération (type URL, optionnel).
federation.socialnetworks.mastodon =
# Lien du compte Diaspora de la fédération (type URL, optionnel).
federation.socialnetworks.diaspora =
# Lien du compte PeerTube de la fédération(type URL, optionnel).
federation.socialnetworks.peertube =
# Lien du compte Funkwhale de la fédération (type URL, optionnel).
federation.socialnetworks.funkwhale =
# Lien du compte Pixelfeld de la fédération (type URL, optionnel).
federation.socialnetworks.pixelfeld =
# Lien du compte Mobilizon de la fédération (type URL, optionnel).
federation.socialnetworks.mobilizon =
# Lien de la page web des mentions légales de la fédération (type URL, recommandé).
federation.legal.url =
# Lien de la documentation web de la fédération (type URL, recommandé).
federation.documentation.url =
# Lien de la documentation technique de la fédération (type URL, recommandé).
federation.guide.technical =
# Lien des tutoriels web de la fédération (type URL, recommandé).
federation.guide.technical =
# Date de naissance de la fédération (type DATE (AAAA-MM-JJ ou JJ/MM/AAAA), recommandé).
federation.startdate =
# [Subs]
# Un lien vers un fichier properties complémentaire (type URL, optionnel)
# Une clé (nomination libre) pour chacune de vos organisations,
# par exemple : subs.monchaton = https://www.monchaton.ext/.well-known/monchaton.properties
subs.01 =
# [Metrics]

View file

@ -0,0 +1,136 @@
# membres.properties
# [File]
# Classe du fichier (valeur parmi {Federation, Organization, Service, Device}, obligatoire).
file.class = organization
# Version de l'ontologie utilisée utilisé (type STRING, recommandé, ex. ChatonsInfos-0.1).
file.protocol = ChatonsInfos-0.5
# Date et horaire de génération du fichier (type DATETIME, recommandé, ex. 2020-07-06T14:23:20).
file.datetime =
# Nom du générateur du fichier (type STRING, recommandé, ex. Christian avec ses doigts).
file.generator =
# [Organisation]
# Nom de l'organisation (type STRING, obligatoire, ex. LibreServiceEU).
organization.name =
# Description de l'organisation (type STRING, recommandé, ex. LibreServiceEU est le chaton de Devinsy).
organization.description =
# Type d'organisation (un parmi {ASSOCIATION, INFORMAL, COOPERATIVE, MICROCOMPANY, COMPANY, INDIVIDUAL, OTHER}, obligatoire).
organization.type =
# Lien du site web de l'organisation (type URL, recommandé, ex. https://www.libre-service.eu/).
organization.website =
# Lien du logo de l'organisation (type URL, recommandé, ex. https://www.libre-service.eu/.well-known/statoolinfos/libre-service.eu-logo-carre.svg).
organization.logo =
# Liens vers les comptes réseaux sociaux de l'organisation (type URL, optionnel).
# Liste non exhaustive à laquelle vous pouvez ajouter d'autres services.
organization.socialnetworks.diaspora =
organization.socialnetworks.facebook =
organization.socialnetworks.funkwhale =
organization.socialnetworks.mastodon =
organization.socialnetworks.pleroma =
organization.socialnetworks.mobilizon =
organization.socialnetworks.peertube =
organization.socialnetworks.pixelfeld =
organization.socialnetworks.twitter =
# Adresse vers les salons/équipes de discussion publics de l'organisation (type STRING, optionnel).
# Liste non exhaustive à laquelle vous pouvez ajouter d'autres services.
organization.chatrooms.xmpp =
organization.chatrooms.irc =
organization.chatrooms.matrix =
organization.chatrooms.rocketchat =
organization.chatrooms.mattermost =
# Nom du propriétaire de l'organisation (type STRING, optionnel, ex. Devinsy).
organization.owner.name =
# Lien du site web du propriétaire de l'organisation (type URL, optionnel, ex. https://www.devinsy.fr/).
organization.owner.website =
# Lien du logo du propriétaire de l'organisation (type URL, optionnel, ex. https://www.devinsy.fr/logo_devinsy.svg).
organization.owner.logo =
# Lien de la page web de contact de l'organisation (type URL, recommandé, ex. https://www.libre-service.eu/contact.html).
organization.contact.url =
# Courriel de contact de l'organisation (type EMAIL, recommandé, ex. contact@libre-service.eu).
organization.contact.email =
# Lien de la page des mentions légales de l'organisation (type URL, recommandé, ex. https://www.libre-service.eu/mentions_legales.html).
organization.legal.url =
# Lien de la documentation technique de l'organisation (type URL, recommandé, ex. https://forge.devinsy.fr/libre-service.eu/documentation).
organization.guide.technical =
# Lien de la documentation utilisateur de l'organisation (type URL, recommandé, ex. https://www.libre-service.eu/services.xhtml).
organization.guide.user =
# Statut de l'organisation (un parmi {ACTIVE, IDLE, AWAY}, obligatoire).
organization.status.level =
# Description du statut de l'organisation (type STRING, optionnel, ex. en sommeil).
organization.status.description =
# Date de création de l'organisation (type DATE, recommandé, ex. 08/11/2018).
organization.startdate =
# Date de fermeture de l'organisation (type DATE, optionnel, ex. 22/02/2022).
organization.enddate =
# Date d'entrée dans le collectif (type DATE, obligatoire, ex. 08/11/2018).
organization.memberof.chatons.startdate =
# Date de sortie du collectif (type DATE, optionnel, ex. 08/11/2019).
organization.memberof.chatons.enddate =
# Statut en tant que membre de l'organisation (un parmi {ACTIVE, IDLE, AWAY}, obligatoire).
organization.memberof.chatons.status.level =
# Description du statut en tant que membre de l'organisation (type STRING, optionnel, ex. en sommeil).
organization.memberof.chatons.status.description =
# Pays de l'organisation (type STRING, recommandé, ex. France).
organization.country.name =
# Code pays de l'organisation (type COUNTRY_CODE sur 2 caractères, obligatoire, ex.ex. FR ou BE ou CH ou DE ou GB).
# Table ISO 3166-1 alpha-2 : https://fr.wikipedia.org/wiki/ISO_3166-1#Table_de_codage
organization.country.code =
# Géolocalisation de l'organisation
# Coordonnées GPS
# Latitude (type DECIMAL_DEGREE, recommandé, format DD, ex. 15,23456).
organization.geolocation.latitude =
# Longitude (type DECIMAL_DEGREE, recommandé, format DD, ex. -30,67890).
organization.geolocation.longitude =
# Adresse (type STRING, recommandé, ex. 1 rue croquette, 92370 Chaville).
organization.geolocation.address =
# Liens vers les services de paiement permettant de récolter des donations pour votre chaton (type URL, optionnel).
# Dans le cas d'une solution maison (exemple : pont vers votre banque), choisir "organization.funding.custom".
# Liste non exhaustive à laquelle vous pouvez ajouter d'autres services.
organization.funding.liberapay =
organization.funding.tipee =
organization.funding.helloasso =
organization.funding.paypal =
organization.funding.custom =
# [Subs]
# Un lien vers un fichier properties complémentaire (type URL, optionnel)
# Une clé (nomination libre) pour chacun de vos services,
# par exemple pour un service etherpad : subs.etherpad = https://www.monchaton.ext/.well-known/etherpad.properties
subs.foo1 =
# [Metrics]

View file

@ -0,0 +1,163 @@
# service.properties
#WARNING : cette fiche service ne concerne que les services logiciels
# [File]
# Classe du fichier (valeur parmi {Federation, Organization, Service, Device}, obligatoire).
file.class = service
# Version de l'ontologie utilisée utilisé (type STRING, recommandé).
file.protocol = ChatonsInfos-0.5
# Date et horaire de génération du fichier (type DATETIME, recommandé, ex. 2020-07-06T14:23:20).
file.datetime =
# Nom du générateur du fichier (type STRING, recommandé).
file.generator =
# [Service]
# Nom du service (type STRING, obligatoire).
service.name =
# Description du service (type STRING, recommandé).
service.description =
# Lien du site web du service (type URL, obligatoire - si pas possible, merci de créer une page de présentation du service).
service.website =
# Lien du logo du service (type URL, recommandé, ex. https://www.libre-service.eu/.well-known/statoolinfos/logo.svg).
service.logo =
# Lien de la page web des mentions légales du service (type URL, recommandé).
service.legal.url =
# Lien de la documentation web du service (type URL, recommandé).
service.guide.technical =
# Lien des aides web pour le service (type URL, recommandé).
service.guide.user =
# Lien de la page de support du service (type URL, recommandé).
service.contact.url =
# Courriel du support du service (type EMAIL, recommandé).
service.contact.email =
# Date d'ouverture du service (type DATE, obligatoire, ex. 22/02/2022).
service.startdate =
# Date de fermeture du service (type DATE, optionnel, ex. 22/02/2022).
service.enddate =
# Statut du service (un parmi {OK, WARNING, ALERT, ERROR, OVER, VOID}, obligatoire).
# OK : tout va bien (service en fonctionnement nominal).
# WARNING : attention (service potentiellement incomplet, maintenance prévue, etc.).
# ALERT : alerte (le service connait des dysfonctionnements, le service va bientôt fermer, etc.).
# ERROR : problème majeur (service en panne).
# OVER : terminé (le service n'existe plus).
# VOID : indéterminé (service non ouvert officiellement, configuration ChatonsInfos en cours, etc.).
service.status.level =
# Description du statut du service (type STRING, optionnel, ex. mise à jour en cours)
service.status.description =
# Inscriptions requises pour utiliser le service (un ou plusieurs parmi {None, Free, Member, Client}, obligatoire, ex. Free,Member).
# None : le service s'utilise sans inscription.
# Free : inscription ouverte à tout le monde et gratuite.
# Member : inscription restreinte aux membres (la notion de membre pouvant être très relative, par exemple, une famille, un cercle damis, adhérents d'association…).
# Client : inscription liée à une relation commerciale (facture…).
service.registration =
# Capacité à accueillir de nouveaux utilisateurs (un parmi {OPEN, FULL}, obligatoire).
# OPEN : le service accueille de nouveaux comptes.
# FULL : le service n'accueille plus de nouveau compte pour l'instant.
service.registration.load =
# Type d'installation du service, une valeur parmi {DISTRIBUTION, PROVIDER, PACKAGE, TOOLING, CLONEREPO, ARCHIVE, SOURCES, CONTAINER}, obligatoire.
# DISTRIBUTION : installation via le gestionnaire d'une distribution (apt, yum, etc.).
# PROVIDER : installation via le gestionnaire d'une distribution configuré avec une source externe (ex. /etc/apt/source.list.d/foo.list).
# PACKAGE : installation manuelle d'un paquet compatible distribution (ex. dpkg -i foo.deb).
# TOOLING : installation via un gestionnaire de paquets spécifique, différent de celui de la distribution (ex. pip…).
# CLONEREPO : clone manuel d'un dépôt (git clone…).
# ARCHIVE : application récupérée dans un tgz ou un zip ou un bzip2…
# SOURCES : compilation manuelle à partir des sources de l'application.
# CONTAINER : installation par containeur (Docker, Snap, Flatpak, etc.).
# L'installation d'un service via un paquet Snap avec apt sous Ubuntu doit être renseigné CONTAINER.
# L'installation d'une application ArchLinux doit être renseignée DISTRIBUTION.
# L'installation d'une application Yunohost doit être renseignée DISTRIBUTION.
service.install.type =
# [Software]
# Nom du logiciel (type STRING, obligatoire).
software.name =
# Lien du site web du logiciel (type URL, recommandé).
software.website =
# Lien web vers la licence du logiciel (type URL, obligatoire).
software.license.url =
# Nom de la licence du logiciel (type STRING, obligatoire).
software.license.name =
# Version du logiciel (type STRING, recommandé).
software.version =
# Lien web vers les sources du logiciel (type URL, recommandé).
software.source.url =
# Liste de modules optionnels installés (type VALUES, optionnel, ex. Nextcloud-Calendar,Nextcloud-Talk).
software.modules =
# [Host]
# Nom de l'hébergeur de la machine qui fait tourner le service, dans le cas d'un auto-hébergement c'est vous ! (type STRING, obligatoire).
host.name =
# Description de l'hébergeur (type STRING, optionnel).
host.description =
# Nom générique de la distribution installée sur le serveur (type STRING, obligatoire, ex. YunoHost).
host.server.distribution =
# Type de serveur (un parmi {NANO, PHYSICAL, VIRTUAL, SHARED, CLOUD}, obligatoire, ex. PHYSICAL).
# NANO : nano-ordinateur (Raspberry Pi, Olimex…)
# PHYSICAL : machine physique
# VIRTUAL : machine virtuelle
# SHARED : hébergement mutualisé
# CLOUD : infrastructure multi-serveurs
host.server.type =
# Type d'hébergement (un parmi {HOME, HOSTEDBAY, HOSTEDSERVER, OUTSOURCED}, obligatoire, ex. HOSTEDSERVER).
# HOME : hébergement à domicile
# HOSTEDBAY : serveur personnel hébergé dans une baie d'un fournisseur
# HOSTEDSERVER : serveur d'un fournisseur
# OUTSOURCED : infrastructure totalement sous-traitée
host.provider.type =
# Si vous avez du mal à remplir les champs précédents, ce tableau pourra vous aider :
# NANO PHYSICAL VIRTUAL SHARED CLOUD
# HOME pm pm vm shared cloud
# HOSTEDBAY pm pm vm shared cloud
# HOSTEDSERVER -- pm vm shared cloud
# OUTSOURCED -- -- vps shared cloud
# Légendes : pm : physical machine ; vm : virtual machine ; vps : virtual private server.
# Nom du logiciel hyperviseur (type STRING, optionnel, ex. KVM).
host.provider.hypervisor =
# Pays de l'hébergeur (type STRING, recommandé).
host.country.name =
# Code pays de l'hébergeur (type COUNTRY_CODE sur 2 caractères, obligatoire, ex. FR ou BE ou CH ou DE ou GB).
# Table ISO 3166-1 alpha-2 : https://fr.wikipedia.org/wiki/ISO_3166-1#Table_de_codage
host.country.code =
# [Subs]
# Un lien vers un fichier properties complémentaire (type URL, optionnel).
# Une clé (nomination libre) pour chacun de vos métriques spécifiques,
# par exemple pour un service etherpad : subs.metrics-etherpad = https://www.monchaton.ext/.well-known/metrics-etherpad.properties
subs.foo =

View file

@ -0,0 +1,43 @@
# File + organization + services + machines + metrics
# [File]
file.class=organization
file.generator=Cpm
file.datetime=2022-07-22T17:35:58
file.protocol=StatoolInfos-0.5
# [Organization]
organization.name=Services au public
organization.description=Les services publics de Libre-service.eu
organization.website=https://www.libre-service.eu/
organization.logo=https://www.libre-service.eu/.well-known/statoolinfos/libre-service.eu-logo-public.png
organization.status.level=ACTIVE
organization.status.description=En activité
organization.owner.name=Libre-service.eu
organization.owner.website=https://www.libre-service.eu/
organization.owner.logo=https://www.libre-service.eu/.well-known/statoolinfos/libre-service.eu-logo-carre.png
organization.contact.url=https://www.libre-service.eu/contact.xhtml
organization.contact.email=contact@libre-service.eu
organization.socialnetworks.mastodon=
organization.legal.url=https://www.libre-service.eu/mentions-legales.xhtml
organization.guide.user=https://www.libre-service.eu/
organization.guide.technical=https://forge.devinsy.fr/libre-service.eu/documentation
organization.startdate=01/10/2021
organization.enddate=
organization.memberof.libreserviceeu.status.level=ACTIVE
organization.memberof.libreserviceeu.status.description=
organization.memberof.libreserviceeu.startdate=01/10/2021
organization.memberof.libreserviceeu.enddate=
organization.country.name=France
organization.country.code=FR
organization.type=INFORMAL
# [Subs]
subs.audio=https://audio.libre-service.eu/.well-known/statoolinfos/audio.libre-service.eu.properties
subs.minetest=https://minetest.libre-service.eu/.well-known/statoolinfos/minetest.libre-service.eu.properties
subs.pad=https://pad.libre-service.eu/.well-known/statoolinfos/pad.libre-service.eu.properties
subs.paste=https://paste.libre-service.eu/.well-known/statoolinfos/paste.libre-service.eu.properties
subs.qrcode=https://qrcode.libre-service.eu/.well-known/statoolinfos/qrcode.libre-service.eu.properties
subs.visio=https://visio.libre-service.eu/.well-known/statoolinfos/visio.libre-service.eu.properties
# [Metrics]

5
snapshot Executable file
View file

@ -0,0 +1,5 @@
#!/bin/bash
cd $(dirname "$0")
./build.sh -snapshot

View file

@ -20,11 +20,15 @@ package fr.devinsy.statoolinfos;
import java.io.File;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.EnhancedPatternLayout;
import org.apache.log4j.Level;
import org.apache.log4j.PropertyConfigurator;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.appender.ConsoleAppender;
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
import org.apache.logging.log4j.core.config.builder.api.RootLoggerComponentBuilder;
import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -35,8 +39,6 @@ import fr.devinsy.statoolinfos.cli.StatoolInfosCLI;
*/
public final class StatoolInfosLauncher
{
private static Logger logger = LoggerFactory.getLogger(StatoolInfosLauncher.class);
/**
* Instantiates a new statool infos launcher.
*/
@ -52,18 +54,63 @@ public final class StatoolInfosLauncher
*/
public static void main(final String[] args)
{
String logFileEnv = System.getenv().get("LOG4J_CONFIGURATION_FILE");
String logFileProperty = System.getProperty("log4j2.configurationFile");
// Configure log.
File loggerConfig = new File("log4j.properties");
if (loggerConfig.exists())
if ((StringUtils.isBlank(logFileEnv) && (StringUtils.isBlank(logFileProperty))))
{
PropertyConfigurator.configure(loggerConfig.getAbsolutePath());
logger.info("Dedicated log configuration done.");
logger.info("Configuration file was found in [{}].", loggerConfig.getAbsoluteFile());
}
else
{
BasicConfigurator.configure(new ConsoleAppender(new EnhancedPatternLayout("%m%n")));
org.apache.log4j.Logger.getRootLogger().setLevel(Level.INFO);
File loggerConfig = new File("log4j2.properties");
if (loggerConfig.exists())
{
// Try to initialize logs with a log file.
Configurator.initialize(null, loggerConfig.getAbsolutePath());
Logger logger = LoggerFactory.getLogger(StatoolInfosLauncher.class);
logger.info("Dedicated log configuration done.");
logger.info("Configuration file was found in [{}].", loggerConfig.getAbsoluteFile());
}
else
{
//
Level logEnvLevel = Level.getLevel(StringUtils.defaultString(System.getenv().get("LOG4J_LEVEL"), " "));
Level logPropertyLevel = Level.getLevel(StringUtils.defaultString(System.getProperty("log4j2.level", " ")));
Level level;
if (logPropertyLevel != null)
{
level = logPropertyLevel;
}
else if (logEnvLevel != null)
{
level = logEnvLevel;
}
else
{
level = Level.INFO;
}
// Build a custom default log configuration.
ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
builder.setStatusLevel(Level.ERROR);
builder.setConfigurationName("CustomDefaultLogger");
AppenderComponentBuilder appenderBuilder = builder.newAppender("Console", "CONSOLE").addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
appenderBuilder.add(builder.newLayout("PatternLayout").addAttribute("pattern", "%m%n"));
RootLoggerComponentBuilder rootLogger = builder.newRootLogger(level);
rootLogger.add(builder.newAppenderRef("Console"));
builder.add(appenderBuilder);
builder.add(rootLogger);
Configurator.reconfigure(builder.build());
Logger logger = LoggerFactory.getLogger(StatoolInfosLauncher.class);
logger.debug("Custom default log configuration done.");
/*
Configurator.initialize(new DefaultConfiguration());
Configurator.setRootLevel(Level.INFO);
Logger logger = LoggerFactory.getLogger(StatoolInfosLauncher.class);
logger.debug("Default log configuration done.");
*/
}
}
// Run.

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2020-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -80,51 +80,106 @@ public class PropertyCheck
this.comment = comment;
}
/**
* Gets the comment.
*
* @return the comment
*/
public String getComment()
{
return this.comment;
}
/**
* Gets the file name.
*
* @return the file name
*/
public String getFileName()
{
return this.fileName;
}
/**
* Gets the index.
*
* @return the index
*/
public long getIndex()
{
return this.index;
}
/**
* Gets the line.
*
* @return the line
*/
public String getLine()
{
return this.line;
}
/**
* Gets the status.
*
* @return the status
*/
public Status getStatus()
{
return this.status;
}
/**
* Sets the comment.
*
* @param comment
* the new comment
*/
public void setComment(final String comment)
{
this.comment = comment;
}
/**
* Sets the file name.
*
* @param fileName
* the new file name
*/
public void setFileName(final String fileName)
{
this.fileName = fileName;
}
/**
* Sets the index.
*
* @param index
* the new index
*/
public void setIndex(final long index)
{
this.index = index;
}
/**
* Sets the line.
*
* @param line
* the new line
*/
public void setLine(final String line)
{
this.line = line;
}
/**
* Sets the status.
*
* @param status
* the new status
*/
public void setStatus(final Status status)
{
this.status = status;

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2020-2022 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -39,9 +39,9 @@ public class PropertyChecker
public static final String BOM = "\ufeff";
public static final String COMMENT = "^#.*$";
public static final String STRING = "^.+$";
public static final String DATETIME = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2}([\\.,]\\d+)?)?([+-]\\d\\d:\\d\\d)?";
public static final String DATETIME = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2}([\\.,]\\d+)?)?([+-]\\d\\d:\\d\\d|Z)?";
public static final String DATE = "^(\\d{4}-\\d{2}-\\d{2}|\\d{2}/\\d{2}/\\d{4}|\\d{2}/\\d{4})";
public static final String URL = "^(http(s)?://)?[\\w-_\\.]+(\\.\\w+)+(:\\d+)?(/.*)?$";
public static final String URL = "^https?://[\\w-_\\.]+(\\.\\w+)+(:\\d+)?(/.*)?$";
public static final String EMAIL = "^.*@.*$";
public static final String NUMERIC = "^\\d+$";
public static final String NUMERICS = "^\\d*(,\\d*)*$";
@ -137,6 +137,7 @@ public class PropertyChecker
this.organizationRules.add("organization.geolocation.latitude", DECIMAL_DEGREE, PropertyMode.OPTIONAL);
this.organizationRules.add("organization.geolocation.longitude", DECIMAL_DEGREE, PropertyMode.OPTIONAL);
this.organizationRules.add("organization.geolocation.address", STRING, PropertyMode.OPTIONAL);
this.organizationRules.add("organization.type", "^(ASSOCIATION|INFORMAL|COOPERATIVE|MICROCOMPANY|COMPANY|INDIVIDUAL|OTHER)$", PropertyMode.MANDATORY);
this.organizationRules.add(SUBS, URL, PropertyMode.OPTIONAL);
this.organizationRules.add(METRICS_NAME, STRING, PropertyMode.OPTIONAL);
@ -183,8 +184,10 @@ public class PropertyChecker
this.serviceRules.add("host.name", STRING, PropertyMode.MANDATORY);
this.serviceRules.add("host.description", STRING, PropertyMode.OPTIONAL);
this.serviceRules.add("host.server.distribution", STRING, PropertyMode.MANDATORY);
this.serviceRules.add("host.server.type", "^(NANO|PHYSICAL|VIRTUAL|SHARED|CLOUD)$", PropertyMode.MANDATORY);
this.serviceRules.add("host.provider.type", "^(HOME|HOSTEDBAY|HOSTEDSERVER|OUTSOURCED)$", PropertyMode.MANDATORY);
this.serviceRules.add("host.provider.hypervisor", STRING, PropertyMode.OPTIONAL);
this.serviceRules.add("host.country.name", STRING, PropertyMode.WISHED);
this.serviceRules.add("host.country.code", COUNTRY_CODE, PropertyMode.MANDATORY);
@ -290,12 +293,12 @@ public class PropertyChecker
check = new PropertyCheck(lineIndex, "", Status.OK);
check.setComment("OK");
}
else if ((StringUtils.isEmpty(line)) || (line.matches(COMMENT)))
else if ((StringUtils.isEmpty(line)) || (isComment(line)))
{
check = new PropertyCheck(lineIndex, line, Status.OK);
check.setComment("OK");
}
else if (!line.matches("^[^#].*[^\\s].*=.*$"))
else if (!isProperty(line))
{
check = new PropertyCheck(lineIndex, line, Status.ERROR);
check.setComment("Ligne malformée");
@ -455,4 +458,83 @@ public class PropertyChecker
//
return result;
}
/**
* Checks if is comment.
*
* @param line
* the line
* @return true, if is comment
*/
public static boolean isComment(final String line)
{
boolean result;
// Method 1
// public static final Pattern COMMENT_PATTERN =
// Pattern.compile(COMMENT);
// result = COMMENT_PATTERN.matcher(line).matches();
// Method 2
// result = StringUtils.startsWith(line, "#");
// Method 3
if ((line != null) && (line.length() > 0) && (line.charAt(0) == '#'))
{
result = true;
}
else
{
result = false;
}
//
return result;
}
/**
* Checks if is property.
*
* @param line
* the line
* @return true, if is property
*/
public static boolean isProperty(final String line)
{
boolean result;
// Method 1, take so much time, > 1000 ms for each property file.
// public static final Pattern PROPERTY_PATTERN =
// Pattern.compile("^[^#].*[^\\s].*=.*$");
// result = PROPERTY_PATTERN.matcher(line).matches();
// Method 2, well optimized, < 1 ms for each property file.
if ((line == null) || (line.length() == 0))
{
result = false;
}
else
{
int splitter = line.indexOf('=');
if (splitter == -1)
{
result = false;
}
else
{
String path = line.substring(0, splitter);
if ((path.length() == 0) || (path.charAt(0) == '#') || (StringUtils.isBlank(path)))
{
result = false;
}
else
{
result = true;
}
}
}
//
return result;
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2020-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -76,8 +76,11 @@ public class PropertyRule
}
/**
* Check path.
*
* @param value
* @return
* the value
* @return true, if successful
*/
public boolean checkPath(final String value)
{
@ -108,11 +111,21 @@ public class PropertyRule
return result;
}
/**
* Gets the label.
*
* @return the label
*/
public String getLabel()
{
return this.label;
}
/**
* Gets the mode.
*
* @return the mode
*/
public PropertyMode getMode()
{
return this.mode;
@ -214,6 +227,12 @@ public class PropertyRule
return result;
}
/**
* Sets the mode.
*
* @param mode
* the new mode
*/
public void setMode(final PropertyMode mode)
{
this.mode = mode;

View file

@ -0,0 +1,184 @@
# [Metrics HTPP].
#
metrics.http.hits.name = Requêtes web
metrics.http.hits.description = Nombre des requêtes web ipv4 et ipv6 reçues.
metrics.http.hits.cumulative = true
metrics.http.hits.ipv4.name = Requêtes web IPv4
metrics.http.hits.ipv4.description = Nombre de requêtes web IPv4 reçues.
metrics.http.hits.ipv4.cumulative = true
metrics.http.hits.ipv6.name = Requêtes web IPv6
metrics.http.hits.ipv6.description = Nombre de requêtes HTTP(S) IPv6 reçues.
metrics.http.hits.ipv6.cumulative = true
metrics.http.hits.bots.name = Requêtes web de robots
metrics.http.hits.bots.description = Nombre de requêtes web émises par des robots.
metrics.http.hits.bots.cumulative = true
metrics.http.hits.humans.name = Requêtes web humaines
metrics.http.hits.humans.description = Nombre de requêtes web émises par des êtres humains.
metrics.http.hits.humans.cumulative = true
metrics.http.hits.humans.ipv4.name = Requêtes web IPv4 humaines
metrics.http.hits.humans.ipv4.description = Nombre de requêtes web IPv4 émises par des êtres humains.
metrics.http.hits.humans.ipv4.cumulative = true
metrics.http.hits.humans.ipv6.name = Requêtes web IPv6 humaines
metrics.http.hits.humans.ipv6.description = Nombre de requêtes web IPv6 émises par des êtres humains.
metrics.http.hits.humans.ipv6.cumulative = true
#
metrics.http.files.name = Fichiers servis
metrics.http.files.description = Nombre de requêtes dont la réponse contenait du contenu (pas 404\u2026).
metrics.http.files.cumulative = true
#
metrics.http.pages.name = Pages servies
metrics.http.pages.description = Nombre de requêtes de page web, une page web étant souvent constituée de plusieurs requêtes.
metrics.http.pages.cumulative = true
#
metrics.http.bytes.name = Octets renvoyés
metrics.http.bytes.description = Nombre d'octets renvoyés.
metrics.http.bytes.cumulative = true
#
metrics.http.errors.name = Erreurs
metrics.http.errors.description = Nombre d'erreurs dans le fichier de logs erreurs.
metrics.http.errors.cumulative = true
metrics.http.errors.php.name = Erreurs PHP
metrics.http.errors.php.description = Nombre d'erreurs PHP dans le fichier de logs erreurs.
metrics.http.errors.php.cumulative = true
#
metrics.http.ip.name = IP visiteuses
metrics.http.ip.description = Nombre des adresses IP visiteuses.
metrics.http.ip.cumulative = false
metrics.http.ip.ipv4.name = IPv4 visiteuses
metrics.http.ip.ipv4.description = Nombre des adresses IPv4 visiteuses
metrics.http.ip.ipv4.cumulative = false
metrics.http.ip.ipv6.name = Ipv6 visiteuses
metrics.http.ip.ipv6.description = Nombre des adresses IPv6 visiteuses.
metrics.http.ip.ipv6.cumulative = false
metrics.http.ip.humans.name = IP humaines
metrics.http.ip.humans.description = Nombre des adresses IP d'êtres humains.
metrics.http.ip.humans.cumulative = false
metrics.http.ip.bots.name = IP de bots
metrics.http.ip.bots.description = Nombre des adresses IP de bots.
metrics.http.ip.bots.cumulative = false
#
metrics.http.visits.name = Visites
metrics.http.visits.description = Nombre des visites. Une visite est un groupe de requêtes en provenance d'un visiteur sur une même période (avec moins de 30 minutes entre chaque requêtes). Si une personne se connecte plusieurs fois dans un délai inférieur à 30 minutes, une seule visite est comptabilisée. Un visiteur peut se définir de différentes façons, le couple adresse IP et UserAgent, par cookie, etc.
metrics.http.visits.cumulative = true
metrics.http.visits.humans.name = Visites d'humains
metrics.http.visits.humans.description = Nombre des visites faites par des êtres humains.
metrics.http.visits.humans.cumulative = true
metrics.http.visits.bots.name = Visites de bots
metrics.http.visits.bots.description = Nombre des visites faites par des bots.
metrics.http.visits.bots.cumulative = true
#
metrics.http.visitors.name = Visiteurs
metrics.http.visitors.description = Nombre des visiteurs. Un visiteur peut se définir de différentes façons, le couple adresse IP et UserAgent, par cookie, etc.
metrics.http.visitors.cumulative = false
metrics.http.visitors.ipv4.name = Visiteurs IPv4
metrics.http.visitors.ipv4.description = Nombre de visiteurs utilisant une adresse IPv4.
metrics.http.visitors.ipv4.cumulative = false
metrics.http.visitors.ipv6.name = Visiteurs IPv6
metrics.http.visitors.ipv6.description = Nombre de visiteurs utilisant une adresse IPv6.
metrics.http.visitors.ipv6.cumulative = false
metrics.http.visitors.humans.name = Visiteurs humains
metrics.http.visitors.humans.description = Nombre de visiteurs humains.
metrics.http.visitors.humans.cumulative = false
metrics.http.visitors.bots.name = Visiteurs bots
metrics.http.visitors.bots.description = Nombre de visiteurs bots.
metrics.http.visitors.bots.cumulative = false
#
metrics.http.status.name =
metrics.http.status.description = Nombre de réponses pour le code XXX
metrics.http.status.cumulative=true
metrics.http.os.name =
metrics.http.os.description = Répartition des requêtes HTTP entre systèmes d'exploitation.
metrics.http.os.cumulative=true
#
metrics.http.browsers.name =
metrics.http.browsers.description = Répartition des requêtes HTTP entre navigateurs.
metrics.http.browsers.cumulative = true
#
metrics.http.devices.name =
metrics.http.devices.description = Répartition des requêtes HTTP entre types d'appareils.
metrics.http.devices.cumulative =
# Répartition du nombre des requêtes HTTP entre pays (le suffixe générique est le code ISO 3166-1 alpha-2).
# Remplacer les XX par le code pays à trouver sur https://fr.wikipedia.org/wiki/ISO_3166-1#Table_de_codage.
metrics.http.countries.name = Nombre de requêtes pour le pays XX
metrics.http.countries.description =
metrics.http.countries.cumulative =
# ===========================================================
# [Metrics génériques].
metrics.service.users.name = Utilisateurs
metrics.service.users.description = Nombre d'utilisateurs. Un utilisateur est visiteur utilisant vraiment le service.
metrics.service.users.cumulative = true
metrics.service.accounts.name = Comptes
metrics.service.accounts.description = Nombre de comptes.
metrics.service.accounts.cumulative = true
metrics.service.accounts.active.name = Comptes actifs
metrics.service.accounts.active.description = Nombre de comptes actifs.
metrics.service.accounts.active.cumulative = true
metrics.service.database.bytes.name = Données en base
metrics.service.database.bytes.description = Taille en octet des données en base.
metrics.service.database.bytes.cumulative = true
metrics.service.files.bytes.name = Espace de fichiers
metrics.service.files.bytes.description = Taille de l'espace disque en octet occupé par les fichiers.
metrics.service.files.bytes.cumulative = true
# [Metrics génériques de modération].
metrics.moderation.reports.name = Comptes signalés
metrics.moderation.reports.description = Nombre de comptes signalés.
metrics.moderation.reports.cumulative = true
metrics.moderation.sanctions.name = Comptes sanctionnés
metrics.moderation.sanctions.description = Nombre de comptes sanctionnés.
metrics.moderation.sanctions.cumulative = true
#
metrics.moderation.accounts.disabled.name = Comptes désactivés
metrics.moderation.accounts.disabled.description = Nombre de comptes désactivés.
metrics.moderation.accounts.disabled.cumulative = true
#
metrics.moderation.accounts.silenced.name = Comptes silenciés
metrics.moderation.accounts.silenced.description = Nombre de comptes silenciés.
metrics.moderation.accounts.silenced.cumulative = true
#
metrics.moderation.accounts.cancelled.name = Comptes supprimés
metrics.moderation.accounts.cancelled.description = Nombre de comptes supprimés.
metrics.moderation.accounts.cancelled.cumulative = true

View file

@ -0,0 +1,160 @@
/*
* Copyright (C) 2020-2024 Christian Pierre MOMON <christian@momon.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
package fr.devinsy.statoolinfos.cli;
import org.apache.commons.lang3.StringUtils;
/**
* The Class CLIUtils.
*/
public final class CLIUtils
{
/**
* Instantiates a new statool infos CLI.
*/
private CLIUtils()
{
}
/**
* Checks if is matching.
*
* @param args
* the args
* @param regexps
* the regexps
* @return true, if is matching
*/
public static boolean isMatching(final String[] args, final String... regexps)
{
boolean result;
if ((args.length == 0) && (regexps == null))
{
result = true;
}
else if ((args.length != 0) && (regexps == null))
{
result = false;
}
else if (args.length != regexps.length)
{
result = false;
}
else
{
boolean ended = false;
int index = 0;
result = false;
while (!ended)
{
if (index < args.length)
{
String arg = StringUtils.trim(args[index]);
String regexp = regexps[index];
if (arg.matches(regexp))
{
index += 1;
}
else
{
ended = true;
result = false;
}
}
else
{
ended = true;
result = true;
}
}
}
//
return result;
}
/**
* Checks if is matching ellipsis.
*
* @param args
* the args
* @param regexps
* the regexps
* @return true, if is matching ellipsis
*/
public static boolean isMatchingEllipsis(final String[] args, final String... regexps)
{
boolean result;
if ((args.length == 0) && (regexps == null))
{
result = true;
}
else if ((args.length != 0) && (regexps == null))
{
result = false;
}
else if (args.length < regexps.length)
{
result = false;
}
else
{
boolean ended = false;
int index = 0;
result = false;
while (!ended)
{
if (index < args.length)
{
String arg = StringUtils.trim(args[index]);
String regexp;
if (index < regexps.length)
{
regexp = regexps[index];
}
else
{
regexp = regexps[regexps.length - 1];
}
if (arg.matches(regexp))
{
index += 1;
}
else
{
ended = true;
result = false;
}
}
else
{
ended = true;
result = true;
}
}
}
//
return result;
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2020-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -26,8 +26,8 @@ import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.statoolinfos.app.StatoolInfosApp;
import fr.devinsy.statoolinfos.core.BotFilter;
import fr.devinsy.statoolinfos.core.StatoolInfos;
import fr.devinsy.statoolinfos.util.BuildInformation;
import fr.devinsy.statoolinfos.util.Chrono;
import fr.devinsy.statoolinfos.util.Files;
@ -109,19 +109,23 @@ public final class StatoolInfosCLI
message.appendln(" statoolinfos build <configurationfile> build property files from conf and input");
message.appendln(" statoolinfos clear <configurationfile> remove property files from conf");
message.appendln(" statoolinfos crawl <configurationfile> crawl all file from conf and input");
message.appendln(" statoolinfos htmlize <configurationfile> generate web pages from conf");
message.appendln(" statoolinfos format <fileordirectory> format property files in tiny way");
message.appendln(" s̶t̶a̶t̶o̶o̶l̶i̶n̶f̶o̶s̶ ̶h̶t̶m̶l̶i̶z̶e̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶ ̶<̶c̶o̶n̶f̶i̶g̶u̶r̶a̶t̶i̶o̶n̶f̶i̶l̶e̶> REMOVED since splitweb");
message.appendln(" statoolinfos probe OPTION [<directory>|<configurationfile>] generate metrics files from conf");
message.appendln(" OPTION = [-full|-today|-previousday|-NN] with NN a day count");
message.appendln(" statoolinfos tagdate <fileordirectory> update the file.datetime file");
message.appendln(" statoolinfos uptime <configurationfile> update uptime journal");
message.appendln();
message.appendln(" statoolinfos format <fileordirectory> format property files in tiny way");
message.appendln(" statoolinfos list ip [-bot|-nobot] <fileordirectory> generate ip list from log file");
message.appendln(" statoolinfos list ua [-bot|-nobot] <fileordirectory> generate user agent list from log file");
message.appendln(" statoolinfos list visitors [-bot|-nobot] <fileordirectory> generate visitors (ip+ua) list from log file");
message.appendln(" statoolinfos stat ip [-bot|-nobot] <fileordirectory> generate stats about ip from log file");
message.appendln(" statoolinfos stat ua [-bot|-nobot] <fileordirectory> generate stats about user agent from log file");
message.appendln(" statoolinfos stat visitors [-bot|-nobot] <fileordirectory> generate stats about visitors (ip+ua) from log file");
message.appendln(" statoolinfos tagdate <fileordirectory> update the file.datetime file");
message.appendln(" statoolinfos list file <logfilesorconfigfile> display http access log files");
message.appendln(" statoolinfos list log [-bot|-nobot] <logfilesorconfigfile> display http access log lines");
message.appendln(" statoolinfos list ip [-bot|-nobot] <logfilesorconfigfile> generate ip list from http log file");
message.appendln(" statoolinfos list ua [-bot|-nobot] <logfilesorconfigfile> generate user agent list from http log file");
message.appendln(" statoolinfos list visitor [-bot|-nobot] <logfilesorconfigfile> generate visitors (ip+ua) list from http log file");
message.appendln(" statoolinfos stat ip [-bot|-nobot] <logfilesorconfigfile> generate stats about ip from http log file");
message.appendln(" statoolinfos stat ua [-bot|-nobot] <logfilesorconfigfile> generate stats about user agent from http log file");
message.appendln(" statoolinfos stat visitor [-bot|-nobot] <logfilesorconfigfile> generate stats about visitor (ip+ua) from http log file");
message.appendln(" statoolinfos list errfile <logfilesorconfigfile> display http error log files");
message.appendln(" statoolinfos list errlog <logfilesorconfigfile> display http error log lines");
System.out.print(message.toString());
}
@ -139,58 +143,23 @@ public final class StatoolInfosCLI
}
/**
* Checks if is matching.
* Normalize bash parameter.
*
* @param args
* the args
* @param regexps
* the regexps
* @return true, if is matching
* @param value
* the value
* @return the string
*/
public static boolean isMatching(final String[] args, final String... regexps)
private static String normalizeBashParameter(final String value)
{
boolean result;
String result;
if ((args.length == 0) && (regexps == null))
if (value == null)
{
result = true;
}
else if ((args.length != 0) && (regexps == null))
{
result = false;
}
else if (args.length != regexps.length)
{
result = false;
result = null;
}
else
{
boolean ended = false;
int index = 0;
result = false;
while (!ended)
{
if (index < args.length)
{
String arg = args[index];
String regexp = regexps[index];
if (arg.matches(regexp))
{
index += 1;
}
else
{
ended = true;
result = false;
}
}
else
{
ended = true;
result = true;
}
}
result = StringUtils.trim(value).replace("\\*", "*").replace("\\?", "?");
}
//
@ -262,51 +231,51 @@ public final class StatoolInfosCLI
logger.debug("{} StatoolInfos call: {}", LocalDateTime.now(), new StringList(args).toStringSeparatedBy(" "));
if (isMatching(args))
if (CLIUtils.isMatching(args))
{
logger.info("No parameter.");
displayHelp();
}
else if (isMatching(args, "(-h|--h|--help)"))
else if (CLIUtils.isMatching(args, "(-h|--h|--help)"))
{
displayHelp();
}
else if (isMatching(args, "(-v|-version|--version)"))
else if (CLIUtils.isMatching(args, "(-v|-version|--version)"))
{
displayVersion();
}
else if (isMatching(args, "build", "\\s*.+\\.conf\\s*"))
else if (CLIUtils.isMatching(args, "build", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[1]));
try
{
StatoolInfos.build(configurationFile);
StatoolInfosApp.build(configurationFile);
}
catch (Exception exception)
{
logger.error("Error with [{}]: {}", configurationFile.getAbsoluteFile(), exception.getMessage());
}
}
else if (isMatching(args, "clear", "\\s*.+\\.conf\\s*"))
else if (CLIUtils.isMatching(args, "clear", ".+\\.conf*"))
{
File configurationFile = new File(StringUtils.trim(args[1]));
try
{
StatoolInfos.clear(configurationFile);
StatoolInfosApp.clear(configurationFile);
}
catch (Exception exception)
{
logger.error("Error with [{}]: {}", configurationFile.getAbsoluteFile(), exception.getMessage());
}
}
else if (isMatching(args, "crawl", "\\s*.+\\.conf\\s*"))
else if (CLIUtils.isMatching(args, "crawl", ".+\\.conf"))
{
Chrono chrono = new Chrono().start();
File configurationFile = new File(StringUtils.trim(args[1]));
try
{
StatoolInfos.crawl(configurationFile);
StatoolInfosApp.crawl(configurationFile);
}
catch (Exception exception)
{
@ -315,14 +284,14 @@ public final class StatoolInfosCLI
}
System.out.println(chrono.format());
}
else if (isMatching(args, "format", "\\s*.+\\s*"))
else if (CLIUtils.isMatching(args, "format", ".+"))
{
Files inputs = FilesUtils.searchEndingWith(new File(args[1]), ".properties");
for (File input : inputs)
{
try
{
StatoolInfos.format(input);
StatoolInfosApp.format(input);
}
catch (Exception exception)
{
@ -331,61 +300,191 @@ public final class StatoolInfosCLI
}
}
}
else if (isMatching(args, "htmlize", "\\s*.+\\.conf\\s*"))
else if (CLIUtils.isMatching(args, "list", "ip", "(-all|-bot|-nobot)", ".+\\.conf*"))
{
Chrono chrono = new Chrono().start();
File configurationFile = new File(StringUtils.trim(args[1]));
try
BotFilter filter = parseLogFilterOption(args[2]);
File configurationFile = new File(StringUtils.trim(args[3]));
StatoolInfosApp.listIps(configurationFile, filter);
}
else if (CLIUtils.isMatching(args, "list", "ip", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfosApp.listIps(configurationFile, BotFilter.ALL);
}
else if (CLIUtils.isMatchingEllipsis(args, "list", "ip", "(-all|-bot|-nobot)", ".+"))
{
BotFilter filter = parseLogFilterOption(args[2]);
Files source = new Files();
for (int index = 3; index < args.length; index++)
{
StatoolInfos.htmlize(configurationFile);
source.add(new File(args[index]));
}
catch (Exception exception)
StatoolInfosApp.listIps(source, filter);
}
else if (CLIUtils.isMatchingEllipsis(args, "list", "ip", ".+"))
{
Files files = new Files();
for (int source = 2; source < args.length; source++)
{
logger.error("Error with [{}]: {}", configurationFile.getAbsoluteFile(), exception.getMessage());
exception.printStackTrace();
files.add(new File(args[source]));
}
System.out.println(chrono.format());
}
else if (isMatching(args, "list", "ip", "\\s*\\S+\\s*"))
{
File source = new File(args[2]);
StatoolInfos.listIps(source, BotFilter.ALL);
StatoolInfosApp.listIps(files, BotFilter.ALL);
}
else if (isMatching(args, "list", "ip", "(-all|-bot|-nobot)", "\\s*\\S+\\s*"))
else if (CLIUtils.isMatching(args, "list", "(file|files)", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfosApp.listAccessFiles(configurationFile);
}
else if (CLIUtils.isMatchingEllipsis(args, "list", "(file|files)", ".+"))
{
Files source = new Files();
for (int index = 2; index < args.length; index++)
{
source.add(new File(args[index]));
}
StatoolInfosApp.listAccessFiles(source);
}
else if (CLIUtils.isMatching(args, "list", "(errfile|errfiles)", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfosApp.listErrorFiles(configurationFile);
}
else if (CLIUtils.isMatchingEllipsis(args, "list", "(errfile|errfiles)", ".+"))
{
Files source = new Files();
for (int index = 2; index < args.length; index++)
{
source.add(new File(args[index]));
}
StatoolInfosApp.listErrorFiles(source);
}
else if (CLIUtils.isMatching(args, "list", "(log|logs)", "(-all|-bot|-nobot)", ".+\\.conf*"))
{
BotFilter filter = parseLogFilterOption(args[2]);
File source = new File(args[3]);
File configurationFile = new File(StringUtils.trim(args[3]));
StatoolInfos.listIps(source, filter);
StatoolInfosApp.listLogs(configurationFile, filter);
}
else if (isMatching(args, "list", "(useragent|ua)", "\\s*\\S+\\s*"))
else if (CLIUtils.isMatching(args, "list", "(log|logs)", ".+\\.conf"))
{
File source = new File(args[2]);
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfos.listUserAgents(source, BotFilter.ALL);
StatoolInfosApp.listLogs(configurationFile, BotFilter.ALL);
}
else if (isMatching(args, "list", "(useragent|ua)", "(-all|-bot|-nobot)", "\\s*\\S+\\s*"))
else if (CLIUtils.isMatchingEllipsis(args, "list", "(log|logs)", "(-all|-bot|-nobot)", ".+"))
{
BotFilter filter = parseLogFilterOption(args[2]);
File source = new File(args[3]);
Files source = new Files();
for (int index = 3; index < args.length; index++)
{
source.add(new File(args[index]));
}
StatoolInfos.listUserAgents(source, filter);
StatoolInfosApp.listLogs(source, filter);
}
else if (isMatching(args, "list", "visitors", "\\s*\\S+\\s*"))
else if (CLIUtils.isMatchingEllipsis(args, "list", "(log|logs)", ".+"))
{
File source = new File(args[2]);
Files source = new Files();
for (int index = 2; index < args.length; index++)
{
source.add(new File(args[index]));
}
StatoolInfos.listVisitors(source, BotFilter.ALL);
StatoolInfosApp.listLogs(source, BotFilter.ALL);
}
else if (isMatching(args, "list", "visitors", "(-all|-bot|-nobot)", "\\s*\\S+\\s*"))
else if (CLIUtils.isMatching(args, "list", "(errlog|errlogs)", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfosApp.listErrorLogs(configurationFile);
}
else if (CLIUtils.isMatchingEllipsis(args, "list", "(errlog|errlogs)", ".+"))
{
Files source = new Files();
for (int index = 2; index < args.length; index++)
{
source.add(new File(args[index]));
}
StatoolInfosApp.listErrorLogs(source);
}
else if (CLIUtils.isMatching(args, "list", "(useragent|ua)", "(-all|-bot|-nobot)", ".+\\.conf*"))
{
BotFilter filter = parseLogFilterOption(args[2]);
File source = new File(args[3]);
File configurationFile = new File(StringUtils.trim(args[3]));
StatoolInfos.listVisitors(source, filter);
StatoolInfosApp.listUserAgents(configurationFile, filter);
}
else if (isMatching(args, "probe", "\\S*(-full|-today|-previousday|-\\d+)\\s*", "\\s*.+\\s*"))
else if (CLIUtils.isMatching(args, "list", "(useragent|ua)", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfosApp.listUserAgents(configurationFile, BotFilter.ALL);
}
else if (CLIUtils.isMatchingEllipsis(args, "list", "(useragent|ua)", "(-all|-bot|-nobot)", ".+"))
{
BotFilter filter = parseLogFilterOption(args[2]);
Files source = new Files();
for (int index = 3; index < args.length; index++)
{
source.add(new File(args[index]));
}
StatoolInfosApp.listUserAgents(source, filter);
}
else if (CLIUtils.isMatchingEllipsis(args, "list", "(useragent|ua)", ".+"))
{
Files source = new Files();
for (int index = 2; index < args.length; index++)
{
source.add(new File(args[index]));
}
StatoolInfosApp.listUserAgents(source, BotFilter.ALL);
}
else if (CLIUtils.isMatching(args, "list", "(visitor|visitors)", "(-all|-bot|-nobot)", ".+\\.conf*"))
{
BotFilter filter = parseLogFilterOption(args[2]);
File configurationFile = new File(StringUtils.trim(args[3]));
StatoolInfosApp.listVisitors(configurationFile, filter);
}
else if (CLIUtils.isMatching(args, "list", "(visitor|visitors)", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfosApp.listVisitors(configurationFile, BotFilter.ALL);
}
else if (CLIUtils.isMatchingEllipsis(args, "list", "(visitor|visitors)", "(-all|-bot|-nobot)", ".+"))
{
BotFilter filter = parseLogFilterOption(args[2]);
Files source = new Files();
for (int index = 3; index < args.length; index++)
{
source.add(new File(args[index]));
}
StatoolInfosApp.listVisitors(source, filter);
}
else if (CLIUtils.isMatchingEllipsis(args, "list", "(visitor|visitors)", ".+"))
{
Files source = new Files();
for (int index = 2; index < args.length; index++)
{
source.add(new File(args[index]));
}
StatoolInfosApp.listVisitors(source, BotFilter.ALL);
}
else if (CLIUtils.isMatching(args, "probe", "(-full|-today|-previousday|-\\d+)", ".+"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
@ -422,7 +521,7 @@ public final class StatoolInfosCLI
try
{
System.out.println("Probing [" + input + "] with day count filter " + dayCountFilter);
StatoolInfos.probe(input, dayCountFilter);
StatoolInfosApp.probe(input, dayCountFilter);
}
catch (Exception exception)
{
@ -438,52 +537,116 @@ public final class StatoolInfosCLI
exception.printStackTrace();
}
}
else if (isMatching(args, "stat", "ip", "\\s*\\S+\\s*"))
{
File source = new File(args[2]);
StatoolInfos.statIps(source, BotFilter.ALL);
}
else if (isMatching(args, "stat", "ip", "(-all|-bot|-nobot)", "\\s*\\S+\\s*"))
else if (CLIUtils.isMatching(args, "stat", "ip", "(-all|-bot|-nobot)", ".+\\.conf*"))
{
BotFilter filter = parseLogFilterOption(args[2]);
File source = new File(args[3]);
File configurationFile = new File(StringUtils.trim(args[3]));
StatoolInfos.statIps(source, filter);
StatoolInfosApp.statIps(configurationFile, filter);
}
else if (isMatching(args, "stat", "(useragent|ua)", "\\s*\\S+\\s*"))
else if (CLIUtils.isMatching(args, "stat", "ip", ".+\\.conf"))
{
File source = new File(args[2]);
StatoolInfos.statUserAgents(source, BotFilter.ALL);
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfosApp.statIps(configurationFile, BotFilter.ALL);
}
else if (isMatching(args, "stat", "(useragent|ua)", "(-all|-bot|-nobot)", "\\s*\\S+\\s*"))
else if (CLIUtils.isMatchingEllipsis(args, "stat", "ip", "(-all|-bot|-nobot)", ".+"))
{
BotFilter filter = parseLogFilterOption(args[2]);
File source = new File(args[3]);
Files source = new Files();
for (int index = 3; index < args.length; index++)
{
source.add(new File(args[index]));
}
StatoolInfos.statUserAgents(source, filter);
StatoolInfosApp.statIps(source, filter);
}
else if (isMatching(args, "stat", "visitors", "\\s*\\S+\\s*"))
else if (CLIUtils.isMatchingEllipsis(args, "stat", "ip", ".+"))
{
File source = new File(args[2]);
Files source = new Files();
for (int index = 2; index < args.length; index++)
{
source.add(new File(args[index]));
}
StatoolInfos.statVisitors(source, BotFilter.ALL);
StatoolInfosApp.statIps(source, BotFilter.ALL);
}
else if (isMatching(args, "stat", "visitors", "(-all|-bot|-nobot)", "\\s*\\S+\\s*"))
else if (CLIUtils.isMatching(args, "stat", "(useragent|ua)", "(-all|-bot|-nobot)", ".+\\.conf*"))
{
BotFilter filter = parseLogFilterOption(args[2]);
File source = new File(args[3]);
File configurationFile = new File(StringUtils.trim(args[3]));
StatoolInfos.statVisitors(source, filter);
StatoolInfosApp.statUserAgents(configurationFile, filter);
}
else if (isMatching(args, "tagdate", "\\s*.+\\s*"))
else if (CLIUtils.isMatching(args, "stat", "(useragent|ua)", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfosApp.statUserAgents(configurationFile, BotFilter.ALL);
}
else if (CLIUtils.isMatchingEllipsis(args, "stat", "(useragent|ua)", "(-all|-bot|-nobot)", ".+"))
{
BotFilter filter = parseLogFilterOption(args[2]);
Files source = new Files();
for (int index = 3; index < args.length; index++)
{
source.add(new File(args[index]));
}
StatoolInfosApp.statUserAgents(source, filter);
}
else if (CLIUtils.isMatchingEllipsis(args, "stat", "(useragent|ua)", ".+"))
{
Files source = new Files();
for (int index = 2; index < args.length; index++)
{
source.add(new File(args[index]));
}
StatoolInfosApp.statUserAgents(source, BotFilter.ALL);
}
else if (CLIUtils.isMatching(args, "stat", "(visitor|visitors)", "(-all|-bot|-nobot)", ".+\\.conf*"))
{
BotFilter filter = parseLogFilterOption(args[2]);
File configurationFile = new File(StringUtils.trim(args[3]));
StatoolInfosApp.statVisitors(configurationFile, filter);
}
else if (CLIUtils.isMatching(args, "stat", "(visitor|visitors)", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfosApp.statVisitors(configurationFile, BotFilter.ALL);
}
else if (CLIUtils.isMatchingEllipsis(args, "stat", "(visitor|visitors)", "(-all|-bot|-nobot)", ".+"))
{
BotFilter filter = parseLogFilterOption(args[2]);
Files source = new Files();
for (int index = 3; index < args.length; index++)
{
source.add(new File(args[index]));
}
StatoolInfosApp.statVisitors(source, filter);
}
else if (CLIUtils.isMatchingEllipsis(args, "stat", "(visitor|visitors)", ".+"))
{
Files source = new Files();
for (int index = 2; index < args.length; index++)
{
source.add(new File(args[index]));
}
StatoolInfosApp.statVisitors(source, BotFilter.ALL);
}
else if (CLIUtils.isMatching(args, "tagdate", ".+"))
{
Files inputs = FilesUtils.searchEndingWith(new File(args[1]), ".properties");
for (File input : inputs)
{
try
{
StatoolInfos.tagDate(input);
StatoolInfosApp.tagDate(input);
}
catch (Exception exception)
{
@ -492,14 +655,14 @@ public final class StatoolInfosCLI
}
}
}
else if (isMatching(args, "uptime", "\\s*.+\\.conf\\s*"))
else if (CLIUtils.isMatching(args, "uptime", ".+\\.conf"))
{
Chrono chrono = new Chrono().start();
File configurationFile = new File(StringUtils.trim(args[1]));
try
{
StatoolInfos.uptime(configurationFile);
StatoolInfosApp.uptime(configurationFile);
}
catch (Exception exception)
{

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2020-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -18,7 +18,7 @@
*/
package fr.devinsy.statoolinfos.core;
import fr.devinsy.statoolinfos.metrics.http.HttpAccessLog;
import fr.devinsy.statoolinfos.metrics.httpaccess.HttpAccessLog;
/**
* The Enum LogFilter.

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2020-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -22,6 +22,8 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import org.apache.commons.lang3.StringUtils;
import fr.devinsy.strings.StringList;
/**
@ -54,7 +56,7 @@ public class Categories extends ArrayList<Category>
for (Category category : this)
{
if (category.getSoftwares().containsAnyIgnoreCase(softwareName))
if (category.matchesSoftware(softwareName))
{
result.add(category);
}
@ -64,6 +66,43 @@ public class Categories extends ArrayList<Category>
return result;
}
/**
* Gets the by technical name.
*
* @param technicalName
* the technical name
* @return the by technical name
*/
public Category getByTechnicalName(final String technicalName)
{
Category result;
Iterator<Category> iterator = this.iterator();
boolean ended = false;
result = null;
while (!ended)
{
if (iterator.hasNext())
{
Category category = iterator.next();
if (StringUtils.equals(category.getTechnicalName(), technicalName))
{
ended = true;
result = category;
}
}
else
{
ended = true;
result = null;
}
}
//
return result;
}
/**
* Matches.
*
@ -84,7 +123,7 @@ public class Categories extends ArrayList<Category>
{
Category category = iterator.next();
if (category.getSoftwares().containsIgnoreCase(softwareName))
if (category.matchesSoftware(softwareName))
{
ended = true;
result = true;

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2020-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -18,6 +18,8 @@
*/
package fr.devinsy.statoolinfos.core;
import java.util.Iterator;
import org.apache.commons.lang3.StringUtils;
import fr.devinsy.strings.StringList;
@ -27,22 +29,25 @@ import fr.devinsy.strings.StringList;
*/
public class Category
{
public static final String DEFAULT_LOGO_PATH = "categories/default.svg";
public static final String DEFAULT_LOGO_PATH = "default.svg";
private String name;
private String technicalName;
private String description;
private StringList softwares;
private String logoPath;
/**
* Instantiates a new category.
*
* @param name
* the name
* @param description
* the description
*/
public Category(final String name, final String description)
{
this.name = name;
this.description = description;
this.softwares = new StringList();
this.logoPath = DEFAULT_LOGO_PATH;
this(name, description, null);
}
/**
@ -58,11 +63,17 @@ public class Category
public Category(final String name, final String description, final StringList softwares)
{
this.name = name;
this.technicalName = StatoolInfosUtils.toTechnicalName(getName());
this.description = description;
this.softwares = new StringList(softwares);
this.logoPath = DEFAULT_LOGO_PATH;
}
/**
* Gets the description.
*
* @return the description
*/
public String getDescription()
{
return this.description;
@ -90,11 +101,21 @@ public class Category
return result;
}
/**
* Gets the name.
*
* @return the name
*/
public String getName()
{
return this.name;
}
/**
* Gets the softwares.
*
* @return the softwares
*/
public StringList getSoftwares()
{
return this.softwares;
@ -109,7 +130,7 @@ public class Category
{
String result;
result = StatoolInfosUtils.toTechnicalName(getName());
result = this.technicalName;
//
return result;
@ -126,19 +147,58 @@ public class Category
{
boolean result;
if (this.softwares.containsIgnoreCase(service.getSoftwareName()))
result = matchesSoftware(service.getSoftwareName());
//
return result;
}
/**
* Matches.
*
* @param softwareName
* the software name
* @return true, if successful
*/
public boolean matchesSoftware(final String softwareName)
{
boolean result;
String target = StringUtils.stripAccents(softwareName).replaceAll("[\\W\\s]", "");
boolean ended = false;
Iterator<String> iterator = this.softwares.iterator();
result = false;
while (!ended)
{
result = true;
}
else
{
result = false;
if (iterator.hasNext())
{
String source = iterator.next();
source = StringUtils.stripAccents(source).replaceAll("[\\W\\s]", "");
if (StringUtils.equalsIgnoreCase(target, source))
{
ended = true;
result = true;
}
}
else
{
ended = true;
result = false;
}
}
//
return result;
}
/**
* Sets the description.
*
* @param description
* the new description
*/
public void setDescription(final String description)
{
this.description = description;
@ -158,10 +218,16 @@ public class Category
}
else
{
this.logoPath = "categories/" + logoPath;
this.logoPath = logoPath;
}
}
/**
* Sets the name.
*
* @param name
* the new name
*/
public void setName(final String name)
{
this.name = name;

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2020-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -25,6 +25,7 @@ import java.net.URL;
import org.apache.commons.lang3.StringUtils;
import fr.devinsy.statoolinfos.properties.PathProperties;
import fr.devinsy.statoolinfos.properties.PathProperty;
import fr.devinsy.statoolinfos.properties.PathPropertyList;
import fr.devinsy.strings.StringList;
@ -54,6 +55,23 @@ public class Configuration extends PathPropertyList
super(properties);
}
/**
* Adds the.
*
* @param path
* the path
* @param value
* the value
*/
public void add(final String path, final String value)
{
if (!StringUtils.isBlank(path))
{
PathProperty property = new PathProperty(path, value);
this.add(property);
}
}
/**
* Gets the builds the directory.
*
@ -143,15 +161,16 @@ public class Configuration extends PathPropertyList
*
* @return the category file
* @throws StatoolInfosException
* the statool infos exception
*/
public File getCategoryFile() throws StatoolInfosException
{
File result;
String path = get("conf.htmlize.categories");
String path = get("conf.categories");
if (StringUtils.isBlank(path))
{
throw new StatoolInfosException("Entry conf.htmlize.categories is missing in configuration file.");
result = null;
}
else
{
@ -253,6 +272,27 @@ public class Configuration extends PathPropertyList
return result;
}
/**
* Gets the database config.
*
* @param prefix
* the prefix
* @return the database config
*/
public DatabaseConfig getDatabaseConfig(final String prefix)
{
DatabaseConfig result;
result = new DatabaseConfig();
result.setUrl(get(prefix + ".database.url"));
result.setUser(get(prefix + ".database.user"));
result.setPassword(get(prefix + ".database.password"));
//
return result;
}
/**
* Gets the edito directory.
*
@ -278,54 +318,30 @@ public class Configuration extends PathPropertyList
}
/**
* Gets the htmlize directory.
* Gets the probe http access log date pattern.
*
* @return the htmlize directory
* @return the probe http access log date pattern
*/
public File getHtmlizeDirectory()
{
File result;
String path = getHtmlizeDirectoryPath();
if (StringUtils.isBlank(path))
{
result = null;
}
else
{
result = new File(path);
}
//
return result;
}
/**
* Gets the htmlize directory path.
*
* @return the htmlize directory path
*/
public String getHtmlizeDirectoryPath()
public String getProbeHttpAccessLogDateTimePattern()
{
String result;
result = get("conf.htmlize.directory");
result = get("conf.probe.httpaccesslog.datetimepattern");
//
return result;
}
/**
* Gets the htmlize input path.
* Gets the probe http access log path filter.
*
* @return the htmlize input path
* @throws MalformedURLException
* @return the probe http access log path filter
*/
public URL getHtmlizeInputURL() throws MalformedURLException
public String getProbeHttpAccessLogPathFilter()
{
URL result;
String result;
result = new URL(get("conf.htmlize.input"));
result = get("conf.probe.httpaccesslog.pathfilter");
//
return result;
@ -361,6 +377,65 @@ public class Configuration extends PathPropertyList
return result;
}
/**
* Gets the probe http access log sources.
*
* @return the probe http access log sources
*/
public StringList getProbeHttpAccessLogSources()
{
StringList result;
result = new StringList();
String source = getProbeHttpAccessLogSource();
if (StringUtils.isNotBlank(source))
{
String[] paths = source.split(",");
for (String path : paths)
{
if (StringUtils.isNotBlank(path))
{
result.add(StringUtils.trim(path));
}
}
}
//
return result;
}
/**
* Gets the probe http error log date time pattern.
*
* @return the probe http error log date time pattern
*/
public String getProbeHttpErrorLogDateTimePattern()
{
String result;
result = get("conf.probe.httperrorlog.datetimepattern");
//
return result;
}
/**
* Gets the probe http error log pattern.
*
* @return the probe http error log pattern
*/
public String getProbeHttpErrorLogPattern()
{
String result;
result = get("conf.probe.httperrorlog.pattern");
//
return result;
}
/**
* Gets the probe http error log source.
*
@ -453,6 +528,28 @@ public class Configuration extends PathPropertyList
return result;
}
/**
* Checks if is category file defined.
*
* @return true, if is category file defined
*/
public boolean isCategoryFileDefined()
{
boolean result;
if (StringUtils.isBlank(get("conf.categories")))
{
result = false;
}
else
{
result = true;
}
//
return result;
}
/**
* Checks if is federation.
*

View file

@ -0,0 +1,150 @@
/*
* Copyright (C) 2021-2023 Christian Pierre MOMON <christian@momon.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
package fr.devinsy.statoolinfos.core;
import org.apache.commons.lang3.StringUtils;
/**
* The Class DatabaseConfig.
*/
public class DatabaseConfig
{
private String url;
private String user;
private String password;
/**
* Instantiates a new database config.
*/
public DatabaseConfig()
{
this.url = null;
this.user = null;
this.password = null;
}
/**
* Gets the password.
*
* @return the password
*/
public String getPassword()
{
return this.password;
}
/**
* Gets the url.
*
* @return the url
*/
public String getUrl()
{
return this.url;
}
/**
* Gets the user.
*
* @return the user
*/
public String getUser()
{
return this.user;
}
/**
* Checks if is sets the.
*
* @return true, if is sets the
*/
public boolean isSet()
{
boolean result;
if (StringUtils.isAnyBlank(this.url, this.user))
{
result = false;
}
else
{
result = true;
}
//
return result;
}
/**
* 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;
}
/**
* Sets the user.
*
* @param user
* the new user
*/
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;
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2020-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -32,8 +32,9 @@ import fr.devinsy.statoolinfos.crawl.CrawlCache;
import fr.devinsy.statoolinfos.crawl.CrawlJournal;
import fr.devinsy.statoolinfos.properties.PathProperties;
import fr.devinsy.statoolinfos.properties.PathProperty;
import fr.devinsy.statoolinfos.properties.PathPropertyList;
import fr.devinsy.statoolinfos.properties.PathPropertyUtils;
import fr.devinsy.statoolinfos.util.Chrono;
import fr.devinsy.statoolinfos.properties.PropertyClassType;
import fr.devinsy.strings.StringList;
import fr.devinsy.strings.StringSet;
@ -64,33 +65,9 @@ public class Factory
{
Categories result;
result = new Categories();
PathProperties properties = PathPropertyUtils.load(source);
StringSet prefixes = properties.getSubPrefixes();
for (String prefix : prefixes)
{
String name = properties.get(prefix + ".name");
String description = properties.get(prefix + ".description");
String softwares = properties.get(prefix + ".softwares");
String logoPath = properties.get(prefix + ".logo");
StringList softwareList = new StringList();
if (StringUtils.isNotBlank(softwares))
{
for (String string : softwares.split("[;,]"))
{
softwareList.add(string.trim());
}
}
Category category = new Category(name, description, softwareList);
category.setLogoPath(logoPath);
result.add(category);
}
result.sortByName();
result = loadCategories(properties);
//
return result;
@ -128,6 +105,102 @@ public class Factory
return result;
}
/**
* Load categories.
*
* @param properties
* the properties
* @return the categories
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static Categories loadCategories(final PathProperties properties) throws IOException
{
Categories result;
result = new Categories();
StringSet prefixes = properties.getSubPrefixes();
for (String prefix : prefixes)
{
String name = properties.get(prefix + ".name");
String description = properties.get(prefix + ".description");
String softwares = properties.get(prefix + ".softwares");
String logoPath = properties.get(prefix + ".logo");
StringList softwareList = new StringList();
if (StringUtils.isNotBlank(softwares))
{
for (String string : softwares.split("[;,]"))
{
softwareList.add(string.trim());
}
}
Category category = new Category(name, description, softwareList);
category.setLogoPath(logoPath);
result.add(category);
}
result.sortByName();
//
return result;
}
/**
* Load categories.
*
* @param source
* the source
* @return the categories
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static Categories loadCategories(final URL source) throws IOException
{
Categories result;
PathProperties properties = PathPropertyUtils.load(source);
result = loadCategories(properties);
//
return result;
}
/**
* Load categories.
*
* @param source
* the source
* @param federation
* the federation
* @return the categories
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static Categories loadCategories(final URL source, final Federation federation) throws IOException
{
Categories result;
result = loadCategories(source);
Category other = new Category("Autres", "Qui ne rentre pas dans une catégorie existante.");
result.add(other);
for (Software software : federation.getSoftwares().values())
{
if (!result.matches(software.getName()))
{
other.getSoftwares().add(software.getName());
}
}
//
return result;
}
/**
* Load configuration.
*
@ -136,15 +209,20 @@ public class Factory
* @return the configuration
* @throws StatoolInfosException
* the statool infos exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static Configuration loadConfiguration(final File configurationFile) throws StatoolInfosException, IOException
public static Configuration loadConfiguration(final File configurationFile) throws StatoolInfosException
{
Configuration result;
PathProperties properties = PathPropertyUtils.load(configurationFile);
result = new Configuration(properties);
try
{
PathProperties properties = PathPropertyUtils.load(configurationFile);
result = new Configuration(properties);
}
catch (IOException exception)
{
throw new StatoolInfosException("Error reading configuration file: " + configurationFile, exception);
}
//
return result;
@ -168,7 +246,6 @@ public class Factory
Federation result;
System.out.println("Loading federation " + inputURL);
Chrono chrono = new Chrono().start();
if (inputURL == null)
{
@ -199,7 +276,7 @@ public class Factory
result = new Federation(properties);
result.setInputURL(inputURL);
result.setInputFile(federationFile);
result.setLogoFileName(result.getTechnicalName() + "-logo" + StringUtils.defaultIfBlank(cache.getExtension(result.getLogoURL()), ".png"));
result.setLogoFileName("logo" + StringUtils.defaultIfBlank(cache.getExtension(result.getLogoURL()), ".png"));
PropertyChecker checker = new PropertyChecker();
PropertyChecks checks = checker.checkFederation(result.getInputFile());
@ -225,7 +302,6 @@ public class Factory
result.getCrawlJournal().addAll(cache.restoreCrawlJournal());
}
}
System.out.println("Federation loaded in " + chrono.format());
//
return result;
@ -251,7 +327,6 @@ public class Factory
System.out.println("Loading metrics " + inputURL);
File inputFile = cache.restoreFile(inputURL);
if (inputFile == null)
{
logger.warn("WARNING: metrics not found in cache [{}]", inputURL);
@ -308,7 +383,7 @@ public class Factory
{
result.setInputFile(inputFile);
result.setInputURL(inputURL);
result.setLogoFileName(result.getTechnicalName() + "-logo" + StringUtils.defaultIfBlank(cache.getExtension(result.getLogoURL()), ".png"));
result.setLogoFileName("logo" + StringUtils.defaultIfBlank(cache.getExtension(result.getLogoURL()), ".png"));
//
PropertyChecker checker = new PropertyChecker();
@ -354,8 +429,15 @@ public class Factory
/**
* Load service.
*
* @param inputURL
* the input URL
* @param cache
* the cache
* @param organization
* the organization
* @return the service
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static Service loadService(final URL inputURL, final CrawlCache cache, final Organization organization) throws IOException
{
@ -372,43 +454,51 @@ public class Factory
}
else
{
PathProperties properties = PathPropertyUtils.load(inputFile);
result = new Service(properties);
result.setOrganization(organization);
result.setInputFile(inputFile);
result.setInputURL(inputURL);
result.setLogoFileName(organization.getTechnicalName() + "-" + result.getTechnicalName() + "-logo" + StringUtils.defaultIfBlank(cache.getExtension(result.getLogoURL()), ".png"));
//
PathProperties subs = result.getByPrefix("subs");
for (PathProperty property : subs)
PathPropertyList properties = PathPropertyUtils.load(inputFile);
if (properties.getClassType() != PropertyClassType.SERVICE)
{
if (StringUtils.startsWith(property.getValue(), "http"))
logger.warn("WARNING: not file class service [{}]", inputURL);
result = null;
}
else
{
result = new Service(properties);
result.setOrganization(organization);
result.setInputFile(inputFile);
result.setInputURL(inputURL);
result.setLogoFileName("logo" + StringUtils.defaultIfBlank(cache.getExtension(result.getLogoURL()), ".png"));
//
PathProperties subs = result.getByPrefix("subs");
for (PathProperty property : subs)
{
URL metricsInputURL = new URL(property.getValue());
Metrics metrics = loadMetrics(metricsInputURL, cache, organization.getTechnicalName() + "-" + result.getTechnicalName());
if (metrics != null)
if (StringUtils.startsWith(property.getValue(), "http"))
{
result.getMetrics().add(metrics);
URL metricsInputURL = new URL(property.getValue());
Metrics metrics = loadMetrics(metricsInputURL, cache, organization.getTechnicalName() + "-" + result.getTechnicalName());
if (metrics != null)
{
result.getMetrics().add(metrics);
}
}
}
}
//
PropertyChecker checker = new PropertyChecker();
PropertyChecks checks = checker.checkService(result.getInputFile());
checks.setFileName(result.getLocalFileName());
result.getInputChecks().addAll(checks);
//
PropertyChecker checker = new PropertyChecker();
PropertyChecks checks = checker.checkService(result.getInputFile());
checks.setFileName(result.getLocalFileName());
result.getInputChecks().addAll(checks);
//
CrawlJournal journal = cache.restoreCrawlJournal();
result.getCrawlJournal().add(journal.getByUrl(inputURL));
result.getCrawlJournal().addAll(journal.searchByParent(result.getInputURL()));
//
CrawlJournal journal = cache.restoreCrawlJournal();
result.getCrawlJournal().add(journal.getByUrl(inputURL));
result.getCrawlJournal().addAll(journal.searchByParent(result.getInputURL()));
//
for (Metrics metrics : result.getMetrics())
{
result.addAll(metrics.getByPrefix("metrics."));
//
for (Metrics metrics : result.getMetrics())
{
result.addAll(metrics.getByPrefix("metrics."));
}
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2020-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -21,17 +21,19 @@ package fr.devinsy.statoolinfos.core;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Year;
import org.apache.commons.lang3.StringUtils;
import fr.devinsy.statoolinfos.checker.PropertyChecks;
import fr.devinsy.statoolinfos.crawl.CrawlJournal;
import fr.devinsy.statoolinfos.htmlize.charts.MonthValues;
import fr.devinsy.statoolinfos.htmlize.charts.WeekValues;
import fr.devinsy.statoolinfos.htmlize.charts.YearValues;
import fr.devinsy.statoolinfos.properties.MonthValues;
import fr.devinsy.statoolinfos.properties.PathProperties;
import fr.devinsy.statoolinfos.properties.PathPropertyList;
import fr.devinsy.statoolinfos.properties.WeekValues;
import fr.devinsy.statoolinfos.properties.YearValues;
import fr.devinsy.statoolinfos.uptime.URLSet;
import fr.devinsy.statoolinfos.util.URLUtils;
@ -81,6 +83,75 @@ public class Federation extends PathPropertyList
}
}
/**
* Gets the organizations active.
*
* @return the organizations active
*/
public Organizations getActiveOrganizations()
{
Organizations result;
result = this.organizations.filterActiveFor(getTechnicalName());
//
return result;
}
/**
* Gets the active services.
*
* @return the active services
*/
public long getActiveServiceCount()
{
long result;
result = 0;
for (Organization organization : getActiveOrganizations())
{
result += organization.getActiveServiceCount();
}
//
return result;
}
/**
* Gets the active services.
*
* @return the active services
*/
public Services getActiveServices()
{
Services result;
result = new Services();
for (Organization organization : getActiveOrganizations())
{
result.addAll(organization.getActiveServices());
}
//
return result;
}
/**
* Gets the away organizations.
*
* @return the away organizations
*/
public Organizations getAwayOrganizations()
{
Organizations result;
result = this.organizations.filterAwayFor(getTechnicalName());
//
return result;
}
/**
* Gets the contact email.
*
@ -146,6 +217,11 @@ public class Federation extends PathPropertyList
return result;
}
/**
* Gets the crawl journal.
*
* @return the crawl journal
*/
public CrawlJournal getCrawlJournal()
{
return this.crawlJournal;
@ -166,6 +242,26 @@ public class Federation extends PathPropertyList
return result;
}
/**
* Gets the idle organizations.
*
* @return the idle organizations
*/
public Organizations getIdleOrganizations()
{
Organizations result;
result = this.organizations.getIdles();
//
return result;
}
/**
* Gets the input checks.
*
* @return the input checks
*/
public PropertyChecks getInputChecks()
{
return this.inputChecks;
@ -193,11 +289,21 @@ public class Federation extends PathPropertyList
return result;
}
/**
* Gets the input file.
*
* @return the input file
*/
public File getInputFile()
{
return this.inputFile;
}
/**
* Gets the input URL.
*
* @return the input URL
*/
public URL getInputURL()
{
return this.inputURL;
@ -250,6 +356,11 @@ public class Federation extends PathPropertyList
return result;
}
/**
* Gets the logo file name.
*
* @return the logo file name
*/
public String getLogoFileName()
{
return this.logoFileName;
@ -285,6 +396,38 @@ public class Federation extends PathPropertyList
return result;
}
/**
* Gets the member organizations.
*
* @return the member organizations
*/
public Organizations getMemberOrganizations()
{
Organizations result;
result = this.organizations.filterMemberFor(getTechnicalName());
//
return result;
}
/**
* Gets the member organizations.
*
* @param year
* the year
* @return the member organizations
*/
public Organizations getMemberOrganizations(final Year year)
{
Organizations result;
result = this.organizations.filterMemberFor(year);
//
return result;
}
/**
* Gets the metric month values all.
*
@ -381,6 +524,11 @@ public class Federation extends PathPropertyList
return result;
}
/**
* Gets the organizations.
*
* @return the organizations
*/
public Organizations getOrganizations()
{
return this.organizations;
@ -396,7 +544,7 @@ public class Federation extends PathPropertyList
int result;
result = 0;
for (Organization organization : this.organizations)
for (Organization organization : getActiveOrganizations())
{
result += organization.getServiceCount();
}
@ -405,6 +553,60 @@ public class Federation extends PathPropertyList
return result;
}
/**
* Gets the service count by.
*
* @param year
* the year
* @return the service count by
*/
public long getServiceCountBy(final Year year)
{
long result;
Organizations organizations = this.organizations.filterMemberFor(year);
result = 0;
for (Organization organization : organizations)
{
for (Service service : organization.getServices().getBy(year))
{
Year memberStart = organization.getMemberStartYear();
Year memberEnd = organization.getMemberEndYear();
Year serviceStart = service.getStartYear();
Year serviceEnd = service.getEndYear();
if (StatoolInfosUtils.overlapp(memberStart, memberEnd, serviceStart, serviceEnd))
{
result += 1;
}
}
}
//
return result;
}
/**
* Gets the all services.
*
* @return the all services
*/
public Services getServices()
{
Services result;
result = new Services();
for (Organization organization : getActiveOrganizations())
{
result.addAll(organization.getServices());
}
//
return result;
}
/**
* Gets the all services.
*
@ -436,7 +638,7 @@ public class Federation extends PathPropertyList
result = new Softwares();
for (Service service : getServicesAll())
for (Service service : getServices())
{
if (StringUtils.isNotBlank(service.getSoftwareName()))
{
@ -459,7 +661,22 @@ public class Federation extends PathPropertyList
*
* @return the start date
*/
public String getStartDate()
public LocalDate getStartDate()
{
LocalDate result;
result = StatoolInfosUtils.parseDate(getStartDateValue());
//
return result;
}
/**
* Gets the start date.
*
* @return the start date
*/
public String getStartDateValue()
{
String result;
@ -469,6 +686,29 @@ public class Federation extends PathPropertyList
return result;
}
/**
* Gets the start year.
*
* @return the start year
*/
public Year getStartYear()
{
Year result;
LocalDate date = getStartDate();
if (date == null)
{
result = null;
}
else
{
result = Year.from(date);
}
//
return result;
}
/**
* Gets the technical doc website.
*
@ -609,11 +849,23 @@ public class Federation extends PathPropertyList
this.inputFile = inputFile;
}
/**
* Sets the input URL.
*
* @param inputURL
* the new input URL
*/
public void setInputURL(final URL inputURL)
{
this.inputURL = inputURL;
}
/**
* Sets the logo file name.
*
* @param logoFileName
* the new logo file name
*/
public void setLogoFileName(final String logoFileName)
{
this.logoFileName = logoFileName;

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2021 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2021-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -23,8 +23,6 @@ import java.net.URL;
import java.time.LocalDateTime;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.statoolinfos.checker.PropertyChecks;
import fr.devinsy.statoolinfos.properties.PathProperties;
@ -37,8 +35,6 @@ public class Metrics extends PathPropertyList
{
private static final long serialVersionUID = -1608084706095266037L;
private static Logger logger = LoggerFactory.getLogger(Metrics.class);
private String localFileNamePrefix;
private File inputFile;
private URL inputURL;
@ -99,16 +95,31 @@ public class Metrics extends PathPropertyList
return result;
}
/**
* Gets the input checks.
*
* @return the input checks
*/
public PropertyChecks getInputChecks()
{
return this.inputChecks;
}
/**
* Gets the input file.
*
* @return the input file
*/
public File getInputFile()
{
return this.inputFile;
}
/**
* Gets the input URL.
*
* @return the input URL
*/
public URL getInputURL()
{
return this.inputURL;
@ -144,6 +155,11 @@ public class Metrics extends PathPropertyList
return result;
}
/**
* Gets the local file name prefix.
*
* @return the local file name prefix
*/
public String getLocalFileNamePrefix()
{
return this.localFileNamePrefix;
@ -165,16 +181,34 @@ public class Metrics extends PathPropertyList
return result;
}
/**
* Sets the input file.
*
* @param inputFile
* the new input file
*/
public void setInputFile(final File inputFile)
{
this.inputFile = inputFile;
}
/**
* Sets the input URL.
*
* @param inputURL
* the new input URL
*/
public void setInputURL(final URL inputURL)
{
this.inputURL = inputURL;
}
/**
* Sets the local file name prefix.
*
* @param localFileNamePrefix
* the new local file name prefix
*/
public void setLocalFileNamePrefix(final String localFileNamePrefix)
{
this.localFileNamePrefix = localFileNamePrefix;

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2020-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -22,17 +22,18 @@ import java.io.File;
import java.net.URL;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Year;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import fr.devinsy.statoolinfos.checker.PropertyChecks;
import fr.devinsy.statoolinfos.crawl.CrawlJournal;
import fr.devinsy.statoolinfos.htmlize.charts.MonthValues;
import fr.devinsy.statoolinfos.htmlize.charts.WeekValues;
import fr.devinsy.statoolinfos.htmlize.charts.YearValues;
import fr.devinsy.statoolinfos.properties.MonthValues;
import fr.devinsy.statoolinfos.properties.PathProperties;
import fr.devinsy.statoolinfos.properties.PathPropertyList;
import fr.devinsy.statoolinfos.properties.WeekValues;
import fr.devinsy.statoolinfos.properties.YearValues;
import fr.devinsy.statoolinfos.uptime.URLSet;
import fr.devinsy.statoolinfos.util.URLUtils;
@ -42,6 +43,25 @@ import fr.devinsy.statoolinfos.util.URLUtils;
public class Organization extends PathPropertyList
{
private static final long serialVersionUID = -2709210934548224213L;
public enum Status
{
ACTIVE,
IDLE,
AWAY
}
public enum Type
{
ASSOCIATION,
COMPANY,
COOPERATIVE,
INDIVIDUAL,
INFORMAL,
MICROCOMPANY,
OTHER
}
private Federation federation;
private Services services;
private File inputFile;
@ -75,6 +95,51 @@ public class Organization extends PathPropertyList
this.crawlJournal = new CrawlJournal();
}
/**
* Gets the service active count.
*
* @return the service active count
*/
public int getActiveServiceCount()
{
int result;
result = 0;
for (Service service : this.services)
{
if (service.isActive())
{
result += 1;
}
}
//
return result;
}
/**
* Gets the active services.
*
* @return the active services
*/
public Services getActiveServices()
{
Services result;
result = new Services();
for (Service service : this.services)
{
if (service.isActive())
{
result.add(service);
}
}
//
return result;
}
/**
* Gets the age.
*
@ -84,10 +149,7 @@ public class Organization extends PathPropertyList
{
String result;
LocalDate startDate = StatoolInfosUtils.parseDate(getStartDate());
LocalDate endDate = StatoolInfosUtils.parseDate(getEndDate());
result = StatoolInfosUtils.toHumanDuration(startDate, endDate);
result = StatoolInfosUtils.toHumanDuration(getStartDate(), getEndDate());
//
return result;
@ -208,7 +270,22 @@ public class Organization extends PathPropertyList
*
* @return the end date
*/
public String getEndDate()
public LocalDate getEndDate()
{
LocalDate result;
result = StatoolInfosUtils.parseDate(getEndDateValue());
//
return result;
}
/**
* Gets the end date.
*
* @return the end date
*/
public String getEndDateValue()
{
String result;
@ -218,6 +295,30 @@ public class Organization extends PathPropertyList
return result;
}
/**
* Gets the end year.
*
* @return the end year
*/
public Year getEndYear()
{
Year result;
LocalDate date = getEndDate();
if (date == null)
{
result = null;
}
else
{
result = Year.from(date);
}
//
return result;
}
public Federation getFederation()
{
return this.federation;
@ -400,10 +501,7 @@ public class Organization extends PathPropertyList
{
String result;
LocalDate startDate = StatoolInfosUtils.parseDate(getMemberStartDate());
LocalDate endDate = StatoolInfosUtils.parseDate(getMemberEndDate());
result = StatoolInfosUtils.toHumanDuration(startDate, endDate);
result = StatoolInfosUtils.toHumanDuration(getMemberStartDate(), getMemberEndDate());
//
return result;
@ -414,11 +512,66 @@ public class Organization extends PathPropertyList
*
* @return the member end date
*/
public String getMemberEndDate()
public LocalDate getMemberEndDate()
{
LocalDate result;
result = getDate("organization.memberof." + this.federation.getTechnicalName() + ".enddate");
//
return result;
}
/**
* Gets the member end date.
*
* @param entityName
* the entity name
* @return the member end date
*/
public LocalDate getMemberEndDate(final String entityName)
{
LocalDate result;
result = getDate("organization.memberof." + entityName + ".enddate");
//
return result;
}
/**
* Gets the member end date.
*
* @return the member end date
*/
public String getMemberEndDateValue()
{
String result;
result = get("organization.memberof." + this.federation.getName() + ".enddate");
result = get("organization.memberof." + this.federation.getTechnicalName() + ".enddate");
//
return result;
}
/**
* Gets the member end year.
*
* @return the member end year
*/
public Year getMemberEndYear()
{
Year result;
LocalDate date = getMemberEndDate();
if (date == null)
{
result = null;
}
else
{
result = Year.from(date);
}
//
return result;
@ -429,11 +582,104 @@ public class Organization extends PathPropertyList
*
* @return the member start date
*/
public String getMemberStartDate()
public LocalDate getMemberStartDate()
{
LocalDate result;
result = getDate("organization.memberof." + this.federation.getTechnicalName() + ".startdate");
//
return result;
}
/**
* Gets the member start date.
*
* @param entityName
* the entity name
* @return the member start date
*/
public LocalDate getMemberStartDate(final String entityName)
{
LocalDate result;
result = getDate("organization.memberof." + entityName + ".startdate");
//
return result;
}
/**
* Gets the member start date.
*
* @return the member start date
*/
public String getMemberStartDateValue()
{
String result;
result = get("organization.memberof." + this.federation.getName() + ".startdate");
result = get("organization.memberof." + this.federation.getTechnicalName() + ".startdate");
//
return result;
}
/**
* Gets the member start year.
*
* @return the member start year
*/
public Year getMemberStartYear()
{
Year result;
LocalDate date = getMemberStartDate();
if (date == null)
{
result = null;
}
else
{
result = Year.from(date);
}
//
return result;
}
/**
* Gets the status member of.
*
* @param entityName
* the entity name
* @return the status member of
*/
public Status getMemberStatusOf(final String entityName)
{
Status result;
String value = get("organization.memberof." + entityName + ".status");
if (StringUtils.isBlank(value))
{
result = null;
}
else if (StringUtils.equalsIgnoreCase(value, "ACTIVE"))
{
result = Status.ACTIVE;
}
else if (StringUtils.equalsIgnoreCase(value, "IDLE"))
{
result = Status.IDLE;
}
else if (StringUtils.equalsIgnoreCase(value, "AWAY"))
{
result = Status.AWAY;
}
else
{
result = null;
}
//
return result;
@ -616,21 +862,6 @@ public class Organization extends PathPropertyList
return result;
}
/**
* Gets the service active count.
*
* @return the service active count
*/
public int getServiceActiveCount()
{
int result;
result = this.services.getBy(Service.Status.OK).size();
//
return result;
}
/**
* Gets the service count.
*
@ -656,7 +887,22 @@ public class Organization extends PathPropertyList
*
* @return the start date
*/
public String getStartDate()
public LocalDate getStartDate()
{
LocalDate result;
result = StatoolInfosUtils.parseDate(getStartDateValue());
//
return result;
}
/**
* Gets the start date.
*
* @return the start date
*/
public String getStartDateValue()
{
String result;
@ -666,6 +912,66 @@ public class Organization extends PathPropertyList
return result;
}
/**
* Gets the start year.
*
* @return the start year
*/
public Year getStartYear()
{
Year result;
LocalDate date = getStartDate();
if (date == null)
{
result = null;
}
else
{
result = Year.from(date);
}
//
return result;
}
/**
* Gets the status.
*
* @return the status
*/
public Status getStatus()
{
Status result;
String value = get("organization.status.level", "organization.status");
if (StringUtils.isBlank(value))
{
result = null;
}
else if (StringUtils.equalsIgnoreCase(value, "ACTIVE"))
{
result = Status.ACTIVE;
}
else if (StringUtils.equalsIgnoreCase(value, "IDLE"))
{
result = Status.IDLE;
}
else if (StringUtils.equalsIgnoreCase(value, "AWAY"))
{
result = Status.AWAY;
}
else
{
result = null;
}
//
return result;
}
/**
* Gets the technical guide website.
*
@ -698,6 +1004,49 @@ public class Organization extends PathPropertyList
return result;
}
public Type getType()
{
Type result;
String value = get("organization.type");
if (StringUtils.isBlank(value))
{
result = null;
}
else if (StringUtils.equalsIgnoreCase(value, "ASSOCIATION"))
{
result = Type.ASSOCIATION;
}
else if (StringUtils.equalsIgnoreCase(value, "COOPERATIVE"))
{
result = Type.COOPERATIVE;
}
else if (StringUtils.equalsIgnoreCase(value, "MICROCOMPANY"))
{
result = Type.MICROCOMPANY;
}
else if (StringUtils.equalsIgnoreCase(value, "COMPANY"))
{
result = Type.COMPANY;
}
else if (StringUtils.equalsIgnoreCase(value, "INDIVIDUAL"))
{
result = Type.INDIVIDUAL;
}
else if (StringUtils.equalsIgnoreCase(value, "OTHER"))
{
result = Type.OTHER;
}
else
{
result = null;
}
//
return result;
}
/**
* Gets the URL all.
*
@ -860,6 +1209,83 @@ public class Organization extends PathPropertyList
return result;
}
/**
* Checks if is active.
*
* @return true, if is active
*/
public boolean isActive()
{
boolean result;
if (getStatus() == Status.ACTIVE)
{
result = true;
}
else
{
result = false;
}
//
return result;
}
/**
* Checks if is away.
*
* @return true, if is away
*/
public boolean isAway()
{
boolean result;
Status status = getStatus();
if (status == Status.AWAY)
{
result = true;
}
else
{
result = false;
}
//
return result;
}
/**
* Checks if is away for.
*
* @param entityName
* the entity name
* @return true, if is away for
*/
public boolean isAwayFor(final String entityName)
{
boolean result;
Status memberStatus = getMemberStatusOf(entityName);
LocalDate endDate = getDate("organization.memberof." + entityName + ".enddate");
if (memberStatus == Status.AWAY)
{
result = true;
}
else if ((endDate == null) || (endDate.isAfter(LocalDate.now())))
{
result = false;
}
else
{
result = true;
}
//
return result;
}
/**
* Checks if is default.
*
@ -869,7 +1295,7 @@ public class Organization extends PathPropertyList
{
boolean result;
if ((getServiceCount() == 0) && (getLogoURLValue() == null) && (getStartDate() == null))
if ((getServiceCount() == 0) && (getLogoURLValue() == null) && (getStartDateValue() == null))
{
result = true;
}
@ -882,6 +1308,74 @@ public class Organization extends PathPropertyList
return result;
}
/**
* Checks if is idle.
*
* @return true, if is idle
*/
public boolean isIdle()
{
boolean result;
Status status = getStatus();
if ((status == null) || (status == Status.IDLE))
{
result = true;
}
else
{
result = false;
}
//
return result;
}
/**
* Checks if is member.
*
* @param year
* the year
* @return true, if is member
*/
public boolean isMember(final Year year)
{
boolean result;
if (year == null)
{
result = false;
}
else
{
Year startYear = getMemberStartYear();
if (startYear == null)
{
result = false;
}
else
{
Year endYear = getMemberEndYear();
if (endYear == null)
{
endYear = Year.now();
}
if ((year.isBefore(startYear)) || (year.isAfter(endYear)))
{
result = false;
}
else
{
result = true;
}
}
}
//
return result;
}
/**
* Checks if is valid.
*
@ -905,21 +1399,45 @@ public class Organization extends PathPropertyList
return result;
}
/**
* Sets the federation.
*
* @param federation
* the new federation
*/
public void setFederation(final Federation federation)
{
this.federation = federation;
}
/**
* Sets the input file.
*
* @param inputFile
* the new input file
*/
public void setInputFile(final File inputFile)
{
this.inputFile = inputFile;
}
/**
* Sets the input URL.
*
* @param inputURL
* the new input URL
*/
public void setInputURL(final URL inputURL)
{
this.inputURL = inputURL;
}
/**
* Sets the logo file name.
*
* @param logoFileName
* the new logo file name
*/
public void setLogoFileName(final String logoFileName)
{
this.logoFileName = logoFileName;

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2020-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -18,8 +18,12 @@
*/
package fr.devinsy.statoolinfos.core;
import java.time.Year;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import org.apache.commons.lang3.StringUtils;
/**
* The Class Organizations.
@ -36,6 +40,95 @@ public class Organizations extends ArrayList<Organization>
super();
}
/**
* Instantiates a new organizations.
*
* @param organization
* the organization
*/
public Organizations(final Organization organization)
{
super();
if (organization != null)
{
add(organization);
}
}
/**
* Filter active.
*
* @return the organizations
*/
public Organizations filterActive()
{
Organizations result;
result = new Organizations();
for (Organization organization : this)
{
if (organization.isActive())
{
result.add(organization);
}
}
//
return result;
}
/**
* Filter member of.
*
* @param entityName
* the entity name
* @return the organizations
*/
public Organizations filterActiveFor(final String entityName)
{
Organizations result;
result = new Organizations();
for (Organization organization : this)
{
if ((organization.isActive()) && (!organization.isAwayFor(entityName)))
{
result.add(organization);
}
}
//
return result;
}
/**
* Filter away for.
*
* @param entityName
* the entity name
* @return the organizations
*/
public Organizations filterAwayFor(final String entityName)
{
Organizations result;
result = new Organizations();
for (Organization organization : this)
{
if ((organization.isAway()) || (organization.isAwayFor(entityName)))
{
result.add(organization);
}
}
//
return result;
}
/**
* Filter by social network.
*
@ -85,18 +178,128 @@ public class Organizations extends ArrayList<Organization>
}
/**
* Gets the service active count.
* Filter member for.
*
* @return the service active count
* @param entityName
* the entity name
* @return the organizations
*/
public int getServiceActiveCount()
public Organizations filterMemberFor(final String entityName)
{
Organizations result;
result = new Organizations();
for (Organization organization : this)
{
if ((!organization.isAway()) && (!organization.isAwayFor(entityName)))
{
result.add(organization);
}
}
//
return result;
}
/**
* Filter member for.
*
* @param year
* the year
* @return the organizations
*/
public Organizations filterMemberFor(final Year year)
{
Organizations result;
result = new Organizations();
for (Organization organization : this)
{
if (organization.isMember(year))
{
result.add(organization);
}
}
//
return result;
}
/**
* Gets the active service count.
*
* @return the active service count
*/
public int getActiveServiceCount()
{
int result;
result = 0;
for (Organization organization : this)
{
result += organization.getServiceCount();
result += organization.getActiveServiceCount();
}
//
return result;
}
/**
* Gets the by technical name.
*
* @param technicalName
* the technical name
* @return the by technical name
*/
public Organization getByTechnicalName(final String technicalName)
{
Organization result;
Iterator<Organization> iterator = this.iterator();
boolean ended = false;
result = null;
while (!ended)
{
if (iterator.hasNext())
{
Organization organization = iterator.next();
if (StringUtils.equals(organization.getTechnicalName(), technicalName))
{
ended = true;
result = organization;
}
}
else
{
ended = true;
result = null;
}
}
//
return result;
}
/**
* Gets the idles.
*
* @return the idles
*/
public Organizations getIdles()
{
Organizations result;
result = new Organizations();
for (Organization organization : this)
{
if (organization.isIdle())
{
result.add(organization);
}
}
//

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2020-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -22,16 +22,15 @@ import java.io.File;
import java.net.URL;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Year;
import java.time.YearMonth;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.statoolinfos.checker.PropertyChecks;
import fr.devinsy.statoolinfos.crawl.CrawlJournal;
import fr.devinsy.statoolinfos.htmlize.charts.MonthValues;
import fr.devinsy.statoolinfos.properties.MonthValues;
import fr.devinsy.statoolinfos.properties.PathProperties;
import fr.devinsy.statoolinfos.properties.PathPropertyList;
import fr.devinsy.statoolinfos.uptime.URLSet;
@ -44,8 +43,6 @@ public class Service extends PathPropertyList
{
private static final long serialVersionUID = 3629841771102288863L;
private static Logger logger = LoggerFactory.getLogger(Service.class);
public enum HostProviderType
{
HOME,
@ -136,10 +133,7 @@ public class Service extends PathPropertyList
{
String result;
LocalDate startDate = StatoolInfosUtils.parseDate(getStartDate());
LocalDate endDate = StatoolInfosUtils.parseDate(getEndDate());
result = StatoolInfosUtils.toHumanDuration(startDate, endDate);
result = StatoolInfosUtils.toHumanDuration(getStartDate(), getEndDate());
//
return result;
@ -225,6 +219,11 @@ public class Service extends PathPropertyList
return result;
}
/**
* Gets the crawl journal.
*
* @return the crawl journal
*/
public CrawlJournal getCrawlJournal()
{
return this.crawlJournal;
@ -250,7 +249,22 @@ public class Service extends PathPropertyList
*
* @return the end date
*/
public String getEndDate()
public LocalDate getEndDate()
{
LocalDate result;
result = StatoolInfosUtils.parseDate(getEndDateValue());
//
return result;
}
/**
* Gets the end date value.
*
* @return the end date value
*/
public String getEndDateValue()
{
String result;
@ -260,6 +274,30 @@ public class Service extends PathPropertyList
return result;
}
/**
* Gets the end year.
*
* @return the end year
*/
public Year getEndYear()
{
Year result;
LocalDate date = getEndDate();
if (date == null)
{
result = null;
}
else
{
result = Year.from(date);
}
//
return result;
}
/**
* Gets the host name.
*
@ -275,6 +313,21 @@ public class Service extends PathPropertyList
return result;
}
/**
* Gets the host provider hypervisor.
*
* @return the host provider hypervisor
*/
public String getHostProviderHypervisor()
{
String result;
result = get("host.provider.hypervisor");
//
return result;
}
/**
* Gets the host provider type.
*
@ -299,6 +352,21 @@ public class Service extends PathPropertyList
return result;
}
/**
* Gets the host server distribution.
*
* @return the host server distribution
*/
public String getHostServerDistribution()
{
String result;
result = get("host.server.distribution");
//
return result;
}
/**
* Gets the host server type.
*
@ -323,6 +391,11 @@ public class Service extends PathPropertyList
return result;
}
/**
* Gets the input checks.
*
* @return the input checks
*/
public PropertyChecks getInputChecks()
{
return this.inputChecks;
@ -350,11 +423,21 @@ public class Service extends PathPropertyList
return result;
}
/**
* Gets the input file.
*
* @return the input file
*/
public File getInputFile()
{
return this.inputFile;
}
/**
* Gets the input URL.
*
* @return the input URL
*/
public URL getInputURL()
{
return this.inputURL;
@ -442,11 +525,160 @@ public class Service extends PathPropertyList
return result;
}
/**
* Gets the metrics.
*
* @return the metrics
*/
public MetricsList getMetrics()
{
return this.metricsList;
}
/**
* Gets the month account count.
*
* @return the month account count
*/
public long getMonthAccountCount(final YearMonth month)
{
long result;
result = getMonthCount("metrics.service.accounts", month);
//
return result;
}
/**
* Gets the month active account count.
*
* @return the month active account count
*/
public long getMonthActiveAccountCount(final YearMonth month)
{
long result;
result = getMonthCount("metrics.service.accounts.active", month);
//
return result;
}
/**
* Gets the month count.
*
* @param path
* the path
* @return the month count
*/
public long getMonthCount(final String path, final YearMonth month)
{
long result;
MonthValues values = getMetricMonthValues(path);
values = values.extract(month, month);
result = (long) values.sum();
//
return result;
}
/**
* Gets the month database bytes.
*
* @param month
* the month
* @return the month database bytes
*/
public long getMonthDatabaseBytes(final YearMonth month)
{
long result;
result = getMonthCount("metrics.service.database.bytes", month);
//
return result;
}
/**
* Gets the month datafiles bytes.
*
* @param month
* the month
* @return the month datafiles bytes
*/
public long getMonthDatafilesBytes(final YearMonth month)
{
long result;
result = getMonthCount("metrics.service.datafiles.bytes", month);
//
return result;
}
/**
* Gets the month hit count.
*
* @return the month hit count
*/
public long getMonthHitCount(final YearMonth month)
{
long result;
result = getMonthCount("metrics.http.hits", month);
//
return result;
}
/**
* Gets the month user count.
*
* @return the month user count
*/
public long getMonthUserCount(final YearMonth month)
{
long result;
result = getMonthCount("metrics.service.users", month);
//
return result;
}
/**
* Gets the month visit count.
*
* @return the month visit count
*/
public long getMonthVisitCount(final YearMonth month)
{
long result;
result = getMonthCount("metrics.http.visits", month);
//
return result;
}
/**
* Gets the month visitor count.
*
* @return the month visitor count
*/
public long getMonthVisitorCount(final YearMonth month)
{
long result;
result = getMonthCount("metrics.http.visitors", month);
//
return result;
}
/**
* Gets the name.
*
@ -487,11 +719,7 @@ public class Service extends PathPropertyList
{
long result;
MonthValues values = getMetricMonthValues("metrics.users.count");
values = values.extract(YearMonth.now().minusMonths(1), YearMonth.now().minusMonths(1));
result = (long) values.sum();
result = getMonthUserCount(YearMonth.now().minusMonths(1));
//
return result;
@ -506,11 +734,7 @@ public class Service extends PathPropertyList
{
long result;
MonthValues values = getMetricMonthValues("metrics.http.visits.visitors");
values = values.extract(YearMonth.now().minusMonths(1), YearMonth.now().minusMonths(1));
result = (long) values.sum();
result = getMonthVisitCount(YearMonth.now().minusMonths(1));
//
return result;
@ -685,7 +909,22 @@ public class Service extends PathPropertyList
*
* @return the start date
*/
public String getStartDate()
public LocalDate getStartDate()
{
LocalDate result;
result = StatoolInfosUtils.parseDate(getStartDateValue());
//
return result;
}
/**
* Gets the start date value.
*
* @return the start date value
*/
public String getStartDateValue()
{
String result;
@ -695,6 +934,30 @@ public class Service extends PathPropertyList
return result;
}
/**
* Gets the start year.
*
* @return the start year
*/
public Year getStartYear()
{
Year result;
LocalDate date = getStartDate();
if (date == null)
{
result = null;
}
else
{
result = Year.from(date);
}
//
return result;
}
/**
* Gets the status.
*
@ -859,6 +1122,59 @@ public class Service extends PathPropertyList
return result;
}
/**
* Checks if is active.
*
* @return true, if is active
*/
public boolean isActive()
{
boolean result;
if (((getStatus() == Service.Status.OK) || (getStatus() == Status.WARNING) || (getStatus() == Status.ERROR)) && (!isAway()))
{
result = true;
}
else
{
result = false;
}
//
return result;
}
/**
* Checks if is away.
*
* @return true, if is away
*/
public boolean isAway()
{
boolean result;
if (getEndDateValue() == null)
{
result = false;
}
else
{
LocalDate endDate = getDate("service.enddate");
if ((endDate == null) || (endDate.isAfter(LocalDate.now())))
{
result = false;
}
else
{
result = true;
}
}
//
return result;
}
/**
* Checks if is registration client.
*
@ -971,21 +1287,45 @@ public class Service extends PathPropertyList
return result;
}
/**
* Sets the input file.
*
* @param inputFile
* the new input file
*/
public void setInputFile(final File inputFile)
{
this.inputFile = inputFile;
}
/**
* Sets the input URL.
*
* @param inputURL
* the new input URL
*/
public void setInputURL(final URL inputURL)
{
this.inputURL = inputURL;
}
/**
* Sets the logo file name.
*
* @param logoFileName
* the new logo file name
*/
public void setLogoFileName(final String logoFileName)
{
this.logoFileName = logoFileName;
}
/**
* Sets the organization.
*
* @param organization
* the new organization
*/
public void setOrganization(final Organization organization)
{
this.organization = organization;

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2020-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -18,8 +18,11 @@
*/
package fr.devinsy.statoolinfos.core;
import java.time.LocalDate;
import java.time.Year;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import org.apache.commons.lang3.StringUtils;
@ -40,6 +43,58 @@ public class Services extends ArrayList<Service>
super();
}
/**
* Instantiates a new services.
*
* @param service
* the service
*/
public Services(final Service service)
{
super();
if (service != null)
{
add(service);
}
}
/**
* Count by year.
*
* @param year
* the year
* @return the long
*/
public long countBy(final Year year)
{
long result;
result = 0;
Year now = Year.now();
for (Service service : this)
{
Year start = service.getStartYear();
Year end = service.getEndYear();
if (start != null)
{
if (end == null)
{
end = now;
}
if ((!start.isAfter(year) && (!end.isBefore(year))))
{
result += 1;
}
}
}
//
return result;
}
/**
* Gets the by.
*
@ -117,6 +172,132 @@ public class Services extends ArrayList<Service>
return result;
}
/**
* Gets the by.
*
* @param year
* the year
* @return the by
*/
public Services getBy(final Year year)
{
Services result;
result = new Services();
if (year != null)
{
for (Service service : this)
{
Year startYear = service.getStartYear();
Year endYear = service.getEndYear();
if (endYear == null)
{
endYear = Year.now();
}
if ((startYear != null) && (!year.isBefore(startYear)) && (!year.isAfter(endYear)))
{
result.add(service);
}
}
}
//
return result;
}
/**
* Gets the by technical name.
*
* @param technicalName
* the technical name
* @return the by technical name
*/
public Service getByTechnicalName(final String technicalName)
{
Service result;
Iterator<Service> iterator = this.iterator();
boolean ended = false;
result = null;
while (!ended)
{
if (iterator.hasNext())
{
Service service = iterator.next();
if (StringUtils.equals(service.getTechnicalName(), technicalName))
{
ended = true;
result = service;
}
}
else
{
ended = true;
result = null;
}
}
//
return result;
}
/**
* Gets the older.
*
* @return the older
*/
public Service getOldestService()
{
Service result;
result = null;
LocalDate oldestDate = null;
for (Service current : this)
{
LocalDate date = current.getStartDate();
if (date != null)
{
LocalDate currentDate = current.getStartDate();
if ((result == null) || (currentDate.isBefore(oldestDate)))
{
result = current;
oldestDate = currentDate;
}
}
}
//
return result;
}
/**
* Gets the oldest year.
*
* @return the oldest year
*/
public Year getOldestStartYear()
{
Year result;
Service oldestService = getOldestService();
if (oldestService == null)
{
result = null;
}
else
{
result = oldestService.getStartYear();
}
//
return result;
}
/**
* Reverse.
*

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2020-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -72,16 +72,31 @@ public class Software
this.aliases = new StringList(softwares);
}
/**
* Gets the aliases.
*
* @return the aliases
*/
public StringList getAliases()
{
return this.aliases;
}
/**
* Gets the description.
*
* @return the description
*/
public String getDescription()
{
return this.description;
}
/**
* Gets the name.
*
* @return the name
*/
public String getName()
{
return this.name;
@ -102,20 +117,30 @@ public class Software
return result;
}
/**
* Sets the description.
*
* @param description
* the new description
*/
public void setDescription(final String description)
{
this.description = description;
}
/**
* Sets the name.
*
* @param name
* the new name
*/
public void setName(final String name)
{
this.name = name;
}
/**
* To string.
*
* @return the string
/*
* {@inheritDoc}
*/
@Override
public String toString()

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2020-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -77,6 +77,8 @@ public class Softwares extends HashMap<String, Software>
*/
public void put(final Software software)
{
put(buildKey(software.getName()), software);
for (String alias : software.getAliases())
{
put(buildKey(alias), software);

View file

@ -1,553 +0,0 @@
/*
* Copyright (C) 2020 Christian Pierre MOMON <christian@momon.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
package fr.devinsy.statoolinfos.core;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.statoolinfos.HtmlizerContext;
import fr.devinsy.statoolinfos.build.Builder;
import fr.devinsy.statoolinfos.crawl.Crawler;
import fr.devinsy.statoolinfos.htmlize.Htmlizer;
import fr.devinsy.statoolinfos.metrics.Prober;
import fr.devinsy.statoolinfos.metrics.http.HttpAccessLog;
import fr.devinsy.statoolinfos.metrics.http.HttpAccessLogAnalyzer;
import fr.devinsy.statoolinfos.properties.PathProperties;
import fr.devinsy.statoolinfos.properties.PathPropertyUtils;
import fr.devinsy.statoolinfos.stats.ip.IpStat;
import fr.devinsy.statoolinfos.stats.ip.IpStator;
import fr.devinsy.statoolinfos.stats.useragent.UserAgentStat;
import fr.devinsy.statoolinfos.stats.useragent.UserAgentStator;
import fr.devinsy.statoolinfos.stats.visitor.VisitorStat;
import fr.devinsy.statoolinfos.stats.visitor.VisitorStator;
import fr.devinsy.statoolinfos.uptime.UptimeJournal;
import fr.devinsy.statoolinfos.uptime.UptimeSurveyor;
import fr.devinsy.statoolinfos.util.Chrono;
import fr.devinsy.statoolinfos.util.LineIterator;
import fr.devinsy.strings.StringList;
import fr.devinsy.strings.StringsUtils;
/**
* The Class StatoolInfos.
*/
public class StatoolInfos
{
private static Logger logger = LoggerFactory.getLogger(StatoolInfos.class);
/**
* Builds the.
*
* @param configurationFile
* the input
* @throws StatoolInfosException
* the statool infos exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void build(final File configurationFile) throws StatoolInfosException, IOException
{
Builder.build(configurationFile);
}
/**
* Clear.
*
* @param configurationFile
* the input
* @throws StatoolInfosException
* the statool infos exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void clear(final File configurationFile) throws StatoolInfosException, IOException
{
logger.info("Clear {}", configurationFile.getAbsolutePath());
Configuration configuration = Factory.loadConfiguration(configurationFile);
Builder.clear(configuration);
new Crawler(configuration.getCrawlCacheDirectory()).clear();
Htmlizer.clear(configuration);
}
/**
* Crawl.
*
* @param configurationFile
* the input
* @throws StatoolInfosException
* the statool infos exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void crawl(final File configurationFile) throws StatoolInfosException, IOException
{
Configuration configuration = Factory.loadConfiguration(configurationFile);
Crawler crawler = new Crawler(configuration.getCrawlCacheDirectory());
crawler.crawl(configuration.getCrawlInputURL());
crawler.storeJournal();
}
/**
* Format.
*
* @param inputFile
* the input file
* @throws StatoolInfosException
* the statool infos exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void format(final File inputFile) throws StatoolInfosException, IOException
{
logger.info("Format {}", inputFile);
if (inputFile == null)
{
throw new StatoolInfosException("Input is undefined.");
}
else if (!inputFile.exists())
{
throw new StatoolInfosException("Input does not exist.");
}
else if (!inputFile.isFile())
{
throw new StatoolInfosException("Input is not a file.");
}
else
{
// Load input properties.
PathProperties inputs = PathPropertyUtils.load(inputFile);
// Save input properties.
inputFile.renameTo(new File(inputFile.getParentFile(), inputFile.getName() + ".bak"));
PathPropertyUtils.save(inputFile, inputs);
}
}
/**
* Htmlize.
*
* @param configurationFile
* the input
* @throws StatoolInfosException
* the statool infos exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void htmlize(final File configurationFile) throws StatoolInfosException, IOException
{
Htmlizer.htmlize(configurationFile);
}
/**
* List ips.
*
* @param source
* the source
* @throws IOException
*/
public static void listIps(final File source, final BotFilter filter)
{
try
{
IpStator stator = new IpStator();
Chrono chrono = new Chrono().start();
LineIterator iterator = new LineIterator(source);
while (iterator.hasNext())
{
String line = iterator.next();
HttpAccessLog log = HttpAccessLogAnalyzer.parseLog(line, HttpAccessLogAnalyzer.COMBINED_PATTERN);
if (filter.matches(log))
{
stator.putLog(log);
}
}
for (IpStat stat : stator.getIps())
{
System.out.println(stat.getValue());
}
System.err.println(String.format("%s %10d", "Ip count: ", stator.getIps().size()));
System.err.println(String.format("%s %10d", "Log count: ", stator.getLogCount()));
System.err.println(chrono.format());
}
catch (IllegalArgumentException exception)
{
System.out.println("Bad format line detected. Aborting…");
exception.printStackTrace();
}
catch (DateTimeParseException exception)
{
System.out.println("Bad datetime format detected. Aborting…");
}
catch (IOException exception)
{
System.out.println("File error detected. Aborting…");
exception.printStackTrace();
}
}
/**
* List user agents.
*
* @param source
* the source
*/
public static void listUserAgents(final File source, final BotFilter filter)
{
try
{
UserAgentStator stator = new UserAgentStator();
Chrono chrono = new Chrono().start();
LineIterator iterator = new LineIterator(source);
while (iterator.hasNext())
{
String line = iterator.next();
HttpAccessLog log = HttpAccessLogAnalyzer.parseLog(line, HttpAccessLogAnalyzer.COMBINED_PATTERN);
if (filter.matches(log))
{
stator.putLog(log);
}
}
for (UserAgentStat stat : stator.getUserAgentStats().sortByLabel())
{
System.out.println(stat.getUserAgent());
}
System.err.println(String.format("%s %10d", "UserAgent count: ", stator.getUserAgentStats().size()));
System.err.println(String.format("%s %10d", "Log count: ", stator.getLogCount()));
System.err.println(chrono.format());
}
catch (IllegalArgumentException exception)
{
System.out.println("Bad format line detected. Aborting…");
exception.printStackTrace();
}
catch (DateTimeParseException exception)
{
System.out.println("Bad datetime format detected. Aborting…");
exception.printStackTrace();
}
catch (IOException exception)
{
System.out.println("File error detected. Aborting…");
exception.printStackTrace();
}
}
/**
* List visitors.
*
* @param source
* the source
*/
public static void listVisitors(final File source, final BotFilter filter)
{
try
{
VisitorStator stator = new VisitorStator();
Chrono chrono = new Chrono().start();
LineIterator iterator = new LineIterator(source);
while (iterator.hasNext())
{
String line = iterator.next();
HttpAccessLog log = HttpAccessLogAnalyzer.parseLog(line, HttpAccessLogAnalyzer.COMBINED_PATTERN);
if (filter.matches(log))
{
stator.putLog(log);
}
}
for (VisitorStat stat : stator.getVisitorStats().sortByIp())
{
System.out.println(stat.getIp() + " " + stat.getUserAgent());
}
System.err.println(String.format("%s %10d", "Visitor count: ", stator.getVisitorStats().size()));
System.err.println(String.format("%s %10d", "Log count: ", stator.getLogCount()));
System.err.println(chrono.format());
}
catch (IllegalArgumentException exception)
{
System.out.println("Bad format line detected. Aborting…");
exception.printStackTrace();
}
catch (DateTimeParseException exception)
{
System.out.println("Bad datetime format detected. Aborting…");
exception.printStackTrace();
}
catch (IOException exception)
{
System.out.println("File error detected. Aborting…");
exception.printStackTrace();
}
}
/**
* Stat.
*
* @param configurationFile
* the configuration file
* @throws StatoolInfosException
* the statool infos exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void probe(final File configurationFile, final int dayCountFilter) throws StatoolInfosException, IOException
{
Prober.probe(configurationFile, dayCountFilter);
}
/**
* Stat ips.
*
* @param source
* the source
*/
public static void statIps(final File source, final BotFilter filter)
{
try
{
IpStator stator = new IpStator();
Chrono chrono = new Chrono().start();
LineIterator iterator = new LineIterator(source);
while (iterator.hasNext())
{
String line = iterator.next();
HttpAccessLog log = HttpAccessLogAnalyzer.parseLog(line, HttpAccessLogAnalyzer.COMBINED_PATTERN);
if (filter.matches(log))
{
stator.putLog(log);
}
}
System.err.println("IpCount Ip");
for (IpStat stat : stator.getIps().sortByCount().reverse())
{
System.out.println(stat.getCount() + " " + stat.getValue());
}
System.err.println(String.format("%s %10d", "Ip count: ", stator.getIps().size()));
System.err.println(String.format("%s %10d", "Log count: ", stator.getLogCount()));
System.err.println(chrono.format());
}
catch (IllegalArgumentException exception)
{
System.out.println("Bad format line detected. Aborting…");
exception.printStackTrace();
}
catch (DateTimeParseException exception)
{
System.out.println("Bad datetime format detected. Aborting…");
exception.printStackTrace();
}
catch (IOException exception)
{
System.out.println("File error detected. Aborting…");
exception.printStackTrace();
}
}
/**
* Stat user agents.
*
* @param source
* the source
*/
public static void statUserAgents(final File source, final BotFilter filter)
{
try
{
UserAgentStator stator = new UserAgentStator();
Chrono chrono = new Chrono().start();
LineIterator iterator = new LineIterator(source);
while (iterator.hasNext())
{
String line = iterator.next();
HttpAccessLog log = HttpAccessLogAnalyzer.parseLog(line, HttpAccessLogAnalyzer.COMBINED_PATTERN);
if (filter.matches(log))
{
stator.putLog(log);
}
}
System.err.println("LogCount IpCount VisitCount UserAgent");
for (UserAgentStat stat : stator.getUserAgentStats().sortByCount().reverse())
{
System.out.println(String.format("%d %d %d %s", stat.getLogCount(), stat.getIpCount(), stat.getVisitCount(), stat.getUserAgent()));
}
System.err.println(String.format("%s %10d", "User Agent count: ", stator.getUserAgentStats().size()));
System.err.println(String.format("%s %10d", "Log count: ", stator.getLogCount()));
System.err.println(chrono.format());
}
catch (IllegalArgumentException exception)
{
System.out.println("Bad format line detected. Aborting…");
exception.printStackTrace();
}
catch (DateTimeParseException exception)
{
System.out.println("Bad datetime format detected. Aborting…");
exception.printStackTrace();
}
catch (IOException exception)
{
System.out.println("File error detected. Aborting…");
exception.printStackTrace();
}
}
/**
* Stat visitors.
*
* @param source
* the source
*/
public static void statVisitors(final File source, final BotFilter filter)
{
try
{
VisitorStator stator = new VisitorStator();
Chrono chrono = new Chrono().start();
LineIterator iterator = new LineIterator(source);
while (iterator.hasNext())
{
String line = iterator.next();
HttpAccessLog log = HttpAccessLogAnalyzer.parseLog(line, HttpAccessLogAnalyzer.COMBINED_PATTERN);
if (filter.matches(log))
{
stator.putLog(log);
}
}
System.err.println("VisitCount LogCount VisitDuration VisitDuration Ip UserAgent");
for (VisitorStat stat : stator.getVisitorStats().sortByVisitCount().reverse())
{
System.out.println(
String.format("%d %d %d %s %s %s", stat.getVisits().size(), stat.getLogCount(), stat.getVisits().getDurationSum().toSeconds(), Chrono.format(stat.getVisits().getDurationSum()),
stat.getIp(), stat.getUserAgent()));
}
System.err.println(String.format("%s %10d", "Visitor count: ", stator.getVisitorStats().size()));
System.err.println(String.format("%s %10d", "Log count: ", stator.getLogCount()));
System.err.println(chrono.format());
}
catch (IllegalArgumentException exception)
{
System.out.println("Bad format line detected. Aborting…");
exception.printStackTrace();
}
catch (DateTimeParseException exception)
{
System.out.println("Bad datetime format detected. Aborting…");
exception.printStackTrace();
}
catch (IOException exception)
{
System.out.println("File error detected. Aborting…");
exception.printStackTrace();
}
}
/**
* Tag date.
*
* @param inputFile
* the source
* @throws StatoolInfosException
* the statool infos exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void tagDate(final File inputFile) throws StatoolInfosException, IOException
{
System.out.println("TagDate " + inputFile);
if (inputFile == null)
{
throw new StatoolInfosException("Null parameter [source].");
}
else if (!inputFile.exists())
{
throw new StatoolInfosException("Input does not exist.");
}
else if (!inputFile.isFile())
{
throw new StatoolInfosException("Input is not a file.");
}
else
{
StringList lines = StringsUtils.load(inputFile);
for (int lineIndex = 0; lineIndex < lines.size(); lineIndex++)
{
String line = lines.get(lineIndex);
if (StringUtils.startsWith(line, "file.datetime="))
{
lines.set(lineIndex, "file.datetime=" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")));
}
}
inputFile.renameTo(new File(inputFile.getParentFile(), inputFile.getName() + ".bak"));
StringsUtils.save(inputFile, lines);
}
}
/**
* Uptime.
*
* @param configurationFile
* the configuration file
* @throws StatoolInfosException
* the statool infos exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void uptime(final File configurationFile) throws StatoolInfosException, IOException
{
HtmlizerContext.instance().configure(configurationFile);
UptimeJournal journal = HtmlizerContext.instance().getUptimeJournal();
Federation federation = HtmlizerContext.instance().getFederation();
UptimeSurveyor.survey(journal, federation.getURLActiveAll());
HtmlizerContext.instance().getCache().storeUptimeJournal(journal);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2020-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -16,31 +16,25 @@
* You should have received a copy of the GNU Affero General Public License
* along with StatoolInfos. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.devinsy.statoolinfos;
package fr.devinsy.statoolinfos.core;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import fr.devinsy.statoolinfos.core.Categories;
import fr.devinsy.statoolinfos.core.Configuration;
import fr.devinsy.statoolinfos.core.Factory;
import fr.devinsy.statoolinfos.core.Federation;
import fr.devinsy.statoolinfos.core.StatoolInfosException;
import fr.devinsy.statoolinfos.crawl.CrawlCache;
import fr.devinsy.statoolinfos.uptime.UptimeJournal;
/**
* The Class Manager.
* The Class StatoolInfosContext.
*/
public class HtmlizerContext
public class StatoolInfosContext
{
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(HtmlizerContext.class);
private static class SingletonHolder
{
private static final HtmlizerContext instance = new HtmlizerContext();
}
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(StatoolInfosContext.class);
private LocalDateTime initDateTime;
private Configuration configuration;
private Federation federation;
private Categories categories;
@ -48,10 +42,18 @@ public class HtmlizerContext
private UptimeJournal uptimeJournal;
/**
* Instantiates a new manager.
* Instantiates a new statool infos context.
*
* @param configurationFile
* the configuration file
* @throws StatoolInfosException
* the statool infos exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
private HtmlizerContext()
public StatoolInfosContext(final File configurationFile) throws StatoolInfosException, IOException
{
configure(configurationFile);
}
/**
@ -59,44 +61,41 @@ public class HtmlizerContext
*
* @param configurationFile
* the configuration file
* @throws IOException
* @throws StatoolInfosException
* the statool infos exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public void configure(final File configurationFile) throws StatoolInfosException, IOException
{
this.configuration = Factory.loadConfiguration(configurationFile);
logger.info("Cache setting: {}", this.configuration.getCrawlCachePath());
logger.info("Htmlize input setting: {}", this.configuration.getHtmlizeInputURL());
logger.info("Htmlize directory setting: {}", this.configuration.getHtmlizeDirectoryPath());
logger.info("Cache input setting: {}", this.configuration.getCrawlInputURL());
this.cache = new CrawlCache(this.configuration.getCrawlCacheDirectory());
File htmlizeDirectory = this.configuration.getHtmlizeDirectory();
if (htmlizeDirectory == null)
if (this.configuration.isFederation())
{
throw new IllegalArgumentException("Htmlize directory undefined.");
}
else if (!htmlizeDirectory.exists())
{
throw new IllegalArgumentException("Htmlize directory is missing.");
}
else if (!htmlizeDirectory.isDirectory())
{
throw new IllegalArgumentException("Htmlize directory is not a directory.");
}
else
{
if (this.configuration.isFederation())
long startTime = System.currentTimeMillis();
System.out.println("Loading configuration file.");
this.federation = Factory.loadFederation(this.configuration.getCrawlInputURL(), this.cache);
if (this.configuration.isCategoryFileDefined())
{
this.federation = Factory.loadFederation(this.configuration.getHtmlizeInputURL(), this.cache);
this.categories = Factory.loadCategories(this.configuration.getCategoryFile(), this.federation);
this.uptimeJournal = this.cache.restoreUptimeJournal();
}
else
{
throw new IllegalArgumentException("Not a federation configuration.");
URL categoriesURL = StatoolInfosContext.class.getResource("/fr/devinsy/statoolinfos/core/categories.properties");
this.categories = Factory.loadCategories(categoriesURL, this.federation);
}
this.uptimeJournal = this.cache.restoreUptimeJournal();
this.initDateTime = LocalDateTime.now();
System.out.println("Loaded configuration context in " + (System.currentTimeMillis() - startTime) + " ms.");
}
else
{
throw new IllegalArgumentException("Not a federation configuration.");
}
}
@ -161,32 +160,39 @@ public class HtmlizerContext
}
/**
* Htmlize directory.
* Gets the uptime journal.
*
* @return the file
* @return the uptime journal
*/
public File getHtmlizeDirectory()
{
File result;
result = this.configuration.getHtmlizeDirectory();
//
return result;
}
public UptimeJournal getUptimeJournal()
{
return this.uptimeJournal;
}
/**
* Instance.
* Checks if is expired.
*
* @return the manager
* @return true, if is expired
*/
public static HtmlizerContext instance()
public boolean isExpired()
{
return SingletonHolder.instance;
boolean result;
getCache();
long cacheTime = this.getCache().getDirectory().lastModified();
LocalDateTime cacheDateTime = LocalDateTime.ofEpochSecond(cacheTime / 1000, 0, OffsetDateTime.now().getOffset());
if (cacheDateTime.isAfter(this.initDateTime))
{
result = true;
}
else
{
result = false;
}
//
return result;
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2020-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -27,6 +27,7 @@ import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.Year;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
@ -49,8 +50,6 @@ import org.apache.tika.Tika;
import org.apache.tika.mime.MimeType;
import org.apache.tika.mime.MimeTypeException;
import org.apache.tika.mime.MimeTypes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.strings.StringList;
import fr.devinsy.strings.StringsUtils;
@ -60,11 +59,35 @@ import fr.devinsy.strings.StringsUtils;
*/
public class StatoolInfosUtils
{
private static Logger logger = LoggerFactory.getLogger(StatoolInfosUtils.class);
public static final DateTimeFormatter PATTERN_SHORTDATE = DateTimeFormatter.ofPattern("dd/MM/yyyy", Locale.FRANCE);
public static final DateTimeFormatter PATTERN_LONGDATE = DateTimeFormatter.ofPattern("dd/MM/yyyy HH':'mm", Locale.FRANCE);
/**
* Default if zero.
*
* @param value
* the value
* @param defaultValue
* the default value
* @return the string
*/
public static String defaultIfZero(final long value, final String defaultValue)
{
String result;
if (value == 0)
{
result = defaultValue;
}
else
{
result = String.valueOf(value);
}
//
return result;
}
/**
* Epoch to local date time.
*
@ -180,6 +203,63 @@ public class StatoolInfosUtils
return new Date().getTime();
}
/**
* Overlapp.
*
* @param start1
* the start 1
* @param end1
* the end 1
* @param start2
* the start 2
* @param end2
* the end 2
* @return true, if successful
*/
public static boolean overlapp(final Year start1, final Year end1, final Year start2, final Year end2)
{
boolean result;
if ((start1 == null) || (start2 == null))
{
result = false;
}
else
{
Year end11;
if (end1 == null)
{
end11 = Year.now();
}
else
{
end11 = end1;
}
Year end22;
if (end2 == null)
{
end22 = Year.now();
}
else
{
end22 = end2;
}
if ((end22.isBefore(start1)) || (start2.isAfter(end11)))
{
result = false;
}
else
{
result = true;
}
}
//
return result;
}
/**
* Parses the date.
*
@ -209,6 +289,10 @@ public class StatoolInfosUtils
{
result = LocalDate.parse("01/" + date, DateTimeFormatter.ofPattern("dd/MM/yyyy"));
}
else if (date.matches("\\d{4}-\\d{2}"))
{
result = LocalDate.parse(date + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
}
else
{
result = null;
@ -523,6 +607,13 @@ public class StatoolInfosUtils
return result;
}
/**
* To integer.
*
* @param value
* the value
* @return the integer
*/
public static Integer toInteger(final String value)
{
Integer result;
@ -733,6 +824,7 @@ public class StatoolInfosUtils
* the url
* @return the local date time
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static LocalDateTime urlLastModified(final URL url) throws IOException
{

View file

@ -0,0 +1,438 @@
# Warning: UTF-8 file.
# History:
# 2021-2023 CHATONS stats workgroup with Angie from Framasoft, MrFlo and Cpm.
# 2024 Cpm.
# [Categories]
# Outils de communication
## Courrier électronique / mail (alternative à Gmail, Hotmail, YahooMail, etc.)
categories.mail.name=Courrier électronique
categories.mail.description=
categories.mail.logo=mail.svg
categories.mail.softwares=BlueMind, Rainloop, Roundcube, SOgo, Mailman, Dovecot, Postfix, Snappymail
## Carnet d'adresse (alternative à Google Contacts)
categories.adressbook.name=Carnet d'adresses
categories.adressbook.description=
categories.adressbook.logo=adressbook.svg
categories.adressbook.softwares=Radicale, SOgo, Nextcloud Contact, Nextcloud, Davical, InfCloud
## Liste de diffusion (alternative à Google Groupes)
categories.mailinglist.name=Liste de diffusion
categories.mailinglist.description=
categories.mailinglist.logo=mailinglist.svg
categories.mailinglist.softwares=Sympa
## Lettres d'information (alternative à MailChimp)
categories.newsletter.name=Lettres d'informations
categories.newsletter.description=Générateur de lettres d'information
categories.newsletter.logo=newsletter.svg
categories.newsletter.softwares=PHPList, wassup
## Audioconférence (alternative à Discord)
categories.audioconf.name=Audioconférence
categories.audioconf.description=
categories.audioconf.logo=audioconf.svg
categories.audioconf.softwares=Mumble, MumbleWeb, Mumble Web, Wire
## Visioconférence (alternative à Skype, Hangouts, etc.)
categories.videoconf.name=Visioconférence
categories.videoconf.description=Pour faire des visio-conférences.
categories.videoconf.logo=videoconf.svg
categories.videoconf.softwares=Jitsi, Jitsi Meet, BigBlueButton, OpenMeetings, Jami, Nextcloud Talk, Galène
## Messagerie instantanée (alternative à Slack)
categories.im.name=Messagerie instantanée
categories.im.description=
categories.im.logo=im.svg
categories.im.softwares=Mattermost, RocketChat, MongooseIM, Tracim, Twake, BitlBee
## Chat IRC ou Jabber (alternative à MSN)
categories.chat.name=Chat
categories.chat.description=
categories.chat.logo=chat.svg
categories.chat.softwares=IRC, Jabber, ejabberd, Synapse, Metronome, Matrix, Element, Element Web, Riot, Prosody, MyCryptoChat, Converse, Glowing bear, BitlBee
## Forum (alternative à Discord)
categories.forum.name=Forum
categories.forum.description=
categories.forum.logo=forum.svg
categories.forum.softwares=Discourse, Flarum
## Réseau social (alternative à Facebook)
categories.socialnetwork.name=Réseau social
categories.socialnetwork.description=
categories.socialnetwork.logo=socialnetwork.svg
categories.socialnetwork.softwares=Diaspora*, Movim
## Microblogging (alternative à Twitter)
categories.microblogging.name=Microblogging
categories.microblogging.description=
categories.microblogging.logo=microblogging.svg
categories.microblogging.softwares=Mastodon, Pleroma
## Organisation d'évènements (alternative aux évènements Facebook, MeetUp, EventBrite)
categories.events.name=Organisation d'évènements
categories.events.description=
categories.events.logo=events.svg
categories.events.softwares=Mobilizon
## Gestion de groupes (alternative aux groupes Facebook)
categories.groups.name=Gestion de groupes
categories.groups.description=
categories.groups.logo=groups.svg
categories.groups.softwares=Mobilizon, Agorakit
## Gestionnaire de notifications
categories.notifications.name=Gestionnaire de notifications
categories.notifications.description=
categories.notifications.logo=notifications.svg
categories.notifications.softwares=ntfy
# Outils Internet
## Moteur de recherche (alternative à Google Search)
categories.search.name=Moteur de recherche
categories.search.description=
categories.search.logo=search.svg
categories.search.softwares=SearX
## Serveurs de jeux vidéo
categories.videogames.name=Serveurs de jeux vidéo
categories.videogames.description=
categories.videogames.logo=videogames.svg
categories.videogames.softwares=Minetest, Trivabble, Codenames Green, Terraforming Mars
## Cartographie (alternative à Google Maps, Mappy, etc.)
categories.maps.name=Cartographie
categories.maps.description=
categories.maps.logo=maps.svg
categories.maps.softwares=OpenStreetMap, GoGoCarto, uMap
## Outils de sondage (alternative à SurveyMonkey)
categories.survey.name=Sondage
categories.survey.description=
categories.survey.logo=survey.svg
categories.survey.softwares=LimeSurvey
## Outils de traduction
categories.translator.name=Outils de traduction
categories.translator.description=
categories.translator.logo=translator.svg
categories.translator.softwares=LibreTranslate, Weblate, Zanata
## Générateur de code-barres
categories.barcode.name=Générateur de code-barres
categories.barcode.description=
categories.barcode.logo=qrcode.svg
categories.barcode.softwares=LibreQR
## Raccourcisseur d'URL (alternative à Bit.ly, tinyurl, etc.)
categories.urlshrinker.name=Raccourcisseur d'URL
categories.urlshrinker.description=Pour partager des URL raccourcies.
categories.urlshrinker.logo=urlshrinker.svg
categories.urlshrinker.softwares=Yourls, LSTU, Rs-Short, Polr
## Transfert de messages ou de bouts de textes (alternative à PasteBin)
categories.bin.name=Transfert de messages ou de bouts de texte
categories.bin.description=
categories.bin.logo=bin.svg
categories.bin.softwares=PrivateBin, 0bin.net, Paste
## Gestionnaire de marques-pages / favoris (alternative à Del.icio.us, Diigo, Pearltrees, etc.)
categories.bookmarks.name=Gestionnaire de marques-pages
categories.bookmarks.description=
categories.bookmarks.logo=bookmarks.svg
categories.bookmarks.softwares=Shaarli
## Générateur de flux RSS
categories.rssgen.name=Générateur de flux RSS
categories.rssgen.description=
categories.rssgen.logo=rssgen.svg
categories.rssgen.softwares=RSS Bridge
## Agrégateur de flux RSS (alternative à Netvibes, Feedly, InoReader, etc.)
categories.rss.name=Agrégateur de flux RSS
categories.rss.description=
categories.rss.logo=rss.svg
categories.rss.softwares=Cyca, FreshRSS, Tiny Tiny RSS
## Sauvegarde de contenus web (alternative à Pocket, Instapaper, etc.)
categories.saveforlater.name=Sauvegarde de contenus web
categories.saveforlater.description=
categories.saveforlater.logo=saveforlater.svg
categories.saveforlater.softwares=Wallabag
## Gestionnaire de mots de passe (alternative à LastPass, Dashlane, etc.)
categories.password.name=Gestionnaire de mots de passe
categories.password.description=
categories.password.logo=password.svg
categories.password.softwares=Bitwarden, Vaultwarden, Nextcloud Passman
## Forge logicielle (alternative à Github)
categories.git.name=Forge logicielle
categories.git.description=Pour partager des dépôts versionnés
categories.git.logo=git.svg
categories.git.softwares=GitLab, GitLab CE,GitLabCE,Gogs,Gitea,Gitolite, Forgejo
## Mesure de statistiques (alternative à Google Analytics)
categories.metrics.name=Mesure de statistiques
categories.metrics.description=
categories.metrics.logo=metrics.svg
categories.metrics.softwares=Matomo, Open Web Analytics, Dolomon
## Proxy - Intermédiaire de relais et/ou d'anonymisation
categories.proxy.name=Proxy
categories.proxy.description=
categories.proxy.logo=proxy.svg
categories.proxy.softwares=Squid, Nitter,Invidious, Bibliogram, PeerJS Server, PeerServer, Coturn
## VPN - Réseau privé virtuel
categories.vpn.name=VPN
categories.vpn.description=
categories.vpn.logo=vpn.svg
categories.vpn.softwares=OpenVPN, tinc
# Outils de travail
## Agenda partagé (alternative à Google Agenda)
categories.calendar.name=Agenda
categories.calendar.description=
categories.calendar.logo=calendar.svg
categories.calendar.softwares=Radicale, SOgo, Nextcloud Calendar, Nextcloud, Tracim, Baïkal, Davical, InfCloud
## Rédaction collaborative (alternative à Google Docs)
categories.pad.name=Traitement de texte collaboratif
categories.pad.description=
categories.pad.logo=pad.svg
categories.pad.softwares=Etherpad, Etherpad-lite, CodiMD, Cryptpad, HedgeDoc, MyPads, Nextcloud OnlyOffice, Nextcloud Collabora Online, OnlyOffice, Collabora Online, Tracim Collabora Online, Libreto
## Tableur collaboratif (alternative à Google Sheets)
categories.calc.name=Tableur collaboratif
categories.calc.description=
categories.calc.logo=calc.svg
categories.calc.softwares=Ethercalc, Cryptpad, Nextcloud OnlyOffice, Nextcloud Collabora Online, OnlyOffice, Collabora Online
## Tableau blanc collaboratif (alternative à Stoodle)
categories.board.name=Tableau blanc collaboratif
categories.board.description=
categories.board.logo=board.svg
categories.board.softwares=Scrumblr, Whiteboard
## Présentation collaborative (alternative à Google Drive)
categories.slide.name=Présentation en ligne
categories.slide.description=
categories.slide.logo=slide.svg
categories.slide.softwares=Strut, Nextcloud OnlyOffice, Nextcloud Collabora Online, OnlyOffice, Collabora Online
## Questionnaire en ligne (alternative à Google Forms)
categories.form.name=Questionnaire en ligne
categories.form.description=
categories.form.logo=form.svg
categories.form.softwares=Yakforms
## Aide à la prise de rendez-vous (alternative à Doodle)
categories.date.name=Aide à la prise de rendez-vous
categories.date.description=
categories.date.logo=date.svg
categories.date.softwares=Framadate, OpenSondage
## Création de schémas et diagrammes (alternative à Visio)
categories.diagram.name=Création de schémas et diagrammes
categories.diagram.description=
categories.diagram.logo=diagram.svg
categories.diagram.softwares=Drawio
## Carte heuristique / mentale (alternative à Mindmeister)
categories.mindmap.name=Carte heuristique
categories.mindmap.description=
categories.mindmap.logo=mindmap.svg
categories.mindmap.softwares=WiseMapping, MyMind, My Mind
## Gestionnaire de tâches (alternative à Google Tasks)
categories.tasks.name=Gestionnaire de tâches
categories.tasks.description=
categories.tasks.logo=tasks.svg
categories.tasks.softwares= Taskwarrior
## Prise de note (alternative à Evernote, OneNote, etc.)
categories.notes.name=Prise de note
categories.notes.description=
categories.notes.logo=notes.svg
categories.notes.softwares=Turtl, Tracim
## Tableau Kanban (alternative à Trello, Asana, etc.)
categories.kanbanboard.name=Tableau Kanban
categories.kanbanboard.description=
categories.kanbanboard.logo=kanban.svg
categories.kanbanboard.softwares=Kanboard, Wekan, Nullboard
## Outils de prise de décision (alternative à Klaxoon)
categories.decision.name=Outils de prise de décision
categories.decision.description=
categories.decision.logo=decision.svg
categories.decision.softwares=Loomio, VotAR
## Gestionnaire de signature électronique
categories.electronicsignature.name=Gestionnaire de signature électronique
categories.electronicsignature.description=
categories.electronicsignature.logo=esignature.svg
categories.electronicsignature.softwares=Signature PDF
## Plateforme de formation / LMS
categories.lms.name=Plateforme de formation / LMS (Learning Management System)
categories.lms.description=
categories.lms.logo=lms.svg
categories.lms.softwares=Moodle, Scenarii, YesWiki, Open edX
# Services de partage de fichiers
## Stockage / partage de documents (alternative à Dropbox, Google Drive, OneDrive, etc.)
categories.cloud.name=Stockage/ partage de documents
categories.cloud.description=
categories.cloud.logo=cloud.svg
categories.cloud.softwares=Nextcloud, Owncloud, Seafile, Tracim, Minio, ProFTPD
## Partage temporaire de fichiers (alternative à WeTransfer, DropSend)
categories.temporaryfilesharing.name=Partage temporaire de fichiers
categories.temporaryfilesharing.description=Pour partager des fichiers de façon temporaire.
categories.temporaryfilesharing.logo=temporaryfilesharing.svg
categories.temporaryfilesharing.softwares=Firefox Send,FirefoxSend, Lufi, FileToLink, File2Link, Plik
## Stockage/partage d'images (alternative à Img.ur)
categories.pic.name= Stockage et partage d'images
categories.pic.description=
categories.pic.logo=pic.svg
categories.pic.softwares=Lutim, Pixelfed
## Stockage/partage d'albums de photos (alternative à Google Photos, Flickr, etc.)
categories.gallery.name= Stockage et partage d'albums photos
categories.gallery.description=
categories.gallery.logo=gallery.svg
categories.gallery.softwares=Piwigo, Mediagoblin
## Diffusion de fichiers vidéos (alternative à YouTube, DailyMotion, Viméo, etc.)
categories.tube.name= Diffusion de fichiers vidéo
categories.tube.description=
categories.tube.logo=tube.svg
categories.tube.softwares=PeerTube, Mediagoblin
## Diffusion de fichiers audio (alternative à Soundcloud)
categories.podcast.name= Diffusion de fichiers audio
categories.podcast.description=
categories.podcast.logo=podcast.svg
categories.podcast.softwares=Funkwhale, Mediagoblin
## Diffusion en direct de flux audio et vidéo
categories.streaming.name= Diffusion en direct de flux audio et vidéo
categories.streaming.description=
categories.streaming.logo=streaming.svg
categories.streaming.softwares=PeerTube, Icecast
## Hébergement de sites web / blogs / capsules
categories.website.name= Hébergement de sites web / blogs / capsules
categories.website.description=
categories.website.logo=website.svg
categories.website.softwares=Wordpress, Joomla!, Plume, SPIP, Grav, PrettyNoemie CMS, Write Freely, Vger, ISPconfig, Garage, Apache Httpd, Nginx, Twins
## Hébergement d'une plateforme de commentaires (alternative à Disqus)
categories.commenting.name=Hébergement d'une plateforme de commentaires
categories.commenting.description=
categories.commenting.logo=commenting.svg
categories.commenting.softwares=Commento
## Hébergement de wikis
categories.wiki.name=Wiki
categories.wiki.description=Modification collaborative de texte
categories.wiki.logo=wiki.svg
categories.wiki.softwares=Dokuwiki, Mediawiki
## Hébergement d'une ferme de wikis
categories.wikifarm.name= Hébergement d'une ferme de wikis
categories.wikifarm.description=
categories.wikifarm.logo=wikifarm.svg
categories.wikifarm.softwares=YesWiki, Bookstack
# Services de gestion
## Gestionnaire de finances personnelles
categories.finance.name=Gestionnaire de finances personnelles
categories.finance.description=
categories.finance.logo=finance.svg
categories.finance.softwares=Kresus, IHateMoney
## Gestionnaire de facturation / paiement
categories.billing.name=Gestionnaire de facturation / paiement
categories.billing.description=
categories.billing.logo=billing.svg
categories.billing.softwares=
## Progiciel de Gestion Intégré (PGI, ERP en anglais)
categories.erp.name=Progiciel de Gestion Intégré
categories.erp.description=
categories.erp.logo=erp.svg
categories.erp.softwares=Dolibarr, Odoo, Diacamma
## Progiciel de Gestion associative
categories.asso.name=Progiciel de Gestion associative
categories.asso.description=
categories.asso.logo=association.svg
categories.asso.softwares=Bénévalibre, Galette, Structura, Garradin, Paheko
## Gestionnaire de tickets pour le support technique
categories.ticketing.name=Gestionnaire de tickets pour le support technique
categories.ticketing.description=
categories.ticketing.logo=ticketing.svg
categories.ticketing.softwares=Mantis, MantisBT, Redmine, Gitlab, Gitea, RT, Request Tracker, OSTicket, Freescout
# Outils d'administration système
## Outils de monitoring
categories.monitoring.name=Outils de monitoring
categories.monitoring.description=
categories.monitoring.logo=monitoring.svg
categories.monitoring.softwares=Healthchecks, Monitorix, Gotify, naemon
## Outils d'automatisation
categories.automated.name=Outils d'automatisation
categories.automated.description=
categories.automated.logo=automated.svg
categories.automated.softwares=CyberChef, Buildbot
## Administration de machines virtuelles
categories.vps.name=Administration de machines virtuelles
categories.vps.description=
categories.vps.logo=vps.svg
categories.vps.softwares=Ganeti
## Fournisseur de machines physiques ou virtuelles
categories.server.name= Fournisseur de comptes Shell, machines physiques ou virtuelles
categories.server.description=
categories.server.logo=server.svg
categories.server.softwares=OpenSSH, Docker, KVM, QEMU, libvirt, VirtualBox, Proxmox
## Fournisseur de stockage (accès à un support de stockage, sans faire tourner des applications)
categories.storage.name= Fournisseur de stockage
categories.storage.description=
categories.storage.logo=storage.svg
categories.storage.softwares=MinIO, BorgBackup, borgmatic, Garage, ProFTPD, rsync
## Fournisseur de bases de données
categories.database.name= Fournisseur de bases de données
categories.database.description=
categories.database.logo=database.svg
categories.database.softwares=MariaDB, PostgreSQL, MongoDB, SQLite, Redis, CouchDb, Cassandra
## Résilience - Outils de réplication et de backup
categories.resilience.name=Outils de réplication et de backup
categories.resilience.description=
categories.resilience.logo=resilience.svg
categories.resilience.softwares=MariaDB, PostgreSQL, rsync
## Outils de DNS
categories.dns.name=Outils de DNS
categories.dns.description=
categories.dns.logo=dns.svg
categories.dns.softwares=bind9

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2020-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -116,6 +116,11 @@ public class CrawlCache
}
}
/**
* Gets the directory.
*
* @return the directory
*/
public File getDirectory()
{
return this.directory;
@ -147,8 +152,11 @@ public class CrawlCache
}
/**
* @return
* Restore crawl journal.
*
* @return the crawl journal
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public CrawlJournal restoreCrawlJournal() throws IOException
{
@ -231,7 +239,7 @@ public class CrawlCache
}
else
{
logger.info("CatGeneratoring from {}", url);
logger.info("Restoring logo from {}", url);
File logoFile = restoreFile(url);
if (logoFile == null)
{
@ -261,9 +269,13 @@ public class CrawlCache
}
/**
* Restore to properties.
*
* @param url
* @return
* the url
* @return the path properties
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public PathProperties restoreToProperties(final URL url) throws IOException
{
@ -446,10 +458,11 @@ public class CrawlCache
}
/**
* Gets the journal URL.
* Gets the crawl journal URL.
*
* @return the journal URL
* @return the crawl journal URL
* @throws MalformedURLException
* the malformed URL exception
*/
public static URL getCrawlJournalURL() throws MalformedURLException
{

View file

@ -161,7 +161,7 @@ public class CrawlJournalFile
PrintWriter out = null;
try
{
out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8));
write(out, source);
}
finally

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2021 Christian Pierre MOMON <christian@momon.org>
* Copyright (C) 2021-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of StatoolInfos, simple service statistics tool.
*
@ -34,6 +34,8 @@ public class CrawlLog
*
* @param url
* the url
* @param parentUrl
* the parent url
* @param status
* the status
*/
@ -44,6 +46,11 @@ public class CrawlLog
this.status = status;
}
/**
* Gets the parent url.
*
* @return the parent url
*/
public URL getParentUrl()
{
return this.parentUrl;
@ -71,11 +78,21 @@ public class CrawlLog
return result;
}
/**
* Gets the status.
*
* @return the status
*/
public CrawlStatus getStatus()
{
return this.status;
}
/**
* Gets the url.
*
* @return the url
*/
public URL getUrl()
{
return this.url;

Some files were not shown because too many files have changed in this diff Show more