Compare commits

..

34 commits
0.3 ... 0.17

Author SHA1 Message Date
94b231f74b Upgrade log4j libs from 2.17.1 to 2.23.1. 2024-08-21 16:36:40 +02:00
474a13b7e2 Cleaned code and Javadoc. 2024-08-18 23:34:02 +02:00
08e6071876 Improved HtmlCache class. 2024-08-18 22:37:29 +02:00
5e807b5200 Added KissDispatcher Processor setting in Ant script. 2024-08-18 22:37:10 +02:00
dd682a6b0a Made a Javadoc review. 2024-08-18 22:36:23 +02:00
33252b83ab Added a first version of HtmlCache class. 2024-08-12 17:31:15 +02:00
f90a88521f Improved logs. 2024-08-12 17:30:53 +02:00
0017f5a84e Added clear caches features. 2024-08-12 14:23:22 +02:00
40fa91feb4 Added feature about annotation for KissDispatcher. 2024-08-12 03:35:46 +02:00
d872a7528b Fixed Java upgrade. 2024-08-12 03:34:22 +02:00
0f8d487c32 Removed not useful log. 2024-08-12 03:33:34 +02:00
4e95cbd8ec Set explicitly UTF-8 as the project encoding. 2024-08-12 03:32:59 +02:00
1996d2f719 Refactored hugely hooks, added hook cache and servlet cache. 2024-08-08 17:23:52 +02:00
74ee23a382 Added RewriteHook. 2024-07-26 19:34:07 +02:00
c1603461f0 Upgraded log4j libs. 2024-07-26 19:33:39 +02:00
78f16db8f0 Build 0.17.1 2023-12-01 05:27:08 +01:00
5b096f4d79 Fixed FolderHook. 2023-12-01 05:26:38 +01:00
3a79d8e214 Build 0.17.0 2023-11-29 16:26:06 +01:00
67a2993cf5 Migrated to Tomcat 10.1. Improved code, Javadoc, doc, process… 2023-11-29 16:25:42 +01:00
02a8c54cb6 Javadoc review. 2023-11-28 03:28:49 +01:00
590c99c19b Fixed Java 17 migration. 2023-11-28 02:22:43 +01:00
07d0eb52b2 Clean code. 2023-11-28 00:38:36 +01:00
bac5b466b3 Improved Hooks. 2023-11-27 23:34:07 +01:00
eeba80d4b2 Removed unuseful devinsy-xml lib. 2023-11-27 19:24:54 +01:00
1ed5d0d029 Upgraded xidyn lib to 1.17.0. 2023-11-27 19:23:32 +01:00
f1d20d7c75 Upgraded devinsy-strings lib to 0.17.0. 2023-11-27 19:15:14 +01:00
99595ca81b Configured new version 0.17, Java 17 and Tomcat 10.1. 2023-11-27 19:13:42 +01:00
3abef0d595 Upgraded commons-lang3 to 3.13.0. 2023-11-26 20:46:45 +01:00
6b4e95c941 Migrated to Log4j2. 2021-12-28 18:26:02 +01:00
b70b496bbf Upgraded lib and dev environment. 2021-11-27 15:46:54 +01:00
9b9721f275 Improved short url hook. 2021-11-27 15:44:42 +01:00
d33924e876 Step in work. 2021-11-27 01:55:09 +01:00
50a2de3164 Step in dev. 2021-11-27 00:48:53 +01:00
c50aca1771 Step in 0.11 refactoring. 2021-07-10 19:46:31 +02:00
121 changed files with 5569 additions and 1734 deletions

View file

@ -2,28 +2,28 @@
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="test"/>
<classpathentry kind="lib" path="lib/servlet-api.jar" sourcepath="/KIWA/resources/extra-jars/servlet-api-2.4-sources.jar"/>
<classpathentry kind="lib" path="lib/commons-codec-1.8.jar" sourcepath="lib/commons-codec-1.8-sources.jar"/>
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
<classpathentry kind="lib" path="lib/commons-fileupload-1.3.jar" sourcepath="lib/commons-fileupload-1.3-sources.jar"/>
<classpathentry kind="lib" path="lib/commons-lang3-3.1-sources.jar"/>
<classpathentry kind="lib" path="lib/commons-lang3-3.1.jar" sourcepath="lib/commons-lang3-3.1-sources.jar"/>
<classpathentry kind="lib" path="lib/Logs/log4j-1.2.17-source.zip"/>
<classpathentry kind="lib" path="lib/Logs/log4j-1.2.17.jar"/>
<classpathentry kind="lib" path="lib/Logs/slf4j-api-1.7.5-sources.jar"/>
<classpathentry kind="lib" path="lib/Logs/slf4j-api-1.7.5.jar"/>
<classpathentry kind="lib" path="lib/Logs/slf4j-log4j12-1.7.5-sources.jar"/>
<classpathentry kind="lib" path="lib/Logs/slf4j-log4j12-1.7.5.jar"/>
<classpathentry kind="lib" path="lib/UnitTesting/hamcrest-core-1.3-sources.jar"/>
<classpathentry kind="lib" path="lib/UnitTesting/hamcrest-core-1.3.jar"/>
<classpathentry kind="lib" path="lib/UnitTesting/junit-4.11-sources.jar"/>
<classpathentry kind="lib" path="lib/UnitTesting/junit-4.11.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk1.6.0_45">
<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/devinsy-utils-0.3.2-sources.zip"/>
<classpathentry kind="lib" path="lib/devinsy-utils-0.3.2.jar"/>
<classpathentry kind="lib" path="lib/commons-codec-1.8.jar" sourcepath="lib/commons-codec-1.8-sources.jar"/>
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
<classpathentry kind="lib" path="lib/commons-fileupload-1.3.jar" sourcepath="lib/commons-fileupload-1.3-sources.jar"/>
<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/UnitTesting/junit-4.12.jar" sourcepath="lib/UnitTesting/junit-4.12-sources.jar"/>
<classpathentry kind="lib" path="lib/commons-io-2.7.jar" sourcepath="lib/commons-io-2.7-sources.jar"/>
<classpathentry kind="lib" path="lib/commons-lang3-3.13.0.jar" sourcepath="lib/commons-lang3-3.13.0-sources.jar"/>
<classpathentry kind="con" path="org.eclipse.jst.server.core.container/org.eclipse.jst.server.tomcat.runtimeTarget/apache-tomcat-10.1.12">
<attributes>
<attribute name="owner.project.facets" value="jst.utility"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="lib/devinsy-strings-0.17.0.jar" sourcepath="lib/devinsy-strings-0.17.0-sources.zip"/>
<classpathentry kind="lib" path="lib/Logs/log4j-api-2.23.1.jar" sourcepath="lib/Logs/log4j-api-2.23.1-sources.jar"/>
<classpathentry kind="lib" path="lib/Logs/log4j-core-2.23.1.jar" sourcepath="lib/Logs/log4j-core-2.23.1-sources.jar"/>
<classpathentry kind="lib" path="lib/Logs/log4j-slf4j2-impl-2.23.1.jar" sourcepath="lib/Logs/log4j-slf4j2-impl-2.32.1-sources.jar"/>
<classpathentry kind="lib" path="lib/Logs/slf4j-api-2.0.16.jar" sourcepath="lib/Logs/slf4j-api-2.0.16-sources.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,4 @@
eclipse.preferences.version=1
filter_fields=false
project_specific_settings=true
replacements=<?xml version\="1.0" standalone\="yes"?>\n\n<replacements>\n<replacement key\="get" scope\="1" mode\="0">Gets the</replacement>\n<replacement key\="set" scope\="1" mode\="0">Sets the</replacement>\n<replacement key\="add" scope\="1" mode\="0">Adds the</replacement>\n<replacement key\="edit" scope\="1" mode\="0">Edits the</replacement>\n<replacement key\="remove" scope\="1" mode\="0">Removes the</replacement>\n<replacement key\="init" scope\="1" mode\="0">Inits the</replacement>\n<replacement key\="parse" scope\="1" mode\="0">Parses the</replacement>\n<replacement key\="create" scope\="1" mode\="0">Creates the</replacement>\n<replacement key\="build" scope\="1" mode\="0">Builds the</replacement>\n<replacement key\="is" scope\="1" mode\="0">Checks if is</replacement>\n<replacement key\="print" scope\="1" mode\="0">Prints the</replacement>\n<replacement key\="has" scope\="1" mode\="0">Checks for</replacement>\n</replacements>\n\n

View file

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

View file

@ -1,41 +1,80 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
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
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
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=0
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_binary_expression=16
org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
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
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
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
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_shift_operator=0
org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16
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
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration=0
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method=1
org.eclipse.jdt.core.formatter.blank_lines_before_field=0
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
@ -44,6 +83,7 @@ org.eclipse.jdt.core.formatter.blank_lines_before_method=1
org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
org.eclipse.jdt.core.formatter.blank_lines_before_package=0
org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch=0
org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=next_line
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=next_line
@ -53,11 +93,17 @@ org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=next_line
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=next_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=next_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=next_line
org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=next_line
org.eclipse.jdt.core.formatter.brace_position_for_record_constructor=next_line
org.eclipse.jdt.core.formatter.brace_position_for_record_declaration=next_line
org.eclipse.jdt.core.formatter.brace_position_for_switch=next_line
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=next_line
org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=false
org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=false
org.eclipse.jdt.core.formatter.comment.format_block_comments=false
org.eclipse.jdt.core.formatter.comment.format_header=false
org.eclipse.jdt.core.formatter.comment.format_html=true
@ -66,8 +112,11 @@ org.eclipse.jdt.core.formatter.comment.format_line_comments=true
org.eclipse.jdt.core.formatter.comment.format_source_code=true
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
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
@ -82,6 +131,7 @@ org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=false
org.eclipse.jdt.core.formatter.indent_empty_lines=false
@ -90,6 +140,7 @@ org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
org.eclipse.jdt.core.formatter.indentation.size=4
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
@ -98,6 +149,7 @@ org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
@ -111,11 +163,14 @@ 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
org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default=insert
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
@ -141,10 +196,17 @@ 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
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_not_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
@ -161,6 +223,7 @@ org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not ins
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
@ -169,13 +232,19 @@ org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case=insert
org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default=insert
org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
@ -192,6 +261,7 @@ org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not in
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
@ -218,10 +288,16 @@ 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
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
@ -233,6 +309,8 @@ org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
@ -248,6 +326,7 @@ org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
@ -258,9 +337,12 @@ org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not inser
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
@ -272,20 +354,66 @@ org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_decla
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.join_lines_in_comments=true
org.eclipse.jdt.core.formatter.join_wrapped_lines=true
org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_code_block_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_method_body_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line=one_line_never
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.lineSplit=200
org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.lineSplit=150
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block=0
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block=0
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block=0
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body=0
org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block=0
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines
org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines
org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines
org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines
org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines
org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines
org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines
org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines
org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration=common_lines
org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines
org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.jdt.core.formatter.tabulation.char=space
org.eclipse.jdt.core.formatter.tabulation.size=4
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_binary_operator=true
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
org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true
org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true
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,54 +8,147 @@ 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=true
cleanup.convert_to_switch_expressions=false
cleanup.correct_indentation=false
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=true
cleanup.remove_redundant_type_arguments=true
cleanup.remove_trailing_whitespaces=true
cleanup.remove_trailing_whitespaces_all=true
cleanup.remove_trailing_whitespaces_ignore_empty=false
cleanup.remove_unnecessary_array_creation=false
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
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.useless_continue=false
cleanup.useless_return=false
cleanup.valueof_rather_than_instantiation=false
cleanup_profile=_Kiss4web
cleanup_settings_version=2
eclipse.preferences.version=1
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
formatter_profile=_Kiss4web
formatter_settings_version=12
formatter_settings_version=23
jautodoc.cleanup.add_header=false
jautodoc.cleanup.javadoc=false
jautodoc.cleanup.replace_header=false
org.eclipse.jdt.ui.text.custom_code_templates=
sp_cleanup.add_default_serial_version_id=true
sp_cleanup.add_generated_serial_version_id=false
sp_cleanup.add_missing_annotations=true

View file

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

116
README.md
View file

@ -13,9 +13,17 @@ Kiss4web builds on:
- KissDispatcher: call the good Java Servlet for each HTTP request,
- Xidyn: a template solution to dynamize HTML sources.
## Author
Lead developer: Christian Pierre MOMON <christian.momon@devinsy.fr>
## License
Kiss4web is released under the GNU LGPL license.
## Developing environment
Kiss4web-demo project uses strictly Eclipse Kepler, Java 6, GIT.
Kiss4web project uses strictly Eclipse 4.29, Java 17, tomcat 10.1 and Git.
## Build
@ -26,7 +34,109 @@ Kiss4web uses Ant and generates a kiss4web-x.y.z folder which contains:
- x-core.jar : only compiled class without any library.
- x-core-source.jar : sources.
## Dependencies
# License
The kiss4web jar requires:
- commons-io
- commons-lang3
- devinsy-strings
Kiss4web is released under the GNU LGPL license.
## Usages
```
B --> FooAppLauncher -------------------------> FooApp
[ServletContextListener] [Singleton]
|
| setMode(Mode.OPEN)
\ /
A --> Kiss4webLauncher ----setMode(Mode.OPEN)---> Kiss4web <Mode.APP_INIT>
[ServletContextListener] [Singleton]
```
KissDispatcher is initialized with Mode.APP_INIT.
### Usage A: default
The easier way, in case you have no application initialization step. The Kiss4webLauncher set a default log4j2 configuration and set the KissDispatcher to Mode.OPEN state with a default set of hooks.
Edit `…/WebContent/WEB-INF/web.xml` :
```
<listener>
<listener-class>fr.devinsy.kiss4web.Kiss4webLauncher</listener-class>
</listener>
<servlet>
<servlet-name>Application dispatcher</servlet-name>
<servlet-class>fr.devinsy.kiss4web.dispatcher.KissDispatcher</servlet-class>
<init-param>
<param-name>webClassesRootPackage</param-name>
<param-value>website</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Application dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
```
You can create …/WebContent/WEB-INF/log4j2.properties:
```
# Log configuration
# #################
# priority setting: DEBUG < INFO < WARN < ERROR
name = Log4j2 Properties Config
status = ERROR
dest = err
# Logger settings.
rootLogger.level = INFO
rootLogger.appenderRefs = a, b
rootLogger.appenderRef.a.ref = CONSOLE
rootLogger.appenderRef.b.ref = LOGFILE
logger.statoolinfos.name = fr.devinsy.statoolinfos
logger.statoolinfos.level = INFO
logger.xidyn.name = fr.devinsy.xidyn
logger.xidyn.level = WARN
# Appenders settings.
appenders = CONSOLE, LOGFILE
appender.CONSOLE.type = Console
appender.CONSOLE.name = CONSOLE
appender.CONSOLE.layout.type = PatternLayout
appender.CONSOLE.layout.pattern = %d{ISO8601} - FooApp [%-5p] %34.34c.%25M - %m%n
appender.LOGFILE.type = File
appender.LOGFILE.name = LOGFILE
appender.LOGFILE.filename = /srv/fooapp/rslisi.log
appender.LOGFILE.layout.type = PatternLayout
appender.LOGFILE.layout.pattern = %d{ISO8601} - FooApp [%-5p] %34.34c.%25M - %m%n
```
### Usage B: custom init
If you want manage an application initialization step, do not use the Kiss4webLauncher as class listener. Create your own FooAppLauncher and make it calls `Kiss4web.instance().setMode(Mode.OPEN)` when the init step is over.
Edit `…/WebContent/WEB-INF/web.xml` :
```
<listener>
<listener-class>org.foo.app.FooAppLauncher</listener-class>
</listener>
<servlet>
<servlet-name>Application dispatcher</servlet-name>
<servlet-class>fr.devinsy.kiss4web.dispatcher.KissDispatcher</servlet-class>
<init-param>
<param-name>webClassesRootPackage</param-name>
<param-value>website</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Application dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
```

View file

@ -110,6 +110,7 @@
<attribute name="Built-By" value="${user.name} using ant" />
<attribute name="Built-Date" value="${dist.time}" />
</manifest>
<service type="javax.annotation.processing.Processor" provider="fr.devinsy.kiss4web.dispatcher.annotation.KissServletProcessor" />
<fileset dir="${build.classes}" />
</jar>

View file

@ -1,3 +1,3 @@
#Build Number for ANT. Do not edit!
#Wed Sep 21 14:25:05 CEST 2016
build.number=1
#Fri Dec 01 05:27:08 CET 2023
build.number=2

View file

