Split and huge refactoring from StatoolInfos to StatoolInfosWeb.

This commit is contained in:
Christian P. MOMON 2024-08-09 02:01:43 +02:00
parent 9227238b25
commit 143df42993
653 changed files with 10392 additions and 53508 deletions

View file

@ -1,36 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<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"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="lib/commons-codec-1.8.jar" sourcepath="lib/commons-codec-1.8-sources.jar"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="test"/>
<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.web"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/>
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
<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/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-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/Logs/slf4j-api-1.7.32.jar" sourcepath="lib/Logs/slf4j-api-1.7.32-sources.jar"/>
<classpathentry kind="lib" path="lib/Logs/log4j-api-2.17.1.jar" sourcepath="lib/Logs/log4j-api-2.17.1-sources.jar"/>
<classpathentry kind="lib" path="lib/Logs/log4j-core-2.17.1.jar" sourcepath="lib/Logs/log4j-core-2.17.1-sources.jar"/>
<classpathentry kind="lib" path="lib/Logs/log4j-slf4j-impl-2.17.1.jar" sourcepath="lib/Logs/log4j-slf4j-impl-2.17.1-sources.jar"/>
<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="output" path="bin"/>
<classpathentry combineaccessrules="false" kind="src" path="/StatoolInfos"/>
<classpathentry combineaccessrules="false" kind="src" path="/kiss4web"/>
<classpathentry kind="output" path="build/classes"/>
</classpath>

4
.gitignore vendored
View file

@ -1,4 +1,2 @@
/bin
/build
/dist
/build/
*~

View file

@ -1,17 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>StatoolInfos</name>
<name>StatoolInfosWeb</name>
<comment></comment>
<projects>
<project>kiss4web</project>
<project>StatoolInfos</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
@ -24,7 +26,8 @@
<natures>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
</natures>
</projectDescription>

12
.settings/.jsdtscope Normal file
View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry excluding="**/node_modules/*|**/*.min.js|**/bower_components/*" kind="src" path="webapp"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
<attributes>
<attribute name="hide" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
<classpathentry kind="output" path=""/>
</classpath>

View file

@ -1,59 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<project>
<owner></owner>
<copyright><![CDATA[Copyright (C) 2013, 2014 Christian Pierre MOMON, DEVINSY
This file is part of SikevaDB, simple key value database.
SikevaDB 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.
SikevaDB 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 SikevaDB. If not, see <http://www.gnu.org/licenses/>.]]></copyright>
<header contentId="org.eclipse.pde.fragmentManifest" excluded="true" />
<header contentId="org.eclipse.pde.pluginProperties" excluded="true" />
<header contentId="org.eclipse.pde.productFile" excluded="true" />
<header contentId="org.eclipse.jst.j2ee.appclientDD" excluded="true" />
<header contentId="org.eclipse.ant.core.antBuildFile" excluded="true" />
<header contentId="org.eclipse.core.runtime.xml" postBlankLines="0" lineFormat="false" preserveFirstLine="true">
<beginLine><![CDATA[<!--]]></beginLine>
<linePrefix><![CDATA[ ]]></linePrefix>
<endLine><![CDATA[-->]]></endLine>
<firstLinePattern><![CDATA[<\?xml version=.*\?>]]></firstLinePattern>
</header>
<header contentId="org.eclipse.pde.simpleCheatSheet" excluded="true" />
<header contentId="org.eclipse.jst.j2ee.webDD" excluded="true" />
<header contentId="org.eclipse.pde.compositeCheatSheet" excluded="true" />
<header contentId="org.eclipse.pde.schema" excluded="true" />
<header contentId="org.eclipse.pde.tocFile" excluded="true" />
<header contentId="org.eclipse.jst.j2ee.earDD" excluded="true" />
<header contentId="org.eclipse.pde.ctxHelpFile" excluded="true" />
<header contentId="org.eclipse.jdt.core.JARManifest" excluded="true" />
<header contentId="org.eclipse.pde.categoryManifest" excluded="true" />
<header contentId="org.eclipse.pde.buildProperties" excluded="true" />
<header contentId="org.eclipse.ui.views.log.log" excluded="true" />
<header contentId="org.eclipse.pde.siteManifest" excluded="true" />
<header contentId="org.eclipse.pde.targetFile" excluded="true" />
<header contentId="org.eclipse.pde.bundleManifest" excluded="true" />
<header contentId="org.eclipse.jst.j2ee.connectorDD" excluded="true" />
<header contentId="org.eclipse.pde.pluginManifest" excluded="true" />
<header contentId="org.eclipse.core.runtime.text" postBlankLines="0" lineFormat="true" preserveFirstLine="false">
<beginLine><![CDATA[#-------------------------------------------------------------------------------]]></beginLine>
<linePrefix><![CDATA[# ]]></linePrefix>
<endLine><![CDATA[#-------------------------------------------------------------------------------]]></endLine>
</header>
<header contentId="org.eclipse.jst.j2ee.ejbDD" excluded="true" />
<header contentId="org.eclipse.pde.featureManifest" excluded="true" />
<header contentId="org.eclipse.jdt.core.javaSource" postBlankLines="0" lineFormat="false" preserveFirstLine="false">
<beginLine><![CDATA[/**]]></beginLine>
<linePrefix><![CDATA[ * ]]></linePrefix>
<endLine><![CDATA[ */]]></endLine>
</header>
</project>

View file

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

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
@ -22,19 +22,28 @@ 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.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 +53,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 +63,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 +74,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 +126,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
@ -151,13 +166,6 @@ org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_ini
org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case=insert
@ -191,6 +199,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 +291,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 +375,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 +407,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 +417,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=true
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_field_access=false
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.correct_indentation=true
sp_cleanup.convert_to_switch_expressions=false
sp_cleanup.correct_indentation=false
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_local_variable_final=true
sp_cleanup.make_parameters_final=false
sp_cleanup.make_private_fields_final=true
sp_cleanup.make_type_abstract_if_missing_method=false
sp_cleanup.make_variable_declarations_final=true
sp_cleanup.make_variable_declarations_final=false
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.on_save_use_additional_actions=true
sp_cleanup.objects_equals=false
sp_cleanup.on_save_use_additional_actions=false
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=true
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
@ -127,29 +245,56 @@ sp_cleanup.remove_trailing_whitespaces_all=true
sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
sp_cleanup.remove_unnecessary_array_creation=false
sp_cleanup.remove_unnecessary_casts=true
sp_cleanup.remove_unnecessary_nls_tags=true
sp_cleanup.remove_unused_imports=true
sp_cleanup.remove_unnecessary_nls_tags=false
sp_cleanup.remove_unused_imports=false
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.sort_members=true
sp_cleanup.single_used_field=false
sp_cleanup.sort_members=false
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=true
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
sp_cleanup.use_blocks=false
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_lambda=true
sp_cleanup.use_parentheses_in_expressions=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_string_is_blank=false
sp_cleanup.use_this_for_non_static_field_access=false
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
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,5 +0,0 @@
XDOCLETBUILDERACTIVE=false
XDOCLETHOME=
XDOCLETUSEGLOBAL=true
XDOCLETVERSION=1.2.1
eclipse.preferences.version=1

View file

@ -1,6 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="SikevaDB">
<wb-resource deploy-path="/" source-path="/src"/>
<wb-resource deploy-path="/" source-path="/test"/>
<wb-module deploy-name="StatoolInfosWeb">
<wb-resource deploy-path="/" source-path="/webapp" tag="defaultRootSource"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/test"/>
<dependent-module archiveName="SikevaDB.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/StatoolInfos/StatoolInfos">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module archiveName="kiss4web.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/kiss4web/kiss4web">
<dependency-type>uses</dependency-type>
</dependent-module>
<property name="context-root" value="StatoolInfosWeb"/>
<property name="java-output-path" value="/StatoolInfosWeb/build/classes"/>
</wb-module>
</project-modules>

View file

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

View file

@ -0,0 +1 @@
org.eclipse.wst.jsdt.launching.baseBrowserLibrary

View file

@ -0,0 +1 @@
Window

View file

@ -1,125 +0,0 @@
# 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]
Changes for metrics:
- …
Changes for web building:
- …
## [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

@ -1,85 +0,0 @@
# Concepts de StatoolInfos
## Principe générale
StatoolInfos s'appuie sur StatoolInfos qui utilise des fichiers publics disponibles via des liens web :
- 1 fichier web public pour décrire la fédération ;
- 1 fichier web public par organisation membre de la fédération ;
- 1 fichier web public par service des organisations.
Chaque fichier web public étant acessible via un lien web, chaque fichier public peut se trouver sur un site web différent.
Chaque fichier web public contient des informations descriptives et potentiellement des métriques d'activité.
Il suffit de récupérer tous les fichiers web publics afin de pouvoir générer des pages web, des statistiques, des graphiques…
## Format des fichiers web publics
Dans StatoolInfos, ce sont des fichiers **properties**, c'est à dire ne contenant que des lignes de texte au format `chemin=valeur`.
Un **chemin** consiste en une suite de mots séparés par des points : `organization.name=Chapril`.
Les lignes vides et les lignes commençant par un `#` sont ignorées.
Exemple :
```
# [Organisation]
organization.name=Chapril
organization.description=Chapril est le chaton de l\'April.
organization.website=https://www.chapril.org/
organization.logo=
organization.owner.name=April
organization.owner.website=https://www.april.org/
organization.owner.logo=
organization.geography=
organization.contact.url=https://www.chapril.org/contact.xhtml
organization.contact.email=contact@chapril.org
organization.legal.url=
organization.technical.url=
organization.startDate=
organization.endDate=
```
## Notion de section
Le premier mot d'un chemin est appelé la **section**. Donc chaque fichier web public est une liste de sections.
Suivant qu'il décrive la fédération, une organisation ou un service, le fichier web public ne contient pas les mêmes sections :
- Fédération = file + federation + subs + metrics
- Organisation = file + organization + subs + metrics
- Service = file + service + host + software + metrics
La liste des chemins de chaque section est normalisée dans une ontologie.
## Des données simples
Dans lignes de **properties**, les valeurs doivent être le plus simple possible.
Voici une liste de types simples :
| Type | Description | Modèle | Exemple |
| ------ | ------ | ------ | ------ |
| 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 |
| NUMERIC | Une valeur numérique | STU | -1234.567 |
| NUMERICS | Une liste de valeurs numériques avec séparateurs | STU | 12.34;56.78;9 |
| SEPARATOR | Un caractère séparateur | `;` ou `,` | Foo;foo;;foo |
| STATUS | Un statut. | ON/MAINTENANCE/DOWN/OFF/DRAFT | ON |
| STRING | Une chaîne de caractères quelconques. Peut contenir des `<br/>` et des `\n`. | ^.*$ | Foo is foo. |
| URL | Un lien web | ^https?://.+\..+/+$ | https://foo.foo/ |
| VALUE | Une chaîne de caractère sans séparateur | Foo |
| VALUES | Liste de valeurs de type VALUE avec séparateurs | STU | foo1;foo2;foo3 |
| WEEKS | Liste de 52 valeurs numériques avec séparateurs | STU | 1;2;3;4;5;…;51;52 |
Note for list:
* une valeur vide ou null est autorisée ;
* si une liste de valeurs contient moins de valeurs qu'attendu alors les valeurs manquantes sont considérées comme vides ou nulles.

View file

@ -1,203 +0,0 @@
# StatoolInfos
StatoolInfos is…
Data are stored in property files. Each entry line uses key defined by convention.
## Primitive Types
| Type | Description | Pattern | Example |
| ------ | ------ | ------ | ------ |
| DATE | A date in ISO format | ISO_DATE | 2020-07-06 |
| DATETIME | A date and time in ISO format | ISO_DATETIME | 2020-07-06T14:23:20 |
| DAYS | List of 366 NUMERIC separated by SEPARATOR | STU | 1;2;3;4;5;…;365 |
| DECIMAL_DEGREE | Longitude or latitidue value | ^[+-]?\\d+[,\\.]\\d{1,8}$ | -12,3456 |
| EMAIL | An electronic address. | ^.+@.+$ | christian@momon.org |
| MONTHS | List of 12 NUMERIC separated by SEPARATOR | STU | 1;2;3;4;5;6;7;9;10;11;12 |
| NUMERIC | A numeric value | STU | -1234.567 |
| NUMERICS | List of NUMERIC separated by SEPARATOR | STU | 12.34;56.78;9 |
| SEPARATOR | The default separator character | `;` | Foo;foo;;foo |
| STATUS | A status. | ON/MAINTENANCE/DOWN/OFF/DRAFT | ON |
| STRING | Foo string. With `<br/>` or `\n`. | ^.*$ | Foo is foo. |
| URL | A web link | ^https?://.+\..+/+$ | https://foo.foo/ |
| VALUE | String not containg SEPARATOR character | Foo |
| VALUES | List of VALUE separated by SEPARATOR | STU | foo1;foo2;foo3 |
| WEEKS | List of 52 NUMERIC separated by SEPARATOR | STU | 1;2;3;4;5;…;51;52 |
Note for list:
* empty value or null value are available;
* shorter list designs empty values.
## Sections
### Federation section
| Field | Type | Mandatory | Description | Example |
| ------ | ------ | ------| ------ | ------ |
| federation.name | STRING | Yes | Name of federation | CHATONS |
| federation.description | STRING | Yes | Desciption of the federation | Collectif CHATONS |
| federation.website | URL | Yes | Official website URL of the federation | https://www.chatons.org/ |
| federation.logo | URL | Wished | URL of the organization logo | https://chatons.org/logo_chatons_v2.png |
| federation.favicon | URL | Wished | URL of the organization favicon | https://chatons.org/sites/default/files/chatons_logo_tiny.png |
| federation.contact.url | URL | No | Contact webpage of the federation | https://www.chatons.org/contact |
| federation.contact.email | EMAIL | Yes | Contact email of the federation | contact@chatons.org |
| federation.legal.url | URL | No | Legal webpage of the federation | https://www.chatons.org/page/mentions-l%C3%A9gales |
| federation.documentation.url | URL | No | Documentation webpage of the federation | https://wiki.chatons.org/ |
| federation.documentation.technical.url | URL | No | Technical documentation webpage of the federation | |
| federation.documentation.tutorial.url | URL | No | Tutorial documentation webpage of the federation | |
| federation.birthdate | DATE | No | Date of birth of the federation | 09/02/2016 |
### File section
| Field | Type | Mandatory | Description | Example |
| ------ | ------ | ------ | ------ | ------ |
| file.class | Federation/Organization/Service/Device | Yes | Class of the content | Service |
| file.protocol | STRING | Yes | Version of the StatoolInfos schema | StatoolInfos-0.1 |
| file.datetime | DATETIME | Yes | Date and time of the file build. | 2020-07-06T14:23:20 |
| file.generator | STRING | Yes | Generator of the file. | Cpm hands |
| file.url | URL | Yes | Origin URL of the file. | Cpm hands |
### Host section (dratf)
| Field | Type | Mandatory | Description | Example |
| ------ | ------ | ------ | ------ | ------ |
| host.name | STRING | Yes | Name of the host | foo |
| host.provider | STRING | Yes | Provider of the host | foo |
| host.description | STRING | Wished | Description of the host | The virtual machine called foo |
| host.type | VPS / CLOUD / LOCATEDSERVER / HOSTSERVER / HOMESERVER / RASPERRY | Wished | Type of the host | HOMESERVER |
| host.country.name | STRING | Wished | Country name of the host | France |
| host.country.code | STRING | Wished | ISO country code of the host | FR |
### Metrics section
| Field | Type | Mandatory | Description | Example |
| ------ | ------ | ------ | ------ | ------ |
| metrics.foo1.foo2.name | STRING | Wished | Name of metric | visitor Ip |
| metrics.foo1.foo2.description | STRING | Wished | Description of metric | Nombre d'ip ayant visitées |
| metrics.foo1.foo2.2020 | NUMERIC | No | Count of foo1.foo2 | 123 |
| metrics.foo1.foo2.2020.months | MONTHS | No | Month count of foo1.foo2 for year 2020 | 100;200;300;;;; |
| metrics.foo1.foo2.2020.weeks | WEEKS | No | Week count of foo1.foo2 for year 2020 | 100;200;300;;;; |
| metrics.foo1.foo2.2020.days | DAYS | No | Day count of foo1.foo2 for year 2020 | 100;200;300;;;; |
Examples:
```
metrics.visitors.ipv4.2020=123
metrics.visitors.ipv6.2020=123
metrics.visitors.total.2020=246
metrics.visitors.ipv4.2020.months=12;34;56;
metrics.visitors.ipv6.2020.months=12;34;56;
metrics.visitors.total.2020.months=24;68;112;
metrics.visitors.ipv4.2020.weeks=123;456;
metrics.visitors.ipv6.2020.weeks=123;456;
metrics.visitors.total.2020.weeks=246;912;
metrics.visitors.ipv4.2020.days=123;456;
metrics.visitors.ipv6.2020.days=123;456;
metrics.visitors.total.2020.days=246;912;
```
### Organization section
| Field | Type | Mandatory | Description | Example |
| ------ | ------ | ------ | ------ | ------ |
| organization.name | STRING | Yes | Name of the organization | Chapril |
| organization.description | STRING | Wished | Description of the organization | Chapril est le chaton de l'April |
| organization.website | URL | Y | Official website of the organization | httsp://www.chapril.org/ |
| organization.logo | URL | Wished | Logo URL of the organization | https://date.chapril.org/Chapril-banner/v1/chapril-logo-small.png |
| organization.favicon | URL | Wished | Favicon URL of the organization | https://date.chapril.org/favicon.png |
| organization.owner.name | STRING | No | Name of the organization owner | April |
| organization.owner.website | URL | No | Official website of the organization owner | https://www.april.org/ |
| organization.owner.logo | URL | No | Logo URL of the organization owner | https://www.april.org/sites/default/themes/zen_april/logo.png |
| organization.owner.favicon | URL | No | Favicon URL of the organization owner | https://www.april.org/sites/default/themes/zen_april/favicon.ico |
| organization.contact.url | URL | Wished | Contact webpage of the organization | https://www.chapril.org/contact.html |
| organization.contact.email | EMAIL | Contact email of the organization | contact@chapril.org |
| organization.legal.url | URL | Wished | Legal webpage of the organization | https://www.chapril.org/cgu.html |
| organization.documentation.technical.url | URL | Wished | Technical documentation webpage of the organization | https://admin.chapril.org/ |
| organization.birthdate | DATE | Wished | Birth date of the organization | 08/11/2018 |
### Service section
| Field | Type | Mandatory | Description | Example |
| ------ | ------ | ------ | ------ | ------ |
| service.name | STRING | Yes | Service name. | MumbleChaprilOrg |
| service.description | STRING | Yes | Service description. | Service libre de conférence audio |
| service.organization.name | STRING | Yes | Organization name. | Chapril |
| service.website.url | URL | Wished | Website of the service | https://mumble.chapril.org/ |
| service.legal.url | URL | Wished | URL | Legal webpage of the organization | https://www.chapril.org/cgu.html |
| service.documentation.technical.url | URL | No | Technical documentation webpage of the service | https://admin.chapril.org/doku.php?id=admin:services:mumble.chapril.org |
| service.documentation.tutorial.url | URL | No | Tutorial documentation webpage of the service | https://www.chapril.org/Mumble.html |
| service.contact.url | URL | Wished | Contact webpage of the service | contact@chapril.org |
| service.contact.email | EMAIL | Wished | Contact email of the service | mumble-support@chapril.org |
| service.birthdate | DATETIME | Wished | Birth date of the service | 20/03/2020 |
| service.deathdate | DATETIME | No | Death date of the service | |
| service.status | STATUS | Yes | Service status. | ON |
| service.registration | None;Free;Member;Client | Yes | Registration requirement | Free; Member|
### Subs section
| Field | Type | Mandatory | Description | Example |
| ------ | ------ | ------ | ------ | ------ |
| subs.foo | URL | No | URL of a sub node. | Firefox Send |
Example:
```
subs.datechaprilorg=https://date.chapril.org/.well-known/datechaprilorg.properties
subs.pastechaprilorg=https://paste.chapril.org/.well-known/pastechaprilorg.properties
subs.dropchaprilorg=https://drop.chapril.org/.well-known/dropchaprilorg.properties
```
### Software section
| Field | Type | Mandatory | Description | Example |
| ------ | ------ | ------ | ------ | ------ |
| software.name | STRING | Yes | Name of the software | Firefox Send |
| software.website | URL | Yes | Offical website of the software | https://send.firefox.com/ |
| software.license.url | URL | Yes | Webpage of the software license | https://forge.april.org/Chapril/drop.chapril.org-firefoxsend/src/branch/chapril-v3.0.21/LICENSE |
| software.license.name | STRING | Yes | Name of the license | Mozilla Public License Version 2.0 |
| software.version | STRING | Yes | Version of the software | Chapril-3.0.21 |
| software.source.url | URL | Yes | URL of the software source | https://forge.april.org/Chapril/drop.chapril.org-firefoxsend/ |
## Classes
### Federation class
Federation = file + federation + subs + metrics
### Organization class
Organization = file + organization + subs + metrics
### Service class
Service = file + service + host + software + metrics + extras
### Device class
Device = file + device + system
# Draft
| Field | Type | Mandatory | Description |
| ------ | ------ | ------ | ------ |
| services.* | URL | Y | URL of the Statool file of the service |
| Field | Type | Mandatory | Description |
| ------ | ------ | ------ | ------ |
| services.urls.* | URL | Y | URL of services |

661
LICENSE
View file

@ -1,661 +0,0 @@
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<http://www.gnu.org/licenses/>.

View file

@ -1,281 +0,0 @@
# Section « File »
Cette section regroupe des informations sur le fichier *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é).
file.datetime = 2020-07-06T14:23:20
# Nom du générateur du fichier (type STRING, recommandé).
file.generator = Christian avec ses doigts
```
# Section « Federation »
Cette section regroupe des informations sur la fédération.
```
# [Federation]
# Nom de la fédération (type STRING, obligatoire).
federation.name= CHATONS
# Description de la fédération (type STRING, recommandé).
federation.description = CHATONS est le Collectif des Hébergeurs Alternatifs, Transparents, Ouverts, Neutres et Solidaires.
# Lien du site web de la fédération (type URL, recommandé).
federation.website = https://www.chatons.org/
# Lien du logo de la fédération (type URL, recommandé).
federation.logo = https://chatons.org/logo_chatons_v2.png
# Lien du favicon de la fédération (type URL, recommandé).
federation.favicon = https://chatons.org/sites/default/files/chatons_logo_tiny.png
# Lien de la page web de contact de la fédération (type URL, recommandé).
federation.contact.url = https://www.chatons.org/contact
# Courriel de contact de la fédération (type EMAIL, recommandé).
federation.contact.email = contact@chatons.org
# Lien de la page web des mentions légales de la fédération (type URL, recommandé).
federation.legal.url = https://www.chatons.org/page/mentions-l%C3%A9gales
# Lien de la documentation web de la fédération (type URL, recommandé).
federation.documentation.url = https://wiki.chatons.org/
# Lien de la documentation technique de la fédération (type URL, recommandé).
federation.documentation.technical.url =
# Lien des tutoriels web de la fédération (type URL, recommandé).
federation.documentation.tutorial.url =
# Date de naissance de la fédération (type DATE, recommandé).
federation.birthdate = 09/02/2016
```
# Section « Organisation »
Cette section regroupe des informations sur l'organisation.
```
# [Organisation]
# Nom de l'organisation (type STRING, obligatoire).
organization.name = Chapril
# Description de l'organisation (type STRING, recommandé).
organization.description = Chapril est le chaton de l'April
# Lien du site web de l'organisation (type URL, recommandé).
organization.website = httsp://www.chapril.org/
# Lien du logo de l'organisation (type URL, recommandé).
organization.logo = https://date.chapril.org/Chapril-banner/v1/chapril-logo-small.png |
# Lien du favicon de l'organisation (type URL, recommandé).
organization.favicon = https://date.chapril.org/favicon.png
# Nome du propriétaire de l'organisation (type STRING, optionnel).
organization.owner.name = April
# Lien du site web du propriétaire de l'organisation (type URL, optionnel).
organization.owner.website = https://www.april.org/
# Lien du logo du propriétaire de l'organisation (type URL, optionnel).
organization.owner.logo = https://www.april.org/sites/default/themes/zen_april/logo.png
# Lien du favicon du propriétaire de l'organisation (type URL, optionnel).
organization.owner.favicon = https://www.april.org/sites/default/themes/zen_april/favicon.ico
# Lien de la page web de contact de l'organisation (type URL, recommandé).
organization.contact.url = https://www.chapril.org/contact.html
# Courriel de contact de l'organisation (type EMAIL, recommandé).
organization.contact.email = contact@chapril.org
# Lien de la page des mentions légales de l'organisation (type URL, recommandé).
organization.legal.url = https://www.chapril.org/cgu.html
# Lien de la documentation technique de l'organisation (type URL, recommandé).
organization.documentation.technical.url = https://admin.chapril.org/
# Date de création de l'organisation (type DATE, recommandé).
organization.birthdate = 08/11/2018
# Date de fermeture de l'organisation (type DATE, recommandé).
organization.deathdate = 08/11/2018
```
# Section « service »
Cette section regroupe des informations sur un service.
```
# [Service]
# Nom du service (type STRING, obligatoire).
service.name = MumbleChaprilOrg
# Description du service (type STRING, recommandé).
service.description = Service libre de conférence audio
# Lien du site web du service (type URL, recommandé).
service.website = https://mumble.chapril.org/
# Lien de la page web des mentions légales du service (type URL, recommandé).
service.legal.url = https://www.chapril.org/cgu.html
# Lien de la documentation web du service (type URL, recommandé).
service.documentation.technical.url = https://admin.chapril.org/doku.php?id=admin:services:mumble.chapril.org
# Lien des aides web pour le service (type URL, recommandé).
service.documentation.tutorial = https://www.chapril.org/Mumble.html
# Lien de la page de support du service (type URL, recommandé).
service.contact.url = https://www.chapril.org/contact.html
# Courriel du support du service (type EMAIL, recommandé).
service.contact.email = mumble-support@chapril.org
# Date d'ouverture du service (type DATE, recommandé).
service.birthdate = 20/03/2020 |
# Date de fermture du service (type DATE, optionnel).
service.deathdate =
# Statut du service (type STATUS, obligatoire).
service.status = ON
# Inscriptions requises pour utiliser le service (parmi None;Free;Member;Client, obligatoire).
service.registration = Free,Member
```
# Section « Software »
Cette section regroupe des information sur le logiciel utilisé par un service.
```
# [Software]
# Nom du logiciel (type STRING, obligatoire).
software.name = Firefox Send
# Lien du site web du logiciel (type URL, recommandé).
software.website = https://send.firefox.com/
# Lien web vers la licence du logiciel (type URL, obligatoire).
software.license.url = https://forge.april.org/Chapril/drop.chapril.org-firefoxsend/src/branch/chapril-v3.0.21/LICENSE
# Nom de la licence du logiciel (type STRING, obligatoire).
software.license.name = Mozilla Public License Version 2.0
# Version du logiciel (type STRING, recommandé).
software.version = Chapril-3.0.21
# Lien web vers les sources du logiciel (type URL, recommandé).
software.source.url = https://forge.april.org/Chapril/drop.chapril.org-firefoxsend/
```
# Section « Host » (expérimental)
Cette section regroupe des informations sur l'hébergeur.
```
# [Host]
# Nom de l'hébergeur (type STRING, obligatoire).
host.name = Foo
#
host.provider =
# Desription de l'hébergeur (type STRING, recommandé).
host.description =
# Type d'hébergement (un parmi VPS / CLOUD / LOCATEDSERVER / HOSTSERVER / HOMESERVER / RASPERRY, recommandé).
host.type =
# Pays de l'hébergeur (type STRING, recommandé).
host.country.name = France
# Code pays de l'hébergeur (type STRING, recommandé).
host.country.code = FR
```
# Section « Subs »
Cette section regroupe des liens vers des entités complémentaires.
Chaque chemin doit être différent mais pas nécessairement signifiant.
```
# [Subs]
# Un lien vers un fichier properties complémentaire (type URL, optionnel).
subs.foo = https://date.chapril.org/.well-known/datechaprilorg.properties
```
Exemple :
```
subs.01 = https://date.chapril.org/.well-known/datechaprilorg.properties
subs.07 = https://paste.chapril.org/.well-known/pastechaprilorg.properties
subs.dropchaprilorg = https://drop.chapril.org/.well-known/dropchaprilorg.properties
```
# Section « Metrics »
Cette section regroupe des informations de métrologie.
```
# [Metrics]
# Nom du métrique (type STRING, recommandé).
metrics.http.total.name = Nombre total de requêtes HTTP
# Description du métriques (type STRING, recommandé).
metrics.http.total.description = Somme des requêtes HTTP ipv4 et ipv6.
# Métrique à valeur anuelle (type NUMERIC, optionnel).
metrics.http.total.2020 = 23232
# Métrique à valeur mensuelle (type MONTHS, optionnel).
metrics.http.total.2020.months=119417,122403,133108,148109,286762,334892
# Métrique à valeur hebdomadaire (type WEEKS, optionnel).
metrics.http.total.2020.months=1194,1224,1331,1481,2867,3348
# Métrique à valeur quotidienne (type DAYS, optionnel).
metrics.http.total.2020.days=11,12,13,14,28,33
```
Exemple :
```
metrics.visitors.ipv4.2020=123
metrics.visitors.ipv6.2020=123
metrics.visitors.total.2020=246
metrics.visitors.ipv4.2020.months=12;34;56;
metrics.visitors.ipv6.2020.months=12;34;56;
metrics.visitors.total.2020.months=24;68;112;
metrics.visitors.ipv4.2020.weeks=123;456;
metrics.visitors.ipv6.2020.weeks=123;456;
metrics.visitors.total.2020.weeks=246;912;
metrics.visitors.ipv4.2020.days=123;456;
metrics.visitors.ipv6.2020.days=123;456;
metrics.visitors.total.2020.days=246;912;
```

267
README.md
View file

@ -1,11 +1,11 @@
# StatoolInfos
# StatoolInfosWeb
StatoolInfos is a simple statistic tool software.
StatoolInfosWeb is a webapp to value the data from StatoolInfos protocol.
## LICENSE
StatoolInfos is released under the GNU AGPL+ license. Enjoy!
StatoolInfosWeb is released under the GNU AGPL+ license. Enjoy!
Authors:
* Christian Pierre MOMON <christian.momon@devinsy.fr>
@ -50,271 +50,22 @@ Read CONCEPT.md and ONTOLOGY.md files.
## Requirements
- Java 11
- Eclipse 4.16 (202006).
- Java 17
- Eclipse 4.29 (2023-09).
## INSTALL
Install Java :
```
apt-get install openjdk-11-jre-headless
apt-get install openjdk-17-jre-headless
```
Download the last release: https://forge.devinsy.fr/devinsy/statoolinfos/releases
Download the last release: https://forge.devinsy.fr/statool/statoolinfosweb/releases
Unzip the package and move the `statoolinfos.jar` and `statoolinfo.sh` files in `/srv/statoolinfos/bin/`.
Create link:
```
cd /srv/statoolinfos/bin/ ; ln -s statoolinfos.sh statoolinfos
```
TODO
## Usage
```
Usage:
statoolinfos [ -h | -help | --help ]
statoolinfos [ -v | -version | --version ]
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 format <fileordirectory> format property files in tiny way
statoolinfos htmlize <configurationfile> generate web pages from conf
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 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
```
## Generate metrics files
### Basics
Create a configuration file `/srv/statoolInfos/conf/foo.bar.org.conf`:
```
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:
```
/srv/statoolinfos/bin/statoolinfos probe -full /srv/statoolinfos/conf/foo.bar.org.conf
```
Create a cron file in `/etc/cron.d/statoolinfos` to update the metric file everyday:
```
1 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:
```
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
```
### GSL metrics
Configuration template:
```
conf.probe.types=GSL
conf.probe.gsl.stats=/foo/bar/stats.properties
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).
# 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.
# 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).
# 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
```
TODO

28
TODO Normal file
View file

@ -0,0 +1,28 @@
_____ ___ ____ ___
|_ _/ _ \| _ \ / _ \
| || | | | | | | | | |
| || |_| | |_| | |_| |
|_| \___/|____/ \___/
== PropertyCheck + PropertyAlert metric files
Actuellement, les fichiers sub.metrics ne sont pas traitables en PropertyCheck et en PropertyAlert via l'interface web.
Suggestions :
- créer un bouton de menu dédié
- rajouter une liste dans la page PropertyCheck
== Menu
Refaire le placement des boutons de menu.
Rassembler ensemble les boutons colorés à côté de la sous-fiche federation/organisation/service.
== Catégorie
Depuis la fiche d'un logiciel, pouvoir accéder à sa fiche catétorie.
== Exports ODS
Lib obsolète à remplacer.
== Icones de catégorie
Revoir les fichiers d'icones de catégorie avec les bonnes licences.

View file

@ -1,168 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project default="main" name="Build-appjar">
<!--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" />
<property name="build.classes" value="${build.dir}/classes" />
<property name="build.javadoc" value="${build.dir}/javadoc" />
<property name="test.src" value="${basedir}/test" />
<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* **/*sources* *src* **/*src*" />
</path>
<property name="classpath.absolute" value="${toString:project.libs}" />
<manifestclasspath property="classpath.relative" jarfile="statoolinfos.jar">
<classpath refid="project.libs" />
</manifestclasspath>
<!-- ***** Main ***** -->
<target name="main" description="Manage distribution build" depends="dist, clean">
<echo>Done.</echo>
</target>
<!-- ***** Help ***** -->
<target name="help" description="Display detailed usage information">
<echo>Type ant -p</echo>
</target>
<!-- ***** Clear ***** -->
<target name="clear" description="Clear temporary directories before work">
<delete dir="${build.dir}" />
</target>
<!-- ***** Clean ***** -->
<target name="clean" description="Clear temporary directories after work">
<delete dir="${build.dir}" />
</target>
<!-- ***** Compile ***** -->
<target name="compile" description="Compile project">
<delete dir="${build.classes}" />
<mkdir dir="${build.classes}" />
<echo>classpath=${toString:project.libs}</echo>
<javac srcdir="${build.src}" destdir="${build.classes}" classpath="${toString:project.libs}" debug="${debug}" deprecation="on" includeantruntime="no" />
</target>
<!-- ***** copy stuff ***** -->
<target name="copysourcestuff" description="Copy source files other than Java">
<copy todir="${build.classes}">
<fileset dir="${build.src}" excludes="**/*.java" />
</copy>
</target>
<!-- ***** JavaDoc ***** -->
<target name="javadoc" description="Javadoc construction">
<javadoc sourcepath="${build.src}" destdir="${build.javadoc}">
<classpath>
<fileset dir="lib" includes="**/*.jar" />
</classpath>
</javadoc>
</target>
<!-- ***** Dist ***** -->
<target name="dist" description="Build distribution directory" depends="clear,compile,copysourcestuff,javadoc">
<!--echo message="==========>Build Classpath: ${classpath.absolute}" /-->
<!--echo message="==========>Manifest Classpath: ${classpath.relative}" /-->
<!-- AUTOMATIC MANAGEMENT -->
<buildnumber file="build.num" description="Id of the build"/>
<property name="dist.version" value="${product.revision.major}.${product.revision.minor}.${build.number}${dist.snapshot}" />
<property name="dist.name" value="${product.name}-${dist.version}" />
<property name="dist.dir" value="${basedir}/dist/${product.name}-${dist.version}" />
<tstamp>
<format property="dist.time" pattern="dd/MM/yyyy HH:mm:ss" />
</tstamp>
<!-- -->
<delete dir="${dist.dir}" />
<mkdir dir="${dist.dir}"/>
<!-- Update build_information.properties file -->
<property name="build.information.file" value="${build.classes}/fr/devinsy/statoolinfos/build_information.properties" />
<propertyfile file="${build.information.file}" >
<entry key="product.name" value="${product.name}"/>
<entry key="product.revision.major" value="${product.revision.major}"/>
<entry key="product.revision.minor" value="${product.revision.minor}"/>
<entry key="product.revision.build" value="${build.number}"/>
<entry key="product.revision.snapshot" value="${dist.snapshot}"/>
<entry key="product.revision.date" type="date" value="now"/>
<entry key="product.revision.generator" value="Ant"/>
<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}">
<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"/>
<attribute name="Multi-Release" value = "true"/>
</manifest>
</jar>
<!-- Package sources -->
<property name="dist.srczip" value="${dist.dir}/${dist.name}-sources.zip" />
<zip destfile="${dist.srczip}" update="true" preserve0permissions="true">
<fileset dir="${build.src}" />
<zipfileset dir="${basedir}/" includes="LICENSE" />
</zip>
<!-- Package Javadoc -->
<property name="dist.javadoc.zip" value="${dist.dir}/${dist.name}-javadoc.zip" />
<zip destfile="${dist.javadoc.zip}" update="true">
<fileset dir="${build.javadoc}" />
<zipfileset dir="${basedir}/" includes="LICENSE" />
</zip>
<!-- 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.md" todir="${dist.dir}/" overwrite="true" failonerror="false" />
<!--copy file="scripts/log4j.properties" todir="${dist.dir}/" overwrite="true" /-->
<mkdir dir="${dist.dir}/conf" />
<copy todir="${dist.dir}/conf">
<fileset dir="${basedir}/resources/conf" includes="*" />
</copy>
<!--
<mkdir dir="${dist.dir}/man"/>
<copy todir="${dist.dir}/man">
<fileset dir="${basedir}/resources/man" includes="*" />
</copy>
-->
<delete file="${build.information.file}" />
</target>
<!-- ***** Build and GIT ***** -->
<target name="buildandgit" depends="dist,clean">
<echo message="Commit build.num" />
<exec executable="git" outputproperty="git.commit.out" failifexecutionfails="true">
<arg line="commit -m 'Build ${dist.version}' build.num" />
</exec>
<echo message="${git.commit.out}" />
<echo message="Tag" />
<exec executable="git" outputproperty="git.tag.out" failifexecutionfails="true">
<arg line="tag -a ${dist.version} -m 'Build ${dist.version}'" />
</exec>
<echo message="${git.tag.out}" />
<echo message="Push" />
<exec executable="git" outputproperty="git.push.out" failifexecutionfails="true">
<arg line="push --follow-tags" />
</exec>
<echo message="${git.push.out}" />
</target>
</project>

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<project default="dist" name="Build">
<!-- -->
<import file="build-appjar.xml" />
<property name="dist.snapshot" value="" />
</project>

View file

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<project default="snapshot" name="Build Snapshot">
<!-- -->
<import file="build-appjar.xml" />
<property name="buildnum.file" value="${basedir}/build.num" />
<property name="buildnum.tmpfile" value="${basedir}/build.num.tmp" />
<tstamp>
<format property="dist.snapshot.number" pattern="yyyyMMddHHmmss" />
</tstamp>
<property name="dist.snapshot" value="-SNAPSHOT_${dist.snapshot.number}" />
<!-- ***** Store ***** -->
<target name="store" description="Store the build number version">
<copy file="${buildnum.file}" tofile="${buildnum.tmpfile}" overwrite="true" />
</target>
<!-- ***** Restore ***** -->
<target name="restore" description="Restore the build number version">
<copy file="${buildnum.tmpfile}" tofile="${buildnum.file}" overwrite="true" />
<delete file="${buildnum.tmpfile}" />
</target>
<!-- ***** Snapshot ***** -->
<target name="snapshot" description="Build a snapshot" depends="store,dist,restore">
</target>
</project>

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<project default="buildandgit" name="BuildAndGit">
<!-- -->
<import file="build-appjar.xml" />
<property name="dist.snapshot" value="" />
</project>

View file

@ -1,3 +0,0 @@
#Build Number for ANT. Do not edit!
#Tue May 09 18:35:03 CEST 2023
build.number=2

View file

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

168
build.sh
View file

@ -1,168 +0,0 @@
#/bin/bash
#
# Display help.
#
function help
{
echo "StatoolInfos 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."
echo " -local, --local build a new version without tag nor version number commit nor Git push."
echo " -tagandpush, --tagandpush build a new version with tag, version number commit and Git push."
echo ""
}
#
# Build snapshot.
#
function build_snapshot
{
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-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"
fi
# Git check.
gitCheck=`which git 2>&1`
if [[ "$gitCheck" =~ ^/.* ]]; then
echo "GIT requirement................ OK"
let "okCount+=1"
else
echo "GIT requirement................ MISSING"
fi
if [ "$okCount" == 4 ]; then
echo "Requirement OK"
ant -f build-tagandpush.xml
else
echo "Requirement MISSING, build abort"
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
fi

View file

@ -1,20 +0,0 @@
Description of used libraries:
- Logs/
- log4j log API
- slf4j-api facade log API
- slf4j-log4j12 adaptation layer between slf4j and log4j
- UnitTesting/
- hamcrest-core required by junit
- hsqldb SQL Database for unit test.
- junit unit tests API
- other:
- commons-codec digest tools
- commons-io
- commons-lang useful tools (StringUtils...)
- devinsy-strings
- devinsy-xml
- hsqldb
- mysql-jdbc

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,26 +0,0 @@
# 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

@ -1,26 +0,0 @@
# 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

@ -1,24 +0,0 @@
#
# 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

View file

@ -1,23 +0,0 @@
#
# 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=/home/cpm/Projets/StatoolInfos/EnvTest/minetest/test.metrics

View file

@ -1,14 +0,0 @@
#
# Sample StatoolInfos config file.
#
# Warning: move this file outside the Git directory.
conf.class=federation
conf.protocol=StatoolInfos-0.5.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

@ -1,22 +0,0 @@
#!/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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View file

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

View file

@ -1,192 +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;
import java.io.File;
import java.io.IOException;
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.
*/
public class HtmlizerContext
{
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 Configuration configuration;
private Federation federation;
private Categories categories;
private CrawlCache cache;
private UptimeJournal uptimeJournal;
/**
* Instantiates a new manager.
*/
private HtmlizerContext()
{
}
/**
* Configure.
*
* @param configurationFile
* the configuration file
* @throws IOException
* @throws StatoolInfosException
*/
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());
this.cache = new CrawlCache(this.configuration.getCrawlCacheDirectory());
File htmlizeDirectory = this.configuration.getHtmlizeDirectory();
if (htmlizeDirectory == null)
{
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())
{
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.");
}
}
}
/**
* Gets the cache.
*
* @return the cache
*/
public CrawlCache getCache()
{
CrawlCache result;
result = this.cache;
//
return result;
}
/**
* Gets the categories.
*
* @return the categories
*/
public Categories getCategories()
{
Categories result;
result = this.categories;
//
return result;
}
/**
* Gets the configuration.
*
* @return the configuration
*/
public Configuration getConfiguration()
{
Configuration result;
result = this.configuration;
//
return result;
}
/**
* Gets the federation.
*
* @return the federation
*/
public Federation getFederation()
{
Federation result;
result = this.federation;
//
return result;
}
/**
* Htmlize directory.
*
* @return the file
*/
public File getHtmlizeDirectory()
{
File result;
result = this.configuration.getHtmlizeDirectory();
//
return result;
}
public UptimeJournal getUptimeJournal()
{
return this.uptimeJournal;
}
/**
* Instance.
*
* @return the manager
*/
public static HtmlizerContext instance()
{
return SingletonHolder.instance;
}
}

View file

@ -1,119 +0,0 @@
/*
* Copyright (C) 2020-2021 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;
import java.io.File;
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;
import fr.devinsy.statoolinfos.cli.StatoolInfosCLI;
/**
* The Class StatoolInfosLauncher.
*/
public final class StatoolInfosLauncher
{
/**
* Instantiates a new statool infos launcher.
*/
private StatoolInfosLauncher()
{
}
/**
* The main method.
*
* @param args
* the arguments
*/
public static void main(final String[] args)
{
String logFileEnv = System.getenv().get("LOG4J_CONFIGURATION_FILE");
String logFileProperty = System.getProperty("log4j2.configurationFile");
// Configure log.
if ((StringUtils.isBlank(logFileEnv) && (StringUtils.isBlank(logFileProperty))))
{
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.
StatoolInfosCLI.run(args);
}
}

View file

@ -1,142 +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.build;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.statoolinfos.core.Configuration;
import fr.devinsy.statoolinfos.core.Factory;
import fr.devinsy.statoolinfos.core.StatoolInfosException;
import fr.devinsy.statoolinfos.properties.PathProperties;
import fr.devinsy.statoolinfos.properties.PathPropertyList;
import fr.devinsy.statoolinfos.properties.PathPropertyUtils;
/**
* The Class StatoolInfos.
*/
public class Builder
{
private static Logger logger = LoggerFactory.getLogger(Builder.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
{
logger.info("Build {}", configurationFile.getAbsolutePath());
Configuration configuration = Factory.loadConfiguration(configurationFile);
logger.info("Build input setting: {}", configuration.getBuildInput());
logger.info("Build directory setting: {}", configuration.getBuildDirectoryPath());
File inputFile = configuration.getBuildInput();
File buildDirectory = configuration.getBuildDirectory();
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 if (buildDirectory == null)
{
throw new StatoolInfosException("Build directory is undefined.");
}
else if (!buildDirectory.exists())
{
throw new StatoolInfosException("Build directory does not exist.");
}
else if (!buildDirectory.isDirectory())
{
throw new StatoolInfosException("Build directory is not a directory.");
}
else
{
// Build file section.
PathProperties target = new PathPropertyList();
target.put("file.class", configuration.get("conf.class"));
target.put("file.generator", "StatoolInfos");
target.put("file.datetime", LocalDateTime.now().toString());
target.put("file.protocol", configuration.get("conf.protocol"));
// Load input properties.
PathProperties input = PathPropertyUtils.load(inputFile);
// Add input properties with file section ones.
target.add(input);
// Save the build properties.
File targetFile = new File(buildDirectory, configuration.getBuildInput().getName());
PathPropertyUtils.save(targetFile, target);
}
}
/**
* Clear.
*
* @param configuration
* the configuration
* @throws StatoolInfosException
* the statool infos exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void clear(final Configuration configuration) throws StatoolInfosException, IOException
{
logger.info("Build directory setting: {}", configuration.getBuildDirectoryPath());
String path = configuration.getBuildDirectoryPath();
if (StringUtils.isBlank(path))
{
logger.warn("Undefined build directory.");
}
else if (!new File(path).exists())
{
logger.warn("Build directory does not exist: {}.", path);
}
else
{
File file = new File(configuration.getBuildDirectory(), configuration.getBuildInput().getName());
if ((file.isFile()) && (StringUtils.endsWith(file.getName(), ".properties")))
{
logger.info("BUILDER : Deleting {}", file.getAbsolutePath());
file.delete();
}
}
}
}

View file

@ -1,132 +0,0 @@
/*
* Copyright (C) 2020-2021 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.checker;
import fr.devinsy.statoolinfos.core.Service.Status;
/**
* The Class PropertyCheck.
*/
public class PropertyCheck
{
private String fileName;
private long index;
private String line;
private Status status;
private String comment;
/**
* Instantiates a new property check.
*
* @param index
* the index
* @param line
* the line
*/
public PropertyCheck(final long index, final String line)
{
this(index, line, Status.VOID);
}
/**
* Instantiates a new property check.
*
* @param index
* the index
* @param line
* the line
* @param status
* the status
*/
public PropertyCheck(final long index, final String line, final Status status)
{
this(index, line, status, "");
}
/**
* Instantiates a new property check.
*
* @param index
* the index
* @param line
* the line
* @param status
* the status
* @param comment
* the comment
*/
public PropertyCheck(final long index, final String line, final Status status, final String comment)
{
this.fileName = null;
this.index = index;
this.line = line;
this.status = status;
this.comment = comment;
}
public String getComment()
{
return this.comment;
}
public String getFileName()
{
return this.fileName;
}
public long getIndex()
{
return this.index;
}
public String getLine()
{
return this.line;
}
public Status getStatus()
{
return this.status;
}
public void setComment(final String comment)
{
this.comment = comment;
}
public void setFileName(final String fileName)
{
this.fileName = fileName;
}
public void setIndex(final long index)
{
this.index = index;
}
public void setLine(final String line)
{
this.line = line;
}
public void setStatus(final Status status)
{
this.status = status;
}
}

View file

@ -1,461 +0,0 @@
/*
* Copyright (C) 2020-2022 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.checker;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import org.apache.commons.lang3.StringUtils;
import fr.devinsy.statoolinfos.checker.PropertyRule.PropertyMode;
import fr.devinsy.statoolinfos.core.Service.Status;
import fr.devinsy.statoolinfos.properties.PathProperty;
import fr.devinsy.strings.StringList;
import fr.devinsy.strings.StringsUtils;
/**
* The Class PropertyChecker.
*/
public class PropertyChecker
{
public static final String ALL = "^.*$";
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|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 = "^https?://[\\w-_\\.]+(\\.\\w+)+(:\\d+)?(/.*)?$";
public static final String EMAIL = "^.*@.*$";
public static final String NUMERIC = "^\\d+$";
public static final String NUMERICS = "^\\d*(,\\d*)*$";
public static final String MONTHS = "^\\d*(,\\d*){0,11}$";
public static final String WEEKS = "^\\d*(,\\d*){0,52}$";
public static final String DAYS = "^\\d*(,\\d*){0,365}$";
public static final String COUNTRY_CODE = "^[a-zA-Z]{2}$";
public static final String DECIMAL_DEGREE = "^[+-]?\\d+[,\\.]\\d{1,8}$";
public static final String SUBS = "^subs\\.\\S+$";
public static final String METRICS_NAME = "^metrics\\.\\S+\\.name$";
public static final String METRICS_DESCRIPTION = "^metrics\\.\\S+\\.description$";
public static final String METRICS_YEAR = "^metrics\\.\\S+\\.\\d{4}$";
public static final String METRICS_MONTHS = "^metrics\\.\\S+\\.\\d{4}\\.months$";
public static final String METRICS_WEEKS = "^metrics\\.\\S+\\.\\d{4}\\.weeks$";
public static final String METRICS_DAYS = "^metrics\\.\\S+\\.\\d{4}\\.days$";
public static final String CRAWL = "^crawl\\.\\S+$";
private PropertyRules federationRules;
private PropertyRules organizationRules;
private PropertyRules serviceRules;
private PropertyRules metricsRules;
/**
* Instantiates a new property checker.
*/
public PropertyChecker()
{
//
this.federationRules = new PropertyRules();
this.federationRules.add("file.class", "^[Ff]ederation$", PropertyMode.MANDATORY);
this.federationRules.add("file.generator", STRING, PropertyMode.WISHED);
this.federationRules.add("file.datetime", DATETIME, PropertyMode.WISHED);
this.federationRules.add("file.protocol", STRING, PropertyMode.WISHED);
this.federationRules.add("federation.name", STRING, PropertyMode.MANDATORY);
this.federationRules.add("federation.description", STRING, PropertyMode.WISHED);
this.federationRules.add("federation.website", URL, PropertyMode.WISHED);
this.federationRules.add("federation.logo", URL, PropertyMode.WISHED);
this.federationRules.add("federation.contact.url", URL, PropertyMode.WISHED);
this.federationRules.add("federation.contact.email", EMAIL, PropertyMode.WISHED);
this.federationRules.add("federation.socialnetworks.*", "^federation\\.socialnetworks\\.\\S+$", URL, PropertyMode.OPTIONAL);
this.federationRules.add("federation.legal.url", URL, PropertyMode.WISHED);
this.federationRules.add("federation.guide.user", URL, PropertyMode.WISHED);
this.federationRules.add("federation.guide.technical", URL, PropertyMode.WISHED);
this.federationRules.add("federation.startdate", DATE, PropertyMode.WISHED);
this.federationRules.add("federation.enddate", DATE, PropertyMode.OPTIONAL);
this.federationRules.add(SUBS, URL, PropertyMode.OPTIONAL);
this.federationRules.add(METRICS_NAME, STRING, PropertyMode.OPTIONAL);
this.federationRules.add(METRICS_DESCRIPTION, STRING, PropertyMode.OPTIONAL);
this.federationRules.add(METRICS_YEAR, NUMERIC, PropertyMode.OPTIONAL);
this.federationRules.add(METRICS_MONTHS, MONTHS, PropertyMode.OPTIONAL);
this.federationRules.add(METRICS_WEEKS, WEEKS, PropertyMode.OPTIONAL);
this.federationRules.add(METRICS_DAYS, DAYS, PropertyMode.OPTIONAL);
this.federationRules.add(CRAWL, ALL, PropertyMode.MANDATORY);
//
this.organizationRules = new PropertyRules();
this.organizationRules.add("file.class", "^[Oo]rganization$", PropertyMode.MANDATORY);
this.organizationRules.add("file.generator", STRING, PropertyMode.WISHED);
this.organizationRules.add("file.datetime", DATETIME, PropertyMode.WISHED);
this.organizationRules.add("file.protocol", STRING, PropertyMode.WISHED);
this.organizationRules.add("organization.name", STRING, PropertyMode.MANDATORY);
this.organizationRules.add("organization.description", STRING, PropertyMode.WISHED);
this.organizationRules.add("organization.status.level", "^(ACTIVE|IDLE|AWAY)$", PropertyMode.MANDATORY);
this.organizationRules.add("organization.status.description", STRING, PropertyMode.OPTIONAL);
this.organizationRules.add("organization.website", URL, PropertyMode.WISHED);
this.organizationRules.add("organization.logo", URL, PropertyMode.WISHED);
this.organizationRules.add("organization.socialnetworks.*", "^organization\\.socialnetworks\\.\\S+$", URL, PropertyMode.OPTIONAL);
this.organizationRules.add("organization.chatrooms.*", "^organization\\.chatrooms\\.\\S+$", STRING, PropertyMode.OPTIONAL);
this.organizationRules.add("organization.owner.name", STRING, PropertyMode.OPTIONAL);
this.organizationRules.add("organization.owner.website", URL, PropertyMode.OPTIONAL);
this.organizationRules.add("organization.owner.logo", URL, PropertyMode.OPTIONAL);
this.organizationRules.add("organization.contact.url", URL, PropertyMode.WISHED);
this.organizationRules.add("organization.contact.email", EMAIL, PropertyMode.WISHED);
this.organizationRules.add("organization.legal.url", "^organization\\.legal(\\.url)?$", URL, PropertyMode.WISHED);
this.organizationRules.add("organization.guide.user", URL, PropertyMode.WISHED);
this.organizationRules.add("organization.guide.technical", URL, PropertyMode.WISHED);
this.organizationRules.add("organization.startdate", DATE, PropertyMode.WISHED);
this.organizationRules.add("organization.enddate", DATE, PropertyMode.OPTIONAL);
this.organizationRules.add("organization.memberof.*.startdate", "^organization\\.memberof\\.\\S+\\.startdate$", DATE, PropertyMode.MANDATORY);
this.organizationRules.add("organization.memberof.*.enddate", "^organization\\.memberof\\.\\S+\\.enddate$", DATE, PropertyMode.OPTIONAL);
this.organizationRules.add("organization.memberof.*.status.level", "^organization\\.memberof\\.\\S+\\.status.level$", "^(ACTIVE|IDLE|AWAY)$", PropertyMode.MANDATORY);
this.organizationRules.add("organization.memberof.*.status.description", "^organization\\.memberof\\.\\S+\\.status.description$", STRING, PropertyMode.OPTIONAL);
this.organizationRules.add("organization.country.name", STRING, PropertyMode.WISHED);
this.organizationRules.add("organization.country.code", COUNTRY_CODE, PropertyMode.MANDATORY);
this.organizationRules.add("organization.funding.*", "^organization\\.funding\\.\\S+$", STRING, PropertyMode.OPTIONAL);
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);
this.organizationRules.add(METRICS_DESCRIPTION, STRING, PropertyMode.OPTIONAL);
this.organizationRules.add(METRICS_YEAR, NUMERIC, PropertyMode.OPTIONAL);
this.organizationRules.add(METRICS_MONTHS, MONTHS, PropertyMode.OPTIONAL);
this.organizationRules.add(METRICS_WEEKS, WEEKS, PropertyMode.OPTIONAL);
this.organizationRules.add(METRICS_DAYS, DAYS, PropertyMode.OPTIONAL);
this.organizationRules.add(CRAWL, ALL, PropertyMode.MANDATORY);
//
this.serviceRules = new PropertyRules();
this.serviceRules.add("file.class", "^[Ss]ervice$", PropertyMode.MANDATORY);
this.serviceRules.add("file.generator", STRING, PropertyMode.WISHED);
this.serviceRules.add("file.datetime", DATETIME, PropertyMode.WISHED);
this.serviceRules.add("file.protocol", STRING, PropertyMode.WISHED);
this.serviceRules.add("service.name", STRING, PropertyMode.MANDATORY);
this.serviceRules.add("service.description", STRING, PropertyMode.WISHED);
this.serviceRules.add("service.website", URL, PropertyMode.MANDATORY);
this.serviceRules.add("service.logo", URL, PropertyMode.WISHED);
this.serviceRules.add("service.contact.url", URL, PropertyMode.WISHED);
this.serviceRules.add("service.contact.email", EMAIL, PropertyMode.WISHED);
this.serviceRules.add("service.legal.url", URL, PropertyMode.WISHED);
this.serviceRules.add("service.guide.user", URL, PropertyMode.WISHED);
this.serviceRules.add("service.guide.technical", URL, PropertyMode.WISHED);
this.serviceRules.add("service.startdate", DATE, PropertyMode.MANDATORY);
this.serviceRules.add("service.enddate", DATE, PropertyMode.OPTIONAL);
this.serviceRules.add("service.status.level", "^(OK|WARNING|ALERT|ERROR|OVER|VOID)$", PropertyMode.MANDATORY);
this.serviceRules.add("service.status.description", STRING, PropertyMode.OPTIONAL);
this.serviceRules.add("service.registration", "^(None|Free|Member|Client)(\\s*[,;+]\\s*(None|Free|Member|Client))*$", PropertyMode.MANDATORY);
this.serviceRules.add("service.registration.load", "^(open|full)$", PropertyMode.MANDATORY);
this.serviceRules.add("service.install.type", "^(DISTRIBUTION|PROVIDER|PACKAGE|TOOLING|CLONEREPO|ARCHIVE|SOURCES|CONTAINER)$", PropertyMode.MANDATORY);
this.serviceRules.add("software.name", STRING, PropertyMode.MANDATORY);
this.serviceRules.add("software.website", URL, PropertyMode.WISHED);
this.serviceRules.add("software.license.url", URL, PropertyMode.MANDATORY);
this.serviceRules.add("software.license.name", STRING, PropertyMode.MANDATORY);
this.serviceRules.add("software.version", STRING, PropertyMode.WISHED);
this.serviceRules.add("software.source.url", URL, PropertyMode.WISHED);
this.serviceRules.add("software.modules", STRING, PropertyMode.OPTIONAL);
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);
this.serviceRules.add(SUBS, URL, PropertyMode.OPTIONAL);
this.serviceRules.add(METRICS_NAME, STRING, PropertyMode.OPTIONAL);
this.serviceRules.add(METRICS_DESCRIPTION, STRING, PropertyMode.OPTIONAL);
this.serviceRules.add(METRICS_YEAR, NUMERIC, PropertyMode.OPTIONAL);
this.serviceRules.add(METRICS_MONTHS, MONTHS, PropertyMode.OPTIONAL);
this.serviceRules.add(METRICS_WEEKS, WEEKS, PropertyMode.OPTIONAL);
this.serviceRules.add(METRICS_DAYS, DAYS, PropertyMode.OPTIONAL);
this.serviceRules.add(CRAWL, ALL, PropertyMode.MANDATORY);
//
this.metricsRules = new PropertyRules();
this.metricsRules.add("file.class", "^[Mm]etrics$", PropertyMode.MANDATORY);
this.metricsRules.add("file.generator", STRING, PropertyMode.WISHED);
this.metricsRules.add("file.datetime", DATETIME, PropertyMode.WISHED);
this.metricsRules.add("file.protocol", STRING, PropertyMode.WISHED);
this.metricsRules.add(METRICS_NAME, STRING, PropertyMode.OPTIONAL);
this.metricsRules.add(METRICS_DESCRIPTION, STRING, PropertyMode.OPTIONAL);
this.metricsRules.add(METRICS_YEAR, NUMERIC, PropertyMode.OPTIONAL);
this.metricsRules.add(METRICS_MONTHS, MONTHS, PropertyMode.OPTIONAL);
this.metricsRules.add(METRICS_WEEKS, WEEKS, PropertyMode.OPTIONAL);
this.metricsRules.add(METRICS_DAYS, DAYS, PropertyMode.OPTIONAL);
this.metricsRules.add(CRAWL, ALL, PropertyMode.MANDATORY);
}
/**
* Check.
*
* @param lines
* the lines
* @return the property checks
*/
public PropertyChecks check(final StringList lines, final PropertyRules rules)
{
PropertyChecks result;
result = new PropertyChecks();
//
if ((lines != null) && (!lines.isEmpty()) && (lines.get(0).startsWith(BOM)))
{
String line = lines.get(0).substring(1);
lines.set(0, line);
}
//
PropertyRules requiredRules = rules.getMandatories();
requiredRules.addAll(rules.getWished());
for (PropertyRule rule : requiredRules)
{
boolean ended = false;
Iterator<String> iterator = lines.iterator();
while (!ended)
{
if (iterator.hasNext())
{
String line = iterator.next();
if ((!StringUtils.isBlank(line)) && (!line.startsWith("#")) && (line.contains("=")))
{
String[] tokens = line.split("=", 2);
PathProperty property = new PathProperty(tokens[0].trim(), tokens[1].trim());
if (rule.checkPath(property.getPath()))
{
ended = true;
}
}
}
else
{
ended = true;
Status status;
switch (rule.getMode())
{
default:
case MANDATORY:
status = Status.ERROR;
break;
case WISHED:
status = Status.WARNING;
break;
}
PropertyCheck check = new PropertyCheck(0, rule.getLabel(), status, "Propriété manquante");
result.add(check);
}
}
}
//
int lineIndex = 1;
for (String line : lines)
{
PropertyCheck check;
if (line == null)
{
check = new PropertyCheck(lineIndex, "", Status.OK);
check.setComment("OK");
}
else if ((StringUtils.isEmpty(line)) || (line.matches(COMMENT)))
{
check = new PropertyCheck(lineIndex, line, Status.OK);
check.setComment("OK");
}
else if (!line.matches("^[^#].*[^\\s].*=.*$"))
{
check = new PropertyCheck(lineIndex, line, Status.ERROR);
check.setComment("Ligne malformée");
}
else
{
String[] tokens = line.split("=", 2);
PathProperty property = new PathProperty(tokens[0].trim(), tokens[1].trim());
PropertyRule rule = rules.find(property.getPath());
check = new PropertyCheck(lineIndex, line, Status.VOID);
if (rule == null)
{
check.setStatus(Status.VOID);
check.setComment("Propriété inconnue");
}
else if (rule.isOptional())
{
if (StringUtils.isBlank(property.getValue()))
{
check.setStatus(Status.OK);
check.setComment("OK");
}
else if (rule.checkValue(property.getValue()))
{
check.setStatus(Status.OK);
check.setComment("OK");
}
else
{
check.setStatus(Status.ERROR);
check.setComment("Valeur incorrecte");
}
}
else if (rule.isWished())
{
if (StringUtils.isBlank(property.getValue()))
{
check.setStatus(Status.WARNING);
check.setComment("Valeur recommandée");
}
else if (rule.checkValue(property.getValue()))
{
check.setStatus(Status.OK);
check.setComment("OK");
}
else
{
check.setStatus(Status.ERROR);
check.setComment("Valeur incorrecte");
}
}
else if (rule.isMandatory())
{
if (StringUtils.isBlank(property.getValue()))
{
check.setStatus(Status.ERROR);
check.setComment("Valeur obligatoire");
}
else if (rule.checkValue(property.getValue()))
{
check.setStatus(Status.OK);
check.setComment("OK");
}
else
{
check.setStatus(Status.ERROR);
check.setComment("Valeur incorrecte");
}
}
}
result.add(check);
lineIndex += 1;
}
//
return result;
}
/**
* Check federation.
*
* @param file
* the file
* @return the property checks
* @throws IOException
*/
public PropertyChecks checkFederation(final File file) throws IOException
{
PropertyChecks result;
StringList lines = StringsUtils.load(file);
result = check(lines, this.federationRules);
//
return result;
}
/**
* Check metrics.
*
* @param file
* the file
* @return the property checks
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public PropertyChecks checkMetrics(final File file) throws IOException
{
PropertyChecks result;
StringList lines = StringsUtils.load(file);
result = check(lines, this.metricsRules);
//
return result;
}
/**
* Check organization.
*
* @param file
* the file
* @return the property checks
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public PropertyChecks checkOrganization(final File file) throws IOException
{
PropertyChecks result;
StringList lines = StringsUtils.load(file);
result = check(lines, this.organizationRules);
//
return result;
}
/**
* Check service.
*
* @param file
* the file
* @return the property checks
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public PropertyChecks checkService(final File file) throws IOException
{
PropertyChecks result;
StringList lines = StringsUtils.load(file);
result = check(lines, this.serviceRules);
//
return result;
}
}

View file

@ -1,197 +0,0 @@
/*
* Copyright (C) 2020-2021 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.checker;
import java.util.ArrayList;
import java.util.regex.Pattern;
import fr.devinsy.statoolinfos.core.Service.Status;
/**
* The Class PropertyChecks.
*/
public class PropertyChecks extends ArrayList<PropertyCheck>
{
private static final long serialVersionUID = 64500205250126257L;
/**
* Instantiates a new property checks.
*/
public PropertyChecks()
{
super();
}
/**
* Extract active lines.
*
* @return the property checks
*/
public PropertyChecks getActiveLines()
{
PropertyChecks result;
result = new PropertyChecks();
Pattern pattern = Pattern.compile("^(\\s*[^#\\s]|#\\s*\\[).*$");
for (PropertyCheck check : this)
{
if (pattern.matcher(check.getLine()).matches())
{
result.add(check);
}
}
//
return result;
}
/**
* Gets the alert count.
*
* @return the alert count
*/
public int getAlertCount()
{
int result;
result = 0;
for (PropertyCheck check : this)
{
if (check.getStatus() == Status.ALERT)
{
result += 1;
}
}
//
return result;
}
/**
* Extract alert lines.
*
* @return the property checks
*/
public PropertyChecks getAlertLines()
{
PropertyChecks result;
result = new PropertyChecks();
for (PropertyCheck check : this)
{
if (check.getStatus() != Status.OK)
{
result.add(check);
}
}
//
return result;
}
/**
* Gets the error count.
*
* @return the error count
*/
public int getErrorCount()
{
int result;
result = 0;
for (PropertyCheck check : this)
{
if (check.getStatus() == Status.ERROR)
{
result += 1;
}
}
//
return result;
}
/**
* Gets the void count.
*
* @return the void count
*/
public int getVoidCount()
{
int result;
result = 0;
for (PropertyCheck check : this)
{
if (check.getStatus() == Status.VOID)
{
result += 1;
}
}
//
return result;
}
/**
* Gets the warning count.
*
* @return the warning count
*/
public int getWarningCount()
{
int result;
result = 0;
for (PropertyCheck check : this)
{
if (check.getStatus() == Status.WARNING)
{
result += 1;
}
}
//
return result;
}
/**
* Sets the file name.
*
* @param fileName
* the new file name
*/
public PropertyChecks setFileName(final String fileName)
{
PropertyChecks result;
for (PropertyCheck check : this)
{
check.setFileName(fileName);
}
result = this;
//
return result;
}
}

View file

@ -1,232 +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.checker;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
/**
* The Class PropertyRule.
*/
public class PropertyRule
{
public enum PropertyMode
{
MANDATORY,
WISHED,
OPTIONAL
}
private String label;
private Pattern pathPattern;
private Pattern valuePattern;
private PropertyMode mode;
/**
* Instantiates a new property rule.
*
* @param pathRegex
* the path
* @param valueRegex
* the pattern
* @param mode
* the mode
*/
public PropertyRule(final String pathRegex, final String valueRegex, final PropertyMode mode)
{
this(pathRegex, pathRegex, valueRegex, mode);
}
/**
* Instantiates a new property rule.
*
* @param label
* the label
* @param pathRegex
* the path regex
* @param valueRegex
* the value regex
* @param mode
* the mode
*/
public PropertyRule(final String label, final String pathRegex, final String valueRegex, final PropertyMode mode)
{
this.pathPattern = Pattern.compile(pathRegex, Pattern.CASE_INSENSITIVE);
this.valuePattern = Pattern.compile(valueRegex, Pattern.CASE_INSENSITIVE);
this.mode = mode;
this.label = label;
}
/**
* @param value
* @return
*/
public boolean checkPath(final String value)
{
boolean result;
Matcher matcher = this.pathPattern.matcher(StringUtils.toRootLowerCase(value));
result = matcher.matches();
//
return result;
}
/**
* Check.
*
* @param value
* the value
* @return true, if successful
*/
public boolean checkValue(final String value)
{
boolean result;
Matcher matcher = this.valuePattern.matcher(value);
result = matcher.matches();
//
return result;
}
public String getLabel()
{
return this.label;
}
public PropertyMode getMode()
{
return this.mode;
}
/**
* Gets the path pattern.
*
* @return the path pattern
*/
public String getPathPattern()
{
String result;
result = this.pathPattern.pattern();
//
return result;
}
/**
* Gets the pattern string.
*
* @return the pattern string
*/
public String getValuePattern()
{
String result;
result = this.valuePattern.pattern();
//
return result;
}
/**
* Checks if is mandatory.
*
* @return true, if is mandatory
*/
public boolean isMandatory()
{
boolean result;
if (this.mode == PropertyMode.MANDATORY)
{
result = true;
}
else
{
result = false;
}
//
return result;
}
/**
* Checks if is optional.
*
* @return true, if is optional
*/
public boolean isOptional()
{
boolean result;
if (this.mode == PropertyMode.OPTIONAL)
{
result = true;
}
else
{
result = false;
}
//
return result;
}
/**
* Checks if is wished.
*
* @return true, if is wished
*/
public boolean isWished()
{
boolean result;
if (this.mode == PropertyMode.WISHED)
{
result = true;
}
else
{
result = false;
}
//
return result;
}
public void setMode(final PropertyMode mode)
{
this.mode = mode;
}
/**
* Sets the pattern.
*
* @param regex
* the new pattern
*/
public void setPattern(final String regex)
{
this.valuePattern = Pattern.compile(regex);
}
}

View file

@ -1,169 +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.checker;
import java.util.ArrayList;
import java.util.Iterator;
import fr.devinsy.statoolinfos.checker.PropertyRule.PropertyMode;
/**
* The Class PropertyRuleList.
*/
public class PropertyRules extends ArrayList<PropertyRule>
{
private static final long serialVersionUID = 5808894132916693496L;
/**
* Instantiates a new property rules.
*/
public PropertyRules()
{
super();
}
/**
* Adds the.
*
* @param path
* the path
* @param pattern
* the pattern
* @param mode
* the mode
*/
public void add(final String path, final String pattern, final PropertyMode mode)
{
String targetPath;
if (path.startsWith("^"))
{
targetPath = path;
}
else
{
targetPath = path.replace(".", "\\.");
}
PropertyRule rule = new PropertyRule(path, targetPath, pattern, mode);
this.add(rule);
}
/**
* Adds the.
*
* @param label
* the label
* @param path
* the path
* @param pattern
* the pattern
* @param mode
* the mode
*/
public void add(final String label, final String path, final String pattern, final PropertyMode mode)
{
PropertyRule rule = new PropertyRule(label, path, pattern, mode);
this.add(rule);
}
/**
* Find.
*
* @param path
* the path
* @return the property rule
*/
public PropertyRule find(final String path)
{
PropertyRule result;
boolean ended = false;
Iterator<PropertyRule> iterator = iterator();
result = null;
while (!ended)
{
if (iterator.hasNext())
{
PropertyRule rule = iterator.next();
if (rule.checkPath(path))
{
ended = true;
result = rule;
}
}
else
{
ended = true;
result = null;
}
}
//
return result;
}
/**
* Gets the mandatories.
*
* @return the mandatories
*/
public PropertyRules getMandatories()
{
PropertyRules result;
result = new PropertyRules();
for (PropertyRule rule : this)
{
if (rule.isMandatory())
{
result.add(rule);
}
}
//
return result;
}
/**
* Gets the wished.
*
* @return the wished
*/
public PropertyRules getWished()
{
PropertyRules result;
result = new PropertyRules();
for (PropertyRule rule : this)
{
if (rule.isWished())
{
result.add(rule);
}
}
//
return result;
}
}

View file

@ -1,184 +0,0 @@
# [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

@ -1,27 +0,0 @@
STRING=
DATETIME=2020-07-06T14:23:20
DATE=
URL=
# [File]
file.class=^(Federation|Organization|Service)$,MANDATORY
file.generator=STRING,WISHED
file.datetime=DATETIME,WISHED
file.protocol=STRING,WISHED
# [Organisation]
organization.name = STRING,MANDATORY
organization.description = STRING,WISHED
organization.website = URL,WISHED
organization.logo = URL,WISHED
organization.favicon = URL, WISHED
organization.owner.name = STRING,OPTIONAL
organization.owner.website = URL,OPTIONAL
organization.owner.logo = URL,OPTIONAL
organization.owner.favicon = URL,OPTIONAL
organization.contact.url = URL,WISHED
organization.contact.email = EMAIL,WISHED
organization.legal.url = URL,WISHED
organization.guide.technical = URL,WISHED
organization.startdate = DATE,WISHED
organization.enddate =DATE,OPTIONAL

View file

@ -1,164 +0,0 @@
/*
* Copyright (C) 2020-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.cli;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class CLIUtils.
*/
public final class CLIUtils
{
private static Logger logger = LoggerFactory.getLogger(CLIUtils.class);
/**
* 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,695 +0,0 @@
/*
* 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 java.io.File;
import java.time.LocalDateTime;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
import fr.devinsy.statoolinfos.util.FilesUtils;
import fr.devinsy.strings.StringList;
/**
* The Class <code>StatoolInfosCLI</code> manages a Command Line Interface for
* StatoolInfos.
*
*/
public final class StatoolInfosCLI
{
private static Logger logger = LoggerFactory.getLogger(StatoolInfosCLI.class);
/**
* Instantiates a new statool infos CLI.
*/
private StatoolInfosCLI()
{
}
/**
* Convert path.
*
* @param path
* the path
* @return the files
*/
public static Files convertPath(final String path)
{
Files result;
result = new Files();
if (StringUtils.isNotBlank(path))
{
File input = new File(path);
if (input.exists())
{
if (input.isFile())
{
result.add(input);
}
else
{
for (File file : input.listFiles())
{
if ((file.isFile()) && (file.getName().endsWith(".conf")))
{
result.add(file);
}
}
}
}
else
{
result.add(input);
}
}
//
return result;
}
/**
* Display help.
*/
public static void displayHelp()
{
StringList message = new StringList();
message.append("StatoolInfos CLI version ").appendln(BuildInformation.instance().version());
message.appendln("Usage:");
message.appendln(" statoolinfos [ -h | -help | --help ]");
message.appendln(" statoolinfos [ -v | -version | --version ]");
message.appendln();
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 format <fileordirectory> format property files in tiny way");
message.appendln(" statoolinfos htmlize <configurationfile> generate web pages from conf");
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 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());
}
/**
* Display version.
*/
public static void displayVersion()
{
StringList message = new StringList();
message.appendln(BuildInformation.instance().version());
System.out.print(message.toString());
}
/**
* Normalize bash parameter.
*
* @param value
* the value
* @return the string
*/
private static String normalizeBashParameter(final String value)
{
String result;
if (value == null)
{
result = null;
}
else
{
result = StringUtils.trim(value).replace("\\*", "*").replace("\\?", "?");
}
//
return result;
}
/**
* Parses the log filter option.
*
* @param source
* the source
* @return the log filter
*/
private static BotFilter parseLogFilterOption(final String source)
{
BotFilter result;
if (StringUtils.equals(source, "-all"))
{
result = BotFilter.ALL;
}
else if (StringUtils.equals(source, "-bot"))
{
result = BotFilter.BOT;
}
else if (StringUtils.equals(source, "-nobot"))
{
result = BotFilter.NOBOT;
}
else
{
result = null;
}
//
return result;
}
/**
*
* This method launch CLI.
*
* @param args
* necessary arguments
*/
public static void run(final String[] args)
{
// Set default catch.
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler()
{
@Override
public void uncaughtException(final Thread thread, final Throwable exception)
{
String message;
if (exception instanceof OutOfMemoryError)
{
message = "Java ran out of memory!\n\n";
}
else
{
message = String.format("An error occured: %1s(%2s)", exception.getClass(), exception.getMessage());
}
logger.error("uncaughtException ", exception);
logger.error(message);
logger.info("Oups, an unexpected error occured. Please try again.");
}
});
logger.debug("{} StatoolInfos call: {}", LocalDateTime.now(), new StringList(args).toStringSeparatedBy(" "));
if (CLIUtils.isMatching(args))
{
logger.info("No parameter.");
displayHelp();
}
else if (CLIUtils.isMatching(args, "(-h|--h|--help)"))
{
displayHelp();
}
else if (CLIUtils.isMatching(args, "(-v|-version|--version)"))
{
displayVersion();
}
else if (CLIUtils.isMatching(args, "build", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[1]));
try
{
StatoolInfos.build(configurationFile);
}
catch (Exception exception)
{
logger.error("Error with [{}]: {}", configurationFile.getAbsoluteFile(), exception.getMessage());
}
}
else if (CLIUtils.isMatching(args, "clear", ".+\\.conf*"))
{
File configurationFile = new File(StringUtils.trim(args[1]));
try
{
StatoolInfos.clear(configurationFile);
}
catch (Exception exception)
{
logger.error("Error with [{}]: {}", configurationFile.getAbsoluteFile(), exception.getMessage());
}
}
else if (CLIUtils.isMatching(args, "crawl", ".+\\.conf"))
{
Chrono chrono = new Chrono().start();
File configurationFile = new File(StringUtils.trim(args[1]));
try
{
StatoolInfos.crawl(configurationFile);
}
catch (Exception exception)
{
logger.error("Error with [{}]: {}", configurationFile.getAbsoluteFile(), exception.getMessage());
exception.printStackTrace();
}
System.out.println(chrono.format());
}
else if (CLIUtils.isMatching(args, "format", ".+"))
{
Files inputs = FilesUtils.searchEndingWith(new File(args[1]), ".properties");
for (File input : inputs)
{
try
{
StatoolInfos.format(input);
}
catch (Exception exception)
{
logger.error("Error with [{}]: {}", input.getAbsoluteFile(), exception.getMessage());
exception.printStackTrace();
}
}
}
else if (CLIUtils.isMatching(args, "htmlize", ".+\\.conf"))
{
Chrono chrono = new Chrono().start();
File configurationFile = new File(StringUtils.trim(args[1]));
try
{
StatoolInfos.htmlize(configurationFile);
}
catch (Exception exception)
{
logger.error("Error with [{}]: {}", configurationFile.getAbsoluteFile(), exception.getMessage());
exception.printStackTrace();
}
System.out.println(chrono.format());
}
else if (CLIUtils.isMatching(args, "list", "ip", "(-all|-bot|-nobot)", ".+\\.conf*"))
{
BotFilter filter = parseLogFilterOption(args[2]);
File configurationFile = new File(StringUtils.trim(args[3]));
StatoolInfos.listIps(configurationFile, filter);
}
else if (CLIUtils.isMatching(args, "list", "ip", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfos.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++)
{
source.add(new File(args[index]));
}
StatoolInfos.listIps(source, filter);
}
else if (CLIUtils.isMatchingEllipsis(args, "list", "ip", ".+"))
{
Files files = new Files();
for (int source = 2; source < args.length; source++)
{
files.add(new File(args[source]));
}
StatoolInfos.listIps(files, BotFilter.ALL);
}
else if (CLIUtils.isMatching(args, "list", "(file|files)", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfos.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]));
}
StatoolInfos.listAccessFiles(source);
}
else if (CLIUtils.isMatching(args, "list", "(errfile|errfiles)", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfos.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]));
}
StatoolInfos.listErrorFiles(source);
}
else if (CLIUtils.isMatching(args, "list", "(log|logs)", "(-all|-bot|-nobot)", ".+\\.conf*"))
{
BotFilter filter = parseLogFilterOption(args[2]);
File configurationFile = new File(StringUtils.trim(args[3]));
StatoolInfos.listLogs(configurationFile, filter);
}
else if (CLIUtils.isMatching(args, "list", "(log|logs)", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfos.listLogs(configurationFile, BotFilter.ALL);
}
else if (CLIUtils.isMatchingEllipsis(args, "list", "(log|logs)", "(-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]));
}
StatoolInfos.listLogs(source, filter);
}
else if (CLIUtils.isMatchingEllipsis(args, "list", "(log|logs)", ".+"))
{
Files source = new Files();
for (int index = 2; index < args.length; index++)
{
source.add(new File(args[index]));
}
StatoolInfos.listLogs(source, BotFilter.ALL);
}
else if (CLIUtils.isMatching(args, "list", "(errlog|errlogs)", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfos.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]));
}
StatoolInfos.listErrorLogs(source);
}
else if (CLIUtils.isMatching(args, "list", "(useragent|ua)", "(-all|-bot|-nobot)", ".+\\.conf*"))
{
BotFilter filter = parseLogFilterOption(args[2]);
File configurationFile = new File(StringUtils.trim(args[3]));
StatoolInfos.listUserAgents(configurationFile, filter);
}
else if (CLIUtils.isMatching(args, "list", "(useragent|ua)", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfos.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]));
}
StatoolInfos.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]));
}
StatoolInfos.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]));
StatoolInfos.listVisitors(configurationFile, filter);
}
else if (CLIUtils.isMatching(args, "list", "(visitor|visitors)", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfos.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]));
}
StatoolInfos.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]));
}
StatoolInfos.listVisitors(source, BotFilter.ALL);
}
else if (CLIUtils.isMatching(args, "probe", "(-full|-today|-previousday|-\\d+)", ".+"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
String filter = StringUtils.trim(args[1]);
int dayCountFilter;
if (filter.equals("-full"))
{
dayCountFilter = -1;
}
else if (filter.equals("-today"))
{
dayCountFilter = 0;
}
else if (filter.equals("-previousday"))
{
dayCountFilter = 1;
}
else
{
dayCountFilter = -1 * NumberUtils.toInt(filter);
}
try
{
Files inputs = FilesUtils.searchEndingWith(configurationFile, ".conf");
if (inputs.isEmpty())
{
System.out.println("No configuration file found.");
}
else
{
for (File input : inputs)
{
try
{
System.out.println("Probing [" + input + "] with day count filter " + dayCountFilter);
StatoolInfos.probe(input, dayCountFilter);
}
catch (Exception exception)
{
logger.error("Error with [{}]: {}", input.getAbsoluteFile(), exception.getMessage());
exception.printStackTrace();
}
}
}
}
catch (Exception exception)
{
logger.error("Error with [{}]: {}", configurationFile.getAbsoluteFile(), exception.getMessage());
exception.printStackTrace();
}
}
else if (CLIUtils.isMatching(args, "stat", "ip", "(-all|-bot|-nobot)", ".+\\.conf*"))
{
BotFilter filter = parseLogFilterOption(args[2]);
File configurationFile = new File(StringUtils.trim(args[3]));
StatoolInfos.statIps(configurationFile, filter);
}
else if (CLIUtils.isMatching(args, "stat", "ip", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfos.statIps(configurationFile, BotFilter.ALL);
}
else if (CLIUtils.isMatchingEllipsis(args, "stat", "ip", "(-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]));
}
StatoolInfos.statIps(source, filter);
}
else if (CLIUtils.isMatchingEllipsis(args, "stat", "ip", ".+"))
{
Files source = new Files();
for (int index = 2; index < args.length; index++)
{
source.add(new File(args[index]));
}
StatoolInfos.statIps(source, BotFilter.ALL);
}
else if (CLIUtils.isMatching(args, "stat", "(useragent|ua)", "(-all|-bot|-nobot)", ".+\\.conf*"))
{
BotFilter filter = parseLogFilterOption(args[2]);
File configurationFile = new File(StringUtils.trim(args[3]));
StatoolInfos.statUserAgents(configurationFile, filter);
}
else if (CLIUtils.isMatching(args, "stat", "(useragent|ua)", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfos.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]));
}
StatoolInfos.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]));
}
StatoolInfos.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]));
StatoolInfos.statVisitors(configurationFile, filter);
}
else if (CLIUtils.isMatching(args, "stat", "(visitor|visitors)", ".+\\.conf"))
{
File configurationFile = new File(StringUtils.trim(args[2]));
StatoolInfos.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]));
}
StatoolInfos.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]));
}
StatoolInfos.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);
}
catch (Exception exception)
{
logger.error("Error with [{}]: {}", input.getAbsoluteFile(), exception.getMessage());
exception.printStackTrace();
}
}
}
else if (CLIUtils.isMatching(args, "uptime", ".+\\.conf"))
{
Chrono chrono = new Chrono().start();
File configurationFile = new File(StringUtils.trim(args[1]));
try
{
StatoolInfos.uptime(configurationFile);
}
catch (Exception exception)
{
logger.error("Error with [{}]: {}", configurationFile.getAbsoluteFile(), exception.getMessage());
exception.printStackTrace();
}
System.out.println(chrono.format());
}
else
{
System.out.println("Bad usage.");
displayHelp();
}
}
}

View file

@ -1,72 +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.cli;
import fr.devinsy.statoolinfos.core.StatoolInfosException;
/**
* The Class StatoolInfosCLIException.
*/
public class StatoolInfosCLIException extends StatoolInfosException
{
private static final long serialVersionUID = 2986878456227891377L;
/**
* Instantiates a new statool infos CLI exception.
*/
public StatoolInfosCLIException()
{
super();
}
/**
* Instantiates a new statool infos CLI exception.
*
* @param message
* the message
*/
public StatoolInfosCLIException(final String message)
{
super(message);
}
/**
* Instantiates a new statool infos CLI exception.
*
* @param message
* the message
* @param cause
* the cause
*/
public StatoolInfosCLIException(final String message, final Throwable cause)
{
super(message, cause);
}
/**
* Instantiates a new statool infos CLI exception.
*
* @param cause
* the cause
*/
public StatoolInfosCLIException(final Throwable cause)
{
super(cause);
}
}

View file

@ -1,67 +0,0 @@
/*
* 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.core;
import fr.devinsy.statoolinfos.metrics.httpaccess.HttpAccessLog;
/**
* The Enum LogFilter.
*/
public enum BotFilter
{
ALL,
BOT,
NOBOT;
/**
* Matches.
*
* @param log
* the log
* @return true, if successful
*/
public boolean matches(final HttpAccessLog log)
{
boolean result;
if (log == null)
{
result = false;
}
else if (this == ALL)
{
result = true;
}
else if ((this == BOT) && (log.isBot()))
{
result = true;
}
else if ((this == NOBOT) && (!log.isBot()))
{
result = true;
}
else
{
result = false;
}
//
return result;
}
}

View file

@ -1,181 +0,0 @@
/*
* Copyright (C) 2020-022 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.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import fr.devinsy.strings.StringList;
/**
* The Class Categories.
*/
public class Categories extends ArrayList<Category>
{
private static final long serialVersionUID = -221887756635386650L;
/**
* Instantiates a new categories.
*/
public Categories()
{
super();
}
/**
* Find by software.
*
* @param softwareName
* the software name
* @return the category
*/
public Categories findBySoftware(final String softwareName)
{
Categories result;
result = new Categories();
for (Category category : this)
{
if (category.matchesSoftware(softwareName))
{
result.add(category);
}
}
//
return result;
}
/**
* Matches.
*
* @param softwareName
* the software name
* @return true, if successful
*/
public boolean matches(final String softwareName)
{
boolean result;
boolean ended = false;
Iterator<Category> iterator = this.iterator();
result = false;
while (!ended)
{
if (iterator.hasNext())
{
Category category = iterator.next();
if (category.matchesSoftware(softwareName))
{
ended = true;
result = true;
}
}
else
{
ended = true;
result = false;
}
}
//
return result;
}
/**
* Reverse.
*
* @return the categories
*/
public Categories reverse()
{
Categories result;
Collections.reverse(this);
result = this;
//
return result;
}
/**
* Sort.
*
* @param sorting
* the sorting
* @return the issues
*/
public Categories sort(final CategoryComparator.Sorting sorting)
{
Categories result;
sort(new CategoryComparator(sorting));
result = this;
//
return result;
}
/**
* Sort by name.
*
* @return the services
*/
public Categories sortByName()
{
Categories result;
result = sort(CategoryComparator.Sorting.NAME);
//
return result;
}
/**
* To string.
*
* @return the string
*/
@Override
public String toString()
{
String result;
StringList buffer = new StringList();
for (Category category : this)
{
buffer.append(category.getName()).append(",");
}
if (!buffer.isEmpty())
{
buffer.removeLast();
}
result = buffer.toString();
//
return result;
}
}

View file

@ -1,220 +0,0 @@
/*
* Copyright (C) 2020-2022 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.util.Iterator;
import org.apache.commons.lang3.StringUtils;
import fr.devinsy.strings.StringList;
/**
* The Class Category.
*/
public class Category
{
public static final String DEFAULT_LOGO_PATH = "categories/default.svg";
private String name;
private String description;
private StringList softwares;
private String logoPath;
/**
* Instantiates a new category.
*/
public Category(final String name, final String description)
{
this.name = name;
this.description = description;
this.softwares = new StringList();
this.logoPath = DEFAULT_LOGO_PATH;
}
/**
* Instantiates a new category.
*
* @param name
* the name
* @param description
* the description
* @param softwares
* the softwares
*/
public Category(final String name, final String description, final StringList softwares)
{
this.name = name;
this.description = description;
this.softwares = new StringList(softwares);
this.logoPath = DEFAULT_LOGO_PATH;
}
public String getDescription()
{
return this.description;
}
/**
* Gets the logo path.
*
* @return the logo path
*/
public String getLogoPath()
{
String result;
if (StringUtils.isBlank(this.logoPath))
{
result = DEFAULT_LOGO_PATH;
}
else
{
result = this.logoPath;
}
//
return result;
}
public String getName()
{
return this.name;
}
public StringList getSoftwares()
{
return this.softwares;
}
/**
* Gets the technical name.
*
* @return the technical name
*/
public String getTechnicalName()
{
String result;
result = StatoolInfosUtils.toTechnicalName(getName());
//
return result;
}
/**
* Matches.
*
* @param service
* the service
* @return true, if successful
*/
public boolean matches(final Service service)
{
boolean result;
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)
{
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;
}
public void setDescription(final String description)
{
this.description = description;
}
/**
* Sets the logo path.
*
* @param logoPath
* the new logo path
*/
public void setLogoPath(final String logoPath)
{
if (StringUtils.isBlank(logoPath))
{
this.logoPath = DEFAULT_LOGO_PATH;
}
else
{
this.logoPath = "categories/" + logoPath;
}
}
public void setName(final String name)
{
this.name = name;
}
/**
* To string.
*
* @return the string
*/
@Override
public String toString()
{
String result;
result = String.format("[name=%s][description=%s][softwares=%s]", this.name, this.description, this.softwares.toStringSeparatedBy(','));
//
return result;
}
}

View file

@ -1,110 +0,0 @@
/*
*
*/
package fr.devinsy.statoolinfos.core;
import java.util.Comparator;
import fr.devinsy.statoolinfos.util.CompareUtils;
/**
* The Class OrganizationComparator.
*/
public class CategoryComparator implements Comparator<Category>
{
public enum Sorting
{
NAME
}
private Sorting sorting;
/**
* Instantiates a new organization comparator.
*
* @param sorting
* the sorting
*/
public CategoryComparator(final Sorting sorting)
{
this.sorting = sorting;
}
/**
* Compare.
*
* @param alpha
* the alpha
* @param bravo
* the bravo
* @return the int
*/
@Override
public int compare(final Category alpha, final Category bravo)
{
int result;
result = compare(alpha, bravo, this.sorting);
//
return result;
}
/**
* Compare.
*
* @param alpha
* the alpha
* @param bravo
* the bravo
* @param sorting
* the sorting
* @return the int
*/
public static int compare(final Category alpha, final Category bravo, final Sorting sorting)
{
int result;
if (sorting == null)
{
result = 0;
}
else
{
switch (sorting)
{
default:
case NAME:
result = CompareUtils.compare(getName(alpha), getName(bravo));
break;
}
}
//
return result;
}
/**
* Gets the name.
*
* @param source
* the source
* @return the name
*/
public static String getName(final Category source)
{
String result;
if (source == null)
{
result = null;
}
else
{
result = source.getName();
}
//
return result;
}
}

View file

@ -1,630 +0,0 @@
/*
* 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.core;
import java.io.File;
import java.net.MalformedURLException;
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;
/**
* The Class PathProperty.
*/
public class Configuration extends PathPropertyList
{
private static final long serialVersionUID = 2085950843956966741L;
/**
* Instantiates a new federation.
*/
public Configuration()
{
super();
}
/**
* Instantiates a new federation.
*
* @param properties
* the properties
*/
public Configuration(final PathProperties properties)
{
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.
*
* @return the builds the directory
*/
public File getBuildDirectory()
{
File result;
String path = getBuildDirectoryPath();
if (StringUtils.isBlank(path))
{
result = null;
}
else
{
result = new File(path);
}
//
return result;
}
/**
* Gets the builds the directory path.
*
* @return the builds the directory path
*/
public String getBuildDirectoryPath()
{
String result;
result = get("conf.build.directory");
//
return result;
}
/**
* Gets the builds the directory valid.
*
* @return the builds the directory valid
*/
public File getBuildDirectoryValid()
{
File result;
result = getBuildDirectory();
if (result == null)
{
throw new IllegalArgumentException("Undefined build directory.");
}
else if (!result.exists())
{
throw new IllegalArgumentException("Build directory does not exist: " + result.getAbsolutePath());
}
//
return result;
}
/**
* Gets the builds the input.
*
* @return the builds the input
*/
public File getBuildInput()
{
File result;
String path = get("conf.build.input");
if (StringUtils.isBlank(path))
{
result = null;
}
else
{
result = new File(path);
}
//
return result;
}
/**
* Gets the category file.
*
* @return the category file
* @throws StatoolInfosException
* the statool infos exception
*/
public File getCategoryFile() throws StatoolInfosException
{
File result;
String path = get("conf.htmlize.categories");
if (StringUtils.isBlank(path))
{
throw new StatoolInfosException("Entry conf.htmlize.categories is missing in configuration file.");
}
else
{
result = new File(path);
}
//
return result;
}
/**
* Gets the class name.
*
* @return the class name
*/
public String getClassName()
{
String result;
result = get("conf.class");
//
return result;
}
/**
* Gets the crawl cache directory.
*
* @return the crawl cache directory
*/
public File getCrawlCacheDirectory()
{
File result;
result = new File(get("conf.crawl.cache"));
//
return result;
}
/**
* Gets the crawl cache path.
*
* @return the crawl cache path
*/
public String getCrawlCachePath()
{
String result;
result = get("conf.crawl.cache");
//
return result;
}
/**
* Gets the crawl input path.
*
* @return the crawl input path
*/
public String getCrawlInputPath()
{
String result;
result = get("conf.crawl.input");
//
return result;
}
/**
* Gets the crawl input.
*
* @return the crawl input
*/
public URL getCrawlInputURL()
{
URL result;
try
{
String path = getCrawlInputPath();
if (StringUtils.isBlank(path))
{
result = null;
}
else
{
result = new URL(path);
}
}
catch (MalformedURLException exception)
{
exception.printStackTrace();
result = null;
}
//
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.
*
* @return the edito directory
*/
public File getEditoDirectory()
{
File result;
String directoryPath = get("conf.htmlize.edito.directory");
if (StringUtils.isBlank(directoryPath))
{
result = null;
}
else
{
result = new File(directoryPath);
}
//
return result;
}
/**
* Gets the htmlize directory.
*
* @return the htmlize directory
*/
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()
{
String result;
result = get("conf.htmlize.directory");
//
return result;
}
/**
* Gets the htmlize input URL.
*
* @return the htmlize input URL
* @throws MalformedURLException
* the malformed URL exception
*/
public URL getHtmlizeInputURL() throws MalformedURLException
{
URL result;
result = new URL(get("conf.htmlize.input"));
//
return result;
}
/**
* Gets the probe http access log date pattern.
*
* @return the probe http access log date pattern
*/
public String getProbeHttpAccessLogDateTimePattern()
{
String result;
result = get("conf.probe.httpaccesslog.datetimepattern");
//
return result;
}
/**
* Gets the probe http access log path filter.
*
* @return the probe http access log path filter
*/
public String getProbeHttpAccessLogPathFilter()
{
String result;
result = get("conf.probe.httpaccesslog.pathfilter");
//
return result;
}
/**
* Gets the probe http access log pattern.
*
* @return the probe http access log pattern
*/
public String getProbeHttpAccessLogPattern()
{
String result;
result = get("conf.probe.httpaccesslog.pattern");
//
return result;
}
/**
* Gets the probe http access log file.
*
* @return the probe http access log file
*/
public String getProbeHttpAccessLogSource()
{
String result;
result = get("conf.probe.httpaccesslog.file");
//
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.
*
* @return the probe http error log source
*/
public String getProbeHttpErrorLogSource()
{
String result;
result = get("conf.probe.httperrorlog.file");
//
return result;
}
/**
* Gets the probe target.
*
* @return the probe target
*/
public File getProbeTarget()
{
File result;
String filename = get("conf.probe.target");
if (StringUtils.isBlank(filename))
{
result = null;
}
else
{
result = new File(filename);
}
//
return result;
}
/**
* Gets the probe types.
*
* @return the probe types
*/
public StringList getProbeTypes()
{
StringList result;
result = new StringList();
String types = get("conf.probe.types");
if (!StringUtils.isBlank(types))
{
for (String token : types.split("[, ;]"))
{
if (!StringUtils.isBlank(token))
{
result.append(token);
}
}
}
//
return result;
}
/**
* Checks for valid cache.
*
* @return true, if successful
*/
public boolean hasValidCache()
{
boolean result;
String path = get("conf.crawl.cache");
if (StringUtils.isBlank(path))
{
result = false;
}
else if (!new File(path).exists())
{
result = false;
}
else
{
result = true;
}
//
return result;
}
/**
* Checks if is federation.
*
* @return true, if is federation
*/
public boolean isFederation()
{
boolean result;
result = StringUtils.equals(getClassName(), "federation");
//
return result;
}
/**
* Checks if is organization.
*
* @return true, if is organization
*/
public boolean isOrganization()
{
boolean result;
result = StringUtils.equals(getClassName(), "organization");
//
return result;
}
/**
* Checks if is service.
*
* @return true, if is service
*/
public boolean isService()
{
boolean result;
result = StringUtils.equals(getClassName(), "service");
//
return result;
}
}

View file

@ -1,150 +0,0 @@
/*
* 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,428 +0,0 @@
/*
* Copyright (C) 2020-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 java.io.File;
import java.io.IOException;
import java.net.URL;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.statoolinfos.checker.PropertyChecker;
import fr.devinsy.statoolinfos.checker.PropertyChecks;
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.properties.PropertyClassType;
import fr.devinsy.statoolinfos.util.Chrono;
import fr.devinsy.strings.StringList;
import fr.devinsy.strings.StringSet;
/**
* The Class PathProperty.
*/
public class Factory
{
private static Logger logger = LoggerFactory.getLogger(Factory.class);
/**
* Instantiates a new factory.
*/
private Factory()
{
}
/**
* Load categories.
*
* @param source
* the source
* @return the categories
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static Categories loadCategories(final File source) throws IOException
{
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();
//
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 File 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.
*
* @param configurationFile
* the configuration file
* @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
{
Configuration result;
PathProperties properties = PathPropertyUtils.load(configurationFile);
result = new Configuration(properties);
//
return result;
}
/**
* Load federation.
*
* @param inputURL
* the input URL
* @param cache
* the cache
* @return the federation
* @throws StatoolInfosException
* the statool infos exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static Federation loadFederation(final URL inputURL, final CrawlCache cache) throws StatoolInfosException, IOException
{
Federation result;
System.out.println("Loading federation " + inputURL);
Chrono chrono = new Chrono().start();
if (inputURL == null)
{
throw new IllegalArgumentException("Null input URL.");
}
else if (cache == null)
{
throw new IllegalArgumentException("Null cache URL.");
}
else
{
File federationFile = cache.restoreFile(inputURL);
if (federationFile == null)
{
throw new IllegalArgumentException("Htmlize input file undefined.");
}
else if (!federationFile.exists())
{
throw new IllegalArgumentException("Htmlize input file is missing.");
}
else if (federationFile.isDirectory())
{
throw new IllegalArgumentException("Htmlize input file is a directory.");
}
else
{
PathProperties properties = PathPropertyUtils.load(federationFile);
result = new Federation(properties);
result.setInputURL(inputURL);
result.setInputFile(federationFile);
result.setLogoFileName(result.getTechnicalName() + "-logo" + StringUtils.defaultIfBlank(cache.getExtension(result.getLogoURL()), ".png"));
PropertyChecker checker = new PropertyChecker();
PropertyChecks checks = checker.checkFederation(result.getInputFile());
result.getInputChecks().addAll(checks);
result.getInputChecks().setFileName(result.getLocalFileName());
PathProperties subs = result.getByPrefix("subs");
for (PathProperty property : subs)
{
if (StringUtils.startsWith(property.getValue(), "http"))
{
URL subInputURL = new URL(property.getValue());
Organization organization = loadOrganization(subInputURL, cache);
if (organization != null)
{
organization.setFederation(result);
result.getOrganizations().add(organization);
}
}
}
//
result.getCrawlJournal().addAll(cache.restoreCrawlJournal());
}
}
System.out.println("Federation loaded in " + chrono.format());
//
return result;
}
/**
* Load metrics.
*
* @param inputURL
* the input URL
* @param cache
* the cache
* @param prefixPath
* the prefix path
* @return the metrics
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static Metrics loadMetrics(final URL inputURL, final CrawlCache cache, final String prefixPath) throws IOException
{
Metrics result;
System.out.println("Loading metrics " + inputURL);
File inputFile = cache.restoreFile(inputURL);
if (inputFile == null)
{
logger.warn("WARNING: metrics not found in cache [{}]", inputURL);
result = null;
}
else
{
PathProperties properties = PathPropertyUtils.load(inputFile);
result = new Metrics(properties);
result.setLocalFileNamePrefix(prefixPath);
result.setInputFile(inputFile);
result.setInputURL(inputURL);
//
PropertyChecker checker = new PropertyChecker();
PropertyChecks checks = checker.checkMetrics(result.getInputFile());
result.getInputChecks().addAll(checks);
result.getInputChecks().setFileName(result.getLocalFileName());
}
//
return result;
}
/**
* Load organization.
*
* @param inputURL
* the input
* @param cache
* the cache
* @return the organization
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static Organization loadOrganization(final URL inputURL, final CrawlCache cache) throws IOException
{
Organization result;
System.out.println("Loading organization " + inputURL);
File inputFile = cache.restoreFile(inputURL);
if (inputFile == null)
{
result = null;
logger.warn("WARNING: organization not found in cache [{}]", inputURL);
}
else
{
PathProperties properties = PathPropertyUtils.load(inputFile);
result = new Organization(properties);
if (result.isValid())
{
result.setInputFile(inputFile);
result.setInputURL(inputURL);
result.setLogoFileName(result.getTechnicalName() + "-logo" + StringUtils.defaultIfBlank(cache.getExtension(result.getLogoURL()), ".png"));
//
PropertyChecker checker = new PropertyChecker();
PropertyChecks checks = checker.checkOrganization(result.getInputFile());
checks.setFileName(result.getLocalFileName());
result.getInputChecks().addAll(checks);
//
PathProperties subs = result.getByPrefix("subs");
for (PathProperty property : subs)
{
if (StringUtils.startsWith(property.getValue(), "http"))
{
URL serviceInputURL = new URL(property.getValue());
Service service = loadService(serviceInputURL, cache, result);
if (service != null)
{
result.getServices().add(service);
}
}
}
//
CrawlJournal journal = cache.restoreCrawlJournal();
result.getCrawlJournal().add(journal.getByUrl(inputURL));
result.getCrawlJournal().addAll(journal.searchByParent(result.getInputURL()));
for (Service service : result.getServices())
{
result.getCrawlJournal().addAll(journal.searchByParent(service.getInputURL()));
}
}
else
{
result = null;
logger.warn("WARNING: organization has invalid file [{}]", inputURL);
}
}
//
return result;
}
/**
* Load service.
*
* @return the service
* @throws IOException
*/
public static Service loadService(final URL inputURL, final CrawlCache cache, final Organization organization) throws IOException
{
Service result;
System.out.println("Loading service " + inputURL);
File inputFile = cache.restoreFile(inputURL);
if (inputFile == null)
{
logger.warn("WARNING: service not found in cache [{}]", inputURL);
result = null;
}
else
{
PathPropertyList properties = PathPropertyUtils.load(inputFile);
if (properties.getClassType() != PropertyClassType.SERVICE)
{
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(organization.getTechnicalName() + "-" + result.getTechnicalName() + "-logo" + StringUtils.defaultIfBlank(cache.getExtension(result.getLogoURL()), ".png"));
//
PathProperties subs = result.getByPrefix("subs");
for (PathProperty property : subs)
{
if (StringUtils.startsWith(property.getValue(), "http"))
{
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);
//
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."));
}
}
}
//
return result;
}
}

View file

@ -1,831 +0,0 @@
/*
* Copyright (C) 2020-2022 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.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.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;
/**
* The Class PathProperty.
*/
public class Federation extends PathPropertyList
{
private static final long serialVersionUID = -8970835291634661580L;
private Organizations organizations;
private URL inputURL;
private File inputFile;
private String logoFileName;
private PropertyChecks inputChecks;
private CrawlJournal crawlJournal;
/**
* Instantiates a new federation.
*/
public Federation()
{
super();
this.inputChecks = new PropertyChecks();
this.organizations = new Organizations();
this.crawlJournal = new CrawlJournal();
}
/**
* Instantiates a new federation.
*
* @param properties
* the properties
*/
public Federation(final PathProperties properties)
{
super(properties);
this.inputChecks = new PropertyChecks();
if ((properties == null) || (StringUtils.isBlank(properties.get("federation.name"))))
{
throw new IllegalArgumentException("Not a federation.");
}
else
{
this.organizations = new Organizations();
this.crawlJournal = new CrawlJournal();
}
}
/**
* 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.
*
* @return the contact email
*/
public String getContactEmail()
{
String result;
result = get("federation.contact.email");
//
return result;
}
/**
* Gets the contact URL.
*
* @return the contact URL
*/
public URL getContactURL()
{
URL result;
result = getURL("federation.contact.url");
//
return result;
}
/**
* Gets the crawl date.
*
* @return the crawl date
*/
public LocalDateTime getCrawlDate()
{
LocalDateTime result;
result = LocalDateTime.parse(get("crawl.datetime"));
//
return result;
}
/**
* Gets the crawled date.
*
* @return the crawled date
*/
public LocalDateTime getCrawledDate()
{
LocalDateTime result;
result = LocalDateTime.parse(get("crawl.file.datetime"));
if (result.getYear() == 1970)
{
result = getCrawlDate();
}
//
return result;
}
public CrawlJournal getCrawlJournal()
{
return this.crawlJournal;
}
/**
* Gets the description.
*
* @return the description
*/
public String getDescription()
{
String result;
result = get("federation.description");
//
return result;
}
/**
* Gets the idle organizations.
*
* @return the idle organizations
*/
public Organizations getIdleOrganizations()
{
Organizations result;
result = this.organizations.getIdles();
//
return result;
}
public PropertyChecks getInputChecks()
{
return this.inputChecks;
}
/**
* Gets the input checks all.
*
* @return the input checks all
*/
public PropertyChecks getInputChecksAll()
{
PropertyChecks result;
result = new PropertyChecks();
result.addAll(this.getInputChecks());
for (Organization organization : this.organizations)
{
result.addAll(organization.getInputChecksAll());
}
//
return result;
}
public File getInputFile()
{
return this.inputFile;
}
public URL getInputURL()
{
return this.inputURL;
}
/**
* Gets the legal website.
*
* @return the legal website
*/
public URL getLegalURL()
{
URL result;
String value = get("federation.legal.url", "federation.legal");
result = URLUtils.of(value);
//
return result;
}
/**
* Gets the local file base name.
*
* @return the local file base name
*/
public String getLocalFileBaseName()
{
String result;
result = getTechnicalName();
//
return result;
}
/**
* Gets the local file name.
*
* @return the local file name
*/
public String getLocalFileName()
{
String result;
result = getTechnicalName() + ".properties";
//
return result;
}
public String getLogoFileName()
{
return this.logoFileName;
}
/**
* Gets the logo URL.
*
* @return the logo URL
*/
public URL getLogoURL()
{
URL result;
try
{
String path = get("federation.logo");
if ((StringUtils.isBlank(path)) || (!StringUtils.startsWith(path, "http")))
{
result = null;
}
else
{
result = new URL(path);
}
}
catch (MalformedURLException exception)
{
result = null;
}
//
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.
*
* @param path
* the path
* @return the metric month values all
*/
public MonthValues getMetricMonthValuesAll(final String path)
{
MonthValues result;
result = getMetricMonthValues(path);
for (Organization organization : getOrganizations())
{
result.addAll(organization.getMetricMonthValuesAll(path));
}
//
return result;
}
/**
* Gets the metric week values all.
*
* @param path
* the path
* @return the metric week values all
*/
public WeekValues getMetricWeekValuesAll(final String path)
{
WeekValues result;
result = getMetricWeekValues(path);
for (Organization organization : getOrganizations())
{
result.addAll(organization.getMetricWeekValuesAll(path));
}
//
return result;
}
/**
* Gets the metric year values all.
*
* @param path
* the path
* @return the metric year values all
*/
public YearValues getMetricYearValuesAll(final String path)
{
YearValues result;
result = getMetricYearValues(path);
for (Organization organization : getOrganizations())
{
result.addAll(organization.getMetricYearValuesAll(path));
}
//
return result;
}
/**
* Gets the name.
*
* @return the name
*/
public String getName()
{
String result;
result = get("federation.name");
//
return result;
}
/**
* Gets the organiation count.
*
* @return the organiation count
*/
public int getOrganiationCount()
{
int result;
result = this.organizations.size();
//
return result;
}
public Organizations getOrganizations()
{
return this.organizations;
}
/**
* Gets the service count.
*
* @return the service count
*/
public int getServiceCount()
{
int result;
result = 0;
for (Organization organization : getActiveOrganizations())
{
result += organization.getServiceCount();
}
//
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.
*
* @return the all services
*/
public Services getServicesAll()
{
Services result;
result = new Services();
for (Organization organization : this.organizations)
{
result.addAll(organization.getServices());
}
//
return result;
}
/**
* Gets the software catalog.
*
* @return the software catalog
*/
public Softwares getSoftwares()
{
Softwares result;
result = new Softwares();
for (Service service : getServices())
{
if (StringUtils.isNotBlank(service.getSoftwareName()))
{
Software software = result.get(service.getSoftwareName());
if (software == null)
{
software = new Software(service.getSoftwareName(), service.getSoftwareDescription());
result.put(software);
}
}
}
//
return result;
}
/**
* Gets the start date.
*
* @return the start date
*/
public LocalDate getStartDate()
{
LocalDate result;
result = StatoolInfosUtils.parseDate(getStartDateValue());
//
return result;
}
/**
* Gets the start date.
*
* @return the start date
*/
public String getStartDateValue()
{
String result;
result = get("federation.startdate");
//
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.
*
* @return the technical doc website
*/
public URL getTechnicalGuideURL()
{
URL result;
String value = get("federation.guide.technical", "federation.guide.technical.url");
result = URLUtils.of(value);
//
return result;
}
/**
* Gets the technical name.
*
* @return the technical name
*/
public String getTechnicalName()
{
String result;
result = StatoolInfosUtils.toTechnicalName(getName());
//
return result;
}
/**
* Gets the URL active all.
*
* @return the URL active all
*/
public URLSet getURLActiveAll()
{
URLSet result;
result = new URLSet();
//
result.add(getContactURL());
result.add(getLegalURL());
result.add(getLogoURL());
result.add(getTechnicalGuideURL());
result.add(getUserGuideURL());
result.add(getWebsiteURL());
//
for (Organization organization : getOrganizations())
{
result.addAll(organization.getURLActiveAll());
}
//
return result;
}
/**
* Gets the URL all.
*
* @return the URL all
*/
public URLSet getURLAll()
{
URLSet result;
result = new URLSet();
//
result.add(getContactURL());
result.add(getLegalURL());
result.add(getLogoURL());
result.add(getTechnicalGuideURL());
result.add(getUserGuideURL());
result.add(getWebsiteURL());
//
for (Organization organization : getOrganizations())
{
result.addAll(organization.getURLAll());
}
//
return result;
}
/**
* Gets the user doc website.
*
* @return the user doc website
*/
public URL getUserGuideURL()
{
URL result;
String value = get("federation.documentation",
"federation.documentation.url",
"federation.documentation.user",
"federation.documentation.user.url",
"service.documentation.tutorial",
"federation.documentation.tutorial.url",
"federation.guide.user",
"federation.guide.user.url");
result = URLUtils.of(value);
//
return result;
}
/**
* Gets the website.
*
* @return the website
*/
public URL getWebsiteURL()
{
URL result;
result = getURL("federation.website");
//
return result;
}
/**
* Sets the input file.
*
* @param inputFile
* the new input file
*/
public void setInputFile(final File inputFile)
{
this.inputFile = inputFile;
}
public void setInputURL(final URL inputURL)
{
this.inputURL = inputURL;
}
public void setLogoFileName(final String logoFileName)
{
this.logoFileName = logoFileName;
}
}

View file

@ -1,182 +0,0 @@
/*
* Copyright (C) 2021 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.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;
import fr.devinsy.statoolinfos.properties.PathPropertyList;
/**
* The Class Metrics.
*/
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;
private PropertyChecks inputChecks;
/**
* Instantiates a new service.
*/
public Metrics()
{
this(null);
}
/**
* Instantiates a new service.
*
* @param properties
* the properties
*/
public Metrics(final PathProperties properties)
{
super(properties);
this.inputChecks = new PropertyChecks();
}
/**
* Gets the crawl date.
*
* @return the crawl date
*/
public LocalDateTime getCrawlDate()
{
LocalDateTime result;
result = LocalDateTime.parse(get("crawl.datetime"));
//
return result;
}
/**
* Gets the crawled date.
*
* @return the crawled date
*/
public LocalDateTime getCrawledDate()
{
LocalDateTime result;
result = LocalDateTime.parse(get("crawl.file.datetime"));
if (result.getYear() == 1970)
{
result = getCrawlDate();
}
//
return result;
}
public PropertyChecks getInputChecks()
{
return this.inputChecks;
}
public File getInputFile()
{
return this.inputFile;
}
public URL getInputURL()
{
return this.inputURL;
}
/**
* Gets the local file base name.
*
* @return the local file base name
*/
public String getLocalFileBaseName()
{
String result;
result = this.localFileNamePrefix + "-" + getTechnicalName();
//
return result;
}
/**
* Gets the local name.
*
* @return the local name
*/
public String getLocalFileName()
{
String result;
result = getLocalFileBaseName() + ".properties";
//
return result;
}
public String getLocalFileNamePrefix()
{
return this.localFileNamePrefix;
}
/**
* Gets the technical name.
*
* @return the technical name
*/
public String getTechnicalName()
{
String result;
String name = FilenameUtils.getBaseName(this.inputURL.getPath());
result = StatoolInfosUtils.toTechnicalName(name);
//
return result;
}
public void setInputFile(final File inputFile)
{
this.inputFile = inputFile;
}
public void setInputURL(final URL inputURL)
{
this.inputURL = inputURL;
}
public void setLocalFileNamePrefix(final String localFileNamePrefix)
{
this.localFileNamePrefix = localFileNamePrefix;
}
}

View file

@ -1,55 +0,0 @@
/*
* Copyright (C) 2021 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.util.ArrayList;
import java.util.Collections;
/**
* The Class MetricsList.
*/
public class MetricsList extends ArrayList<Metrics>
{
private static final long serialVersionUID = 6241734209264875306L;
/**
* Instantiates a new metrics list.
*/
public MetricsList()
{
super();
}
/**
* Reverse.
*
* @return the services
*/
public MetricsList reverse()
{
MetricsList result;
Collections.reverse(this);
result = this;
//
return result;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,182 +0,0 @@
/*
*
*/
package fr.devinsy.statoolinfos.core;
import java.util.Comparator;
import fr.devinsy.statoolinfos.util.CompareUtils;
/**
* The Class OrganizationComparator.
*/
public class OrganizationComparator implements Comparator<Organization>
{
public enum Sorting
{
NAME,
SERVICE_COUNT,
REVERSE_SERVICE_COUNT,
USER_COUNT
}
private Sorting sorting;
/**
* Instantiates a new organization comparator.
*
* @param sorting
* the sorting
*/
public OrganizationComparator(final Sorting sorting)
{
this.sorting = sorting;
}
/**
* Compare.
*
* @param alpha
* the alpha
* @param bravo
* the bravo
* @return the int
*/
@Override
public int compare(final Organization alpha, final Organization bravo)
{
int result;
result = compare(alpha, bravo, this.sorting);
//
return result;
}
/**
* Compare.
*
* @param alpha
* the alpha
* @param bravo
* the bravo
* @param sorting
* the sorting
* @return the int
*/
public static int compare(final Organization alpha, final Organization bravo, final Sorting sorting)
{
int result;
if (sorting == null)
{
result = 0;
}
else
{
switch (sorting)
{
default:
case NAME:
result = CompareUtils.compareIgnoreCase(getName(alpha), getName(bravo));
break;
case SERVICE_COUNT:
result = CompareUtils.compare(getServiceCount(alpha), getServiceCount(bravo));
if (result == 0)
{
result = CompareUtils.compareIgnoreCase(getName(alpha), getName(bravo));
}
break;
case REVERSE_SERVICE_COUNT:
result = -CompareUtils.compare(getServiceCount(alpha), getServiceCount(bravo));
if (result == 0)
{
result = CompareUtils.compareIgnoreCase(getName(alpha), getName(bravo));
}
break;
case USER_COUNT:
result = CompareUtils.compare(getUserCount(alpha), getUserCount(bravo));
break;
}
}
//
return result;
}
/**
* Gets the name.
*
* @param source
* the source
* @return the name
*/
public static String getName(final Organization source)
{
String result;
if (source == null)
{
result = null;
}
else
{
result = source.getName();
}
//
return result;
}
/**
* Gets the service count.
*
* @param source
* the source
* @return the service count
*/
public static Long getServiceCount(final Organization source)
{
Long result;
if (source == null)
{
result = null;
}
else
{
result = (long) source.getServiceCount();
}
//
return result;
}
/**
* Gets the user count.
*
* @param source
* the source
* @return the user count
*/
public static Long getUserCount(final Organization source)
{
Long result;
if (source == null)
{
result = null;
}
else
{
result = (long) source.getUserCount();
}
//
return result;
}
}

View file

@ -1,352 +0,0 @@
/*
* Copyright (C) 2020-2022 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.time.Year;
import java.util.ArrayList;
import java.util.Collections;
/**
* The Class Organizations.
*/
public class Organizations extends ArrayList<Organization>
{
private static final long serialVersionUID = 2092235357983955170L;
/**
* Instantiates a new organizations.
*/
public Organizations()
{
super();
}
/**
* 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.
*
* @param value
* the value
* @return the organizations
*/
public Organizations filterBySocialNetwork(final SocialNetworks value)
{
Organizations result;
result = new Organizations();
for (Organization organization : this)
{
if (organization.hasSocialNetwork(value))
{
result.add(organization);
}
}
//
return result;
}
/**
* Filter by social network.
*
* @return the organizations
*/
public Organizations filterBySocialNetworks()
{
Organizations result;
result = new Organizations();
for (Organization organization : this)
{
if (organization.hasSocialNetwork())
{
result.add(organization);
}
}
//
return result;
}
/**
* Filter member for.
*
* @param entityName
* the entity name
* @return the organizations
*/
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.getActiveServiceCount();
}
//
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);
}
}
//
return result;
}
/**
* Gets the service count.
*
* @return the service count
*/
public int getServiceCount()
{
int result;
result = 0;
for (Organization organization : this)
{
result += organization.getServiceCount();
}
//
return result;
}
/**
* Reverse.
*
* @return the services
*/
public Organizations reverse()
{
Organizations result;
Collections.reverse(this);
result = this;
//
return result;
}
/**
* Sort.
*
* @param sorting
* the sorting
* @return the issues
*/
public Organizations sort(final OrganizationComparator.Sorting sorting)
{
Organizations result;
sort(new OrganizationComparator(sorting));
result = this;
//
return result;
}
/**
* Sort by name.
*
* @return the services
*/
public Organizations sortByName()
{
Organizations result;
result = sort(OrganizationComparator.Sorting.NAME);
//
return result;
}
/**
* Sort by reverse service count.
*
* @return the organizations
*/
public Organizations sortByReverseServiceCount()
{
Organizations result;
result = sort(OrganizationComparator.Sorting.REVERSE_SERVICE_COUNT);
//
return result;
}
/**
* Sort by service count.
*
* @return the organizations
*/
public Organizations sortByServiceCount()
{
Organizations result;
result = sort(OrganizationComparator.Sorting.SERVICE_COUNT);
//
return result;
}
}

View file

@ -1,30 +0,0 @@
/*
* Copyright (C) 2020-2021 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;
/**
* The Enum LogFilter.
*/
public enum ProbePeriod
{
FULL,
TODAY,
PREVIOUS_DAY,
PREVIOUS_DAYS_7;
}

File diff suppressed because it is too large Load diff

View file

@ -1,167 +0,0 @@
/*
* Copyright (C) 2020-2021 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.util.Comparator;
import fr.devinsy.statoolinfos.util.CompareUtils;
/**
* The Class ServiceComparator.
*/
public class ServiceComparator implements Comparator<Service>
{
public enum Sorting
{
NAME,
USER_COUNT,
REVERSE_USER_COUNT
}
private Sorting sorting;
/**
* Instantiates a new category stat comparator.
*
* @param sorting
* the sorting
*/
public ServiceComparator(final Sorting sorting)
{
this.sorting = sorting;
}
/**
* Compare.
*
* @param alpha
* the alpha
* @param bravo
* the bravo
* @return the int
*/
@Override
public int compare(final Service alpha, final Service bravo)
{
int result;
result = compare(alpha, bravo, this.sorting);
//
return result;
}
/**
* Compare.
*
* @param alpha
* the alpha
* @param bravo
* the bravo
* @param sorting
* the sorting
* @return the int
*/
public static int compare(final Service alpha, final Service bravo, final Sorting sorting)
{
int result;
if (sorting == null)
{
result = 0;
}
else
{
switch (sorting)
{
default:
case NAME:
result = CompareUtils.compareIgnoreCase(getName(alpha), getName(bravo));
break;
case USER_COUNT:
result = CompareUtils.compare(getUserCount(alpha), getUserCount(bravo));
if (result == 0)
{
result = CompareUtils.compareIgnoreCase(getName(alpha), getName(bravo));
}
break;
case REVERSE_USER_COUNT:
result = -CompareUtils.compare(getUserCount(alpha), getUserCount(bravo));
if (result == 0)
{
result = CompareUtils.compareIgnoreCase(getName(alpha), getName(bravo));
}
break;
}
}
//
return result;
}
/**
* Gets the name.
*
* @param source
* the source
* @return the name
*/
public static String getName(final Service source)
{
String result;
if (source == null)
{
result = null;
}
else
{
result = source.getName();
}
//
return result;
}
/**
* Gets the user count.
*
* @param source
* the source
* @return the user count
*/
public static Long getUserCount(final Service source)
{
Long result;
if (source == null)
{
result = null;
}
else
{
result = (long) source.getUserCount();
}
//
return result;
}
}

View file

@ -1,319 +0,0 @@
/*
* Copyright (C) 2020-2022 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.time.LocalDate;
import java.time.Year;
import java.util.ArrayList;
import java.util.Collections;
import org.apache.commons.lang3.StringUtils;
import fr.devinsy.statoolinfos.core.Service.Status;
/**
* The Class Services.
*/
public class Services extends ArrayList<Service>
{
private static final long serialVersionUID = -6288956439933064467L;
/**
* Instantiates a new services.
*/
public Services()
{
super();
}
/**
* 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.
*
* @param category
* the category
* @return the by
*/
public Services getBy(final Category category)
{
Services result;
result = new Services();
for (Service service : this)
{
if (category.matches(service))
{
result.add(service);
}
}
//
return result;
}
/**
* Gets the by.
*
* @param software
* the software
* @return the by
*/
public Services getBy(final Software software)
{
Services result;
result = new Services();
for (Service service : this)
{
String serviceSoftwareName = StatoolInfosUtils.toTechnicalName(service.getSoftwareName());
String softwareName = StatoolInfosUtils.toTechnicalName(software.getName());
if (StringUtils.equals(serviceSoftwareName, softwareName))
{
result.add(service);
}
}
//
return result;
}
/**
* Gets the by.
*
* @param status
* the category
* @return the by
*/
public Services getBy(final Status status)
{
Services result;
result = new Services();
for (Service service : this)
{
if (service.getStatus() == status)
{
result.add(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 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.
*
* @return the services
*/
public Services reverse()
{
Services result;
Collections.reverse(this);
result = this;
//
return result;
}
/**
* Sort.
*
* @param sorting
* the sorting
* @return the issues
*/
public Services sort(final ServiceComparator.Sorting sorting)
{
Services result;
sort(new ServiceComparator(sorting));
result = this;
//
return result;
}
/**
* Sort by name.
*
* @return the services
*/
public Services sortByName()
{
Services result;
result = sort(ServiceComparator.Sorting.NAME);
//
return result;
}
/**
* Of.
*
* @param service
* the service
* @return the services
*/
public static Services of(final Service service)
{
Services result;
result = new Services();
if (service != null)
{
result.add(service);
}
//
return result;
}
}

View file

@ -1,28 +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;
/**
* The Enum SocialNetworks.
*/
public enum SocialNetworks
{
DIASPORA,
MASTODON
}

View file

@ -1,130 +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 fr.devinsy.strings.StringList;
/**
* The Class Software.
*/
public class Software
{
private String name;
private String description;
private StringList aliases;
/**
* Instantiates a new software.
*
* @param name
* the name
*/
public Software(final String name)
{
this(name, "");
}
/**
* Instantiates a new software.
*
* @param name
* the name
* @param description
* the description
*/
public Software(final String name, final String description)
{
this.name = name;
this.description = description;
this.aliases = new StringList(name);
}
/**
* Instantiates a new software.
*
* @param name
* the name
* @param description
* the description
* @param softwares
* the softwares
*/
public Software(final String name, final String description, final StringList softwares)
{
this.name = name;
this.description = description;
this.aliases = new StringList(softwares);
}
public StringList getAliases()
{
return this.aliases;
}
public String getDescription()
{
return this.description;
}
public String getName()
{
return this.name;
}
/**
* Gets the technical name.
*
* @return the technical name
*/
public String getTechnicalName()
{
String result;
result = StatoolInfosUtils.toTechnicalName(getName());
//
return result;
}
public void setDescription(final String description)
{
this.description = description;
}
public void setName(final String name)
{
this.name = name;
}
/**
* To string.
*
* @return the string
*/
@Override
public String toString()
{
String result;
result = String.format("[name=%s][description=%s][aliases=%s]", this.name, this.description, this.aliases.toStringSeparatedBy(','));
//
return result;
}
}

View file

@ -1,110 +0,0 @@
/*
*
*/
package fr.devinsy.statoolinfos.core;
import java.util.Comparator;
import fr.devinsy.statoolinfos.util.CompareUtils;
/**
* The Class SoftwareComparator.
*/
public class SoftwareComparator implements Comparator<Software>
{
public enum Sorting
{
NAME
}
private Sorting sorting;
/**
* Instantiates a new organization comparator.
*
* @param sorting
* the sorting
*/
public SoftwareComparator(final Sorting sorting)
{
this.sorting = sorting;
}
/**
* Compare.
*
* @param alpha
* the alpha
* @param bravo
* the bravo
* @return the int
*/
@Override
public int compare(final Software alpha, final Software bravo)
{
int result;
result = compare(alpha, bravo, this.sorting);
//
return result;
}
/**
* Compare.
*
* @param alpha
* the alpha
* @param bravo
* the bravo
* @param sorting
* the sorting
* @return the int
*/
public static int compare(final Software alpha, final Software bravo, final Sorting sorting)
{
int result;
if (sorting == null)
{
result = 0;
}
else
{
switch (sorting)
{
default:
case NAME:
result = CompareUtils.compare(getName(alpha), getName(bravo));
break;
}
}
//
return result;
}
/**
* Gets the name.
*
* @param source
* the source
* @return the name
*/
public static String getName(final Software source)
{
String result;
if (source == null)
{
result = null;
}
else
{
result = source.getName();
}
//
return result;
}
}

View file

@ -1,89 +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.util.ArrayList;
import java.util.Collections;
/**
* The Class Categories.
*/
public class SoftwareList extends ArrayList<Software>
{
private static final long serialVersionUID = -3197394621123996060L;
/**
* Instantiates a new software list.
*/
public SoftwareList()
{
super();
}
/**
* Reverse.
*
* @return the software list
*/
public SoftwareList reverse()
{
SoftwareList result;
Collections.reverse(this);
result = this;
//
return result;
}
/**
* Sort.
*
* @param sorting
* the sorting
* @return the issues
*/
public SoftwareList sort(final SoftwareComparator.Sorting sorting)
{
SoftwareList result;
sort(new SoftwareComparator(sorting));
result = this;
//
return result;
}
/**
* Sort by name.
*
* @return the services
*/
public SoftwareList sortByName()
{
SoftwareList result;
result = sort(SoftwareComparator.Sorting.NAME);
//
return result;
}
}

View file

@ -1,85 +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.util.HashMap;
/**
* The Class Softwares.
*/
public class Softwares extends HashMap<String, Software>
{
private static final long serialVersionUID = 4780901718767657693L;
/**
* Instantiates a new softwares.
*/
public Softwares()
{
super();
}
/**
* Builds the key.
*
* @param source
* the source
* @return the string
*/
private String buildKey(final String source)
{
String result;
result = StatoolInfosUtils.toTechnicalName(source);
//
return result;
}
/**
* Gets the.
*
* @param key
* the key
* @return the software
*/
public Software get(final String key)
{
Software result;
result = super.get(buildKey(key));
//
return result;
}
/**
* Put.
*
* @param software
* the software
*/
public void put(final Software software)
{
for (String alias : software.getAliases())
{
put(buildKey(alias), software);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,72 +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;
/**
* The Class JugaException.
*
* @author Christian Pierre MOMON (christian.momon@devinsy.fr)
*/
public class StatoolInfosException extends Exception
{
private static final long serialVersionUID = 8323299610751708972L;
/**
* Instantiates a new Juga exception.
*/
public StatoolInfosException()
{
super();
}
/**
* Instantiates a new Juga exception.
*
* @param message
* the message
*/
public StatoolInfosException(final String message)
{
super(message);
}
/**
* Instantiates a new Juga exception.
*
* @param message
* the message
* @param cause
* the cause
*/
public StatoolInfosException(final String message, final Throwable cause)
{
super(message, cause);
}
/**
* Instantiates a new Juga exception.
*
* @param cause
* the cause
*/
public StatoolInfosException(final Throwable cause)
{
super(cause);
}
}

View file

@ -1,839 +0,0 @@
/*
* Copyright (C) 2020-2022 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.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
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;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.Locale;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
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;
/**
* The Class StatoolInfosUtils.
*/
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.
*
* @param epoch
* the epoch
* @return the local date time
*/
public static LocalDateTime epochToLocalDateTime(final long epoch)
{
LocalDateTime result;
result = Instant.ofEpochMilli(epoch).atZone(ZoneId.systemDefault()).toLocalDateTime();
//
return result;
}
/**
* File local date time.
*
* @param file
* the file
* @return the local date time
*/
public static LocalDateTime fileLocalDateTime(final File file)
{
LocalDateTime result;
long epoch = file.lastModified();
result = epochToLocalDateTime(epoch);
//
return result;
}
/**
* Find extension.
*
* @param file
* the file
* @return the string
*/
public static String findExtension(final File file)
{
String result;
try
{
Tika tika = new Tika();
String mimeTypeLabel = tika.detect(file);
MimeType mimeType = MimeTypes.getDefaultMimeTypes().forName(mimeTypeLabel);
result = mimeType.getExtension();
// Because Tika failed to recognize SVG file without xml header
// line.
if (result.equals(".txt") && (StringUtils.startsWithIgnoreCase(FileUtils.readFileToString(file, StandardCharsets.UTF_8), "<svg")))
{
result = ".svg";
}
}
catch (IOException | MimeTypeException exception)
{
exception.printStackTrace();
result = "";
}
//
return result;
}
/**
* Generate cat logo.
*
* @param seed
* the seed
* @param target
* the target
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void generateCatLogo(final String seed, final File target) throws IOException
{
URL source = new URL("https://www.peppercarrot.com/extras/html/2016_cat-generator/avatar.php?seed=" + seed);
FileUtils.copyURLToFile(source, target, 5000, 5000);
}
/**
* Gets the week count of year.
*
* @param year
* the year
* @return the week count of year
*/
public static int getWeekCountOfYear(final int year)
{
int result;
result = new GregorianCalendar(year, 11, 01).getActualMaximum(Calendar.WEEK_OF_YEAR);
//
return result;
}
/**
* Gets the current time in long format.
*
* @return the long
*/
public static long now()
{
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.
*
* @param date
* the date
* @return the local date
*/
public static LocalDate parseDate(final String date)
{
LocalDate result;
try
{
if (date == null)
{
result = null;
}
else if (date.matches("^\\d{1,2}/\\d{1,2}/\\d{4}$"))
{
result = LocalDate.parse(date, DateTimeFormatter.ofPattern("dd/MM/yyyy"));
}
else if (date.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$"))
{
result = LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
}
else if (date.matches("^\\d{1,2}/\\d{4}$"))
{
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;
}
}
catch (DateTimeParseException exception)
{
result = null;
}
//
return result;
}
/**
* Sha1sum a file.
*
* @param file
* the file
* @return the string
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static String sha1sum(final File file) throws IOException
{
String result;
result = DigestUtils.sha1Hex(FileUtils.readFileToByteArray(file));
//
return result;
}
/**
* Split day values.
*
* @param values
* the values
* @return the string list
*/
public static StringList splitDayValues(final String values)
{
StringList result;
result = new StringList();
if (StringUtils.isNotBlank(values))
{
for (String value : values.split("[,]"))
{
if (StringUtils.isBlank(value))
{
result.add("");
}
else
{
result.add(value);
}
}
for (int index = result.size(); index < 365; index++)
{
result.add("");
}
}
//
return result;
}
/**
* Split month values.
*
* @param values
* the values
* @return the string list
*/
public static StringList splitMonthValues(final String values)
{
StringList result;
result = new StringList();
if (StringUtils.isNotBlank(values))
{
for (String value : values.split("[,]"))
{
if (StringUtils.isBlank(value))
{
result.add("");
}
else
{
result.add(value);
}
}
for (int index = result.size(); index < 12; index++)
{
result.add("");
}
}
//
return result;
}
/**
* Split week values.
*
* @param values
* the values
* @return the string list
*/
public static StringList splitWeekValues(final String values)
{
StringList result;
result = new StringList();
if (StringUtils.isNotBlank(values))
{
for (String value : values.split("[,]"))
{
if (StringUtils.isBlank(value))
{
result.add("");
}
else
{
result.add(value);
}
}
for (int index = result.size(); index < 52; index++)
{
result.add("");
}
}
//
return result;
}
/**
* To duration.
*
* @param startDate
* the start date
* @param endDate
* the end date
* @return the string
*/
public static String toHumanDuration(final LocalDate startDate, final LocalDate endDate)
{
String result;
if ((startDate == null) && (endDate == null))
{
result = null;
}
else if ((startDate == null) && (endDate != null))
{
result = toHumanDuration(LocalDate.now(), endDate);
}
else if ((startDate != null) && (endDate == null))
{
result = toHumanDuration(startDate, LocalDate.now());
}
else if ((startDate != null) && (endDate != null))
{
Period period = Period.between(startDate, LocalDate.now());
if (period.getYears() == 0)
{
if (period.getMonths() == 0)
{
if (period.getDays() <= 1)
{
result = String.format("%d jour", period.getDays());
}
else
{
result = String.format("%d jours", period.getDays());
}
}
else
{
result = String.format("%d mois", period.getMonths());
}
}
else if (period.getYears() == 1)
{
period.minusYears(1);
if (period.getMonths() == 0)
{
result = "1 an";
}
else
{
result = String.format("1 an et %d mois", period.getMonths());
}
}
else
{
long years = period.getYears();
period.minusYears(period.getYears());
if (period.getMonths() == 0)
{
result = years + " ans";
}
else
{
result = String.format("%d ans et %d mois", years, period.getMonths());
}
}
}
else
{
result = null;
}
//
return result;
}
/**
* To human long.
*
* @param value
* the value
* @return the string
*/
public static String toHumanLong(final LocalDateTime value)
{
String result;
result = toHumanLong(value, null);
//
return result;
}
/**
* To human long.
*
* @param value
* the value
* @param defaultValue
* the default value
* @return the string
*/
public static String toHumanLong(final LocalDateTime value, final String defaultValue)
{
String result;
if (value == null)
{
result = null;
}
else
{
result = value.format(PATTERN_LONGDATE);
}
//
return result;
}
/**
* To human short.
*
* @param value
* the value
* @return the string
*/
public static String toHumanShort(final LocalDateTime value)
{
String result;
result = toHumanShort(value, null);
//
return result;
}
/**
* To human short.
*
* @param value
* the value
* @param defaultValue
* the default value
* @return the string
*/
public static String toHumanShort(final LocalDateTime value, final String defaultValue)
{
String result;
if (value == null)
{
result = null;
}
else
{
result = value.format(PATTERN_SHORTDATE);
}
//
return result;
}
public static Integer toInteger(final String value)
{
Integer result;
if ((value == null) || (!NumberUtils.isDigits(value)))
{
result = null;
}
else
{
result = Integer.parseInt(value);
}
//
return result;
}
/**
* To Json numbers.
*
* @param source
* the source
* @return the string
*/
public static String toJSonNumbers(final StringList source)
{
String result;
result = StringsUtils.toString(source, "[", ",", "]");
//
return result;
}
/**
* To J son numbers.
*
* @param labels
* the labels
* @param values
* the source
* @return the string
*/
public static String toJSonNumbers(final StringList labels, final StringList values)
{
String result;
Iterator<String> labelIterator = labels.iterator();
Iterator<String> valueIterator = values.iterator();
StringList buffer = new StringList();
while (labelIterator.hasNext())
{
String label = labelIterator.next();
String value = valueIterator.next();
// buffer.append("{t: new Date('" + label + "'), y: " + value +
// "}");
buffer.append("{t: '" + label + "', y: " + value + "}");
}
result = StringsUtils.toString(buffer, "[", ",", "]");
//
return result;
}
/**
* To Json strings.
*
* @param source
* the source
* @return the string
*/
public static String toJSonStrings(final StringList source)
{
String result;
StringList target = new StringList();
target.append("[");
for (String string : source)
{
target.append("'");
target.append(string);
target.append("'");
target.append(",");
}
target.removeLast();
target.append("]");
result = target.toString();
//
return result;
}
/**
* To percentage.
*
* @param value
* the value
* @param max
* the max
* @return the string
*/
public static String toPercentage(final int value, final int max)
{
String result;
result = (value * 100 / max) + "&#160;%";
//
return result;
}
/**
* To technical name.
*
* @param source
* the source
* @return the string
*/
public static String toTechnicalName(final String source)
{
String result;
if (source == null)
{
result = null;
}
else
{
result = StringUtils.stripAccents(source.toLowerCase()).replaceAll("[^a-z0-9]+", "");
}
//
return result;
}
/**
* To year week.
*
* @param source
* the source
* @return the string
*/
public static String toYearWeek(final LocalDate source)
{
String result;
if (source == null)
{
result = null;
}
else
{
result = source.format(DateTimeFormatter.ofPattern("YYYYww", Locale.FRANCE));
}
//
return result;
}
/**
* Unactivate SSL check.
*/
public static void unactivateSSLCheck()
{
// Create a trust manager that does not validate certificate chains.
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager()
{
@Override
public void checkClientTrusted(final java.security.cert.X509Certificate[] certs, final String authType)
{
}
@Override
public void checkServerTrusted(final java.security.cert.X509Certificate[] certs, final String authType)
{
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers()
{
return null;
}
}
};
// Install the all-trusting trust manager.
try
{
// SSLContext context = SSLContext.getInstance("SSL");
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
}
catch (Exception exception)
{
}
}
/**
* Url last modified.
*
* @param url
* the url
* @return the local date time
* @throws IOException
*/
public static LocalDateTime urlLastModified(final URL url) throws IOException
{
LocalDateTime result;
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
Long epoch = connection.getLastModified();
connection.disconnect();
result = epochToLocalDateTime(epoch);
// result =
// Instant.ofEpochMilli(epoch).atZone(ZoneId.of("GMT")).toLocalDateTime();
//
return result;
}
}

View file

@ -1,488 +0,0 @@
/*
* Copyright (C) 2020-2021 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.crawl;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.catgenerator.core.BirdGenerator;
import fr.devinsy.catgenerator.core.CatGenerator;
import fr.devinsy.statoolinfos.core.StatoolInfosException;
import fr.devinsy.statoolinfos.core.StatoolInfosUtils;
import fr.devinsy.statoolinfos.properties.PathProperties;
import fr.devinsy.statoolinfos.properties.PathPropertyList;
import fr.devinsy.statoolinfos.properties.PathPropertyUtils;
import fr.devinsy.statoolinfos.uptime.UptimeJournal;
import fr.devinsy.statoolinfos.uptime.UptimeJournalFile;
import fr.devinsy.statoolinfos.util.URLUtils;
/**
* The Class CrawlCache.
*/
public class CrawlCache
{
private static Logger logger = LoggerFactory.getLogger(CrawlCache.class);
public static enum DefaultLogoGenerator
{
CAT,
BIRD
}
private File directory;
/**
* Instantiates a new crawl cache.
*
* @param directory
* the directory
* @throws StatoolInfosException
* the statool infos exception
*/
public CrawlCache(final File directory) throws StatoolInfosException
{
if (directory == null)
{
throw new IllegalArgumentException("Null parameter.");
}
else if (StringUtils.isBlank(directory.getName()))
{
throw new IllegalArgumentException("Crawl cache directory undefined.");
}
else if (!directory.exists())
{
throw new IllegalArgumentException("Crawl cache directory does not exist.");
}
else
{
this.directory = directory;
}
}
/**
* Builds the file.
*
* @param key
* the key
* @return the file
*/
private File buildFile(final URL url)
{
File result;
result = new File(this.directory, DigestUtils.md5Hex(url.toString()));
//
return result;
}
/**
* Clear file in cache. Only files ending with ".property" are deleted.
*/
public void clear()
{
for (File file : this.directory.listFiles())
{
if ((file.isFile()) && ((file.getName().endsWith(".properties")) || file.getName().length() == 32))
{
logger.info("Deleting " + file.getName());
file.delete();
}
}
}
public File getDirectory()
{
return this.directory;
}
/**
* Gets the extension.
*
* @param url
* the url
* @return the extension
*/
public String getExtension(final URL url)
{
String result;
File file = restoreFile(url);
if (file == null)
{
result = null;
}
else
{
result = StatoolInfosUtils.findExtension(file);
}
//
return result;
}
/**
* Restore crawl journal.
*
* @return the crawl journal
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public CrawlJournal restoreCrawlJournal() throws IOException
{
CrawlJournal result;
File journalFile = restoreFile(getCrawlJournalURL());
result = CrawlJournalFile.load(journalFile);
//
return result;
}
/**
* Restore file.
*
* @param url
* the key
* @return the file
*/
public File restoreFile(final URL url)
{
File result;
if (url == null)
{
result = null;
}
else
{
result = buildFile(url);
if (!result.exists())
{
result = null;
}
}
//
return result;
}
/**
* Restore file to.
*
* @param url
* the url
* @param target
* the target
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public void restoreFileTo(final URL url, final File target) throws IOException
{
File source = restoreFile(url);
if (source != null)
{
FileUtils.copyFile(source, target);
}
}
/**
* Restore logo to.
*
* @param url
* the url
* @param target
* the target
* @param seed
* the seed
* @param generator
* the generator
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public void restoreLogoTo(final URL url, final File target, final String seed, final DefaultLogoGenerator generator) throws IOException
{
if ((target == null) || (seed == null))
{
throw new IllegalArgumentException("Null parameter.");
}
else
{
logger.info("CatGeneratoring from {}", url);
File logoFile = restoreFile(url);
if (logoFile == null)
{
try
{
logger.info("CatGeneratoring cat avatar: {}", target.getAbsoluteFile());
if ((generator == null) || (generator == DefaultLogoGenerator.CAT))
{
CatGenerator.buildAvatarTo(seed, target);
}
else
{
BirdGenerator.buildAvatarTo(seed, target);
}
}
catch (IOException exception)
{
logger.warn("CatGeneratoring failed for {}: {}", seed, exception.getMessage());
URLUtils.copyResource("/fr/devinsy/statoolinfos/htmlize/stuff/default-organization-logo.png", target);
}
}
else
{
FileUtils.copyFile(logoFile, target);
}
}
}
/**
* Restore to properties.
*
* @param url
* the url
* @return the path properties
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public PathProperties restoreToProperties(final URL url) throws IOException
{
PathProperties result;
if (url == null)
{
result = new PathPropertyList();
}
else
{
File file = buildFile(url);
result = PathPropertyUtils.load(file);
}
//
return result;
}
/**
* Restore uptime journal.
*
* @return the crawl journal
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public UptimeJournal restoreUptimeJournal() throws IOException
{
UptimeJournal result;
File journalFile = restoreFile(getUptimeJournalURL());
if (journalFile == null)
{
result = new UptimeJournal();
}
else
{
result = UptimeJournalFile.load(journalFile);
}
//
return result;
}
/**
* Store.
*
* @param url
* the url
* @param source
* the source
* @return the file
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public File store(final URL url, final File source) throws IOException
{
File result;
if ((url == null) || (!StringUtils.startsWith(url.getProtocol(), "http")))
{
result = null;
}
else
{
result = buildFile(url);
FileUtils.copyFile(source, result);
}
//
return result;
}
/**
* Store crawl journal.
*
* @param journal
* the journal
*/
public void storeCrawlJournal(final CrawlJournal journal)
{
try
{
File file = Files.createTempFile("tmp-", ".statoolsinfos").toFile();
CrawlJournalFile.save(file, journal);
store(getCrawlJournalURL(), file);
file.delete();
}
catch (IOException exception)
{
exception.printStackTrace();
}
}
/**
* Store.
*
* @param url
* the url
* @param properties
* the properties
* @return the file
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public File storeProperties(final URL url, final PathProperties properties) throws IOException
{
File result;
if ((url == null) || (!StringUtils.startsWith(url.getProtocol(), "http")))
{
result = null;
}
else
{
result = buildFile(url);
PathPropertyUtils.save(result, properties);
}
//
return result;
}
/**
* Store quietly.
*
* @param url
* the url
* @return the file
*/
public File storeQuietly2(final URL url)
{
File result;
try
{
if ((url == null) || (!StringUtils.startsWithIgnoreCase(url.getProtocol(), "http")))
{
result = null;
}
else
{
final int TIMEOUT = 5000;
result = buildFile(url);
FileUtils.copyURLToFile(url, result, TIMEOUT, TIMEOUT);
logger.info("Crawled {}", url);
}
}
catch (IOException exception)
{
logger.info("Store failed for {}: {}", url, exception.getMessage());
result = null;
}
//
return result;
}
/**
* Store journal.
*
* @param journal
* the journal
*/
public void storeUptimeJournal(final UptimeJournal journal)
{
try
{
File file = Files.createTempFile("tmp-", ".statoolsinfos").toFile();
UptimeJournalFile.save(file, journal);
store(getUptimeJournalURL(), file);
file.delete();
}
catch (IOException exception)
{
exception.printStackTrace();
}
}
/**
* Gets the crawl journal URL.
*
* @return the crawl journal URL
* @throws MalformedURLException
* the malformed URL exception
*/
public static URL getCrawlJournalURL() throws MalformedURLException
{
URL result;
result = new URL("http://localhost/crawl.journal");
//
return result;
}
/**
* Gets the uptimes journal URL.
*
* @return the uptimes journal URL
* @throws MalformedURLException
* the malformed URL exception
*/
public static URL getUptimeJournalURL() throws MalformedURLException
{
URL result;
result = new URL("http://localhost/uptimes.journal");
//
return result;
}
}

View file

@ -1,62 +0,0 @@
/*
* Copyright (C) 2021 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.crawl;
import java.time.LocalDateTime;
/**
* The Class CrawlJournal.
*/
public class CrawlJournal extends CrawlLogs
{
private static final long serialVersionUID = -7855320365496351766L;
private LocalDateTime datetime;
/**
* Instantiates a new crawl journal.
*/
public CrawlJournal()
{
super();
this.datetime = LocalDateTime.now();
}
/**
* Gets the date.
*
* @return the date
*/
public LocalDateTime getDatetime()
{
return this.datetime;
}
/**
* Sets the date.
*
* @param date
* the new date
*/
public void setDatetime(final LocalDateTime date)
{
this.datetime = date;
}
}

View file

@ -1,256 +0,0 @@
/*
* Copyright (C) 2021 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.crawl;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class CrawlFile.
*/
public class CrawlJournalFile
{
private static Logger logger = LoggerFactory.getLogger(CrawlJournalFile.class);
/**
* Instantiates a new crawl file.
*/
private CrawlJournalFile()
{
super();
}
/**
* Load.
*
* @param file
* the file
* @return the path property list
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static CrawlJournal load(final File file) throws IOException
{
CrawlJournal result;
result = load(file, StandardCharsets.UTF_8);
//
return result;
}
/**
* Load.
*
* @param file
* the file
* @param charset
* the charset name
* @return the path properties
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static CrawlJournal load(final File file, final Charset charset) throws IOException
{
CrawlJournal result;
if (file == null)
{
throw new IllegalArgumentException("File parameter is null.");
}
else
{
BufferedReader in = null;
try
{
in = new BufferedReader(new InputStreamReader(new FileInputStream(file), charset));
result = read(in);
}
finally
{
IOUtils.closeQuietly(in);
}
result.setDatetime(LocalDateTime.ofEpochSecond(file.lastModified() / 1000, 0, ZoneOffset.UTC));
}
//
return result;
}
/**
* Read.
*
* @param in
* the in
* @return the crawl logs
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static CrawlJournal read(final BufferedReader in) throws IOException
{
CrawlJournal result;
result = new CrawlJournal();
boolean ended = false;
while (!ended)
{
String line = in.readLine();
if (line == null)
{
ended = true;
}
else
{
CrawlLog log = valueOf(line);
result.add(log);
}
}
//
return result;
}
/**
* Save.
*
* @param file
* the file
* @param source
* the source
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void save(final File file, final CrawlJournal source) throws IOException
{
PrintWriter out = null;
try
{
out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8));
write(out, source);
}
finally
{
//
IOUtils.closeQuietly(out);
}
}
/**
* Value of.
*
* @param line
* the line
* @return the path property
*/
public static CrawlLog valueOf(final String line)
{
CrawlLog result;
if (line == null)
{
result = null;
}
else
{
String[] tokens = line.split(" ", 3);
CrawlStatus status = CrawlStatus.valueOf(tokens[0].toUpperCase());
URL parentURL;
try
{
if (StringUtils.equals(tokens[1], "null"))
{
parentURL = null;
}
else
{
parentURL = new URL(tokens[1].trim());
}
}
catch (MalformedURLException exception)
{
logger.error("Error valuing [{}]", line);
exception.printStackTrace();
parentURL = null;
}
URL url;
try
{
url = new URL(tokens[2].trim());
}
catch (MalformedURLException exception)
{
logger.error("Error valuing [{}]", line);
exception.printStackTrace();
url = null;
}
result = new CrawlLog(url, parentURL, status);
}
//
return result;
}
/**
* Write.
*
* @param out
* the out
* @param journal
* the journal
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void write(final PrintWriter out, final CrawlJournal journal) throws IOException
{
if (journal != null)
{
for (CrawlLog log : journal)
{
String line = String.format("%s %s %s", log.getStatus(), log.getParentUrl(), log.getUrl());
out.write(line);
out.write("\n");
}
}
}
}

View file

@ -1,83 +0,0 @@
/*
* Copyright (C) 2021 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.crawl;
import java.net.URL;
/**
* The Class CrawlLog.
*/
public class CrawlLog
{
private URL url;
private URL parentUrl;
private CrawlStatus status;
/**
* Instantiates a new crawl log.
*
* @param url
* the url
* @param status
* the status
*/
public CrawlLog(final URL url, final URL parentUrl, final CrawlStatus status)
{
this.url = url;
this.parentUrl = parentUrl;
this.status = status;
}
public URL getParentUrl()
{
return this.parentUrl;
}
/**
* Gets the parent url value.
*
* @return the parent url value
*/
public String getParentUrlValue()
{
String result;
if (this.parentUrl == null)
{
result = null;
}
else
{
result = this.parentUrl.toString();
}
//
return result;
}
public CrawlStatus getStatus()
{
return this.status;
}
public URL getUrl()
{
return this.url;
}
}

View file

@ -1,227 +0,0 @@
/*
* Copyright (C) 2021 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.crawl;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import org.apache.commons.lang3.StringUtils;
import fr.devinsy.statoolinfos.util.URLUtils;
/**
* The Class CrawlLogs.
*/
public class CrawlLogs extends ArrayList<CrawlLog>
{
private static final long serialVersionUID = -8749217049690008582L;
/**
* Instantiates a new crawl logs.
*/
public CrawlLogs()
{
super();
}
/* (non-Javadoc)
* @see java.util.ArrayList#add(java.lang.Object)
*/
@Override
public boolean add(final CrawlLog log)
{
boolean result;
if (log == null)
{
result = false;
}
else
{
result = super.add(log);
}
//
return result;
}
/**
* Adds the.
*
* @param url
* the url
* @param status
* the status
*/
public void add(final URL url, final URL parentUrl, final CrawlStatus status)
{
this.add(new CrawlLog(url, parentUrl, status));
}
/**
* Find by url.
*
* @param url
* the url
* @return the crawl logs
*/
public CrawlLogs findByUrl(final URL url)
{
CrawlLogs result;
result = new CrawlLogs();
for (CrawlLog log : this)
{
if (StringUtils.equals(log.getUrl().toString(), url.toString()))
{
result.add(log);
}
}
//
return result;
}
/**
* Gets the by url.
*
* @param url
* the url
* @return the by url
*/
public CrawlLog getByUrl(final URL url)
{
CrawlLog result;
boolean ended = false;
Iterator<CrawlLog> iterator = iterator();
result = null;
while (!ended)
{
if (iterator.hasNext())
{
CrawlLog log = iterator.next();
if (URLUtils.equals(log.getUrl(), url))
{
ended = true;
result = log;
}
}
else
{
ended = true;
}
}
//
return result;
}
/**
* Gets the errors.
*
* @return the errors
*/
public CrawlLogs getErrors()
{
CrawlLogs result;
result = new CrawlLogs();
for (CrawlLog log : this)
{
if (log.getStatus().isError())
{
result.add(log);
}
}
//
return result;
}
/**
* Gets the success.
*
* @return the success
*/
public CrawlLogs getSuccess()
{
CrawlLogs result;
result = new CrawlLogs();
for (CrawlLog log : this)
{
if (!log.getStatus().isError())
{
result.add(log);
}
}
//
return result;
}
/**
* Reverse.
*
* @return the categories
*/
public CrawlLogs reverse()
{
CrawlLogs result;
Collections.reverse(this);
result = this;
//
return result;
}
/**
* Gets the by parent.
*
* @param parentURL
* the parent URL
* @return the by parent
*/
public CrawlLogs searchByParent(final URL parentURL)
{
CrawlLogs result;
result = new CrawlLogs();
for (CrawlLog log : this)
{
if (URLUtils.equals(log.getParentUrl(), parentURL))
{
result.add(log);
}
}
//
return result;
}
}

View file

@ -1,50 +0,0 @@
/*
* Copyright (C) 2021 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.crawl;
public enum CrawlStatus
{
BADCHILDCLASS,
BADURLFORMAT,
CONNECTERROR,
DOWNLOADERROR,
EMPTY,
IOERROR,
MISSING,
SUCCESS,
UPDATED,
URLNOTFOUND;
public boolean isError()
{
boolean result;
if ((this == CrawlStatus.SUCCESS) || (this == CrawlStatus.UPDATED))
{
result = false;
}
else
{
result = true;
}
//
return result;
}
}

View file

@ -1,371 +0,0 @@
/*
* Copyright (C) 2020-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.crawl;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.statoolinfos.core.StatoolInfosException;
import fr.devinsy.statoolinfos.core.StatoolInfosUtils;
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.properties.PropertyClassType;
/**
* The Class Crawler.
*/
public class Crawler
{
private static Logger logger = LoggerFactory.getLogger(Crawler.class);
private CrawlCache cache;
private CrawlJournal journal;
/**
* Instantiates a new crawler.
*
* @param rootDirectory
* the root directory
* @throws StatoolInfosException
* the statool infos exception
*/
public Crawler(final File rootDirectory) throws StatoolInfosException
{
logger.info("Crawl cache setting: {}", rootDirectory);
this.cache = new CrawlCache(rootDirectory);
this.journal = new CrawlJournal();
}
/**
* Clear.
*
* @throws StatoolInfosException
* the statool infos exception
*/
public void clear() throws StatoolInfosException
{
this.cache.clear();
}
/**
* Crawl.
*
* @param url
* the input url
* @throws StatoolInfosException
* the statool infos exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public void crawl(final URL url) throws StatoolInfosException, IOException
{
crawl(url, null, null);
}
/**
* Crawl.
*
* @param url
* the url
* @param parentURL
* the parent URL
* @param parent
* the parent
*/
public void crawl(final URL url, final URL parentURL, final PropertyClassType parent)
{
logger.info("Crawling {}", url);
File downloadFile = null;
try
{
try
{
downloadFile = download(url);
}
catch (java.net.ConnectException exception)
{
logger.error("ERROR: crawl failed for [{}]: {}", url.toString(), exception.getMessage());
this.journal.add(url, parentURL, CrawlStatus.CONNECTERROR);
downloadFile = null;
}
catch (java.net.SocketException exception)
{
logger.error("ERROR: crawl failed for [{}]: {}", url.toString(), exception.getMessage());
this.journal.add(url, parentURL, CrawlStatus.CONNECTERROR);
downloadFile = null;
}
catch (FileNotFoundException exception)
{
logger.error("ERROR: crawl failed for [{}]: {}", url.toString(), exception.getMessage());
this.journal.add(url, parentURL, CrawlStatus.URLNOTFOUND);
downloadFile = null;
}
catch (IOException exception)
{
logger.error("ERROR: crawl failed for [{}]: {}", url.toString(), exception.getMessage());
this.journal.add(url, parentURL, CrawlStatus.DOWNLOADERROR);
downloadFile = null;
}
if (downloadFile != null)
{
if (!downloadFile.exists())
{
logger.error("ERROR: download missing.");
this.journal.add(url, parentURL, CrawlStatus.MISSING);
}
else if (downloadFile.length() == 0)
{
logger.error("ERROR: download empty.");
this.journal.add(url, parentURL, CrawlStatus.EMPTY);
}
else
{
PathPropertyList downloadProperties = PathPropertyUtils.load(downloadFile);
PropertyClassType downloadClass = downloadProperties.getClassType();
if ((downloadClass == null) || (!downloadClass.isChildOf(parent)))
{
logger.error("ERROR: bad child class [{}][{}].", downloadClass, parent);
this.journal.add(url, parentURL, CrawlStatus.BADCHILDCLASS);
downloadFile.delete();
}
else
{
File storedFile = this.cache.restoreFile(url);
String storedSha;
if (storedFile == null)
{
storedSha = null;
}
else
{
PathProperties storedProperties = PathPropertyUtils.load(storedFile);
storedSha = storedProperties.get("crawl.file.sha1");
}
String downloadSha = StatoolInfosUtils.sha1sum(downloadFile);
if (StringUtils.equals(downloadSha, storedSha))
{
this.journal.add(url, parentURL, CrawlStatus.SUCCESS);
downloadFile.delete();
}
else
{
// Build crawl data.
PathProperties crawlSection = new PathPropertyList();
crawlSection.put("crawl.crawler", "StatoolInfos");
crawlSection.put("crawl.datetime", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")));
crawlSection.put("crawl.url", url.toString());
crawlSection.put("crawl.file.size", FileUtils.sizeOf(downloadFile));
crawlSection.put("crawl.file.datetime", StatoolInfosUtils.urlLastModified(url).toString());
crawlSection.put("crawl.file.sha1", downloadSha);
String crawlSectionLines = crawlSection.toStringListFormatted().toStringSeparatedBy('\n');
// Add crawl data in crawled file.
String downloadExtendedLines = FileUtils.readFileToString(downloadFile, StandardCharsets.UTF_8) + "\n" + crawlSectionLines;
FileUtils.write(downloadFile, downloadExtendedLines, StandardCharsets.UTF_8);
// Store in cache.
this.cache.store(url, downloadFile);
downloadFile.delete();
//
this.journal.add(url, parentURL, CrawlStatus.UPDATED);
}
// Cache another resources.
crawlLogo(downloadProperties.getURL("federation.logo"), url);
crawlLogo(downloadProperties.getURL("organization.logo"), url);
crawlLogo(downloadProperties.getURL("service.logo"), url);
// Do subs.
PathProperties subs = downloadProperties.getByPrefix("subs");
for (PathProperty property : subs)
{
if (StringUtils.isNotBlank(property.getValue()))
{
try
{
URL subUrl = new URL(property.getValue());
crawl(subUrl, url, downloadClass);
}
catch (java.net.MalformedURLException exception)
{
logger.error("ERROR: subcrawl failed for [{}][{}][{}]: {}", url.toString(), property.getPath(), property.getValue(), exception.getMessage());
this.journal.add(url, parentURL, CrawlStatus.BADURLFORMAT);
exception.printStackTrace();
}
}
}
}
}
}
}
catch (IOException exception)
{
this.journal.add(url, parentURL, CrawlStatus.IOERROR);
}
finally
{
if ((downloadFile != null) && (downloadFile.exists()))
{
downloadFile.delete();
}
}
}
/**
* Crawl logo.
*
* @param url
* the url
* @return the file
*/
public File crawlLogo(final URL url, final URL parentURL)
{
File result;
try
{
if ((url == null) || (!StringUtils.startsWithIgnoreCase(url.getProtocol(), "http")))
{
result = null;
}
else
{
logger.info("Crawling {}", url);
File logoFile;
try
{
logoFile = download(url);
}
catch (java.net.ConnectException exception)
{
logger.error("ERROR: crawl failed (1) for [{}]: {}", url.toString(), exception.getMessage());
this.journal.add(url, parentURL, CrawlStatus.CONNECTERROR);
logoFile = null;
}
catch (FileNotFoundException exception)
{
logger.error("ERROR: crawl failed (2) for [{}]: {}", url.toString(), exception.getMessage());
this.journal.add(url, parentURL, CrawlStatus.URLNOTFOUND);
logoFile = null;
}
catch (IOException exception)
{
logger.error("ERROR: crawl failed (3) for [{}]: {}", url.toString(), exception.getMessage());
this.journal.add(url, parentURL, CrawlStatus.DOWNLOADERROR);
logoFile = null;
}
if (logoFile == null)
{
result = null;
}
else
{
result = this.cache.store(url, logoFile);
this.journal.add(url, parentURL, CrawlStatus.SUCCESS);
logoFile.delete();
}
}
}
catch (IOException exception)
{
logger.info("Store failed for {}: {}", url, exception.getMessage());
result = null;
}
//
return result;
}
/**
* Download.
*
* @param url
* the url
* @return the file
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public File download(final URL url) throws IOException
{
File result;
if (!StringUtils.startsWith(url.getProtocol(), "http"))
{
logger.warn("WARNING: crawl failed because bad http+ protocol for [{}]", url);
result = null;
}
else
{
final int TIMEOUT = 5000;
result = Files.createTempFile("tmp-", ".statoolsinfos").toFile();
result.deleteOnExit();
FileUtils.copyURLToFile(url, result, TIMEOUT, TIMEOUT);
}
//
return result;
}
/**
* Restore journal.
*
* @return the crawl journal
* @throws IOException
*/
public CrawlJournal restoreJournal() throws IOException
{
CrawlJournal result;
logger.info("Restoring crawl journal.");
result = this.cache.restoreCrawlJournal();
//
return result;
}
/**
* Store journal.
*/
public void storeJournal()
{
logger.info("Storing crawl journal.");
this.cache.storeCrawlJournal(this.journal);
}
}

View file

@ -1,95 +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.htmlize;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.statoolinfos.HtmlizerContext;
import fr.devinsy.statoolinfos.core.Federation;
import fr.devinsy.statoolinfos.core.StatoolInfosException;
import fr.devinsy.statoolinfos.crawl.CrawlCache;
import fr.devinsy.xidyn.XidynException;
import fr.devinsy.xidyn.data.TagDataManager;
import fr.devinsy.xidyn.presenters.PresenterUtils;
/**
* The Class AboutPage.
*/
public class AboutPage
{
private static Logger logger = LoggerFactory.getLogger(AboutPage.class);
/**
* Builds the.
*
* @throws StatoolInfosException
* the statool infos exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void build() throws StatoolInfosException, IOException
{
logger.info("Htmlize about page.");
Federation federation = HtmlizerContext.instance().getFederation();
CrawlCache cache = HtmlizerContext.instance().getCache();
File htmlizeDirectory = HtmlizerContext.instance().getHtmlizeDirectory();
String page = htmlize();
FileUtils.write(new File(htmlizeDirectory, "about.xhtml"), page, StandardCharsets.UTF_8);
}
/**
* Builds the.
*
* @return the string
* @throws StatoolInfosException
* the statool infos exception
*/
public static String htmlize() throws StatoolInfosException
{
String result;
try
{
logger.debug("Building about page {}.");
TagDataManager data = new TagDataManager();
String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/about.xhtml", data).toString();
BreadcrumbTrail trail = new BreadcrumbTrail();
trail.add("À propos", "about.xhtml");
result = WebCharterView.build(content, trail);
}
catch (XidynException exception)
{
throw new StatoolInfosException("Error building about page: " + exception.getMessage(), exception);
}
//
return result;
}
}

View file

@ -1,120 +0,0 @@
/*
* Copyright (C) 2020-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.htmlize;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.statoolinfos.HtmlizerContext;
import fr.devinsy.statoolinfos.core.Categories;
import fr.devinsy.statoolinfos.core.Federation;
import fr.devinsy.statoolinfos.core.StatoolInfosException;
import fr.devinsy.statoolinfos.core.StatoolInfosUtils;
import fr.devinsy.statoolinfos.stats.StatAgent;
import fr.devinsy.statoolinfos.stats.categories.CategoryStat;
import fr.devinsy.statoolinfos.stats.categories.CategoryStats;
import fr.devinsy.xidyn.XidynException;
import fr.devinsy.xidyn.data.TagDataManager;
import fr.devinsy.xidyn.presenters.PresenterUtils;
/**
* The Class CategoriesPage.
*/
public class CategoriesPage
{
private static Logger logger = LoggerFactory.getLogger(CategoriesPage.class);
/**
* Builds the.
*
* @throws StatoolInfosException
* the statool infos exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void build() throws StatoolInfosException, IOException
{
Federation federation = HtmlizerContext.instance().getFederation();
File htmlizeDirectory = HtmlizerContext.instance().getHtmlizeDirectory();
Categories categories = HtmlizerContext.instance().getCategories();
logger.info("Htmlize categories page.");
CategoryStats stats = StatAgent.statAllCategories(federation, categories);
String page = CategoriesPage.htmlize(stats);
FileUtils.write(new File(htmlizeDirectory, "categories.xhtml"), page, StandardCharsets.UTF_8);
}
/**
* Builds the.
*
* @param stats
* the stats
* @return the string
* @throws StatoolInfosException
* the statool infos exception
*/
public static String htmlize(final CategoryStats stats) throws StatoolInfosException
{
String result;
try
{
logger.debug("Building categories page.");
TagDataManager data = new TagDataManager();
data.setContent("categoryCount", stats.size());
int index = 0;
for (CategoryStat stat : stats)
{
data.setEscapedContent("categoryListLine", index, "categoryListLineNameValue", stat.getCategory().getName());
data.setAttribute("categoryListLine", index, "categoryListLineNameLink", "href", "category-" + stat.getCategory().getTechnicalName() + ".xhtml");
data.setAttribute("categoryListLine", index, "categoryListLineNameLink", "title", stat.getCategory().getDescription());
data.setAttribute("categoryListLine", index, "categoryListLineNameLogo", "src", stat.getCategory().getLogoPath());
data.setEscapedContent("categoryListLine", index, "categoryListLineSoftwares", stat.getCategory().getSoftwares().sort().toStringWithFrenchCommas());
data.setContent("categoryListLine", index, "categoryListLineOrganizationCount", stat.getOrganizationCount());
data.setContent("categoryListLine", index, "categoryListLineServiceCount", StatoolInfosUtils.defaultIfZero(stat.getServiceCount(), "😿"));
data.setContent("categoryListLine", index, "categoryListLineUserCount", StatoolInfosUtils.defaultIfZero(stat.getUserCount(), "😢"));
data.setContent("categoryListLine", index, "categoryListLineVisitCount", StatoolInfosUtils.defaultIfZero(stat.getVisitCount(), "😞"));
index += 1;
}
String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/categories.xhtml", data).toString();
BreadcrumbTrail trail = new BreadcrumbTrail();
trail.add("Catégories", "categories.xhtml");
result = WebCharterView.build(content, trail);
}
catch (XidynException exception)
{
throw new StatoolInfosException("Error building categories page: " + exception.getMessage(), exception);
}
//
return result;
}
}

View file

@ -1,112 +0,0 @@
/*
* Copyright (C) 2020-2022 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.htmlize;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.statoolinfos.HtmlizerContext;
import fr.devinsy.statoolinfos.core.Categories;
import fr.devinsy.statoolinfos.core.Category;
import fr.devinsy.statoolinfos.core.Federation;
import fr.devinsy.statoolinfos.core.Services;
import fr.devinsy.statoolinfos.core.StatoolInfosException;
import fr.devinsy.statoolinfos.crawl.CrawlCache;
import fr.devinsy.xidyn.XidynException;
import fr.devinsy.xidyn.data.TagDataManager;
import fr.devinsy.xidyn.presenters.PresenterUtils;
/**
* The Class ServicesPage.
*/
public class CategoryPage
{
private static Logger logger = LoggerFactory.getLogger(CategoryPage.class);
/**
* Builds the.
*
* @throws StatoolInfosException
* @throws IOException
*/
public static void buildAll() throws StatoolInfosException, IOException
{
Federation federation = HtmlizerContext.instance().getFederation();
CrawlCache cache = HtmlizerContext.instance().getCache();
File htmlizeDirectory = HtmlizerContext.instance().getHtmlizeDirectory();
Categories categories = HtmlizerContext.instance().getCategories();
logger.info("Htmlize category pages.");
for (Category category : categories)
{
Services services = federation.getServices().getBy(category);
String page = CategoryPage.htmlize(category, services);
FileUtils.write(new File(htmlizeDirectory, "category-" + category.getTechnicalName() + ".xhtml"), page, StandardCharsets.UTF_8);
}
}
/**
* Builds the.
*
* @param category
* the category
* @param services
* the services
* @return the string
* @throws StatoolInfosException
* the statool infos exception
*/
public static String htmlize(final Category category, final Services services) throws StatoolInfosException
{
String result;
try
{
logger.debug("Building category page.");
TagDataManager data = new TagDataManager();
data.setAttribute("categoryLogo", "src", category.getLogoPath());
data.setEscapedContent("categoryName", category.getName());
data.setEscapedContent("categoryDescription", category.getDescription());
data.setEscapedContent("categorySoftwares", category.getSoftwares().sort().toStringWithFrenchCommas());
data.setContent("serviceCount", services.size());
data.setContent("serviceListView", ServiceListView.htmlize(services.sortByName()));
String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/category.xhtml", data).toString();
BreadcrumbTrail trail = new BreadcrumbTrail();
trail.add("Catégories", "categories.xhtml");
trail.add(category.getName(), "category-" + category.getTechnicalName() + ".xhtml");
result = WebCharterView.build(content, trail);
}
catch (XidynException exception)
{
throw new StatoolInfosException("Error building category page: " + exception.getMessage(), exception);
}
//
return result;
}
}

View file

@ -1,127 +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.htmlize;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.statoolinfos.HtmlizerContext;
import fr.devinsy.statoolinfos.core.Configuration;
import fr.devinsy.statoolinfos.core.StatoolInfosException;
import fr.devinsy.xidyn.XidynException;
import fr.devinsy.xidyn.data.TagDataManager;
import fr.devinsy.xidyn.presenters.PresenterUtils;
import fr.devinsy.xidyn.utils.XidynUtils;
/**
* The Class EditoPage.
*/
public class EditoPage
{
private static Logger logger = LoggerFactory.getLogger(EditoPage.class);
/**
* Builds the.
*
* @throws StatoolInfosException
* the statool infos exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void build() throws StatoolInfosException, IOException
{
logger.info("Htmlize edito page.");
Configuration configuration = HtmlizerContext.instance().getConfiguration();
File htmlizeDirectory = HtmlizerContext.instance().getHtmlizeDirectory();
String edito;
File editoDirectory = configuration.getEditoDirectory();
if ((editoDirectory != null) && (editoDirectory.exists()))
{
File editoFile = new File(editoDirectory, "edito.xhtml");
if (editoFile.exists())
{
logger.info("EDITO: found data.");
// Copy files.
FileUtils.copyDirectory(editoDirectory, htmlizeDirectory);
// Load body edito xhtml file.
edito = FileUtils.readFileToString(editoFile, StandardCharsets.UTF_8);
edito = XidynUtils.extractBodyContent(edito);
}
else
{
logger.info("EDITO: not found data.");
edito = null;
}
}
else
{
logger.info("EDITO: not found configuration.");
edito = null;
}
String page = htmlize(edito);
FileUtils.write(new File(htmlizeDirectory, "edito.xhtml"), page, StandardCharsets.UTF_8);
}
/**
* Builds the.
*
* @return the string
* @throws StatoolInfosException
* the statool infos exception
*/
public static String htmlize(final String edito) throws StatoolInfosException
{
String result;
try
{
logger.debug("Building edito page {}.");
TagDataManager data = new TagDataManager();
if (edito != null)
{
data.setContent("edito", edito);
}
String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/edito.xhtml", data).toString();
BreadcrumbTrail trail = new BreadcrumbTrail();
trail.add("Édito", "edito.xhtml");
result = WebCharterView.build(content, trail);
}
catch (XidynException exception)
{
throw new StatoolInfosException("Error building edito page: " + exception.getMessage(), exception);
}
//
return result;
}
}

View file

@ -1,145 +0,0 @@
/*
* Copyright (C) 2021 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.htmlize;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.statoolinfos.HtmlizerContext;
import fr.devinsy.statoolinfos.core.Federation;
import fr.devinsy.statoolinfos.core.StatoolInfosException;
import fr.devinsy.statoolinfos.io.CSVFile;
import fr.devinsy.statoolinfos.io.JSONFile;
import fr.devinsy.statoolinfos.io.ODSFile;
import fr.devinsy.statoolinfos.uptime.ServiceUptimes;
import fr.devinsy.statoolinfos.uptime.ServiceUptimesFile;
import fr.devinsy.xidyn.XidynException;
import fr.devinsy.xidyn.presenters.PresenterUtils;
/**
* The Class ExportsPage.
*/
public class ExportsPage
{
private static Logger logger = LoggerFactory.getLogger(ExportsPage.class);
/**
* Builds the.
*/
public static void build()
{
Federation federation = HtmlizerContext.instance().getFederation();
File htmlizeDirectory = HtmlizerContext.instance().getHtmlizeDirectory();
//
try
{
logger.info("EXPORTS CSV.");
CSVFile.save(new File(htmlizeDirectory, "organizations.csv"), federation.getOrganizations());
CSVFile.save(new File(htmlizeDirectory, "services.csv"), federation.getServicesAll());
}
catch (IOException exception)
{
logger.error("Error during CSV export: " + exception.getMessage(), exception);
}
//
try
{
logger.info("EXPORTS JSON.");
JSONFile.save(new File(htmlizeDirectory, "federation.json"), federation);
JSONFile.save(new File(htmlizeDirectory, "organizations.json"), federation.getOrganizations());
JSONFile.save(new File(htmlizeDirectory, "services.json"), federation.getServicesAll());
}
catch (IOException exception)
{
logger.error("Error during JSON export: " + exception.getMessage(), exception);
}
//
try
{
logger.info("EXPORTS ODS.");
ODSFile.save(new File(htmlizeDirectory, "organizations.ods"), federation.getOrganizations());
ODSFile.save(new File(htmlizeDirectory, "services.ods"), federation.getServicesAll());
}
catch (Exception exception)
{
logger.error("Error during ODS export: " + exception.getMessage(), exception);
}
//
try
{
logger.info("EXPORTS SERVICE UPTIME JOURNAL.");
ServiceUptimes uptimes = ServiceUptimes.of(federation.getServicesAll(), HtmlizerContext.instance().getUptimeJournal());
ServiceUptimesFile.saveCSV(new File(htmlizeDirectory, "serviceUptimeJournal.csv"), uptimes);
ServiceUptimesFile.saveODS(new File(htmlizeDirectory, "serviceUptimeJournal.ods"), uptimes);
}
catch (Exception exception)
{
logger.error("Error during Uptime export: " + exception.getMessage(), exception);
}
//
try
{
String page = htmlize();
FileUtils.write(new File(htmlizeDirectory, "exports.xhtml"), page, StandardCharsets.UTF_8);
}
catch (StatoolInfosException | IOException exception)
{
logger.error("Error building export page: " + exception.getMessage(), exception);
}
}
/**
* Htmlize.
*
* @return the string
* @throws StatoolInfosException
* the statool infos exception
*/
public static String htmlize() throws StatoolInfosException
{
String result;
try
{
logger.info("PAGE EXPORTS.");
String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/exports.xhtml", null).toString();
BreadcrumbTrail trail = new BreadcrumbTrail();
result = WebCharterView.build(content, trail);
}
catch (XidynException exception)
{
throw new StatoolInfosException("Error building federation page: " + exception.getMessage(), exception);
}
//
return result;
}
}

View file

@ -1,74 +0,0 @@
/*
* Copyright (C) 2021 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.htmlize;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.statoolinfos.HtmlizerContext;
import fr.devinsy.statoolinfos.core.Federation;
import fr.devinsy.statoolinfos.core.StatoolInfosException;
import fr.devinsy.xidyn.XidynException;
import fr.devinsy.xidyn.data.TagDataManager;
import fr.devinsy.xidyn.presenters.PresenterUtils;
/**
* The Class CrawlJournalFederationPage.
*/
public class FederationCrawlJournalPage
{
private static Logger logger = LoggerFactory.getLogger(FederationCrawlJournalPage.class);
/**
* Builds the.
*
* @throws StatoolInfosException
* the statool infos exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void build() throws StatoolInfosException, IOException
{
try
{
Federation federation = HtmlizerContext.instance().getFederation();
File htmlizeDirectory = HtmlizerContext.instance().getHtmlizeDirectory();
TagDataManager data = new TagDataManager();
data.setContent("headerView", FederationHeaderView.htmlize(federation));
data.setContent("contentView", CrawlJournalView.htmlize(federation.getCrawlJournal()));
String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/headerContentView.xhtml", data).toString();
BreadcrumbTrail trail = new BreadcrumbTrail();
String page = WebCharterView.build(content, trail);
FileUtils.write(new File(htmlizeDirectory, federation.getLocalFileBaseName() + "-crawl.xhtml"), page, StandardCharsets.UTF_8);
}
catch (XidynException exception)
{
throw new StatoolInfosException("Error building federation crawl journal page: " + exception.getMessage(), exception);
}
}
}

View file

@ -1,101 +0,0 @@
/*
* Copyright (C) 2020-2021 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.htmlize;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.statoolinfos.core.Federation;
import fr.devinsy.statoolinfos.core.StatoolInfosException;
import fr.devinsy.statoolinfos.htmlize.FederationMetricMenuView.PeriodMenu;
import fr.devinsy.statoolinfos.htmlize.FederationMetricMenuView.TypeMenu;
import fr.devinsy.statoolinfos.htmlize.FederationMetricMenuView.ViewMenu;
import fr.devinsy.statoolinfos.htmlize.charts.ChartColor;
import fr.devinsy.xidyn.XidynException;
import fr.devinsy.xidyn.data.TagDataManager;
import fr.devinsy.xidyn.presenters.PresenterUtils;
/**
* The Class FederationMetricsPage.
*/
public class FederationMetricGenericPage
{
private static Logger logger = LoggerFactory.getLogger(FederationMetricGenericPage.class);
/**
* Builds the.
*
* @param htmlizeDirectory
* the htmlize directory
* @param federation
* the federation
* @param view
* the view
* @param period
* the period
* @throws StatoolInfosException
* the statool infos exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void build(final File htmlizeDirectory, final Federation federation, final ViewMenu view, final PeriodMenu period) throws StatoolInfosException, IOException
{
try
{
TagDataManager data = new TagDataManager();
data.setContent("headerView", FederationHeaderView.htmlize(federation));
data.setContent("metricMenuView", FederationMetricMenuView.htmlize(federation, TypeMenu.GENERIC, view, period));
//
FederationMetricHtmlizer.htmlize(data, "graphic.users", federation, view, period, "metrics.service.users", ChartColor.GREEN);
FederationMetricHtmlizer.htmlize(data, "graphic.users.ipv4-ipv6", federation, view, period, "service.users (ipv4 + ipv6)", "metrics.service.users.ipv4", ChartColor.YELLOW,
"metrics.service.users.ipv6", ChartColor.GREEN);
FederationMetricHtmlizer.htmlize(data, "graphic.users.ipv4", federation, view, period, "metrics.service.users.ipv4", ChartColor.YELLOW);
FederationMetricHtmlizer.htmlize(data, "graphic.users.ipv6", federation, view, period, "metrics.service.users.ipv6", ChartColor.GREEN);
FederationMetricHtmlizer.htmlize(data, "graphic.accounts", federation, view, period, "metrics.service.accounts", ChartColor.GREEN);
FederationMetricHtmlizer.htmlize(data, "graphic.accounts.active", federation, view, period, "metrics.service.accounts.active", ChartColor.GREEN);
FederationMetricHtmlizer.htmlize(data, "graphic.database.bytes", federation, view, period, "metrics.service.database.bytes", ChartColor.GREEN);
FederationMetricHtmlizer.htmlize(data, "graphic.datafiles.bytes", federation, view, period, "metrics.service.datafiles.bytes", ChartColor.GREEN);
//
String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/serviceMetricGenericView.xhtml", data).toString();
//
BreadcrumbTrail trail = new BreadcrumbTrail();
trail.add("Metrics génériques");
String page = WebCharterView.build(content, trail);
String filename = String.format("%s-metrics-generic-%s-%s.xhtml", federation.getLocalFileBaseName(), view.getName(), period.getName());
FileUtils.write(new File(htmlizeDirectory, filename), page, StandardCharsets.UTF_8);
}
catch (XidynException exception)
{
throw new StatoolInfosException("Error building federation metrics page: " + exception.getMessage(), exception);
}
}
}

View file

@ -1,264 +0,0 @@
/*
* 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.htmlize;
import java.util.ArrayList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.statoolinfos.core.Federation;
import fr.devinsy.statoolinfos.core.StatoolInfosException;
import fr.devinsy.xidyn.XidynException;
import fr.devinsy.xidyn.data.TagDataManager;
import fr.devinsy.xidyn.presenters.PresenterUtils;
import fr.devinsy.xidyn.utils.XidynUtils;
/**
* The Class OrganizationMetricMenuView.
*/
public class FederationMetricMenuView
{
private static Logger logger = LoggerFactory.getLogger(FederationMetricMenuView.class);
public enum PeriodMenu
{
FULL,
LAST,
Y2021,
Y2022;
/**
* Gets the name.
*
* @return the name
*/
public String getName()
{
String result;
if (this.name().startsWith("Y"))
{
result = this.name().substring(1);
}
else
{
result = this.name().toLowerCase();
}
//
return result;
}
/**
* Gets the years.
*
* @return the years
*/
public static PeriodMenu[] getYears()
{
PeriodMenu[] result;
ArrayList<PeriodMenu> list = new ArrayList<PeriodMenu>();
for (PeriodMenu item : values())
{
if (item.name().startsWith("Y"))
{
list.add(item);
}
}
result = list.toArray(new PeriodMenu[0]);
//
return result;
}
}
public enum TypeMenu
{
SUMMARY,
WEB,
GENERIC,
SPECIFIC;
/**
* Gets the name.
*
* @return the name
*/
public String getName()
{
String result;
result = this.name().toLowerCase();
//
return result;
}
}
public enum ViewMenu
{
YEARS,
MONTHS,
WEEKS,
DAYS;
/**
* Gets the name.
*
* @return the name
*/
public String getName()
{
String result;
result = this.name().toLowerCase();
//
return result;
}
}
/**
* Htmlize.
*
* @param federation
* the service
* @return the string
* @throws StatoolInfosException
* the statool infos exception
*/
public static String htmlize(final Federation federation, final TypeMenu type, final ViewMenu view, final PeriodMenu period) throws StatoolInfosException
{
String result;
try
{
TagDataManager data = new TagDataManager();
//
String filename = String.format("%s-metrics-summary-%s-%s.xhtml", federation.getLocalFileBaseName(), view.getName(), period.getName());
data.setAttribute("summaryTypeButton", "href", filename);
filename = String.format("%s-metrics-generic-%s-%s.xhtml", federation.getLocalFileBaseName(), view.getName(), period.getName());
data.setAttribute("genericTypeButton", "href", filename);
filename = String.format("%s-metrics-specific-%s-%s.xhtml", federation.getLocalFileBaseName(), view.getName(), period.getName());
data.setAttribute("specificTypeButton", "href", filename);
filename = String.format("%s-metrics-web-%s-%s.xhtml", federation.getLocalFileBaseName(), view.getName(), period.getName());
data.setAttribute("webTypeButton", "href", filename);
//
filename = String.format("%s-metrics-%s-years-%s.xhtml", federation.getLocalFileBaseName(), type.getName(), PeriodMenu.FULL.getName());
data.setAttribute("yearsViewButton", "href", filename);
filename = String.format("%s-metrics-%s-months-%s.xhtml", federation.getLocalFileBaseName(), type.getName(), period.getName());
data.setAttribute("monthsViewButton", "href", filename);
filename = String.format("%s-metrics-%s-weeks-%s.xhtml", federation.getLocalFileBaseName(), type.getName(), period.getName());
data.setAttribute("weeksViewButton", "href", filename);
data.setAttribute("daysViewButton", "href", "#");
//
filename = String.format("%s-metrics-%s-%s-full.xhtml", federation.getLocalFileBaseName(), type.getName(), view.getName());
data.setAttribute("fullPeriodButton", "href", filename);
if (view != ViewMenu.YEARS)
{
filename = String.format("%s-metrics-%s-%s-last.xhtml", federation.getLocalFileBaseName(), type.getName(), view.getName());
data.setAttribute("lastPeriodButton", "href", filename);
filename = String.format("%s-metrics-%s-%s-2021.xhtml", federation.getLocalFileBaseName(), type.getName(), view.getName());
data.setAttribute("2021PeriodButton", "href", filename);
filename = String.format("%s-metrics-%s-%s-2022.xhtml", federation.getLocalFileBaseName(), type.getName(), view.getName());
data.setAttribute("2022PeriodButton", "href", filename);
}
//
if ((type == null) || (type == TypeMenu.SUMMARY))
{
data.appendAttribute("summaryTypeButton", "class", "button selected");
}
else if (type == TypeMenu.GENERIC)
{
data.appendAttribute("genericTypeButton", "class", "button selected");
}
else if (type == TypeMenu.WEB)
{
data.appendAttribute("webTypeButton", "class", "button selected");
}
else if (type == TypeMenu.SPECIFIC)
{
data.appendAttribute("specificTypeButton", "class", "button selected");
}
//
if ((view == null) || (view == ViewMenu.YEARS))
{
data.appendAttribute("yearsViewButton", "class", "button selected");
}
else if (view == ViewMenu.MONTHS)
{
data.appendAttribute("monthsViewButton", "class", "button selected");
}
else if (view == ViewMenu.WEEKS)
{
data.appendAttribute("weeksViewButton", "class", "button selected");
}
else if (view == ViewMenu.DAYS)
{
data.appendAttribute("daysViewButton", "class", "button selected");
}
//
if ((period == null) || (period == PeriodMenu.FULL))
{
data.appendAttribute("fullPeriodButton", "class", "button selected");
}
else if (period == PeriodMenu.LAST)
{
data.appendAttribute("lastPeriodButton", "class", "button selected");
}
else if (period == PeriodMenu.Y2021)
{
data.appendAttribute("2021PeriodButton", "class", "button selected");
}
else if (period == PeriodMenu.Y2022)
{
data.appendAttribute("2022PeriodButton", "class", "button selected");
}
//
String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/metricMenuView.xhtml", data).toString();
result = XidynUtils.extractBodyContent(content);
}
catch (XidynException exception)
{
throw new StatoolInfosException("Error building metric menu view: " + exception.getMessage(), exception);
}
//
return result;
}
}

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