@ -1,3 +1,3 @@
product.name=kiss4web
product.revision.major=0
product.revision.minor=3
product.revision.minor=17

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,11 +1,17 @@
Description of used libraries:
== Description of used libraries.
Various:
- commons-codec: digest tools.
- commons-fileupload:
- commons-io:
- devinsy-utils: util tools
- hamcrest-core: required by junit
- junit: unit tests API
- log4j: log API
- servlet-api: servlet API
Log libs:
- log4j: log API
- slf4j-api: facade log API
- slf4j-log4j12: adaptation layer between slf4j and log4j
UnitTest libs:
- hamcrest-core: required by junit
- junit: unit tests API

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
lib/commons-text-1.9.jar Normal file

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,5 +1,5 @@
/**
* Copyright (C) 2013-2016 Christian Pierre MOMON
* Copyright (C) 2013-2023 Christian Pierre MOMON
*
* This file is part of Kiss4web.
*
@ -21,14 +21,11 @@ package fr.devinsy.kiss4web;
import java.io.IOException;
import java.util.Properties;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
*
* @author Christian P. Momon
* The Class BuildInformation.
*/
public class BuildInformation
{
@ -43,16 +40,15 @@ public class BuildInformation
private String author;
/**
*
* Instantiates a new builds the information.
*/
public BuildInformation()
{
Properties build = new Properties();
try
{
//
build.load(BuildInformation.class.getResource("/build_information.properties").openStream());
Properties build = new Properties();
build.load(BuildInformation.class.getResource("/fr.devinsy.kiss4web/build_information.properties").openStream());
//
this.productName = build.getProperty("product.name", "n/a");
@ -66,11 +62,8 @@ public class BuildInformation
}
catch (IOException exception)
{
//
logger.error("Error loading the build.properties file: " + exception.getMessage());
logger.error(ExceptionUtils.getStackTrace(exception));
logger.error("Error loading the build.properties file: " + exception.getMessage(), exception);
//
this.productName = "n/a";
this.majorRevision = "n/a";
this.minorRevision = "n/a";
@ -81,58 +74,97 @@ public class BuildInformation
}
}
/**
* Author.
*
* @return the string
*/
public String author()
{
return this.author;
}
/**
* Builds the date.
*
* @return the string
*/
public String buildDate()
{
return this.buildDate;
}
/**
* Builds the number.
*
* @return the string
*/
public String buildNumber()
{
return this.buildNumber;
}
/**
* Generator.
*
* @return the string
*/
public String generator()
{
return this.generator;
}
/**
* Major revision.
*
* @return the string
*/
public String majorRevision()
{
return this.majorRevision;
}
/**
* Minor revision.
*
* @return the string
*/
public String minorRevision()
{
return this.minorRevision;
}
/**
* Product name.
*
* @return the string
*/
public String productName()
{
return this.productName;
}
/**
* To string.
*
* @return the string
*/
@Override
public String toString()
{
String result;
result = String.format("%s %s.%s.%s built on %s by %s", this.productName, this.majorRevision, this.minorRevision, this.buildNumber, this.buildDate, this.author);
result = String.format("%s %s.%s.%s built on %s by %s", this.productName, this.majorRevision, this.minorRevision, this.buildNumber,
this.buildDate, this.author);
//
return result;
}
/**
* Version.
*
* @return
* @return the string
*/
public String version()
{

View file

@ -1,6 +1,5 @@
/**
* Copyright (C) 2013-2016 Christian Pierre MOMON
* Copyright (C) 2006-2010 Christian Pierre MOMON
* Copyright (C) 2006-2024 Christian Pierre MOMON
*
* This file is part of Kiss4web.
*
@ -21,28 +20,36 @@ package fr.devinsy.kiss4web;
import java.io.UnsupportedEncodingException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
/**
*
* The Class CookieHelper.
*/
public class CookieHelper
{
private static final Logger logger = LoggerFactory.getLogger(CookieHelper.class);
public enum Scope
{
HTTP_AND_HTTPS,
HTTPS_ONLY
}
private static final Logger logger = LoggerFactory.getLogger(CookieHelper.class);
/**
* Builds the cookie.
*
* @param name
* the name
* @param value
* the value
* @param duration
* the duration
* @return the cookie
*/
public static Cookie buildCookie(final String name, final String value, final int duration)
{
@ -55,7 +62,17 @@ public class CookieHelper
}
/**
* Warning: value is UTF-8 URLEncoded!
* Warning: value is UTF-8 URLEncoded!.
*
* @param name
* the name
* @param value
* the value
* @param duration
* the duration
* @param secure
* the secure
* @return the cookie
*/
public static Cookie buildCookie(final String name, final String value, final int duration, final Scope secure)
{
@ -89,7 +106,13 @@ public class CookieHelper
}
/**
* Exists.
*
* @param request
* the request
* @param key
* the key
* @return true, if successful
*/
public static boolean exists(final HttpServletRequest request, final String key)
{
@ -109,7 +132,13 @@ public class CookieHelper
}
/**
* Gets the cookie.
*
* @param cookies
* the cookies
* @param key
* the key
* @return the cookie
*/
public static Cookie getCookie(final Cookie[] cookies, final String key)
{
@ -150,7 +179,13 @@ public class CookieHelper
}
/**
* Gets the cookie.
*
* @param request
* the request
* @param key
* the key
* @return the cookie
*/
public static Cookie getCookie(final HttpServletRequest request, final String key)
{
@ -164,6 +199,12 @@ public class CookieHelper
/**
* Note: value is UTF-8 decoded.
*
* @param cookies
* the cookies
* @param key
* the key
* @return the cookie value
*/
public static Object getCookieValue(final Cookie[] cookies, final String key)
{
@ -193,7 +234,13 @@ public class CookieHelper
}
/**
* Gets the cookie value.
*
* @param request
* the request
* @param key
* the key
* @return the cookie value
*/
public static Object getCookieValue(final HttpServletRequest request, final String key)
{
@ -206,7 +253,12 @@ public class CookieHelper
}
/**
* Reset.
*
* @param response
* the response
* @param key
* the key
*/
public static void reset(final HttpServletResponse response, final String key)
{
@ -214,7 +266,16 @@ public class CookieHelper
}
/**
* Sets the.
*
* @param response
* the response
* @param name
* the name
* @param value
* the value
* @param duration
* the duration
*/
public static void set(final HttpServletResponse response, final String name, final String value, final int duration)
{

View file

@ -1,124 +1,245 @@
/**
* Copyright 2013-2015 Christian Pierre MOMON, DEVINSY, UMR 7186 LESC.
* Copyright 2013-2021 Christian Pierre MOMON
*
* christian.momon@devinsy.fr
*
* This file is part of kiss4web. This software (Kiwa) is a computer program whose
* purpose is to be the Kinsources Web Application, an open interactive platform
* for archiving, sharing, analyzing and comparing kinship data used in
* scientific inquiry.
* This file is part of Kiss4web.
*
* This software is governed by the CeCILL license under French law and abiding
* by the rules of distribution of free software. You can use, modify and/ or
* redistribute the software under the terms of the CeCILL license as circulated
* by CEA, CNRS and INRIA at the following URL "http://www.cecill.info".
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* As a counterpart to the access to the source code and rights to copy, modify
* and redistribute granted by the license, users are provided only with a
* limited warranty and the software's author, the holder of the economic
* rights, and the successive licensors have only limited liability.
* Kiss4web 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 Lesser General Public License for more details.
*
* In this respect, the user's attention is drawn to the risks associated with
* loading, using, modifying and/or developing or reproducing the software by
* the user in light of its specific status of free software, that may mean that
* it is complicated to manipulate, and that also therefore means that it is
* reserved for developers and experienced professionals having in-depth
* computer knowledge. Users are therefore encouraged to load and test the
* software's suitability as regards their requirements in conditions enabling
* the security of their systems and/or data to be ensured and, more generally,
* to use and operate it in the same conditions as regards security.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL license and that you accept its terms.
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web;
import java.io.File;
import javax.naming.ConfigurationException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.util.strings.StringListUtils;
import fr.devinsy.strings.StringsUtils;
/**
*
*
* @author Christian P. Momon
* The Class EnvironmentInformation.
*/
public class EnvironmentInformation
{
private static final Logger logger = LoggerFactory.getLogger(EnvironmentInformation.class);;
private String name;
private String websiteName;
private String websiteUrl;
private String log4jFilePathname;
private Context environment;
/**
* @throws ConfigurationException
* Instantiates a new environment information.
*
* @throws ConfigurationException
* the configuration exception
*/
public EnvironmentInformation() throws ConfigurationException
{
try
{
//
Context initialContext = new InitialContext();
Context environment = (Context) initialContext.lookup("java:comp/env");
//
this.name = (String) environment.lookup("kiss4web.environment.name");
//
this.websiteName = (String) environment.lookup("kiss4web.website.name");
//
this.websiteUrl = (String) environment.lookup("kiss4web.website.url");
if ((this.websiteUrl != null) && (!this.websiteUrl.endsWith("/")))
{
this.websiteUrl = this.websiteUrl + "/";
}
//
this.log4jFilePathname = (String) environment.lookup("kiss4web.log4j.path");
this.environment = (Context) initialContext.lookup("java:comp/env");
}
catch (NamingException exception)
{
logger.error("Error setting the java:comp/env context: ", exception.getMessage());
logger.error(ExceptionUtils.getStackTrace(exception));
logger.error("Environment information:");
logger.error("- name=[" + this.name + "]");
logger.error("- websiteUrl=[" + this.websiteUrl + "]");
logger.error("- log4jPath=[" + this.log4jFilePathname + "]");
logger.error("Error getting context information: ", exception.getMessage(), exception);
throw new ConfigurationException("Error setting environment information: " + exception.getMessage());
}
// Check availability of all fields.
if (isNotAvailable())
if (!isAvailable())
{
logger.error("Environment information:");
logger.error("- name=[" + this.name + "]");
logger.error("- websiteUrl=[" + this.websiteUrl + "]");
logger.error("- log4jPath=[" + this.log4jFilePathname + "]");
throw new ConfigurationException("Environment information is not fully available.");
}
}
/**
* Gets the log 4 j path.
*
* @return
* @return the log 4 j path
* @throws ConfigurationException
* the configuration exception
*/
public String getLog4jPath() throws ConfigurationException
{
String result;
try
{
result = (String) this.environment.lookup("kiss4web.log4j2.path");
}
catch (NamingException exception)
{
throw new ConfigurationException("Context configuration error on log4j2 path.");
}
//
return result;
}
/**
* Gets the name.
*
* @return the name
* @throws ConfigurationException
* the configuration exception
*/
public String getName() throws ConfigurationException
{
String result;
try
{
result = (String) this.environment.lookup("kiss4web.environment.name");
}
catch (NamingException exception)
{
throw new ConfigurationException("Context configuration error on environment name.");
}
//
return result;
}
/**
* Gets the statool infos configuration file.
*
* @return the statool infos configuration file
* @throws ConfigurationException
* the configuration exception
*/
public File getStatoolInfosConfigurationFile() throws ConfigurationException
{
File result;
try
{
String filepath = (String) this.environment.lookup("statoosinfosweb.configuration.file");
if (filepath == null)
{
result = null;
}
else
{
result = new File(filepath);
}
}
catch (NamingException exception)
{
throw new ConfigurationException("Context configuration missing 'statoosinfosweb.configuration.file'.");
}
//
return result;
}
/**
* Gets the website name.
*
* @return the website name
* @throws ConfigurationException
* the configuration exception
*/
public String getWebsiteName() throws ConfigurationException
{
String result;
try
{
result = (String) this.environment.lookup("kiss4web.website.name");
}
catch (NamingException exception)
{
throw new ConfigurationException("Context configuration error on website name.");
}
//
return result;
}
/**
* Gets the website package path.
*
* @return the website package path
* @throws ConfigurationException
* the configuration exception
*/
public String getWebsitePackagePath() throws ConfigurationException
{
String result;
try
{
result = (String) this.environment.lookup("kiss4web.website.packagepath");
if ((result != null) && (!result.endsWith(".")))
{
result = result + ".";
}
}
catch (NamingException exception)
{
throw new ConfigurationException("Context configuration error on website package path.");
}
//
return result;
}
/**
* Gets the website URL path.
*
* @return the website URL path
* @throws ConfigurationException
* the configuration exception
*/
public String getWebsiteURLPath() throws ConfigurationException
{
String result;
try
{
result = (String) this.environment.lookup("kiss4web.website.url");
if ((result != null) && (!result.endsWith("/")))
{
result = result + "/";
}
}
catch (NamingException exception)
{
throw new ConfigurationException("Context configuration error on website package path.");
}
//
return result;
}
/**
* Checks if is available.
*
* @return true, if is available
*/
public boolean isAvailable()
{
boolean result;
if (StringListUtils.containsBlank(this.name, this.websiteName, this.websiteUrl, this.log4jFilePathname))
try
{
if (StringsUtils.containsBlank(getName(), getWebsiteURLPath(), getWebsiteURLPath()))
{
result = false;
}
@ -126,41 +247,13 @@ public class EnvironmentInformation
{
result = true;
}
}
catch (NamingException exception)
{
result = false;
}
//
return result;
}
/**
*
* @return
*/
public boolean isNotAvailable()
{
boolean result;
result = !isAvailable();
return result;
}
public String log4jFilePathname()
{
return this.log4jFilePathname;
}
public String name()
{
return this.name;
}
public String websiteName()
{
return this.websiteName;
}
public String websiteUrl()
{
return this.websiteUrl;
}
}

View file

@ -0,0 +1,200 @@
/*
* Copyright (C) 2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web;
import java.util.HashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.strings.StringList;
import jakarta.servlet.http.HttpServletRequest;
/**
* The Class HtmlCache.
*/
public class HtmlCache extends HashMap<String, String>
{
private static final long serialVersionUID = -310354977854681838L;
private static Logger logger = LoggerFactory.getLogger(HtmlCache.class);
/**
* Instantiates a new html cache.
*/
public HtmlCache()
{
super();
}
/**
* Builds the key.
*
* @param object
* the object
* @param strings
* the strings
* @return the string
*/
public String buildKey(final Object object, final String... strings)
{
String result;
if (object == null)
{
result = null;
}
else
{
result = buildKey(object.getClass().getCanonicalName(), strings);
}
//
return result;
}
/**
* Builds the key.
*
* @param main
* the main
* @param strings
* the strings
* @return the string
*/
public String buildKey(final String main, final String... strings)
{
String result;
if (main == null)
{
result = null;
}
else
{
int capacity = strings.length * 2 + 1;
StringList buffer = new StringList(capacity);
buffer.add(main);
for (int index = 0; index < strings.length; index++)
{
buffer.append('#');
buffer.append(index);
buffer.append(strings[index]);
}
result = buffer.toString();
}
//
return result;
}
/**
* Gets the HTML code using a GET request.
*
* @param request
* the request
* @return the string
*/
public String get(final HttpServletRequest request)
{
String result;
if (request == null)
{
result = null;
}
else
{
String key = request.getPathInfo();
if (request.getQueryString() != null)
{
key = key + "?" + request.getQueryString();
}
result = super.get(key);
if (result != null)
{
logger.info("HTML CACHE MATCHED: [{}]", key);
}
}
//
return result;
}
/**
* Gets the.
*
* @param key
* the key
* @return the string
*/
public String get(final String key)
{
String result;
if (key == null)
{
result = null;
}
else
{
result = super.get(key);
if (result != null)
{
logger.info("HTML Cache matched: [{}]", key);
}
}
//
return result;
}
/**
* Put HTML code using a GET request.
*
* @param html
* the html
* @param request
* the request
* @return the string
*/
public String put(final HttpServletRequest request, final String html)
{
String result;
if ((request == null) || (html == null))
{
result = null;
}
else
{
String key = request.getPathInfo();
if (request.getQueryString() != null)
{
key = key + "?" + request.getQueryString();
}
result = super.put(key, html);
}
//
return result;
}
}

View file

@ -1,5 +1,5 @@
/**
* Copyright (C) 2013-2016 Christian Pierre MOMON
/*
* Copyright (C) 2013-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
@ -21,105 +21,247 @@ package fr.devinsy.kiss4web;
import java.util.Date;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import fr.devinsy.kiss4web.dispatcher.KissDispatcher;
import fr.devinsy.kiss4web.dispatcher.hooks.ApplicationInitFailedHook;
import fr.devinsy.kiss4web.dispatcher.hooks.ApplicationInitHook;
import fr.devinsy.kiss4web.dispatcher.hooks.BlankHook;
import fr.devinsy.kiss4web.dispatcher.hooks.FatalHook;
import fr.devinsy.kiss4web.dispatcher.hooks.FolderHook;
import fr.devinsy.kiss4web.dispatcher.hooks.HookRegister;
import fr.devinsy.kiss4web.dispatcher.hooks.InitFailedHook;
import fr.devinsy.kiss4web.dispatcher.hooks.LongURLHook;
import fr.devinsy.kiss4web.dispatcher.hooks.MaintenanceHook;
import fr.devinsy.kiss4web.dispatcher.hooks.RootHook;
import fr.devinsy.kiss4web.dispatcher.hooks.ShortURLHook;
import fr.devinsy.kiss4web.dispatcher.hooks.WebContentHook;
import fr.devinsy.kiss4web.dispatcher.hooks.WebInfHook;
import fr.devinsy.kiss4web.dispatcher.hooks.XHTMLHook;
/**
*
*
* @author Christian P. Momon
* The Class Kiss4web.
*/
public class Kiss4web
{
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Kiss4web.class);
/**
* The Enum Mode.
*/
public enum Mode
{
INIT,
INIT_FAILED,
APP_INIT,
APP_INIT_FAILED,
OPEN,
MAINTENANCE,
FATAL,
CUSTOM
}
private static class SingletonHolder
{
private static final Kiss4web instance = new Kiss4web();
}
public enum Status
{
INIT_FAILED,
OPENED,
MAINTENANCE
}
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Kiss4web.class);
private BuildInformation buildInformation;
private Status status;
private Mode mode;
/**
* @throws Exception
*
* Instantiates a new kiss 4 web.
*/
private Kiss4web()
{
//
String currentLog = "Kiwa";
String currentLog = "Kiss4web";
//
try
{
//
currentLog = "Kiwa";
logger.info("Kiwa initializing...");
setMode(Mode.INIT);
//
currentLog = "Kiss4web";
logger.info("Kiss4web initializing...");
long startTime = new Date().getTime();
logInit(currentLog, "STARTING");
//
currentLog = "BuildInformation";
this.buildInformation = new BuildInformation();
logger.info(" build information=[" + this.buildInformation.toString() + "]");
logInit(currentLog, "PASSED");
// currentLog = "BuildInformation";
// this.buildInformation = new BuildInformation();
// logger.info(" build information=[" +
// this.buildInformation.toString() + "]");
// logInit(currentLog, "PASSED");
//
currentLog = "Kiwa";
//
setMode(Mode.APP_INIT);
logInit("set APP INIT mode", "PASSED");
//
currentLog = "Kiss4web";
logInit(currentLog, "STARTED");
long endTime = new Date().getTime();
logger.info("Kiss4web initialized in {}ms.", endTime - startTime);
}
catch (Exception exception)
{
//
logInit(currentLog, "FAILED");
//
logger.warn("KISS4WEV INIT FAILED: " + exception.getMessage());
//
logger.warn(ExceptionUtils.getStackTrace(exception));
//
this.status = Kiss4web.Status.INIT_FAILED;
logger.warn("KISS4WEB INIT FAILED: " + exception.getMessage(), exception);
setMode(Mode.INIT_FAILED);
}
}
/**
* Builds the information.
*
* @return the builds the information
*/
public BuildInformation buildInformation()
{
return this.buildInformation;
}
/**
* Gets the mode.
*
* @return
* @return the mode
*/
public Kiss4web.Status getStatus()
public Mode getMode()
{
return this.status;
return this.mode;
}
/**
* Sets the mode.
*
* @param status
* @param mode
* the new mode
*/
public void setStatus(final Status status)
public void setMode(final Mode mode)
{
this.status = status;
switch (mode)
{
case INIT:
{
if (this.mode == null)
{
this.mode = Mode.INIT;
}
}
break;
case INIT_FAILED:
{
if (this.mode == Mode.INIT)
{
this.mode = mode;
HookRegister hooks = new HookRegister("Init failed");
hooks.register(new InitFailedHook());
KissDispatcher.instance().setHookRegister(hooks);
}
}
break;
case APP_INIT:
{
if (this.mode == Mode.INIT)
{
this.mode = mode;
HookRegister hooks = new HookRegister("Application Init");
hooks.register(new ApplicationInitHook());
KissDispatcher.instance().setHookRegister(hooks);
}
}
break;
case APP_INIT_FAILED:
{
if (this.mode == Mode.APP_INIT)
{
this.mode = mode;
HookRegister hooks = new HookRegister("Application Init failed");
hooks.register(new ApplicationInitFailedHook());
KissDispatcher.instance().setHookRegister(hooks);
}
}
break;
case OPEN:
{
if ((this.mode == Mode.APP_INIT) || (this.mode == Mode.MAINTENANCE))
{
this.mode = mode;
HookRegister hooks = new HookRegister("Open");
hooks.register(new BlankHook());
hooks.register(new RootHook());
hooks.register(new LongURLHook());
hooks.register(new FolderHook());
hooks.register(new ShortURLHook());
hooks.register(new XHTMLHook());
hooks.register(new WebContentHook());
hooks.register(new WebInfHook());
KissDispatcher.instance().setHookRegister(hooks);
}
}
break;
case MAINTENANCE:
{
this.mode = mode;
HookRegister hooks = new HookRegister("Maintenance");
hooks.register(new MaintenanceHook());
KissDispatcher.instance().setHookRegister(hooks);
}
break;
case FATAL:
{
this.mode = mode;
HookRegister hooks = new HookRegister("Fatal");
hooks.register(new FatalHook());
KissDispatcher.instance().setHookRegister(hooks);
}
break;
case CUSTOM:
if ((this.mode == Mode.APP_INIT) || (this.mode == Mode.MAINTENANCE) || (this.mode == Mode.OPEN))
{
this.mode = mode;
}
break;
default:
}
}
/**
* Sets the mode custom.
*
* @return
* @param hooks
* the new mode custom
*/
public void setModeCustom(final HookRegister hooks)
{
if (hooks != null)
{
this.mode = Mode.CUSTOM;
KissDispatcher.instance().setHookRegister(hooks);
}
}
/**
* Instance.
*
* @return the kiss 4 web
*/
public static Kiss4web instance()
{
@ -127,9 +269,12 @@ public class Kiss4web
}
/**
* Log init.
*
* @param currentLogItem
* the current log item
* @param status
* the status
*/
private static void logInit(final String currentLogItem, final String status)
{

View file

@ -0,0 +1,71 @@
/*
* Copyright (C) 2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web;
/**
* The Class Kiss4webException.
*/
public class Kiss4webException extends Exception
{
private static final long serialVersionUID = -6018571288000296858L;
/**
* Instantiates a new kiss 4 web exception.
*/
public Kiss4webException()
{
super();
}
/**
* Instantiates a new kiss 4 web exception.
*
* @param message
* the message
*/
public Kiss4webException(final String message)
{
super(message);
}
/**
* Instantiates a new kiss 4 web exception.
*
* @param message
* the message
* @param cause
* the cause
*/
public Kiss4webException(final String message, final Throwable cause)
{
super(message, cause);
}
/**
* Instantiates a new kiss 4 web exception.
*
* @param cause
* the cause
*/
public Kiss4webException(final Throwable cause)
{
super(cause);
}
}

View file

@ -0,0 +1,118 @@
/*
* Copyright (C) 2013-2024 Christian Pierre MOMON <christian.momon@devinsy.fr>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web;
import java.io.File;
import javax.naming.ConfigurationException;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.logging.log4j.core.config.DefaultConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.kiss4web.Kiss4web.Mode;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
/**
* The Class Kiss4WebLauncher.
*
* The Context element represents a web application. If you have implemented a
* Java object that needs to know when this Context is started or stopped, you
* can declare it by nesting a Listener element inside this element.
*/
public class Kiss4webLauncher implements ServletContextListener
{
private static Logger logger = LoggerFactory.getLogger(Kiss4webLauncher.class);
/**
* {@inheritDoc}
*/
@Override
public void contextDestroyed(final ServletContextEvent sce)
{
}
/**
* {@inheritDoc}
*/
@Override
public void contextInitialized(final ServletContextEvent event)
{
System.out.println("========= KISS4WEB WEBAPP LAUNCHING… ==========");
ServletContext context = event.getServletContext();
initLogger(context.getRealPath("/"));
Kiss4web.instance().setMode(Mode.OPEN);
System.out.println("========= KISS4WEB WEBAPP LAUNCHED ==========");
}
/**
* Inits the logger.
*
* @param webappRoot
* the webapp root
*/
public void initLogger(final String webappRoot)
{
// Set logger.
String logFilePathname;
try
{
logFilePathname = new EnvironmentInformation().getLog4jPath();
}
catch (ConfigurationException exception)
{
System.err.println("Error reading the environment information.");
exception.printStackTrace();
logFilePathname = null;
}
if (StringUtils.isBlank(logFilePathname))
{
Configurator.initialize(new DefaultConfiguration());
logger.warn("Log configuration undefined, use of the basic configurator.");
}
else
{
System.out.println("Log configuration defined (" + logFilePathname + "), will use it.");
if (!logFilePathname.startsWith("/"))
{
logFilePathname = webappRoot + logFilePathname;
System.out.println("Log configuration redefined (" + logFilePathname + "), will use it.");
}
if (new File(logFilePathname).exists())
{
Configurator.initialize(null, logFilePathname);
}
else
{
System.out.println("Log configuration FILE NOT FOUND (" + logFilePathname + "), use of the basic configurator.");
Configurator.initialize(new DefaultConfiguration());
}
logger = LoggerFactory.getLogger(this.getClass());
logger.info("Log initialization done.");
}
}
}

View file

@ -1,5 +1,5 @@
/**
* Copyright (C) 2006-2010, 2013-2016 Christian Pierre MOMON
/*
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
@ -19,8 +19,7 @@
package fr.devinsy.kiss4web;
/**
*
* @author Christian Pierre MOMON (christian.momon@devinsy.fr)
* The Class Kiss4webUtils.
*/
public class Kiss4webUtils
{

View file

@ -1,264 +0,0 @@
/**
* Copyright (C) 2006-2010, 2013-2016 Christian Pierre MOMON
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web;
import java.io.IOException;
import java.util.Date;
import javax.naming.ConfigurationException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.kiss4web.hooks.BlankHook;
import fr.devinsy.kiss4web.hooks.FolderHook;
import fr.devinsy.kiss4web.hooks.Hook;
import fr.devinsy.kiss4web.hooks.HookRegister;
import fr.devinsy.kiss4web.hooks.LongURLHook;
import fr.devinsy.kiss4web.hooks.RootHook;
import fr.devinsy.kiss4web.hooks.ShortURLHook;
import fr.devinsy.kiss4web.hooks.WebContentHook;
import fr.devinsy.kiss4web.hooks.WebInfHook;
import fr.devinsy.kiss4web.hooks.XHTMLHook;
/**
*
* According that URL is under UTF-8 format. Set Tomcat connector if needs
* (<connector URIEncoding="UTF-8" />).
*/
public class KissDispatcher extends HttpServlet
{
private static final long serialVersionUID = -3471226305721330069L;
private static Logger logger = LoggerFactory.getLogger(KissDispatcher.class);
public static final int DEFAULT_CACHE_AGE = 2 * 60 * 60;
private KissClassCache cache;
/**
*
*/
public KissDispatcher()
{
this.cache = new KissClassCache();
}
/**
* <pre>
* "/" => "Index_xhtml"
* "/good/" => "good.Good_xhtml"
* "/good/morning.xhtml" => "good.Morning_xhtml"
* "/good/morning_girl.xhtml" => "good.Morning_girl_xhtml"
* "/good/morning-123.xhtml" => "good.Morning_xhtml" ('123' is detected as a parameter, it will be
* decoded in the class called later).
* "/good/morning-/12/toto.jpg" => "good.Morning" ('12' and 'toto.jpg" are detected as a parameter, they
* will be decoded in the class called later).
* </pre>
*
*/
public void dispatch(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
long startTime = new Date().getTime();
request.setCharacterEncoding("UTF-8");
logger.info("==================================================");
logger.info("getContextPath=[" + request.getContextPath() + "]");
logger.info("getPathInfo=[" + request.getPathInfo() + "]");
logger.info("getPathTranslated=[" + request.getPathTranslated() + "]");
logger.info("getQueryString=[" + request.getQueryString() + "]");
logger.info("getRequestURI=[" + request.getRequestURI() + "]");
logger.info("getRequestURL=[" + request.getRequestURL() + "]");
logger.info("getServletPath=[" + request.getServletPath() + "]");
//
/*
* In past, possibility to use the servlet path was enable. It is too
* complexe, not kiss mind.
*
* String path;
* if (request.getPathInfo() == null)
* {
* // web.xml url-pattern= *.xhtml
* path = request.getServletPath();
* }
* else
* {
* // web.xml url-pattern =
* path = request.getPathInfo();
* }
*
* https://issues.apache.org/bugzilla/show_bug.cgi?id=11318
* A number of features have been introduced in later versions of Tomcat
* that relate to URI encoding. This includes a URIEncoding attribute
* on the Coyote HTTP/1.1 connector which defaults to ISO-8859-1.
*
* According to the servlet specification:
* HttpServletRequest.getPathInfo() should be decoded by the web container;
* HttpServletRequest.getRequestURI() should not be decoded by the web container.
*
*
* http://stackoverflow.com/questions/15278512/safe-html-form-accept-charset/15587140#15587140
* The standard URL encoding must use UTF-8 yet servlets not only default to ISO-8859-1 but don't offer
* any way to change that with code.
* Sure you can req.setRequestEncoding("UTF-8") before you read anything, but for some ungodly reason this only affects request body,
* not query string parameters. There is nothing in the servlet request interface to specify the encoding used for query string parameters.
* Using ISO-8859-1 in your form is a hack. Using this ancient encoding will cause more problems than solve for sure.
* Especially since browsers do not support ISO-8859-1 and always treat it as Windows-1252. Whereas servlets treat ISO-8859-1 as ISO-8859-1,
* so you will be screwed beyond belief if you go with this.
* To change this in Tomcat for example, you can use the URIEncoding attribute in your <connector> element:
* <connector ... URIEncoding="UTF-8" ... />
*
* If you don't use a container that has these settings, can't change its settings or some other issue,
* you can still make it work because ISO-8859-1 decoding retains full information from the original binary.
* String correct = new String(request.getParameter("test").getBytes("ISO-8859-1"), "UTF-8")
*
*
* http://tomcat.apache.org/tomcat-5.5-doc/config/http.html
* URIEncoding
* This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL.
* If not specified, ISO-8859-1 will be used.
*
*/
// String urlPath = request.getPathInfo();
HookRegister hookRegister = KissDispatcherFactory.instance().catchers();
if (hookRegister.hooks().isEmpty())
{
hookRegister.register(new BlankHook());
hookRegister.register(new RootHook());
hookRegister.register(new LongURLHook());
hookRegister.register(new FolderHook());
hookRegister.register(new ShortURLHook());
hookRegister.register(new XHTMLHook());
hookRegister.register(new WebContentHook());
hookRegister.register(new WebInfHook());
}
// Search a matching catcher.
Hook hook = hookRegister.getMatching(this.getServletContext(), request);
if (hook == null)
{
logger.info("Request not satisfied [" + request.getPathInfo() + "]");
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
else
{
hook.process(this.getServletConfig(), this.getServletContext(), request, response);
}
//
long endTime = new Date().getTime();
logger.debug("TIME: {}ms {}", endTime - startTime, request.getPathInfo());
}
/**
*
*/
@Override
public void doDelete(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
dispatch(request, response);
}
/**
*
*/
@Override
public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
dispatch(request, response);
}
/**
*
*/
@Override
public void doPost(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
dispatch(request, response);
}
/**
*
*/
@Override
public void doPut(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
dispatch(request, response);
}
/**
*
*/
@Override
public void init() throws ServletException
{
super.init();
// Set logger.
String logFilePathname;
try
{
new EnvironmentInformation().toString();
logFilePathname = new EnvironmentInformation().log4jFilePathname();
}
catch (ConfigurationException exception)
{
System.err.println("Error reading the environment information.");
exception.printStackTrace();
logFilePathname = null;
}
if (StringUtils.isBlank(logFilePathname))
{
org.apache.log4j.BasicConfigurator.configure();
logger.warn("Log configuration undefined, use of the basic configurator.");
}
else
{
try
{
System.out.println("Log configuration defined (" + logFilePathname + "), will use it.");
if (!logFilePathname.startsWith("/"))
{
logFilePathname = getServletContext().getRealPath("/") + logFilePathname;
System.out.println("Log configuration redefined (" + logFilePathname + "), will use it.");
}
org.apache.log4j.PropertyConfigurator.configure(getServletContext().getRealPath("/") + logFilePathname);
}
catch (Exception exception)
{
System.out.println("Log configuration FILE NOT FOUND (" + logFilePathname + "), use of the basic configurator.");
org.apache.log4j.BasicConfigurator.configure();
}
logger = LoggerFactory.getLogger(this.getClass());
logger.info("Log initialization done.");
}
}
}

View file

@ -1,536 +0,0 @@
/**
* Copyright (C) 2006-2010, 2013-2016 Christian Pierre MOMON
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Enumeration;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.kiss4web.catchers.ShortURLRewriter;
import fr.devinsy.util.strings.StringList;
/**
*
*/
public class KissDispatcherUtils
{
public enum ContentDispositionType
{
ATTACHMENT,
INLINE
}
private static Logger logger = LoggerFactory.getLogger(KissDispatcherUtils.class);
/**
*
*/
@Deprecated
public static String buildClassName(final String pathInfo)
{
String result;
result = null;
if (pathInfo.equals("/"))
{
result = "Accueil";
}
else
{
String[] tokens = pathInfo.split("/");
StringBuffer name = new StringBuffer();
for (int tokenCounter = 1; tokenCounter < tokens.length - 1; tokenCounter++)
{
name.append(tokens[tokenCounter]);
name.append('.');
}
if (pathInfo.endsWith("/"))
{
name.append(tokens[tokens.length - 1]);
name.append('.');
}
logger.info("==>[" + tokens[tokens.length - 1] + "]");
name.append(formatClassName(tokens[tokens.length - 1]));
result = name.toString();
}
//
return (result);
}
/**
*
*/
public static String concatenatePackage(final String path, final String className)
{
String result;
if (path == null)
{
result = className;
}
else if (path.endsWith("."))
{
result = path + className;
}
else
{
result = path + "." + className;
}
//
return result;
}
/**
*
* @param className
* @throws IOException
* @throws ServletException
*/
public static void dispatchToServlet(final ServletConfig servletConfig, final HttpServletRequest request, final HttpServletResponse response, final String className) throws IOException,
ServletException
{
HttpServlet servlet = instanciateServlet(className);
// servlet.getServletContext().setAttribute(arg0, arg1);
if (servlet == null)
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html><head></head><body>");
out.println("Unknown page.");
out.println("</body></html>");
out.close();
}
else
{
servlet.init(servletConfig);
servlet.service(request, response);
}
}
/**
*
*/
@Deprecated
public static String formatClassName(final String name)
{
String result;
result = null;
String[] splittedLastToken = name.split("\\.");
String last = splittedLastToken[0];
// logger.info ("last=" + last);
String[] tokens = last.split("_");
StringBuffer all = new StringBuffer();
for (String token : tokens)
{
// logger.info ("tok=" + token);
all.append(Character.toUpperCase(token.charAt(0)));
all.append(token.substring(1));
}
result = all.toString();
//
return (result);
}
/**
*
*/
public static HttpServlet instanciateServlet(final String className)
{
HttpServlet result;
Class<HttpServlet> servletClass = null;
try
{
servletClass = (Class<HttpServlet>) Class.forName(className);
}
catch (java.lang.ClassNotFoundException exception)
{
result = null;
}
logger.info("class=" + servletClass);
if (servletClass == null)
{
result = null;
logger.error("unknown page: (" + className + ")");
}
else
{
try
{
result = servletClass.newInstance();
}
catch (java.lang.InstantiationException exception)
{
logger.error("Can't instanciate servlet (" + className + ")", exception);
result = null;
}
catch (java.lang.IllegalAccessException exception)
{
logger.error("(2) Can't instanciate servlet (" + className + ")", exception);
result = null;
}
}
//
return result;
}
/**
* Convert a path in a class name, using kiss conventions.
*
* <pre>
* "/" => "Index_xhtml"
* "/good/" => "good.Good_xhtml"
* "/good/morning.xhtml" => "good.Morning_xhtml"
* "/good/morning_girl.xhtml" => "good.Morning_girl_xhtml"
* "/good/morning-123.xhtml" => "good.Morning_xhtml" ('123' is detected as a parameter, it will be
* decoded in the class called later).
* "/good/morning-/12/toto.jpg" => "good.Morning" ('12' and 'toto.jpg" are detected as a parameter, they
* will be decoded in the class called later).
* </pre>
*
*/
@Deprecated
public static String pathInfoToClassName(final String pathInfo)
{
String result;
if ((pathInfo == null) || (pathInfo.length() == 0))
{
result = null;
}
else if (pathInfo.equals("/"))
{
result = "Index_xhtml";
}
else
{
int keywordIndex = pathInfo.lastIndexOf("-/");
if (keywordIndex != -1)
{
// Long rewrited URL case.
String[] tokens = pathInfo.substring(0, keywordIndex).split("/");
StringList name = new StringList();
// Note: as pathInfo starts always with a '/', the first
// good token index is 1.
for (int tokenCounter = 1; tokenCounter < (tokens.length - 1); tokenCounter++)
{
name.append(tokens[tokenCounter]);
name.append('.');
}
String lastToken = tokens[tokens.length - 1];
name.append(lastToken.substring(0, 1).toUpperCase()).append(lastToken.substring(1).replace('.', '_'));
result = name.toString();
}
else
{
StringList name = new StringList();
String[] tokens = pathInfo.split("/");
// Note: as pathInfo starts always with a '/', the first
// good token index is 1.
for (int tokenCounter = 1; tokenCounter < (tokens.length - 1); tokenCounter++)
{
name.append(tokens[tokenCounter]);
name.append('.');
}
String lastToken = tokens[tokens.length - 1];
if (pathInfo.endsWith("/"))
{
name.append(lastToken).append(".").append(lastToken.substring(0, 1).toUpperCase()).append(lastToken.substring(1)).append("_xhtml");
}
else
{
String className = ShortURLRewriter.unrewrite(lastToken);
if (className == null)
{
name.append(lastToken.substring(0, 1).toUpperCase()).append(lastToken.substring(1).replace('.', '_'));
}
else
{
name.append(lastToken.substring(0, 1).toUpperCase()).append(className);
}
}
result = name.toString();
logger.debug("==>[" + tokens[tokens.length - 1] + "]");
}
}
logger.info("[" + pathInfo + "] => [" + result + "]");
//
return result;
}
/**
*
*/
@Deprecated
public static String pathInfoToClassName(final String pathInfo, final String prefix)
{
String result;
String className = pathInfoToClassName(pathInfo);
if (prefix == null)
{
result = className;
}
else if (prefix.endsWith("."))
{
result = prefix + className;
}
else
{
result = prefix + "." + className;
}
//
return result;
}
/**
*
*/
public static void returnAttachmentFile(final HttpServletResponse response, final File file, final String mimeType) throws IOException
{
returnFile(response, file, mimeType, ContentDispositionType.ATTACHMENT);
}
/**
*
*/
public static void returnFile(final HttpServletResponse response, final File file, final String mimeType, final ContentDispositionType contentDisposition) throws IOException
{
if ((file == null) || (!file.exists()))
{
logger.warn("File not found [" + file.getAbsolutePath() + "]");
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
else
{
/*
* response.setContentType("application/" + extension);
* response.setContentLength((int) data.length);
* response.setHeader("Content-Disposition"
* ,"attachment; filename=\"" + filename + "\"");
* response.flushBuffer();
*/
response.reset();
response.setContentType(mimeType);
response.setContentLength((int) file.length());
String contentDispositionToken;
if (contentDisposition == ContentDispositionType.ATTACHMENT)
{
contentDispositionToken = "attachment";
}
else
{
contentDispositionToken = "inline";
}
response.setHeader("Content-Disposition", contentDispositionToken + "; filename=\"" + file.getName() + "\"");
response.setDateHeader("Expires", new Date().getTime() + KissDispatcher.DEFAULT_CACHE_AGE * 1000);
response.setHeader("Cache-Control", "max-age=" + KissDispatcher.DEFAULT_CACHE_AGE);
response.flushBuffer();
ServletOutputStream out = response.getOutputStream();
FileInputStream in = null;
try
// Only for the in.
{
byte[] buffer = new byte[64 * 1024];
in = new FileInputStream(file);
boolean ended = false;
while (!ended)
{
int count = in.read(buffer);
if (count == -1)
{
ended = true;
}
else
{
out.write(buffer, 0, count);
}
}
out.flush();
out.close();
}
catch (IOException exception)
{
response.sendError(HttpServletResponse.SC_PARTIAL_CONTENT);
}
finally
{
if (in != null)
{
in.close();
}
}
}
}
/**
*
*/
public static void returnFile(final HttpServletResponse response, final String fileName, final byte[] data, final String mimeType, final ContentDispositionType contentDisposition,
final int cacheAge) throws IOException
{
if (data == null)
{
logger.warn("data is null.");
}
/*
* response.setContentType("application/" + extension);
* response.setContentLength((int) data.length);
* response.setHeader("Content-Disposition"
* ,"attachment; filename=\"" + filename + "\"");
* response.flushBuffer();
*/
response.reset();
response.setContentType(mimeType);
response.setContentLength(data.length);
String contentDispositionToken;
if (contentDisposition == ContentDispositionType.ATTACHMENT)
{
contentDispositionToken = "attachment";
}
else
{
contentDispositionToken = "inline";
}
response.setHeader("Content-Disposition", contentDispositionToken + "; filename=\"" + fileName + "\"");
response.setDateHeader("Expires", new Date().getTime() + cacheAge * 1000);
response.setHeader("Cache-Control", "max-age=" + cacheAge);
response.flushBuffer();
ServletOutputStream out = response.getOutputStream();
try
{
out.write(data, 0, data.length);
}
catch (IOException exception)
{
exception.printStackTrace();
response.sendError(HttpServletResponse.SC_PARTIAL_CONTENT);
}
finally
{
try
{
out.flush();
out.close();
}
catch (IOException exception)
{
exception.printStackTrace();
}
}
}
/**
*
*/
public static void returnInlineFile(final HttpServletResponse response, final File file, final String mimeType) throws IOException
{
returnFile(response, file, mimeType, ContentDispositionType.INLINE);
}
/**
*
* @param request
* @return
*/
public static String showParameters(final HttpServletRequest request)
{
String result;
//
StringList buffer = new StringList();
//
boolean ended = false;
Enumeration<String> names = request.getParameterNames();
buffer.appendln("Parameter list:");
while (!ended)
{
if (names.hasMoreElements())
{
String name = names.nextElement();
buffer.append("[").append(name).append("]=[").append(request.getParameter(name)).appendln("]");
}
else
{
ended = true;
}
}
//
result = buffer.toString();
//
return result;
}
}

View file

@ -0,0 +1,82 @@
/**
* Copyright (C) 2021-2023 Christian Pierre MOMON
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web;
import java.io.IOException;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
/**
* The Class Page.
*/
public abstract class Page
{
private static final long serialVersionUID = 7583814104851219020L;
private static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Page.class);
private HttpServletRequest request;
private HttpServletResponse response;
/**
* Instantiates a new page.
*
* @param request
* the request
* @param response
* the response
* @throws ServletException
* the servlet exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public Page(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
{
this.request = request;
this.response = response;
}
/**
* Do get.
*/
public void doGet()
{
}
/**
* Do post.
*/
public void doPost()
{
}
/**
* Redirect.
*
* @param urlPath
* the url path
*/
public void redirect(final String urlPath)
{
Redirector.redirect(this.response, urlPath);
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (C) 2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web;
import java.util.HashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class PageCache.
*/
public class PageCache extends HashMap<String, String>
{
private static final long serialVersionUID = 6600633944028794039L;
private static Logger logger = LoggerFactory.getLogger(PageCache.class);
/**
* Instantiates a new kiss page cache.
*/
public PageCache()
{
super();
}
}

View file

@ -1,5 +1,5 @@
/**
* Copyright (C) 2006-2010, 2013-2016 Christian Pierre MOMON
* Copyright (C) 2006-2024 Christian Pierre MOMON
*
* This file is part of Kiss4web.
*
@ -18,16 +18,18 @@
*/
package fr.devinsy.kiss4web;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.servlet.http.HttpServletResponse;
/**
*
* The Class Redirector.
*/
public class Redirector
{
private static final Logger logger = LoggerFactory.getLogger(Redirector.class);
public enum Type
{
MOVED_PERMANENTLY(HttpServletResponse.SC_MOVED_PERMANENTLY),
@ -40,6 +42,11 @@ public class Redirector
this.statusCode = value;
}
/**
* Status code.
*
* @return the int
*/
public int statusCode()
{
int result;
@ -51,24 +58,28 @@ public class Redirector
}
}
private static final Logger logger = LoggerFactory.getLogger(Redirector.class);
/**
* Redirect.
*
* @param response
* the response
* @param destination
* the destination
*/
public static void redirect(final HttpServletResponse response, final String destination)
{
logger.info("Redirect to <" + destination + ">");
redirect(response, destination, Type.MOVED_TEMPORARILY);
}
/**
* Redirect.
*
* @param response
* the response
* @param destination
* if null then use the "/" value.
* @param type
* the type
*/
public static void redirect(final HttpServletResponse response, final String destination, final Type type)
{
@ -94,5 +105,3 @@ public class Redirector
}
}
}
// ////////////////////////////////////////////////////////////////////////

View file

@ -1,5 +1,5 @@
/**
* Copyright (C) 2006-2010, 2013-2016 Christian Pierre MOMON
* Copyright (C) 2006-2023 Christian Pierre MOMON
*
* This file is part of Kiss4web.
*
@ -18,17 +18,16 @@
*/
package fr.devinsy.kiss4web;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.util.strings.StringList;
import fr.devinsy.strings.StringList;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
/**
*
* The Class SimpleSecurityAgent.
*/
public class SimpleSecurityAgent
{
@ -46,7 +45,12 @@ public class SimpleSecurityAgent
private int authenticationDuration;
/**
* Instantiates a new simple security agent.
*
* @param prefix
* the prefix
* @param secretKey
* the secret key
*/
public SimpleSecurityAgent(final String prefix, final String secretKey)
{
@ -58,7 +62,11 @@ public class SimpleSecurityAgent
}
/**
* Account id.
*
* @param request
* the request
* @return the string
*/
public String accountId(final HttpServletRequest request)
{
@ -71,7 +79,11 @@ public class SimpleSecurityAgent
}
/**
* Auth.
*
* @param request
* the request
* @return the string
*/
public String auth(final HttpServletRequest request)
{
@ -85,6 +97,10 @@ public class SimpleSecurityAgent
/**
* This method builds a key from keys and a secret key.
*
* @param keys
* the keys
* @return the string
*/
public String computeAuth(final String... keys)
{
@ -113,9 +129,11 @@ public class SimpleSecurityAgent
}
/**
* Digest with secret.
*
* @param source
* @return
* the source
* @return the string
*/
public String digestWithSecret(final String source)
{
@ -136,8 +154,9 @@ public class SimpleSecurityAgent
}
/**
* Gets the authentication duration.
*
* @return
* @return the authentication duration
*/
public int getAuthenticationDuration()
{
@ -146,6 +165,12 @@ public class SimpleSecurityAgent
/**
* Check authentication and refresh it (reset countdown).
*
* @param request
* the request
* @param response
* the response
* @return true, if is authenticated
*/
public boolean isAuthenticated(final HttpServletRequest request, final HttpServletResponse response)
{
@ -177,7 +202,12 @@ public class SimpleSecurityAgent
}
/**
* Reset.
*
* @param request
* the request
* @param response
* the response
*/
public void reset(final HttpServletRequest request, final HttpServletResponse response)
{
@ -187,7 +217,16 @@ public class SimpleSecurityAgent
}
/**
* Sets the authenticated.
*
* @param request
* the request
* @param response
* the response
* @param accountId
* the account id
* @param userId
* the user id
*/
public void setAuthenticated(final HttpServletRequest request, final HttpServletResponse response, final String accountId, final String userId)
{
@ -202,8 +241,10 @@ public class SimpleSecurityAgent
}
/**
* Sets the authentication duration.
*
* @param duration
* the new authentication duration
*/
public void setAuthenticationDuration(final int duration)
{
@ -211,7 +252,11 @@ public class SimpleSecurityAgent
}
/**
* User id.
*
* @param request
* the request
* @return the string
*/
public String userId(final HttpServletRequest request)
{
@ -224,7 +269,11 @@ public class SimpleSecurityAgent
}
/**
* Digest.
*
* @param keys
* the keys
* @return the string
*/
public static String digest(final String... keys)
{

View file

@ -0,0 +1,163 @@
/*
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.kiss4web.dispatcher.annotation.AnnotationHooks;
import fr.devinsy.kiss4web.dispatcher.annotation.AnnotationUtils;
import fr.devinsy.kiss4web.dispatcher.hooks.ErrorServlet;
import fr.devinsy.kiss4web.dispatcher.hooks.Hook;
import fr.devinsy.kiss4web.dispatcher.hooks.HookRegister;
import fr.devinsy.kiss4web.dispatcher.hooks.InitHook;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
/**
* The Class KissDispatcher.
*
* According that URL is under UTF-8 format. Set Tomcat connector if needs
*
* <pre>
* <connector URIEncoding="UTF-8" />.
* </pre>
*/
public class KissDispatcher
{
private static final Logger logger = LoggerFactory.getLogger(KissDispatcher.class);
public static final int DEFAULT_CACHE_AGE = 2 * 60 * 60;
private static KissDispatcher instance = new KissDispatcher();
private HookRegister hookRegister;
// Pathinfo -> Servlet.
private ServletCache cache;
private AnnotationHooks annotationHooks;
/**
* Instantiates a new kiss dispatcher.
*/
private KissDispatcher()
{
this.cache = new ServletCache();
this.hookRegister = new HookRegister("Init").register(new InitHook());
this.annotationHooks = AnnotationUtils.getAnnotationHooks();
}
/**
* Clear.
*/
public void clear()
{
this.cache.clear();
logger.info("KissDispatcher PATHINFO Cache: CLEARED");
KissDispatcherFactory.instance().clearCache();
}
/**
* Gets the annotation hooks.
*
* @return the annotation hooks
*/
public AnnotationHooks getAnnotationHooks()
{
return this.annotationHooks;
}
/**
* Provide servlet.
*
* @param config
* the config
* @param request
* the request
* @return the http servlet
*/
public HttpServlet provideServlet(final ServletConfig config, final HttpServletRequest request)
{
HttpServlet result;
try
{
result = this.cache.get(request.getPathInfo());
if (result == null)
{
logger.debug("PathInfo is NOT matching servlet cache.");
Hook hook = this.hookRegister.getMatching(config.getServletContext(), request);
if (hook == null)
{
result = new ErrorServlet("Hook not found.");
}
else
{
logger.debug("Hook matching: {}", hook.getClass().getCanonicalName());
String servletClassName = hook.getServletClassName(config, request);
Class<HttpServlet> servletClass = KissDispatcherUtils.pickServletClass(servletClassName);
result = KissDispatcherFactory.instance().provideServlet(config, servletClass);
this.cache.put(request.getPathInfo(), result);
}
}
else
{
logger.debug("PathInfo is matching servlet cache [{}]", result.getClass().getCanonicalName());
}
}
catch (IllegalArgumentException | SecurityException | ServletException exception)
{
result = new ErrorServlet("Error instanciating servlet.", exception);
}
//
return result;
}
/**
* Sets the hook register.
*
* @param register
* the new hook register
*/
public void setHookRegister(final HookRegister register)
{
if ((register != null) && (!register.isEmpty()))
{
HookRegister target = new HookRegister(register.getName());
target.registerAll(register);
this.hookRegister = target;
KissDispatcherFactory.instance().clearCache();
}
}
/**
* Instance.
*
* @return the kiss dispatcher
*/
public static KissDispatcher instance()
{
return instance;
}
}

View file

@ -0,0 +1,108 @@
/*
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
/**
* A factory for creating KissDispatcher objects.
*
*/
public class KissDispatcherFactory
{
static Logger logger = LoggerFactory.getLogger(KissDispatcherFactory.class);
private static class SingletonHolder
{
private static final KissDispatcherFactory instance = new KissDispatcherFactory();
}
/*
* Need to avoid servlet duplication when more than pathinfo is matching a servlet.
* ClassPath -> Servlet.
*/
private ServletCache cache;
/**
* Instantiates a new kiss dispatcher factory.
*/
private KissDispatcherFactory()
{
this.cache = new ServletCache();
}
/**
* Clear cache.
*/
public void clearCache()
{
this.cache.clear();
logger.info("KissDispatcherFactory Servlet Cache: CLEARED");
}
/**
* Provide servlet.
*
* @param config
* the config
* @param servletClass
* the servlet class
* @return the http servlet
* @throws ServletException
* the servlet exception
*/
public HttpServlet provideServlet(final ServletConfig config, final Class<HttpServlet> servletClass) throws ServletException
{
HttpServlet result;
if ((config == null) || (servletClass == null))
{
throw new ServletException("Null parameter detected calling KDF.provideServlet method.");
}
else
{
String className = servletClass.getCanonicalName();
result = this.cache.get(className);
if (result == null)
{
result = KissDispatcherUtils.instanciateServlet(className);
result.init(config);
this.cache.put(className, result);
}
}
//
return result;
}
/**
* Instance.
*
* @return the kiss dispatcher factory
*/
public static KissDispatcherFactory instance()
{
return SingletonHolder.instance;
}
}

View file

@ -0,0 +1,135 @@
/**
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher;
import java.io.IOException;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
/**
* The Class KissDispatcher.
*
*/
public class KissDispatcherServlet extends HttpServlet
{
private static final long serialVersionUID = -7278690604864844533L;
private static final Logger logger = LoggerFactory.getLogger(KissDispatcherServlet.class);
/**
* Instantiates a new kiss dispatcher.
*/
public KissDispatcherServlet()
{
}
/**
* {@inheritDoc}
*/
@Override
public void init() throws ServletException
{
super.init();
System.out.println("KissDispatcher INIT.");
}
/**
* {@inheritDoc}
*/
@Override
public void service(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
long startTime = new Date().getTime();
request.setCharacterEncoding("UTF-8");
logger.info("==================================================");
logger.info("getContextPath=[" + request.getContextPath() + "]");
logger.info("getPathInfo=[" + request.getPathInfo() + "]");
logger.info("getPathTranslated=[" + request.getPathTranslated() + "]");
logger.info("getQueryString=[" + request.getQueryString() + "]");
logger.info("getRequestURI=[" + request.getRequestURI() + "]");
logger.info("getRequestURL=[" + request.getRequestURL() + "]");
logger.info("getServletPath=[" + request.getServletPath() + "]");
/*
* In past, possibility to use the servlet path was enable. It is too
* complexe, not kiss mind.
*
* String path;
* if (request.getPathInfo() == null)
* {
* // web.xml url-pattern= *.xhtml
* path = request.getServletPath();
* }
* else
* {
* // web.xml url-pattern =
* path = request.getPathInfo();
* }
*
* https://issues.apache.org/bugzilla/show_bug.cgi?id=11318
* A number of features have been introduced in later versions of Tomcat
* that relate to URI encoding. This includes a URIEncoding attribute
* on the Coyote HTTP/1.1 connector which defaults to ISO-8859-1.
*
* According to the servlet specification:
* HttpServletRequest.getPathInfo() should be decoded by the web container;
* HttpServletRequest.getRequestURI() should not be decoded by the web container.
*
*
* http://stackoverflow.com/questions/15278512/safe-html-form-accept-charset/15587140#15587140
* The standard URL encoding must use UTF-8 yet servlets not only default to ISO-8859-1 but don't offer
* any way to change that with code.
* Sure you can req.setRequestEncoding("UTF-8") before you read anything, but for some ungodly reason this only affects request body,
* not query string parameters. There is nothing in the servlet request interface to specify the encoding used for query string parameters.
* Using ISO-8859-1 in your form is a hack. Using this ancient encoding will cause more problems than solve for sure.
* Especially since browsers do not support ISO-8859-1 and always treat it as Windows-1252. Whereas servlets treat ISO-8859-1 as ISO-8859-1,
* so you will be screwed beyond belief if you go with this.
* To change this in Tomcat for example, you can use the URIEncoding attribute in your <connector> element:
* <connector ... URIEncoding="UTF-8" ... />
*
* If you don't use a container that has these settings, can't change its settings or some other issue,
* you can still make it work because ISO-8859-1 decoding retains full information from the original binary.
* String correct = new String(request.getParameter("test").getBytes("ISO-8859-1"), "UTF-8")
*
*
* http://tomcat.apache.org/tomcat-5.5-doc/config/http.html
* URIEncoding
* This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL.
* If not specified, ISO-8859-1 will be used.
*
*/
// String urlPath = request.getPathInfo();
HttpServlet servlet = KissDispatcher.instance().provideServlet(this.getServletConfig(), request);
servlet.service(request, response);
//
long endTime = new Date().getTime();
logger.debug("TIME: {}ms {}", endTime - startTime, request.getPathInfo());
}
}

View file

@ -0,0 +1,955 @@
/*
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.kiss4web.dispatcher.hooks.ShortURLRewriter;
import fr.devinsy.strings.StringList;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
/**
* The Class KissDispatcherUtils.
*/
public class KissDispatcherUtils
{
static Logger logger = LoggerFactory.getLogger(KissDispatcherUtils.class);
public enum ContentDispositionType
{
ATTACHMENT,
INLINE
}
/**
* Builds the class name.
*
* @param pathInfo
* the path info
* @return the string
*/
@Deprecated
public static String buildClassName(final String pathInfo)
{
String result;
result = null;
if (pathInfo.equals("/"))
{
result = "Accueil";
}
else
{
String[] tokens = pathInfo.split("/");
StringBuffer name = new StringBuffer();
for (int tokenCounter = 1; tokenCounter < tokens.length - 1; tokenCounter++)
{
name.append(tokens[tokenCounter]);
name.append('.');
}
if (pathInfo.endsWith("/"))
{
name.append(tokens[tokens.length - 1]);
name.append('.');
}
logger.info("==>[" + tokens[tokens.length - 1] + "]");
name.append(formatClassName(tokens[tokens.length - 1]));
result = name.toString();
}
//
return (result);
}
/**
* Concatenate package.
*
* @param path
* the path
* @param className
* the class name
* @return the string
*/
public static String concatenatePackage(final String path, final String className)
{
String result;
if (path == null)
{
result = className;
}
else if (path.endsWith("."))
{
result = path + className;
}
else
{
result = path + "." + className;
}
//
return result;
}
/**
* Dispatch to servlet.
*
* @param servletConfig
* the servlet config
* @param request
* the request
* @param response
* the response
* @param className
* the class name
* @throws IOException
* Signals that an I/O exception has occurred.
* @throws ServletException
* the servlet exception
*/
@Deprecated
public static void dispatchToServlet(final ServletConfig servletConfig, final HttpServletRequest request, final HttpServletResponse response,
final String className) throws IOException, ServletException
{
HttpServlet servlet = instanciateServlet(className);
// servlet.getServletContext().setAttribute(arg0, arg1);
if (servlet == null)
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html><head></head><body>");
out.println("Unknown page.");
out.println("</body></html>");
out.close();
}
else
{
servlet.init(servletConfig);
servlet.service(request, response);
}
}
/**
* Format class name.
*
* @param name
* the name
* @return the string
*/
@Deprecated
public static String formatClassName(final String name)
{
String result;
result = null;
String[] splittedLastToken = name.split("\\.");
String last = splittedLastToken[0];
// logger.info ("last=" + last);
String[] tokens = last.split("_");
StringBuffer all = new StringBuffer();
for (String token : tokens)
{
// logger.info ("tok=" + token);
all.append(Character.toUpperCase(token.charAt(0)));
all.append(token.substring(1));
}
result = all.toString();
//
return (result);
}
/**
* Instanciate servlet.
*
* @param className
* the class pathname
* @return the http servlet
*/
public static HttpServlet instanciateServlet(final String className)
{
HttpServlet result;
Class<HttpServlet> servletClass = null;
try
{
servletClass = (Class<HttpServlet>) Class.forName(className);
}
catch (java.lang.ClassNotFoundException exception)
{
result = null;
}
if (servletClass == null)
{
result = null;
logger.warn("unknown page: [{}]", className);
}
else
{
try
{
// result = servletClass.newInstance();
result = servletClass.getConstructor().newInstance();
}
catch (java.lang.InstantiationException exception)
{
logger.error("Can't instanciate servlet (" + className + ")", exception);
result = null;
}
catch (java.lang.IllegalAccessException exception)
{
logger.error("(2) Can't instanciate servlet (" + className + ")", exception);
result = null;
}
catch (IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException exception)
{
logger.error("(3) Can't instanciate servlet (" + className + ")", exception);
result = null;
}
}
//
return result;
}
/**
* Checks if is available path.
*
* @param path
* the path
* @return true, if is available path
*/
public static boolean isAvailablePath(final String path)
{
boolean result;
if (pickServletClass(path) == null)
{
result = false;
}
else
{
result = true;
}
//
return result;
}
/**
* Path to class.
*
* @param className
* the class pathname
* @return the class
*/
public static Class nameToClass(final String className)
{
Class result;
try
{
result = Class.forName(className);
}
catch (java.lang.ClassNotFoundException exception)
{
result = null;
}
//
return result;
}
/**
* Convert a path in a class name, using kiss conventions.
*
* <pre>
* "/" => "Index_xhtml"
* "/good/" => "good.Good_xhtml"
* "/good/morning.xhtml" => "good.Morning_xhtml"
* "/good/morning_girl.xhtml" => "good.Morning_girl_xhtml"
* "/good/morning-123.xhtml" => "good.Morning_xhtml" ('123' is detected as a parameter, it will be
* decoded in the class called later).
* "/good/morning-/12/toto.jpg" => "good.Morning" ('12' and 'toto.jpg" are detected as a parameter, they
* will be decoded in the class called later).
* </pre>
*
* @param pathInfo
* the path info
* @return the string
*/
@Deprecated
public static String pathInfoToClassName(final String pathInfo)
{
String result;
if ((pathInfo == null) || (pathInfo.length() == 0))
{
result = null;
}
else if (pathInfo.equals("/"))
{
result = "Index_xhtml";
}
else
{
int keywordIndex = pathInfo.lastIndexOf("-/");
if (keywordIndex != -1)
{
// Long rewrited URL case.
String[] tokens = pathInfo.substring(0, keywordIndex).split("/");
StringList name = new StringList();
// Note: as pathInfo starts always with a '/', the first
// good token index is 1.
for (int tokenCounter = 1; tokenCounter < (tokens.length - 1); tokenCounter++)
{
name.append(tokens[tokenCounter]);
name.append('.');
}
String lastToken = tokens[tokens.length - 1];
name.append(lastToken.substring(0, 1).toUpperCase()).append(lastToken.substring(1).replace('.', '_'));
result = name.toString();
}
else
{
StringList name = new StringList();
String[] tokens = pathInfo.split("/");
// Note: as pathInfo starts always with a '/', the first
// good token index is 1.
for (int tokenCounter = 1; tokenCounter < (tokens.length - 1); tokenCounter++)
{
name.append(tokens[tokenCounter]);
name.append('.');
}
String lastToken = tokens[tokens.length - 1];
if (pathInfo.endsWith("/"))
{
name.append(lastToken).append(".").append(lastToken.substring(0, 1).toUpperCase()).append(lastToken.substring(1))
.append("_xhtml");
}
else
{
String className = ShortURLRewriter.unrewrite(lastToken);
if (className == null)
{
name.append(lastToken.substring(0, 1).toUpperCase()).append(lastToken.substring(1).replace('.', '_'));
}
else
{
name.append(lastToken.substring(0, 1).toUpperCase()).append(className);
}
}
result = name.toString();
logger.debug("==>[" + tokens[tokens.length - 1] + "]");
}
}
logger.info("[" + pathInfo + "] => [" + result + "]");
//
return result;
}
/**
* Path info to class name.
*
* @param pathInfo
* the path info
* @param prefix
* the prefix
* @return the string
*/
@Deprecated
public static String pathInfoToClassName(final String pathInfo, final String prefix)
{
String result;
String className = pathInfoToClassName(pathInfo);
if (prefix == null)
{
result = className;
}
else if (prefix.endsWith("."))
{
result = prefix + className;
}
else
{
result = prefix + "." + className;
}
//
return result;
}
/**
* Path to servlet class.
*
* @param className
* the class pathname
* @return the class
*/
public static Class<HttpServlet> pickServletClass(final String className)
{
Class<HttpServlet> result;
// String className = KissDispatcherUtils.translateToClassName(path);
logger.info("className=[{}]", className);
result = nameToClass(className);
if (result == null)
{
logger.info("Trying with Page suffix.");
result = nameToClass(className.replaceAll("Xhtml$", "Page"));
}
if (result == null)
{
logger.info("Trying with Do suffix.");
result = nameToClass(className.replaceAll("Xhtml$", "Do"));
}
logger.debug("servletClass={}", result);
//
return result;
}
/**
* Return attachment file.
*
* @param response
* the response
* @param file
* the file
* @param mimeType
* the mime type
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void returnAttachmentFile(final HttpServletResponse response, final File file, final String mimeType) throws IOException
{
returnFile(response, file, mimeType, ContentDispositionType.ATTACHMENT);
}
/**
* Return file.
*
* @param response
* the response
* @param file
* the file
* @param mimeType
* the mime type
* @param contentDisposition
* the content disposition
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void returnFile(final HttpServletResponse response, final File file, final String mimeType,
final ContentDispositionType contentDisposition) throws IOException
{
returnFile(response, file, null, mimeType, contentDisposition);
}
/**
* Return file.
*
* @param response
* the response
* @param file
* the file
* @param targetFilename
* the target filename, in case the name of file is not the one
* intended, if null then the file name is used
* @param mimeType
* the mime type
* @param contentDisposition
* the content disposition
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void returnFile(final HttpServletResponse response, final File file, final String targetFilename, final String mimeType,
final ContentDispositionType contentDisposition) throws IOException
{
if ((file == null) || (!file.exists()))
{
logger.warn("File not found [" + file.getAbsolutePath() + "]");
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
else
{
/*
* response.setContentType("application/" + extension);
* response.setContentLength((int) data.length);
* response.setHeader("Content-Disposition"
* ,"attachment; filename=\"" + filename + "\"");
* response.flushBuffer();
*/
response.reset();
response.setContentType(mimeType);
response.setContentLength((int) file.length());
String contentDispositionToken;
if (contentDisposition == ContentDispositionType.ATTACHMENT)
{
contentDispositionToken = "attachment";
}
else
{
contentDispositionToken = "inline";
}
response.setHeader("Content-Disposition",
contentDispositionToken + "; filename=\"" + Objects.toString(targetFilename, file.getName()) + "\"");
response.setDateHeader("Expires", new Date().getTime() + KissDispatcher.DEFAULT_CACHE_AGE * 1000);
response.setHeader("Cache-Control", "max-age=" + KissDispatcher.DEFAULT_CACHE_AGE);
response.flushBuffer();
ServletOutputStream out = response.getOutputStream();
FileInputStream in = null;
try
// Only for the in.
{
byte[] buffer = new byte[64 * 1024];
in = new FileInputStream(file);
boolean ended = false;
while (!ended)
{
int count = in.read(buffer);
if (count == -1)
{
ended = true;
}
else
{
out.write(buffer, 0, count);
}
}
out.flush();
out.close();
}
catch (IOException exception)
{
System.out.println("/!\\/!\\/!\\/!\\/!\\/!\\/!\\/!\\/!\\/!\\/!\\/!\\/!\\/!\\/!\\");
exception.printStackTrace();
// TODO As sendError cannot be send because partial content has
// been send, we have to replace this with a better way.
response.sendError(HttpServletResponse.SC_PARTIAL_CONTENT);
}
finally
{
if (in != null)
{
in.close();
}
}
}
}
/**
* Return file.
*
* @param response
* the response
* @param fileName
* the file name
* @param data
* the data
* @param mimeType
* the mime type
* @param contentDisposition
* the content disposition
* @param cacheAge
* the cache age
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void returnFile(final HttpServletResponse response, final String fileName, final byte[] data, final String mimeType,
final ContentDispositionType contentDisposition, final int cacheAge) throws IOException
{
if (data == null)
{
logger.warn("data is null.");
}
/*
* response.setContentType("application/" + extension);
* response.setContentLength((int) data.length);
* response.setHeader("Content-Disposition"
* ,"attachment; filename=\"" + filename + "\"");
* response.flushBuffer();
*/
response.reset();
response.setContentType(mimeType);
response.setContentLength(data.length);
String contentDispositionToken;
if (contentDisposition == ContentDispositionType.ATTACHMENT)
{
contentDispositionToken = "attachment";
}
else
{
contentDispositionToken = "inline";
}
response.setHeader("Content-Disposition", contentDispositionToken + "; filename=\"" + fileName + "\"");
response.setDateHeader("Expires", new Date().getTime() + cacheAge * 1000);
response.setHeader("Cache-Control", "max-age=" + cacheAge);
response.flushBuffer();
ServletOutputStream out = response.getOutputStream();
try
{
out.write(data, 0, data.length);
}
catch (IOException exception)
{
exception.printStackTrace();
response.sendError(HttpServletResponse.SC_PARTIAL_CONTENT);
}
finally
{
try
{
out.flush();
out.close();
}
catch (IOException exception)
{
exception.printStackTrace();
}
}
}
/**
* Return inline file.
*
* @param response
* the response
* @param file
* the file
* @param mimeType
* the mime type
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void returnInlineFile(final HttpServletResponse response, final File file, final String mimeType) throws IOException
{
returnFile(response, file, mimeType, ContentDispositionType.INLINE);
}
/**
* Return inline file.
*
* @param response
* the response
* @param file
* the file
* @param targetFilename
* the target filename
* @param mimeType
* the mime type
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void returnInlineFile(final HttpServletResponse response, final File file, final String targetFilename, final String mimeType)
throws IOException
{
returnFile(response, file, targetFilename, mimeType, ContentDispositionType.INLINE);
}
/**
* Show parameters.
*
* @param request
* the request
* @return the string
*/
public static String showParameters(final HttpServletRequest request)
{
String result;
//
StringList buffer = new StringList();
//
boolean ended = false;
Enumeration<String> names = request.getParameterNames();
buffer.appendln("Parameter list:");
while (!ended)
{
if (names.hasMoreElements())
{
String name = names.nextElement();
buffer.append("[").append(name).append("]=[").append(request.getParameter(name)).appendln("]");
}
else
{
ended = true;
}
}
//
result = buffer.toString();
//
return result;
}
/**
* Translate to class name.
*
* <pre>
* "/" => "IndexXhtml"
* "/good/" => "good.IndexXhtml"
* "/good/morning.xhtml" => "good.MorningXhtml"
* "/good/morning_girl.xhtml" => "good.MorningGirlXhtml"
* "/good/morning-girl.xhtml" => "good.MorningGirlXhtml"
* </pre>
*
* @param urlPath
* the url path
* @return the string
*/
public static String translateToClassName(final String urlPath)
{
String result;
if (urlPath == null)
{
result = null;
}
else
{
if (urlPath.length() == 1)
{
result = "IndexXhtml";
}
else if (urlPath.endsWith("/"))
{
StringBuffer buffer = new StringBuffer(urlPath.length() + 50);
for (int index = 1; index < urlPath.length(); index++)
{
char letter = urlPath.charAt(index);
if (letter == '/')
{
buffer.append('.');
}
else
{
buffer.append(letter);
}
}
buffer.append("IndexXhtml");
result = buffer.toString();
}
else
{
int lastToken = urlPath.lastIndexOf('/');
StringBuffer buffer = new StringBuffer(urlPath.length());
for (int index = 1; index <= lastToken; index++)
{
char letter = urlPath.charAt(index);
if (letter == '/')
{
buffer.append('.');
}
else
{
buffer.append(letter);
}
}
boolean capitalizedNext = true;
for (int index = lastToken + 1; index < urlPath.length(); index++)
{
char letter = urlPath.charAt(index);
if ((letter == '_') || (letter == '-') || (letter == '.'))
{
capitalizedNext = true;
}
else
{
if (capitalizedNext)
{
buffer.append(Character.toUpperCase(letter));
capitalizedNext = false;
}
else
{
buffer.append(letter);
}
}
}
result = buffer.toString();
}
}
KissDispatcherFactory.logger.info(urlPath + " -> " + result);
//
return result;
}
/**
* Translate to class name.
*
* <pre>
* "/" => "Index_xhtml"
* "/good/" => "good.Index_xhtml"
* "/good/morning.xhtml" => "good.MorningXhtml"
* "/good/morning_girl.xhtml" => "good.Morning-Girl_xhtml"
* "/good/morning-girl.xhtml" => "good.Morning_Girl_xhtml"
* </pre>
*
* @param urlPath
* the url path
* @return the string
*/
public static String translateToClassNameAlternative(final String urlPath)
{
String result;
if (urlPath == null)
{
result = null;
}
else
{
if (urlPath.length() == 1)
{
result = "IndexXhtml";
}
else if (urlPath.endsWith("/"))
{
StringBuffer buffer = new StringBuffer(urlPath.length() + 50);
for (int index = 1; index < urlPath.length(); index++)
{
char letter = urlPath.charAt(index);
if (letter == '/')
{
buffer.append('.');
}
else
{
buffer.append(letter);
}
}
buffer.append(".Index_xhtml");
result = buffer.toString();
}
else
{
int lastToken = urlPath.lastIndexOf('/');
StringBuffer buffer = new StringBuffer(urlPath.length());
for (int index = 1; index <= lastToken; index++)
{
char letter = urlPath.charAt(index);
if (letter == '/')
{
buffer.append('.');
}
else
{
buffer.append(letter);
}
}
if (lastToken + 1 < urlPath.length())
{
buffer.append(Character.toUpperCase(urlPath.charAt(lastToken + 1)));
}
for (int index = lastToken + 2; index < urlPath.length(); index++)
{
char letter = urlPath.charAt(index);
if (letter == '.')
{
buffer.append('_');
}
else
{
buffer.append(letter);
}
}
result = buffer.toString();
}
}
KissDispatcherFactory.logger.info(urlPath + " -> " + result);
//
return result;
}
}

View file

@ -0,0 +1,106 @@
/*
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher;
import java.util.HashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.servlet.http.HttpServlet;
/**
* The Class ServletCache.
*/
public class ServletCache extends HashMap<String, HttpServlet>
{
private static final long serialVersionUID = -7727974577347443504L;
private static Logger logger = LoggerFactory.getLogger(ServletCache.class);
/**
* Instantiates a new kiss dispatcher cache.
*/
public ServletCache()
{
super();
}
/**
* Gets the first servlet matching path in the cache.
*
* @param path
* the path
* @return the http servlet
*/
public HttpServlet get(final String... path)
{
HttpServlet result;
boolean ended = false;
int index = 0;
result = null;
while (!ended)
{
if (index < path.length)
{
result = super.get(path[index]);
if (result == null)
{
index += 1;
}
else
{
ended = true;
}
}
else
{
ended = true;
result = null;
}
}
//
return result;
}
/**
* Gets the first servlet matching path in the cache.
*
* @param firstPath
* the first path to try
* @param secondPath
* the second path to try
* @return the http servlet
*/
public HttpServlet get(final String firstPath, final String secondPath)
{
HttpServlet result;
result = get(firstPath);
if (result == null)
{
result = get(secondPath);
}
//
return result;
}
}

View file

@ -0,0 +1,112 @@
/**
* Copyright (C) 2021-2023 Christian Pierre MOMON
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher;
import java.util.Iterator;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.strings.StringList;
import jakarta.servlet.http.HttpServlet;
/**
* The Class WebsiteClasspaths.
*/
public class WebsiteClasspaths extends StringList
{
private static final long serialVersionUID = 3403269660538375143L;
private static Logger logger = LoggerFactory.getLogger(WebsiteClasspaths.class);
/**
* Instantiates a new website classpaths.
*/
public WebsiteClasspaths()
{
super();
}
/**
* {@inheritDoc}
*/
@Override
public boolean add(final String classpath)
{
boolean result;
if (StringUtils.isBlank(classpath))
{
result = false;
}
else
{
if (classpath.endsWith("."))
{
result = super.add(classpath);
}
else
{
result = super.add(classpath + ".");
}
}
//
return result;
}
/**
* Instanciate servlet.
*
* @param className
* the class name
* @return the http servlet
*/
public HttpServlet instanciateServlet(final String className)
{
HttpServlet result;
boolean ended = false;
result = null;
Iterator<String> iterator = this.iterator();
while (!ended)
{
if (iterator.hasNext())
{
String classpath = iterator.next();
String classPath = classpath + className;
logger.debug("Trying {}", classPath);
result = KissDispatcherUtils.instanciateServlet(classPath);
if (result != null)
{
ended = true;
}
}
else
{
ended = true;
result = null;
}
}
//
return result;
}
}

View file

@ -0,0 +1,45 @@
/*
* Copyright (C) 2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.annotation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.kiss4web.dispatcher.hooks.RewriteHook;
/**
* The Class AnnotationHook.
*/
public class AnnotationHook extends RewriteHook
{
private static Logger logger = LoggerFactory.getLogger(AnnotationHook.class);
/**
* Instantiates a new annotation hook.
*
* @param regex
* the regex
* @param targetClassName
* the target class name
*/
public AnnotationHook(final String regex, final String targetClassName)
{
super(regex, targetClassName);
}
}

View file

@ -0,0 +1,37 @@
/**
* Copyright (C) 2024 Christian Pierre MOMON
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.annotation;
import java.util.ArrayList;
/**
* The Class AnnotationHooks.
*/
public class AnnotationHooks extends ArrayList<AnnotationHook>
{
private static final long serialVersionUID = 1979896054785066359L;
/**
* Instantiates a new hook list.
*/
public AnnotationHooks()
{
super();
}
}

View file

@ -0,0 +1,152 @@
/*
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.annotation;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.servlet.http.HttpServlet;
/**
* The Class AnnotationUtils.
*/
public class AnnotationUtils
{
private static final Logger logger = LoggerFactory.getLogger(AnnotationUtils.class);
/**
* Recursive method used to find all classes in a given directory and
* subdirs.
*
* @param directory
* The base directory
* @param packageName
* The package name for classes found inside the base directory
* @return The classes
* @throws ClassNotFoundException
*/
private static List<Class> findClasses(final File directory, final String packageName) throws ClassNotFoundException
{
List<Class> result;
result = new ArrayList<Class>();
if (directory.exists())
{
File[] files = directory.listFiles();
for (File file : files)
{
if (file.isDirectory())
{
assert !file.getName().contains(".");
result.addAll(findClasses(file, packageName + "." + file.getName()));
}
else if (file.getName().endsWith(".class"))
{
result.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
}
}
}
//
return result;
}
/**
* Gets the annotation hooks.
*
* @return the annotation hooks
*/
public static AnnotationHooks getAnnotationHooks()
{
AnnotationHooks result;
try
{
result = new AnnotationHooks();
Class[] classes = getClasses("website");
for (Class clazz : classes)
{
if (clazz.isAnnotationPresent(KissServlet.class))
{
// System.out.println("==> " + clazz.getName() + " " +
// clazz.getCanonicalName());
// System.out.println("==> " + ((Class<HttpServlet>)
// clazz).getAnnotation(KissServlet.class).value());
String className = clazz.getCanonicalName();
String regexPathInfo = ((Class<HttpServlet>) clazz).getAnnotation(KissServlet.class).value();
AnnotationHook hook = new AnnotationHook(regexPathInfo, className);
result.add(hook);
}
}
}
catch (ClassNotFoundException | IOException exception)
{
logger.error("Package website undefined, KissServlet annotations ignored.", exception);
result = new AnnotationHooks();
}
//
return result;
}
/**
* Gets the classes.
*
* @param packageName
* the package name
* @return the classes
* @throws ClassNotFoundException
* the class not found exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
private static Class[] getClasses(final String packageName) throws ClassNotFoundException, IOException
{
Class[] result;
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
assert classLoader != null;
String path = packageName.replace('.', '/');
Enumeration<URL> resources = classLoader.getResources(path);
List<File> dirs = new ArrayList<File>();
while (resources.hasMoreElements())
{
URL resource = resources.nextElement();
dirs.add(new File(resource.getFile()));
}
ArrayList<Class> classes = new ArrayList<Class>();
for (File directory : dirs)
{
classes.addAll(findClasses(directory, packageName));
}
result = classes.toArray(new Class[classes.size()]);
//
return result;
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (C) 2024 Christian Pierre MOMON
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* The Interface KissServlet.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface KissServlet
{
/**
* Value of the pathInfo regex to map on the annoted class..
*
* @return the string
*/
String value();
}

View file

@ -0,0 +1,70 @@
/*
* Copyright (C) 2024 Christian Pierre MOMON
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.annotation;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
/**
* The Class KissServletProcessor.
*/
@javax.annotation.processing.SupportedAnnotationTypes("fr.devinsy.kiss4web.dispatcher.annotation.KissServlet")
@javax.annotation.processing.SupportedSourceVersion(javax.lang.model.SourceVersion.RELEASE_17)
public class KissServletProcessor extends AbstractProcessor
{
/**
* {@inheritDoc}
*/
@Override
public synchronized void init(final ProcessingEnvironment processingEnv)
{
super.init(processingEnv);
// Initialization code, if needed
// System.out.println("=============== @INIT");
}
/**
* {@inheritDoc}
*/
@Override
public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv)
{
for (TypeElement annotation : annotations)
{
// Find elements annotated with MyCustomAnnotation
for (Element element : roundEnv.getElementsAnnotatedWith(annotation))
{
// Process each element
this.processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Processing: " + element.getSimpleName());
// Your processing logic here
System.out.println("=============== YOOOOOOOOOOP");
}
}
//
return true; // No further processing of this annotation type
}
}

View file

@ -0,0 +1,38 @@
/*
* Copyright (C) 2018-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class ApplicationInitFailedHook.
*/
public class ApplicationInitFailedHook extends DirectHook
{
private static Logger logger = LoggerFactory.getLogger(ApplicationInitFailedHook.class);
/**
* Instantiates a new application init failed hook.
*/
public ApplicationInitFailedHook()
{
super("/fr/devinsy/kiss4web/dispatcher/hooks/ApplicationInitFailedServlet");
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class ApplicationInitFailedServlet.
*/
public class ApplicationInitFailedServlet extends DirectServlet
{
private static final long serialVersionUID = 3354542049753884236L;
private static final Logger logger = LoggerFactory.getLogger(ApplicationInitFailedServlet.class);
/**
* Instantiates a new application init failed servlet.
*/
public ApplicationInitFailedServlet()
{
super("/fr/devinsy/kiss4web/dispatcher/hooks/applicationInitFailed.xhtml");
}
}

View file

@ -0,0 +1,38 @@
/*
* Copyright (C) 2018-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class InitHook.
*/
public class ApplicationInitHook extends DirectHook
{
private static Logger logger = LoggerFactory.getLogger(ApplicationInitHook.class);
/**
* Instantiates a new inits the hook.
*/
public ApplicationInitHook()
{
super("/fr/devinsy/kiss4web/dispatcher/hooks/ApplicationInitServlet");
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class ApplicationInitServlet.
*/
public class ApplicationInitServlet extends DirectServlet
{
private static final long serialVersionUID = 6515114898805106148L;
private static final Logger logger = LoggerFactory.getLogger(ApplicationInitServlet.class);
/**
* Instantiates a new application init servlet.
*/
public ApplicationInitServlet()
{
super("/fr/devinsy/kiss4web/dispatcher/hooks/applicationInitServlet.xhtml");
}
}

View file

@ -1,5 +1,5 @@
/**
* Copyright (C) 2006-2010, 2013-2016 Christian Pierre MOMON
/*
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
@ -16,28 +16,24 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.hooks;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
package fr.devinsy.kiss4web.dispatcher.hooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
/**
*
* The Class BlankHook.
*/
public class BlankHook extends HookCore
{
private static Logger logger = LoggerFactory.getLogger(BlankHook.class);
/**
*
* Instantiates a new blank hook.
*/
public BlankHook()
{
@ -45,29 +41,21 @@ public class BlankHook extends HookCore
}
/**
* @throws IOException
*
* {@inheritDoc}
*/
@Override
public void process(final ServletConfig servletConfig, final ServletContext servletContext, final HttpServletRequest request,
final HttpServletResponse response) throws IOException
public String getServletClassName(final ServletConfig config, final HttpServletRequest request)
{
logger.debug("Doing catch.");
String result;
response.setContentType("text/html");
PrintWriter out = response.getWriter();
result = "/fr/devinsy/kiss4web/dispatcher/hooks/BlankServlet";
out.println("<html><head></head><body>");
out.println("Null path.");
out.println("</body></html>");
out.close();
//
return result;
}
/**
*
* @param urlPath
* @return
* {@inheritDoc}
*/
@Override
public boolean matches(final ServletContext servletContext, final HttpServletRequest request)

View file

@ -0,0 +1,39 @@
/*
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class BlankSerlvet.
*/
public class BlankSerlvet extends DirectServlet
{
private static final long serialVersionUID = -3751754076316971589L;
private static final Logger logger = LoggerFactory.getLogger(BlankSerlvet.class);
/**
* Instantiates a new blank serlvet.
*/
public BlankSerlvet()
{
super("/fr/devinsy/kiss4web/dispatcher/hooks/blank.xhtml");
}
}

View file

@ -1,5 +1,5 @@
/**
* Copyright (C) 2006-2010, 2013-2016 Christian Pierre MOMON
/*
* Copyright (C) 2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
@ -16,52 +16,52 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.hooks;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
package fr.devinsy.kiss4web.dispatcher.hooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
*/
public class StatisticsHook extends HookCore
{
private static Logger logger = LoggerFactory.getLogger(StatisticsHook.class);
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
/**
*
* The Class DirectHook.
*/
public StatisticsHook()
public class DirectHook extends HookCore
{
private static Logger logger = LoggerFactory.getLogger(DirectHook.class);
private String targetClassName;
/**
* Instantiates a new direct hook.
*
* @param targetClassName
* the target class name
*/
public DirectHook(final String targetClassName)
{
super();
setTerminal(false);
this.targetClassName = targetClassName;
}
/**
* @throws IOException
*
* {@inheritDoc}
*/
@Override
public void process(final ServletConfig servletConfig, final ServletContext servletContext, final HttpServletRequest request,
final HttpServletResponse response) throws IOException
public String getServletClassName(final ServletConfig config, final HttpServletRequest request)
{
logger.debug("Doing catch.");
String result;
// TODO store statistics.
result = this.targetClassName;
//
return result;
}
/**
*
* @param urlPath
* @return
* {@inheritDoc}
*/
@Override
public boolean matches(final ServletContext servletContext, final HttpServletRequest request)

View file

@ -0,0 +1,96 @@
/*
* Copyright (C) 2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
/**
* The Class DirectServlet.
*/
public class DirectServlet extends HttpServlet
{
private static final long serialVersionUID = 3433035754728880755L;
private static final Logger logger = LoggerFactory.getLogger(DirectServlet.class);
private String path;
/**
* Instantiates a new direct servlet.
*
* @param path
* the path
*/
public DirectServlet(final String path)
{
super();
this.path = path;
}
/**
* Dispatch.
*
* @param request
* the request
* @param response
* the response
* @throws IOException
* Signals that an I/O exception has occurred.
* @throws ServletException
* the servlet exception
*/
public void dispatch(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
// Get page.
URL url = Hook.class.getResource(this.path);
String xhtml = IOUtils.toString(url, StandardCharsets.UTF_8);
// Display page.
response.setContentType("application/xhtml+xml; charset=UTF-8");
response.getWriter().println(xhtml);
}
/**
* {@inheritDoc}
*/
@Override
public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
dispatch(request, response);
}
/**
* {@inheritDoc}
*/
@Override
public void doPost(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
dispatch(request, response);
}
}

View file

@ -0,0 +1,38 @@
/*
* Copyright (C) 2018-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class ErrorHook.
*/
public class ErrorHook extends RewriteHook
{
private static Logger logger = LoggerFactory.getLogger(ErrorHook.class);
/**
* Instantiates a new error hook.
*/
public ErrorHook()
{
super(".*", "/fr/devinsy/kiss4web/dispatcher/hooks/ErrorServlet");
}
}

View file

@ -0,0 +1,117 @@
/*
* Copyright (C) 2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
/**
* The Class ErrorServlet.
*/
public class ErrorServlet extends HttpServlet
{
private static final long serialVersionUID = -4906221802965761187L;
private static final Logger logger = LoggerFactory.getLogger(ErrorServlet.class);
private String message;
private Exception exception;
/**
* Instantiates a new error servlet.
*
* @param message
* the message
*/
public ErrorServlet(final String message)
{
this(message, null);
}
/**
* Instantiates a new error servlet.
*
* @param message
* the message
* @param exception
* the exception
*/
public ErrorServlet(final String message, final Exception exception)
{
this.message = message;
this.exception = exception;
}
/**
* Dispatch.
*
* @param request
* the request
* @param response
* the response
* @throws IOException
* Signals that an I/O exception has occurred.
* @throws ServletException
* the servlet exception
*/
public void dispatch(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
ServletContext context = this.getServletContext();
// Get page.
// TODO dynamize!!!
URL url = Hook.class.getResource("/fr/devinsy/kiss4web/dispatcher/hooks/error.xhtml");
String xhtml = IOUtils.toString(url, StandardCharsets.UTF_8);
// Display page.
response.setContentType("application/xhtml+xml; charset=UTF-8");
response.getWriter().println(xhtml);
}
/**
* {@inheritDoc}
*/
@Override
public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
dispatch(request, response);
}
/**
* {@inheritDoc}
*/
@Override
public void doPost(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
dispatch(request, response);
}
}

View file

@ -0,0 +1,38 @@
/*
* Copyright (C) 2018-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class FatalHook.
*/
public class FatalHook extends DirectHook
{
private static Logger logger = LoggerFactory.getLogger(FatalHook.class);
/**
* Instantiates a new fatal hook.
*/
public FatalHook()
{
super("/fr/devinsy/kiss4web/dispatcher/hooks/FatalServlet");
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (C) 2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class FatalServlet.
*/
public class FatalServlet extends DirectServlet
{
private static final long serialVersionUID = 634762859496474527L;
private static final Logger logger = LoggerFactory.getLogger(FatalServlet.class);
/**
* Instantiates a new fatal servlet.
*/
public FatalServlet()
{
super("/fr/devinsy/kiss4web/dispatcher/hooks/fatal.xhtml");
}
}

View file

@ -1,5 +1,5 @@
/**
* Copyright (C) 2006-2010, 2013-2016 Christian Pierre MOMON
/*
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
@ -16,30 +16,25 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.hooks;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
package fr.devinsy.kiss4web.dispatcher.hooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.kiss4web.KissDispatcherUtils;
import fr.devinsy.kiss4web.dispatcher.KissDispatcherUtils;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
/**
*
* The Class FolderHook.
*/
public class FolderHook extends HookCore
{
private static Logger logger = LoggerFactory.getLogger(FolderHook.class);
/**
*
* Instantiates a new folder hook.
*/
public FolderHook()
{
@ -47,24 +42,21 @@ public class FolderHook extends HookCore
}
/**
* @throws IOException
* @throws ServletException
*
* {@inheritDoc}
*/
@Override
public void process(final ServletConfig servletConfig, final ServletContext servletContext, final HttpServletRequest request,
final HttpServletResponse response) throws IOException, ServletException
public String getServletClassName(final ServletConfig config, final HttpServletRequest request)
{
logger.debug("Doing catch.");
String result;
String urlPath = request.getPathInfo();
KissDispatcherUtils.dispatchToServlet(servletConfig, request, response, urlPath);
result = "website." + KissDispatcherUtils.translateToClassName(request.getPathInfo());
//
return result;
}
/**
*
* @param urlPath
* @return
* {@inheritDoc}
*/
@Override
public boolean matches(final ServletContext servletContext, final HttpServletRequest request)
@ -85,5 +77,4 @@ public class FolderHook extends HookCore
//
return result;
}
}

View file

@ -1,5 +1,5 @@
/**
* Copyright (C) 2006-2010, 2013-2016 Christian Pierre MOMON
/*
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
@ -16,41 +16,36 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.hooks;
package fr.devinsy.kiss4web.dispatcher.hooks;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
/**
*
* The Interface Hook.
*/
public interface Hook
{
/**
* Gets the servlet.
*
* @param config
* the config
* @param request
* @param response
* @throws Exception
* the request
* @return the servlet
*/
void process(final ServletConfig servletConfig, final ServletContext servletContext, final HttpServletRequest request,
final HttpServletResponse response) throws IOException, ServletException;
String getServletClassName(ServletConfig config, HttpServletRequest request);
/**
* Matches.
*
* @param source
* @return
* @param servletContext
* the servlet context
* @param request
* the request
* @return true, if successful
*/
boolean matches(final ServletContext servletContext, final HttpServletRequest request);
/**
*
*
* @return true if it is a final hook, false otherwise.
*/
boolean isTerminal();
}

View file

@ -1,5 +1,5 @@
/**
* Copyright (C) 2006-2010, 2013-2016 Christian Pierre MOMON
/*
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
@ -16,35 +16,18 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.hooks;
package fr.devinsy.kiss4web.dispatcher.hooks;
/**
*
* The Class HookCore.
*/
public abstract class HookCore implements Hook
{
private boolean terminal;
public void setTerminal(boolean terminal)
{
this.terminal = terminal;
}
/**
*
* Instantiates a new hook core.
*/
public HookCore()
{
super();
this.terminal = true;
}
/**
*
*/
public boolean isTerminal()
{
return this.terminal;
}
}

View file

@ -0,0 +1,171 @@
/*
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import java.util.Collection;
import java.util.Iterator;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
/**
* The Class HookRegister.
*/
public class HookRegister
{
private String name;
private Hooks hooks;
/**
* Instantiates a new hook register.
*
* @param name
* the name
*/
public HookRegister(final String name)
{
super();
this.name = name;
this.hooks = new Hooks();
}
/**
* Hooks.
*
* @return the list
*/
public Hooks getHooks()
{
return this.hooks;
}
/**
* Gets the matching.
*
* @param servletContext
* the servlet context
* @param request
* the request
* @return the matching
*/
public Hook getMatching(final ServletContext servletContext, final HttpServletRequest request)
{
Hook result;
boolean ended = false;
Iterator<Hook> iterator = this.hooks.iterator();
result = null;
while (!ended)
{
if (iterator.hasNext())
{
Hook currentHook = iterator.next();
if (currentHook.matches(servletContext, request))
{
ended = true;
result = currentHook;
}
}
else
{
ended = true;
result = null;
}
}
//
return result;
}
/**
* Gets the name.
*
* @return the name
*/
public String getName()
{
return this.name;
}
/**
* Checks if is empty.
*
* @return true, if is empty
*/
public boolean isEmpty()
{
boolean result;
result = this.hooks.isEmpty();
//
return result;
}
/**
* Register.
*
* @param hooks
* the hooks
* @return the hook register
*/
public HookRegister register(final Collection<? extends Hook> hooks)
{
HookRegister result;
this.hooks.addAll(hooks);
result = this;
//
return result;
}
/**
* Register.
*
* @param hook
* the hook
* @return the hook register
*/
public HookRegister register(final Hook hook)
{
HookRegister result;
this.hooks.add(hook);
result = this;
//
return result;
}
/**
* Register all.
*
* @param register
* the register
*/
public void registerAll(final HookRegister register)
{
this.hooks.addAll(register.getHooks());
}
}

View file

@ -0,0 +1,37 @@
/**
* Copyright (C) 2021 Christian Pierre MOMON
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import java.util.ArrayList;
/**
* The Class HookList.
*/
public class Hooks extends ArrayList<Hook>
{
private static final long serialVersionUID = 3580793472824912708L;
/**
* Instantiates a new hook list.
*/
public Hooks()
{
super();
}
}

View file

@ -0,0 +1,38 @@
/**
* Copyright (C) 2018-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class InitFailedHook.
*/
public class InitFailedHook extends DirectHook
{
private static Logger logger = LoggerFactory.getLogger(InitFailedHook.class);
/**
* Instantiates a new init failed hook.
*/
public InitFailedHook()
{
super("/fr/devinsy/kiss4web/dispatcher/hooks/initFailedServlet.xhtml");
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (C) 2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class InitFailedServlet.
*/
public class InitFailedServlet extends DirectServlet
{
private static final long serialVersionUID = -8117673535638021417L;
private static final Logger logger = LoggerFactory.getLogger(InitFailedServlet.class);
/**
* Instantiates a new inits the failed servlet.
*/
public InitFailedServlet()
{
super("/fr/devinsy/kiss4web/dispatcher/hooks/maintenance.xhtml");
}
}

View file

@ -0,0 +1,38 @@
/*
* Copyright (C) 2018-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class InitHook.
*/
public class InitHook extends DirectHook
{
private static Logger logger = LoggerFactory.getLogger(InitHook.class);
/**
* Instantiates a new init the hook.
*/
public InitHook()
{
super("/fr/devinsy/kiss4web/dispatcher/hooks/InitServlet");
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (C) 2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class InitServlet.
*/
public class InitServlet extends DirectServlet
{
private static final long serialVersionUID = -6057469263221296444L;
private static final Logger logger = LoggerFactory.getLogger(InitServlet.class);
/**
* Instantiates a new inits the servlet.
*/
public InitServlet()
{
super("/fr/devinsy/kiss4web/dispatcher/hooks/maintenance.xhtml");
}
}

View file

@ -1,5 +1,5 @@
/**
* Copyright (C) 2006-2010, 2013-2016 Christian Pierre MOMON
/*
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
@ -16,30 +16,25 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.hooks;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
package fr.devinsy.kiss4web.dispatcher.hooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.kiss4web.KissDispatcherUtils;
import fr.devinsy.kiss4web.dispatcher.KissDispatcherUtils;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
/**
*
* The Class LongURLHook.
*/
public class LongURLHook extends HookCore
{
private static Logger logger = LoggerFactory.getLogger(LongURLHook.class);
/**
*
* Instantiates a new long URL hook.
*/
public LongURLHook()
{
@ -47,27 +42,22 @@ public class LongURLHook extends HookCore
}
/**
* @throws IOException
* @throws ServletException
*
* {@inheritDoc}
*/
@Override
public void process(final ServletConfig servletConfig, final ServletContext servletContext, final HttpServletRequest request,
final HttpServletResponse response) throws IOException, ServletException
public String getServletClassName(final ServletConfig config, final HttpServletRequest request)
{
logger.debug("Doing catch.");
String result;
String urlPath = request.getPathInfo();
result = "website." + KissDispatcherUtils.translateToClassName(LongURLRewriter.unrewrite(urlPath));
String rewritedURLPath = LongURLRewriter.unrewrite(urlPath);
KissDispatcherUtils.dispatchToServlet(servletConfig, request, response, rewritedURLPath);
//
return result;
}
/**
*
* @param urlPath
* @return
* {@inheritDoc}
*/
@Override
public boolean matches(final ServletContext servletContext, final HttpServletRequest request)
@ -76,7 +66,15 @@ public class LongURLHook extends HookCore
String urlPath = request.getPathInfo();
result = LongURLRewriter.matches(urlPath);
if (LongURLRewriter.matches(urlPath))
{
urlPath = ShortURLRewriter.unrewrite(urlPath);
result = KissDispatcherUtils.isAvailablePath(urlPath);
}
else
{
result = false;
}
//
return result;

View file

@ -1,5 +1,5 @@
/**
* Copyright (C) 2006-2010, 2013-2016 Christian Pierre MOMON
* Copyright (C) 2006-2024 Christian Pierre MOMON
*
* This file is part of Kiss4web.
*
@ -16,20 +16,19 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.hooks;
package fr.devinsy.kiss4web.dispatcher.hooks;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.util.strings.StringList;
import fr.devinsy.strings.StringList;
import jakarta.servlet.http.HttpServletRequest;
/**
*
* The Class LongURLRewriter.
*/
public class LongURLRewriter
{
@ -41,9 +40,11 @@ public class LongURLRewriter
private static final Pattern REWRITE_PARAMETER = Pattern.compile("[^%\\w\\d]");
/**
* Matches.
*
* @param urlPath
* @return
* the url path
* @return true, if successful
*/
public static boolean matches(final String urlPath)
{
@ -57,19 +58,6 @@ public class LongURLRewriter
return result;
}
/**
*
*/
public static String[] unrewriteParameters(final HttpServletRequest request)
{
String[] result;
result = unrewriteParameters(request.getRequestURI());
//
return result;
}
/**
* This method gives a way for a long rewriting URL format. Long as in REST.
*
@ -86,6 +74,11 @@ public class LongURLRewriter
*
* Note: "-/" is used to indicate the beginning of parameters.
*
* @param path
* the path
* @param parameters
* the parameters
* @return the string
*/
public static String rewrite(final String path, final String... parameters)
{
@ -113,12 +106,13 @@ public class LongURLRewriter
}
/**
* This methods unrewrite a pathinfo.
*
* /catalog/article-/123/2016/12/14/resume.xhtml -> /catalog/article.xhtml
*
* @param source
* an URL path.
* @return
* @return the string
*/
public static String unrewrite(final String source)
{
@ -141,6 +135,23 @@ public class LongURLRewriter
return result;
}
/**
* Unrewrite parameters.
*
* @param request
* the request
* @return the string[]
*/
public static String[] unrewriteParameters(final HttpServletRequest request)
{
String[] result;
result = unrewriteParameters(request.getRequestURI());
//
return result;
}
/**
* Extract values from a path.
*
@ -153,7 +164,7 @@ public class LongURLRewriter
*
* @param source
* an URL path.
* @return
* @return the string[]
*/
public static String[] unrewriteParameters(final String source)
{

View file

@ -0,0 +1,79 @@
/*
* Copyright (C) 2018-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import java.io.File;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
/**
* The Class MaintenanceHook.
*/
public class MaintenanceHook extends HookCore
{
private static Logger logger = LoggerFactory.getLogger(MaintenanceHook.class);
/**
* Instantiates a new maintenance hook.
*/
public MaintenanceHook()
{
super();
}
/**
* {@inheritDoc}
*/
@Override
public String getServletClassName(final ServletConfig config, final HttpServletRequest request)
{
String result;
result = "/fr/devinsy/kiss4web/dispatcher/hooks/MaintenanceServlet";
//
return result;
}
/**
* {@inheritDoc}
*/
@Override
public boolean matches(final ServletContext servletContext, final HttpServletRequest request)
{
boolean result;
if (new File(servletContext.getRealPath("/") + request.getPathInfo()).exists())
{
result = true;
}
else
{
result = false;
}
//
return result;
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (C) 2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class MaintenanceServlet.
*/
public class MaintenanceServlet extends DirectServlet
{
private static final long serialVersionUID = 1116048013331691997L;
private static final Logger logger = LoggerFactory.getLogger(MaintenanceServlet.class);
/**
* Instantiates a new maintenance servlet.
*/
public MaintenanceServlet()
{
super("/fr/devinsy/kiss4web/dispatcher/hooks/maintenance.xhtml");
}
}

View file

@ -0,0 +1,114 @@
/*
* Copyright (C) 2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.kiss4web.dispatcher.KissDispatcherUtils;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
/**
* The Class RewriteHook.
*/
public class RewriteHook extends HookCore
{
private static Logger logger = LoggerFactory.getLogger(RewriteHook.class);
private Pattern pattern;
private String targetClassName;
/**
* Instantiates a new rewrite hook.
*
* @param regex
* the regex
* @param targetClassName
* the target class name
*/
public RewriteHook(final String regex, final String targetClassName)
{
super();
this.pattern = Pattern.compile(regex);
this.targetClassName = targetClassName;
}
/**
* Gets the servlet class path.
*
* @param config
* the config
* @param request
* the request
* @return the servlet class path
*/
@Override
public String getServletClassName(final ServletConfig config, final HttpServletRequest request)
{
String result;
result = this.targetClassName;
//
return result;
}
/**
* {@inheritDoc}
*/
@Override
public boolean matches(final ServletContext servletContext, final HttpServletRequest request)
{
boolean result;
String urlPath = request.getPathInfo();
if (this.pattern.matcher(urlPath).matches())
{
result = KissDispatcherUtils.isAvailablePath(this.targetClassName);
}
else
{
result = false;
}
//
return result;
}
/**
* To string.
*
* @return the string
*/
@Override
public String toString()
{
String result;
result = this.pattern.toString() + " -> " + this.targetClassName;
//
return result;
}
}

View file

@ -1,5 +1,5 @@
/**
* Copyright (C) 2006-2010, 2013-2016 Christian Pierre MOMON
/*
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
@ -16,30 +16,25 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.hooks;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
package fr.devinsy.kiss4web.dispatcher.hooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.kiss4web.KissDispatcherUtils;
import fr.devinsy.kiss4web.dispatcher.KissDispatcherUtils;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
/**
*
* The Class RootHook.
*/
public class RootHook extends HookCore
{
private static Logger logger = LoggerFactory.getLogger(RootHook.class);
/**
*
* Instantiates a new root hook.
*/
public RootHook()
{
@ -47,25 +42,27 @@ public class RootHook extends HookCore
}
/**
* @throws IOException
* @throws ServletException
* Gets the servlet class path.
*
* @param config
* the config
* @param request
* the request
* @return the servlet class path
*/
@Override
public void process(final ServletConfig servletConfig, final ServletContext servletContext, final HttpServletRequest request,
final HttpServletResponse response) throws IOException, ServletException
public String getServletClassName(final ServletConfig config, final HttpServletRequest request)
{
logger.debug("Doing catch.");
String result;
String className = "index.xhtml";
result = "website." + KissDispatcherUtils.translateToClassName("/index.xhtml");
KissDispatcherUtils.dispatchToServlet(servletConfig, request, response, className);
//
return result;
}
/**
*
* @param urlPath
* @return
* {@inheritDoc}
*/
@Override
public boolean matches(final ServletContext servletContext, final HttpServletRequest request)

View file

@ -1,5 +1,5 @@
/**
* Copyright (C) 2006-2010, 2013-2016 Christian Pierre MOMON
/*
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
@ -16,30 +16,25 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.hooks;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
package fr.devinsy.kiss4web.dispatcher.hooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.kiss4web.KissDispatcherUtils;
import fr.devinsy.kiss4web.dispatcher.KissDispatcherUtils;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
/**
*
* The Class ShortURLHook.
*/
public class ShortURLHook extends HookCore
{
private static Logger logger = LoggerFactory.getLogger(ShortURLHook.class);
/**
*
* Instantiates a new short URL hook.
*/
public ShortURLHook()
{
@ -47,27 +42,26 @@ public class ShortURLHook extends HookCore
}
/**
* @throws IOException
* @throws ServletException
*
* {@inheritDoc}
*/
@Override
public void process(final ServletConfig servletConfig, final ServletContext servletContext, final HttpServletRequest request,
final HttpServletResponse response) throws IOException, ServletException
public String getServletClassName(final ServletConfig config, final HttpServletRequest request)
{
String result;
logger.debug("Doing catch.");
String urlPath = request.getPathInfo();
result = "website." + KissDispatcherUtils.translateToClassName(ShortURLRewriter.unrewrite(urlPath));
String rewritedURLPath = ShortURLRewriter.unrewrite(urlPath);
logger.info("rewritedURLPath={}", result);
KissDispatcherUtils.dispatchToServlet(servletConfig, request, response, rewritedURLPath);
//
return result;
}
/**
*
* @param urlPath
* @return
* {@inheritDoc}
*/
@Override
public boolean matches(final ServletContext servletContext, final HttpServletRequest request)
@ -76,7 +70,15 @@ public class ShortURLHook extends HookCore
String urlPath = request.getPathInfo();
result = ShortURLRewriter.matches(urlPath);
if (ShortURLRewriter.matches(urlPath))
{
urlPath = ShortURLRewriter.unrewrite(urlPath);
result = KissDispatcherUtils.isAvailablePath(urlPath);
}
else
{
result = false;
}
//
return result;

View file

@ -1,5 +1,5 @@
/**
* Copyright (C) 2006-2010, 2013-2016 Christian Pierre MOMON
* Copyright (C) 2006-2024 Christian Pierre MOMON
*
* This file is part of Kiss4web.
*
@ -16,20 +16,19 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.hooks;
package fr.devinsy.kiss4web.dispatcher.hooks;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.util.strings.StringList;
import fr.devinsy.strings.StringList;
import jakarta.servlet.http.HttpServletRequest;
/**
*
* The Class ShortURLRewriter.
*/
public class ShortURLRewriter
{
@ -48,28 +47,27 @@ public class ShortURLRewriter
*/
private static char NONE = (char) 0;
private static int[] rewritingParameterMapping = {
/* 00 */NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
/* 10 */NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
/* 20 */'-', NONE, NONE, '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-',
/* 30 */'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '-', '-', '-', '-', '-',
/* 40 */'\u0040', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
/* 50 */'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '-', '-', '-', '-', '-',
/* 60 */'-', '\u0061', '\u0062', '\u0063', '\u0064', '\u0065', '\u0066', '\u0067', '\u0068', '\u0069', '\u006A', '\u006B', '\u006C', '\u006D', '\u006E', '\u006F',
/* 70 */'\u0070', '\u0071', '\u0072', '\u0073', '\u0074', '\u0075', '\u0076', '\u0077', '\u0078', '\u0079', '\u007A', '\u007B', '\u007C', '\u007D', '-', '-',
/* 80 */NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
/* 90 */NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
/* A0 */'\u00A0', '\u00A1', '\u00A2', '\u00A3', '\u00A4', '\u00A5', '\u00A6', '\u00A7', '\u00A8', '\u00A9', '\u00AA', '\u00AB', '\u00AC', '\u00AD', '\u00AE', '\u00AF',
/* B0 */'-', '\u00B1', '\u00B2', '\u00B3', '\u00B4', '\u00B5', '\u00B6', '\u00B7', '\u00B8', '\u00B9', '\u00BA', '\u00BB', '\u00BC', '\u00BD', '\u00BE', '\u00BF',
/* C0 */'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i',
/* D0 */'\u00D0', '\u00D1', 'o', 'o', 'o', 'o', 'o', 'o', '\u00D8', 'u', 'u', 'u', 'u', 'y', '\u00DE', '\u00DF',
/* E0 */'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i',
/* F0 */'o', 'n', 'o', 'o', 'o', 'o', 'o', '\u00F7', '-', 'u', 'u', 'u', 'u', 'y', '-', 'y' };
private static int[] rewritingParameterMapping = { /* 00 */NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
NONE, NONE, /* 10 */NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, /* 20 */'-', NONE,
NONE, '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', /* 30 */'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '-',
'-', '-', '-', '-', /* 40 */'\u0040', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* 50 */'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '-', '-', '-', '-', '-', /* 60 */'-', '\u0061', '\u0062', '\u0063', '\u0064', '\u0065', '\u0066',
'\u0067', '\u0068', '\u0069', '\u006A', '\u006B', '\u006C', '\u006D', '\u006E', '\u006F', /* 70 */'\u0070', '\u0071', '\u0072', '\u0073',
'\u0074', '\u0075', '\u0076', '\u0077', '\u0078', '\u0079', '\u007A', '\u007B', '\u007C', '\u007D', '-', '-', /* 80 */NONE, NONE, NONE,
NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, /* 90 */NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, /* A0 */'\u00A0', '\u00A1', '\u00A2', '\u00A3', '\u00A4', '\u00A5', '\u00A6', '\u00A7',
'\u00A8', '\u00A9', '\u00AA', '\u00AB', '\u00AC', '\u00AD', '\u00AE', '\u00AF', /* B0 */'-', '\u00B1', '\u00B2', '\u00B3', '\u00B4',
'\u00B5', '\u00B6', '\u00B7', '\u00B8', '\u00B9', '\u00BA', '\u00BB', '\u00BC', '\u00BD', '\u00BE', '\u00BF', /* C0 */'a', 'a', 'a', 'a',
'a', 'a', 'a', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', /* D0 */'\u00D0', '\u00D1', 'o', 'o', 'o', 'o', 'o', 'o', '\u00D8', 'u', 'u',
'u', 'u', 'y', '\u00DE', '\u00DF', /* E0 */'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', /* F0 */'o',
'n', 'o', 'o', 'o', 'o', 'o', '\u00F7', '-', 'u', 'u', 'u', 'u', 'y', '-', 'y' };
/**
* Matches.
*
* @param url
* @return
* the url
* @return true, if successful
*/
public static boolean matches(final String url)
{
@ -93,9 +91,17 @@ public class ShortURLRewriter
*
* <pre>
* "/good/article.xhtm?id=123&class=today&title=story's about me"
* => rewriteShorturl("/good/article", "xhtml", "123", "Story's aboute me");
* => rewriteShorturl("/good/article", "xhtml", "123", "Story's about me");
* => "/good/article-123-today-story-s-about-me.xhtml"
* </pre>
*
* @param uri
* the uri
* @param extension
* the extension
* @param parameters
* the parameters
* @return the string
*/
public static String rewrite(final String uri, final String extension, final String... parameters)
{
@ -125,9 +131,11 @@ public class ShortURLRewriter
}
/**
* Rewrite parameter.
*
* @param parameter
* @return
* the parameter
* @return the string
*/
public static String rewriteParameter(final String parameter)
{
@ -175,11 +183,13 @@ public class ShortURLRewriter
}
/**
* This method unrewrite a pathInfo.
*
* article.xhtm?id=123 -> article.xhtml
*
* @param source
* @return
* the source
* @return the string
*/
public static String unrewrite(final String source)
{
@ -203,7 +213,11 @@ public class ShortURLRewriter
}
/**
* Unrewrite parameter.
*
* @param request
* the request
* @return the string
*/
public static String unrewriteParameter(final HttpServletRequest request)
{
@ -217,6 +231,10 @@ public class ShortURLRewriter
/**
* Return value of the first parameter.
*
* @param path
* the path
* @return the string
*/
public static String unrewriteParameter(final String path)
{
@ -238,7 +256,11 @@ public class ShortURLRewriter
}
/**
* Unrewrite parameters.
*
* @param request
* the request
* @return the string[]
*/
public static String[] unrewriteParameters(final HttpServletRequest request)
{
@ -252,6 +274,10 @@ public class ShortURLRewriter
/**
* Extract value from a path. Example: "/article-123.xhtml" => "123".
*
* @param path
* the path
* @return the string[]
*/
public static String[] unrewriteParameters(final String path)
{

View file

@ -1,5 +1,5 @@
/**
* Copyright (C) 2006-2010, 2013-2016 Christian Pierre MOMON
/*
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
@ -16,31 +16,26 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.hooks;
package fr.devinsy.kiss4web.dispatcher.hooks;
import java.io.File;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.kiss4web.KissDispatcherUtils;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
/**
*
* The Class WebContentHook.
*/
public class WebContentHook extends HookCore
{
private static Logger logger = LoggerFactory.getLogger(WebContentHook.class);
/**
*
* Instantiates a new web content hook.
*/
public WebContentHook()
{
@ -48,35 +43,28 @@ public class WebContentHook extends HookCore
}
/**
* @throws IOException
* @throws ServletException
*
* {@inheritDoc}
*/
@Override
public void process(final ServletConfig servletConfig, final ServletContext servletContext, final HttpServletRequest request,
final HttpServletResponse response) throws IOException, ServletException
public String getServletClassName(final ServletConfig servletConfig, final HttpServletRequest request)
{
logger.debug("Doing catch.");
String result;
String path = servletContext.getRealPath("/") + request.getPathInfo();
logger.info("path=[{}]", path);
result = WebContentServlet.class.getCanonicalName();
String mimeType = servletContext.getMimeType(path);
KissDispatcherUtils.returnInlineFile(response, new File(path), mimeType);
logger.info("File returned directly [{}] with mimetype [{}].", path, servletContext.getMimeType(path));
//
return result;
}
/**
*
* @param urlPath
* @return
* {@inheritDoc}
*/
@Override
public boolean matches(final ServletContext servletContext, final HttpServletRequest request)
{
boolean result;
logger.info("Check for {}", servletContext.getRealPath("/") + request.getPathInfo());
if (new File(servletContext.getRealPath("/") + request.getPathInfo()).exists())
{
result = true;

View file

@ -0,0 +1,91 @@
/**
* Copyright (C) 2006-2024 Christian Pierre MOMON
*
* This file is part of Kiss4web.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiss4web 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.dispatcher.hooks;
import java.io.File;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.kiss4web.dispatcher.KissDispatcherUtils;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
/**
* The Class WebContentServlet.
*/
public class WebContentServlet extends HttpServlet
{
private static final long serialVersionUID = 3203080393289058696L;
private static final Logger logger = LoggerFactory.getLogger(WebContentServlet.class);
/**
* Instantiates a new web content servlet.
*/
public WebContentServlet()
{
}
/**
* Dispatch.
*
* @param request
* the request
* @param response
* the response
* @throws IOException
* Signals that an I/O exception has occurred.
* @throws ServletException
* the servlet exception
*/
public void dispatch(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
ServletContext context = this.getServletContext();
String path = context.getRealPath("/") + request.getPathInfo();
logger.info("path=[{}]", path);
String mimeType = context.getMimeType(path);
KissDispatcherUtils.returnInlineFile(response, new File(path), mimeType);
logger.info("File returned directly [{}] with mimetype [{}].", path, mimeType);
}
/**
* {@inheritDoc}
*/
@Override
public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
dispatch(request, response);
}
/**
* {@inheritDoc}
*/
@Override
public void doPost(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
dispatch(request, response);
}
}

View file

@ -1,5 +1,5 @@
/**
* Copyright (C) 2006-2010, 2013-2016 Christian Pierre MOMON
/*
* Copyright (C) 2006-2024 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Kiss4web.
*
@ -16,31 +16,26 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web.hooks;
package fr.devinsy.kiss4web.dispatcher.hooks;
import java.io.File;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.kiss4web.KissDispatcherUtils;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
/**
*
* The Class WebInfHook.
*/
public class WebInfHook extends HookCore
{
private static Logger logger = LoggerFactory.getLogger(WebInfHook.class);
/**
*
* Instantiates a new web inf hook.
*/
public WebInfHook()
{
@ -48,36 +43,27 @@ public class WebInfHook extends HookCore
}
/**
* @throws IOException
* @throws ServletException
*
* {@inheritDoc}
*/
@Override
public void process(final ServletConfig servletConfig, final ServletContext servletContext, final HttpServletRequest request,
final HttpServletResponse response) throws IOException, ServletException
public String getServletClassName(final ServletConfig servletConfig, final HttpServletRequest request)
{
logger.debug("Doing catch.");
String result;
String path = servletContext.getRealPath("/") + "WEB-INF/classes/website" + request.getPathInfo();
logger.info("path=[{}]", path);
String mimeType = servletContext.getMimeType(path);
KissDispatcherUtils.returnInlineFile(response, new File(path), mimeType);
logger.info("File returned directly [{}] with mimetype [{}].", path, servletContext.getMimeType(path));
result = WebInfServlet.class.getCanonicalName();
//
return result;
}
/**
*
* @param urlPath
* @return
* {@inheritDoc}
*/
@Override
public boolean matches(final ServletContext servletContext, final HttpServletRequest request)
{
boolean result;
logger.info("Check for {}", servletContext.getRealPath("/") + "WEB-INF/classes/website" + request.getPathInfo());
if (new File(servletContext.getRealPath("/") + "WEB-INF/classes/website" + request.getPathInfo()).exists())
{
result = true;
@ -90,4 +76,5 @@ public class WebInfHook extends HookCore
//
return result;
}
}

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