Compare commits

..

48 commits
master ... 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
99bf85794b Renamed catcher to hook. Improved hooking. 2016-12-06 14:36:45 +01:00
ad97832f48 Improved log configuration init. 2016-12-06 14:35:18 +01:00
cc4bec97c2 Fixed test. 2016-10-03 05:48:51 +02:00
bf94f1abbc Refactored build. 2016-09-21 14:27:25 +02:00
2927fd3d38 Fixed readme. 2016-09-21 14:24:51 +02:00
58aca5c9c8 Added Readme.md file. 2016-09-19 15:46:39 +02:00
e4385f7164 Debugged, improved, refactored code (catchers, dispatching, starting…). 2016-09-15 01:46:21 +02:00
305d2ac7ba Update devins-utils lib to 0.3.2. 2016-09-15 01:44:34 +02:00
b03dec79ee Refactored lot of code about dispatcher with catcher concept. Improved
the lib folder. Added tests.
2016-09-12 05:09:54 +02:00
e120c640fa Updated devinsy-utils jar. 2016-09-08 03:49:55 +02:00
4de5e49850 Refactor formatter and clean up code. 2016-09-08 03:45:06 +02:00
90a8d57df4 Updated headers. Made code review. Improved code design. 2016-09-07 14:44:32 +02:00
5003530064 Update buildjar version to 1.4. 2014-11-26 18:52:23 +01:00
6bde2a313f Initialize branch 0.3. 2014-10-23 18:17:33 +02:00
128 changed files with 8590 additions and 2733 deletions

View file

@ -2,20 +2,28 @@
<classpath> <classpath>
<classpathentry kind="src" path="src"/> <classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="test"/> <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="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
<classpathentry kind="lib" path="lib/hamcrest-core-1.3.jar"/>
<classpathentry kind="lib" path="lib/junit-4.11.jar"/>
<classpathentry kind="lib" path="lib/log4j-1.2.17.jar"/>
<classpathentry kind="lib" path="lib/slf4j-api-1.7.5.jar"/>
<classpathentry kind="lib" path="lib/slf4j-log4j12-1.7.5.jar"/>
<classpathentry kind="lib" path="lib/devinsy-utils-0.2.0.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="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
<attributes> <attributes>
<attribute name="module" value="true"/>
<attribute name="owner.project.facets" value="java"/> <attribute name="owner.project.facets" value="java"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="lib" path="lib/commons-codec-1.8.jar" sourcepath="lib/commons-codec-1.8-sources.jar"/>
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
<classpathentry kind="lib" path="lib/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"/> <classpathentry kind="output" path="bin"/>
</classpath> </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 eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 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.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.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.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_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_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 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_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_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_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=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_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_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=80
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 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_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_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_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_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_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_resources_in_try=80
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 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_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_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_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_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_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.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_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_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_field=0
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 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_new_chunk=1
org.eclipse.jdt.core.formatter.blank_lines_before_package=0 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_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.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_annotation_type_declaration=next_line
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_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_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_constant=next_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=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_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_switch=next_line
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=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_block_comment=false
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_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_block_comments=false
org.eclipse.jdt.core.formatter.comment.format_header=false org.eclipse.jdt.core.formatter.comment.format_header=false
org.eclipse.jdt.core.formatter.comment.format_html=true 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.format_source_code=true
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=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_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_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.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.line_length=80
org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_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_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_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_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_body_declarations_compare_to_type_header=true
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=false org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=false
org.eclipse.jdt.core.formatter.indent_empty_lines=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_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=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.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_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_local_variable=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=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_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_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_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_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_catch_in_try_statement=insert
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not 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_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_method_body=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=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_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_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=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_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_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_angle_bracket_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=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_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_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_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_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_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=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_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_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_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=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_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_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_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_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_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=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_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_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not 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_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=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_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_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_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_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_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_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=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_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_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_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_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_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=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_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_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_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_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_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_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_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_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_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=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_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_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_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_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_brace_in_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not 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_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_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_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_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_synchronized=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=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_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_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not 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=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_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_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_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_brackets_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=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.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_lines_in_comments=true
org.eclipse.jdt.core.formatter.join_wrapped_lines=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_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_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_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.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_block_comments_on_first_column=false
org.eclipse.jdt.core.formatter.never_indent_line_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_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.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.put_empty_statement_on_new_line=true
org.eclipse.jdt.core.formatter.tabulation.char=tab org.eclipse.jdt.core.formatter.tabulation.char=space
org.eclipse.jdt.core.formatter.tabulation.size=4 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_on_off_tags=false
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=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_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.formatter.wrap_outer_expressions_when_nested=true
org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter

View file

@ -1,3 +1,203 @@
cleanup.add_all=false
cleanup.add_default_serial_version_id=false
cleanup.add_generated_serial_version_id=true
cleanup.add_missing_annotations=true
cleanup.add_missing_deprecated_annotations=true
cleanup.add_missing_methods=false
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 eclipse.preferences.version=1
formatter_profile=_Devinsy editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
formatter_settings_version=12 formatter_profile=_Kiss4web
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
sp_cleanup.add_missing_deprecated_annotations=true
sp_cleanup.add_missing_methods=false
sp_cleanup.add_missing_nls_tags=false
sp_cleanup.add_missing_override_annotations=true
sp_cleanup.add_missing_override_annotations_interface_methods=true
sp_cleanup.add_serial_version_id=false
sp_cleanup.always_use_blocks=true
sp_cleanup.always_use_parentheses_in_expressions=false
sp_cleanup.always_use_this_for_non_static_field_access=true
sp_cleanup.always_use_this_for_non_static_method_access=false
sp_cleanup.convert_to_enhanced_for_loop=false
sp_cleanup.correct_indentation=true
sp_cleanup.format_source_code=true
sp_cleanup.format_source_code_changes_only=false
sp_cleanup.make_local_variable_final=false
sp_cleanup.make_parameters_final=true
sp_cleanup.make_private_fields_final=false
sp_cleanup.make_type_abstract_if_missing_method=false
sp_cleanup.make_variable_declarations_final=true
sp_cleanup.never_use_blocks=false
sp_cleanup.never_use_parentheses_in_expressions=true
sp_cleanup.on_save_use_additional_actions=true
sp_cleanup.organize_imports=true
sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
sp_cleanup.remove_private_constructors=true
sp_cleanup.remove_trailing_whitespaces=false
sp_cleanup.remove_trailing_whitespaces_all=true
sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
sp_cleanup.remove_unnecessary_casts=true
sp_cleanup.remove_unnecessary_nls_tags=true
sp_cleanup.remove_unused_imports=true
sp_cleanup.remove_unused_local_variables=false
sp_cleanup.remove_unused_private_fields=true
sp_cleanup.remove_unused_private_members=false
sp_cleanup.remove_unused_private_methods=true
sp_cleanup.remove_unused_private_types=true
sp_cleanup.sort_members=true
sp_cleanup.sort_members_all=false
sp_cleanup.use_blocks=true
sp_cleanup.use_blocks_only_for_return_and_throw=false
sp_cleanup.use_parentheses_in_expressions=false
sp_cleanup.use_this_for_non_static_field_access=true
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
sp_cleanup.use_this_for_non_static_method_access=false
sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true

View file

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

142
README.md Normal file
View file

@ -0,0 +1,142 @@
# Kiss4web
Welcome! Welcome in a world of K.I.S.S.
K.I.S.S. = Keep It Simple, Stupid (https://en.wikipedia.org/wiki/KISS_principle).
Nowadays, make a Web site involves to use complex and heavy frameworks. Nevertheless, to build a web page and to return it, does not maybe ask so much complexity.
Kiss4web is a K.I.S.S. solution for building web applications.
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 project uses strictly Eclipse 4.29, Java 17, tomcat 10.1 and Git.
## Build
Kiss4web uses Ant and generates a kiss4web-x.y.z folder which contains:
- x.jar : full software.
- x-core.jar : only compiled class without any library.
- x-core-source.jar : sources.
## Dependencies
The kiss4web jar requires:
- commons-io
- commons-lang3
- devinsy-strings
## 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

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?> <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<project default="dist" name="jarbuild"> <project default="dist" name="Build-libjar">
<!--ANT 1.7 is required --> <!--ANT 1.7 is required -->
<property name="buildjar.version" value="1.3" /> <property name="buildjar.version" value="1.5" />
<property file="build.properties" /> <property file="build.properties" />
<property name="build.dir" value="${basedir}/build" /> <property name="build.dir" value="${basedir}/build" />
<property name="build.src" value="${basedir}/src" /> <property name="build.src" value="${basedir}/src" />
@ -25,23 +25,31 @@
<pathelement path="${test.classes}" /> <pathelement path="${test.classes}" />
</path> </path>
<!-- ***** Help ***** --> <!-- ***** Help ***** -->
<target name="help" description="Display detailed usage information"> <target name="help" description="Display detailed usage information">
<echo>Type ant -p</echo> <echo>Type ant -p</echo>
</target> </target>
<!-- ***** Clear ***** -->
<target name="clear" description="Clean temporary directories before work">
<delete dir="${build.dir}" />
</target>
<!-- ***** Clean ***** --> <!-- ***** Clean ***** -->
<target name="clean" description="Clean temporary directories"> <target name="clean" description="Clean temporary directories afeter work">
<delete dir="${build.dir}" /> <delete dir="${build.dir}" />
</target> </target>
<!-- ***** Compile ***** --> <!-- ***** Compile ***** -->
<target name="compile" description="Compile main code"> <target name="compile" description="Compile main code">
<mkdir dir="${build.dir}/classes" /> <delete dir="${build.classes}" />
<mkdir dir="${build.classes}" />
<javac srcdir="${build.src}" destdir="${build.classes}" debug="${debug}" deprecation="on" includeantruntime="false"> <javac srcdir="${build.src}" destdir="${build.classes}" debug="${debug}" deprecation="on" includeantruntime="false">
<classpath refid="test.classpath.compile" /> <classpath refid="build.classpath" />
</javac> </javac>
<copy todir="${build.classes}">
<fileset dir="${build.src}" excludes="**/*.java" />
</copy>
</target> </target>
<!-- ***** Compile test ***** --> <!-- ***** Compile test ***** -->
@ -50,11 +58,13 @@
<javac srcdir="${test.src}" destdir="${test.classes}" debug="${debug}" deprecation="on" includeantruntime="false"> <javac srcdir="${test.src}" destdir="${test.classes}" debug="${debug}" deprecation="on" includeantruntime="false">
<classpath refid="test.classpath.compile" /> <classpath refid="test.classpath.compile" />
</javac> </javac>
<copy todir="${test.classes}">
<fileset dir="${test.src}" excludes="**/*.java" />
</copy>
</target> </target>
<!-- ***** Test ***** --> <!-- ***** Test ***** -->
<target name="test" description="Run unit tests" depends="clean,compile,compile-test"> <target name="test" description="Run unit tests" depends="clear,compile,compile-test">
<mkdir dir="${build.dir}/test-reports" /> <mkdir dir="${build.dir}/test-reports" />
<junit printsummary="yes" haltonfailure="no"> <junit printsummary="yes" haltonfailure="no">
<classpath refid="test.classpath.run" /> <classpath refid="test.classpath.run" />
@ -77,33 +87,31 @@
</target> </target>
<!-- ***** Dist ***** --> <!-- ***** Dist ***** -->
<target name="dist" description="Build distribution" depends="clean,compile,javadoc"> <target name="dist" description="Build distribution" depends="clear,compile,javadoc">
<!-- -->
<buildnumber file="build.num" description="Id of the build" />
<!-- AUTOMATIC MANAGEMENT --> <!-- AUTOMATIC MANAGEMENT -->
<buildnumber file="build.num" description="Id of the build" />
<property name="dist.version" value="${product.revision.major}.${product.revision.minor}.${build.number}" /> <property name="dist.version" value="${product.revision.major}.${product.revision.minor}.${build.number}" />
<property name="dist.name" value="${product.name}-${dist.version}" /> <property name="dist.name" value="${product.name}-${dist.version}" />
<property name="dist.dir" value="${basedir}/dist/${dist.name}" /> <property name="dist.dir" value="${basedir}/dist/${dist.name}" />
<!-- --> <!-- -->
<mkdir dir="${dist.dir}" /> <copy file="LICENSE" todir="${dist.dir}/" overwrite="true" failonerror="false" />
<copy file="README" todir="${dist.dir}/" overwrite="true" failonerror="false" />
<!-- --> <copy file="README.md" todir="${dist.dir}/" overwrite="true" failonerror="false" />
<copy file="LICENSE" todir="${dist.dir}/" overwrite="true" />
<!-- Package main --> <!-- Package main -->
<property name="dist.jar" value="${dist.dir}/${dist.name}.jar" /> <property name="dist.jar" value="${dist.dir}/${dist.name}.jar" />
<tstamp> <tstamp>
<format property="dist.time" pattern="dd/MM/yyyy HH:mm:ss" />
<!-- TODAY --> <!-- TODAY -->
<format property="dist.time" pattern="dd/MM/yyyy HH:mm:ss" />
</tstamp> </tstamp>
<jar destfile="${dist.jar}"> <jar destfile="${dist.jar}">
<manifest> <manifest>
<attribute name="Built-By" value="${user.name} using ant" /> <attribute name="Built-By" value="${user.name} using ant" />
<attribute name="Built-Date" value="${dist.time}" /> <attribute name="Built-Date" value="${dist.time}" />
</manifest> </manifest>
<service type="javax.annotation.processing.Processor" provider="fr.devinsy.kiss4web.dispatcher.annotation.KissServletProcessor" />
<fileset dir="${build.classes}" /> <fileset dir="${build.classes}" />
<zipfileset dir="${basedir}/" includes="LICENSE" />
</jar> </jar>
<!-- Package sources --> <!-- Package sources -->
@ -115,37 +123,40 @@
<!-- Package Javadoc --> <!-- Package Javadoc -->
<property name="dist.javadoc.zip" value="${dist.dir}/${dist.name}-javadoc.zip" /> <property name="dist.javadoc.zip" value="${dist.dir}/${dist.name}-javadoc.zip" />
<zip destfile="${dist.javadoc.zip}" update="true" preserve0permissions="true"> <zip destfile="${dist.javadoc.zip}" update="true">
<fileset dir="${build.javadoc}" /> <fileset dir="${build.javadoc}" />
<zipfileset dir="${basedir}/" includes="LICENSE" /> <zipfileset dir="${basedir}/" includes="LICENSE" />
</zip> </zip>
<!-- Package lib --> <!-- Zip package -->
<copy todir="${dist.dir}/lib" overwrite="true"> <property name="dist.zip" value="${basedir}/dist/${dist.name}.zip" />
<fileset dir="lib" excludes="hamcrest-core*,junit*" /> <!--
</copy> <property name="dist.zip" value="${basedir}/dist/${dist.name}.zip" />
<zip destfile="${dist.zip}" update="true">
<fileset dir="${dist.dir}" />
<zipfileset filemode="755" dir="${dist.dir}/" includes="*.sh *.command" />
</zip>
-->
</target> </target>
<!-- ***** Dist ***** --> <!-- ***** Build and GIT ***** -->
<target name="buildandgit" depends="dist"> <target name="buildandgit" depends="dist,clean">
<!-- GIT actions--> <echo message="Commit build.num" />
<echo message="Commit build.num"/>
<exec executable="git" outputproperty="git.commit.out" failifexecutionfails="true"> <exec executable="git" outputproperty="git.commit.out" failifexecutionfails="true">
<arg line="commit -m 'Build ${dist.version}' build.num"/> <arg line="commit -m 'Build ${dist.version}' build.num" />
</exec> </exec>
<echo message="${git.commit.out}" /> <echo message="${git.commit.out}" />
<echo message="Tag"/> <echo message="Tag" />
<exec executable="git" outputproperty="git.tag.out" failifexecutionfails="true"> <exec executable="git" outputproperty="git.tag.out" failifexecutionfails="true">
<arg line="tag -a ${dist.version} -m 'Build ${dist.version}'"/> <arg line="tag -a ${dist.version} -m 'Build ${dist.version}'" />
</exec> </exec>
<echo message="${git.tag.out}" /> <echo message="${git.tag.out}" />
<echo message="Push"/> <echo message="Push" />
<exec executable="git" outputproperty="git.push.out" failifexecutionfails="true"> <exec executable="git" outputproperty="git.push.out" failifexecutionfails="true">
<arg line="push"/> <arg line="push --follow-tags" />
</exec> </exec>
<echo message="${git.push.out}" /> <echo message="${git.push.out}" />
</target> </target>
</project> </project>

View file

@ -1,3 +1,3 @@
#Build Number for ANT. Do not edit! #Build Number for ANT. Do not edit!
#Wed Feb 05 00:08:42 CET 2014 #Fri Dec 01 05:27:08 CET 2023
build.number=7 build.number=2

View file

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

View file

@ -1,5 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?> <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<project default="dist" name="kiss4web"> <project default="main" name="Build">
<!-- --> <!-- ***** Import ***** -->
<import file="buildjar.xml" /> <import file="build-libjar.xml" />
<!-- ***** Main ***** -->
<target name="main" description="" depends="dist,clean" />
</project> </project>

View file

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?> <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<project default="buildandgit" name="sikevadb"> <project default="main" name="Buildandgit">
<!-- --> <!-- -->
<import file="buildjar.xml" /> <import file="build.xml" />
<target name="main" description="" depends="buildandgit,clean"/>
</project> </project>

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-codec: digest tools.
- commons-fileupload: - commons-fileupload:
- commons-io: - commons-io:
- devinsy-utils: util tools - devinsy-utils: util tools
- hamcrest-core: required by junit
- junit: unit tests API
- log4j: log API
- servlet-api: servlet API - servlet-api: servlet API
Log libs:
- log4j: log API
- slf4j-api: facade log API - slf4j-api: facade log API
- slf4j-log4j12: adaptation layer between slf4j and log4j - 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.

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.

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

@ -0,0 +1,178 @@
/**
* Copyright (C) 2013-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 java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class BuildInformation.
*/
public class BuildInformation
{
private static final Logger logger = LoggerFactory.getLogger(BuildInformation.class);
private String productName;
private String majorRevision;
private String minorRevision;
private String buildNumber;
private String buildDate;
private String generator;
private String author;
/**
* Instantiates a new builds the information.
*/
public BuildInformation()
{
try
{
Properties build = new Properties();
build.load(BuildInformation.class.getResource("/fr.devinsy.kiss4web/build_information.properties").openStream());
//
this.productName = build.getProperty("product.name", "n/a");
this.majorRevision = build.getProperty("product.revision.major", "n/a");
this.minorRevision = build.getProperty("product.revision.minor", "n/a");
this.buildNumber = build.getProperty("product.revision.build", "n/a");
this.buildDate = build.getProperty("product.revision.date", "n/a");
this.generator = build.getProperty("product.revision.generator", "n/a");
this.author = build.getProperty("product.revision.author", "n/a");
}
catch (IOException exception)
{
logger.error("Error loading the build.properties file: " + exception.getMessage(), exception);
this.productName = "n/a";
this.majorRevision = "n/a";
this.minorRevision = "n/a";
this.buildNumber = "n/a";
this.buildDate = "n/a";
this.generator = "n/a";
this.author = "n/a";
}
}
/**
* 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);
//
return result;
}
/**
* Version.
*
* @return the string
*/
public String version()
{
String result;
result = String.format("%s.%s.%s", this.majorRevision, this.minorRevision, this.buildNumber);
//
return result;
}
}

View file

@ -1,72 +1,89 @@
/** /**
* Copyright (C) 2006-2010, 2013-2014 Christian Pierre MOMON * Copyright (C) 2006-2024 Christian Pierre MOMON
* *
* This file is part of Devinsy-utils. * This file is part of Kiss4web.
* *
* Kiss4web is free software: you can redistribute it and/or modify * Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * 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 * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Kiss4web is distributed in the hope that it will be useful, * Kiss4web is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/> * along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/ */
package fr.devinsy.kiss4web; package fr.devinsy.kiss4web;
import java.io.UnsupportedEncodingException;
import javax.servlet.http.Cookie; import java.io.UnsupportedEncodingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; 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 public class CookieHelper
{ {
private static final Logger logger = LoggerFactory.getLogger(CookieHelper.class);
public enum Scope public enum Scope
{ {
HTTP_AND_HTTPS, HTTPS_ONLY HTTP_AND_HTTPS,
HTTPS_ONLY
} }
static private 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
*/ */
static public Cookie buildCookie(final String name, final String value, final int duration) public static Cookie buildCookie(final String name, final String value, final int duration)
{ {
Cookie result; Cookie result;
result = buildCookie(name, value, duration, Scope.HTTP_AND_HTTPS); result = buildCookie(name, value, duration, Scope.HTTP_AND_HTTPS);
// //
return (result); return result;
} }
/** /**
* 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
*/ */
static public Cookie buildCookie(final String name, final String value, final int duration, final Scope secure) public static Cookie buildCookie(final String name, final String value, final int duration, final Scope secure)
{ {
Cookie result; Cookie result;
//
try try
{ {
result = new Cookie(name, java.net.URLEncoder.encode(value, "UTF-8")); result = new Cookie(name, java.net.URLEncoder.encode(value, "UTF-8"));
result.setMaxAge(duration); result.setMaxAge(duration);
result.setPath("/"); result.setPath("/");
//
boolean secureValue; boolean secureValue;
if (secure == Scope.HTTPS_ONLY) if (secure == Scope.HTTPS_ONLY)
{ {
@ -85,13 +102,19 @@ public class CookieHelper
} }
// //
return (result); return result;
} }
/** /**
* Exists.
* *
* @param request
* the request
* @param key
* the key
* @return true, if successful
*/ */
static public boolean exists(final HttpServletRequest request, final String key) public static boolean exists(final HttpServletRequest request, final String key)
{ {
boolean result; boolean result;
@ -105,13 +128,19 @@ public class CookieHelper
} }
// //
return (result); return result;
} }
/** /**
* Gets the cookie.
* *
* @param cookies
* the cookies
* @param key
* the key
* @return the cookie
*/ */
static public Cookie getCookie(final Cookie[] cookies, final String key) public static Cookie getCookie(final Cookie[] cookies, final String key)
{ {
Cookie result = null; Cookie result = null;
@ -146,26 +175,38 @@ public class CookieHelper
} }
// //
return (result); return result;
} }
/** /**
* Gets the cookie.
* *
* @param request
* the request
* @param key
* the key
* @return the cookie
*/ */
static public Cookie getCookie(final HttpServletRequest request, final String key) public static Cookie getCookie(final HttpServletRequest request, final String key)
{ {
Cookie result = null; Cookie result = null;
result = getCookie(request.getCookies(), key); result = getCookie(request.getCookies(), key);
// //
return (result); return result;
} }
/** /**
* Note: value is UTF-8 decoded. * Note: value is UTF-8 decoded.
*
* @param cookies
* the cookies
* @param key
* the key
* @return the cookie value
*/ */
static public Object getCookieValue(final Cookie[] cookies, final String key) public static Object getCookieValue(final Cookie[] cookies, final String key)
{ {
Object result; Object result;
@ -189,34 +230,54 @@ public class CookieHelper
} }
// //
return (result); return result;
} }
/** /**
* Gets the cookie value.
* *
* @param request
* the request
* @param key
* the key
* @return the cookie value
*/ */
static public Object getCookieValue(final HttpServletRequest request, final String key) public static Object getCookieValue(final HttpServletRequest request, final String key)
{ {
Object result; Object result;
result = getCookieValue(request.getCookies(), key); result = getCookieValue(request.getCookies(), key);
// //
return (result); return result;
} }
/** /**
* Reset.
* *
* @param response
* the response
* @param key
* the key
*/ */
static public void reset(final HttpServletResponse response, final String key) public static void reset(final HttpServletResponse response, final String key)
{ {
response.addCookie(buildCookie(key, "", 0)); response.addCookie(buildCookie(key, "", 0));
} }
/** /**
* Sets the.
* *
* @param response
* the response
* @param name
* the name
* @param value
* the value
* @param duration
* the duration
*/ */
static public void set(final HttpServletResponse response, final String name, final String value, final int duration) public static void set(final HttpServletResponse response, final String name, final String value, final int duration)
{ {
response.addCookie(buildCookie(name, value, duration)); response.addCookie(buildCookie(name, value, duration));
} }

View file

@ -0,0 +1,259 @@
/**
* Copyright 2013-2021 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 javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.strings.StringsUtils;
/**
* The Class EnvironmentInformation.
*/
public class EnvironmentInformation
{
private static final Logger logger = LoggerFactory.getLogger(EnvironmentInformation.class);;
private Context environment;
/**
* Instantiates a new environment information.
*
* @throws ConfigurationException
* the configuration exception
*/
public EnvironmentInformation() throws ConfigurationException
{
try
{
Context initialContext = new InitialContext();
this.environment = (Context) initialContext.lookup("java:comp/env");
}
catch (NamingException exception)
{
logger.error("Error getting context information: ", exception.getMessage(), exception);
throw new ConfigurationException("Error setting environment information: " + exception.getMessage());
}
// Check availability of all fields.
if (!isAvailable())
{
throw new ConfigurationException("Environment information is not fully available.");
}
}
/**
* Gets the log 4 j path.
*
* @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;
try
{
if (StringsUtils.containsBlank(getName(), getWebsiteURLPath(), getWebsiteURLPath()))
{
result = false;
}
else
{
result = true;
}
}
catch (NamingException exception)
{
result = false;
}
//
return result;
}
}

View file

@ -1,100 +0,0 @@
/**
* Copyright (C) 2006-2010, 2013-2014 Christian Pierre MOMON
*
* This file is part of Devinsy-utils.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web;
import java.util.List;
import org.apache.commons.fileupload.FileItem;
/**
*
*/
public class FileItemHelper
{
// static private final Logger logger =
// LoggerFactory.getLogger(FileItemHelper.class);
/**
* List FileItem
*/
static public FileItem getItem(final List items, final String name)
{
FileItem result;
if (name == null)
{
result = null;
}
else
{
result = null;
boolean ended = false;
int itemIndex = 0;
while (!ended)
{
if (itemIndex < items.size())
{
FileItem item = (FileItem) items.get(itemIndex);
if (name.equals(item.getFieldName()))
{
ended = true;
result = item;
}
else
{
itemIndex += 1;
}
}
else
{
ended = true;
result = null;
}
}
}
//
return (result);
}
/**
* List FileItem
*/
static public String getItemValue(final List items, final String name)
{
String result;
FileItem item = getItem(items, name);
if (item == null)
{
result = null;
}
else
{
result = item.getString();
}
//
return (result);
}
}
// ////////////////////////////////////////////////////////////////////////

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

@ -0,0 +1,283 @@
/*
* Copyright (C) 2013-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.Date;
import org.apache.commons.lang3.StringUtils;
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;
/**
* 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();
}
private BuildInformation buildInformation;
private Mode mode;
/**
* Instantiates a new kiss 4 web.
*/
private Kiss4web()
{
String currentLog = "Kiss4web";
try
{
//
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");
//
//
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("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 the mode
*/
public Mode getMode()
{
return this.mode;
}
/**
* Sets the mode.
*
* @param mode
* the new mode
*/
public void setMode(final Mode mode)
{
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.
*
* @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()
{
return SingletonHolder.instance;
}
/**
* Log init.
*
* @param currentLogItem
* the current log item
* @param status
* the status
*/
private static void logInit(final String currentLogItem, final String status)
{
logger.info(String.format("%s%s%s", currentLogItem, StringUtils.repeat('.', 40 - StringUtils.length(currentLogItem)), 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

@ -0,0 +1,32 @@
/*
* 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;
/**
* The Class Kiss4webUtils.
*/
public class Kiss4webUtils
{
/**
*
*/
public Kiss4webUtils()
{
}
}

View file

@ -1,36 +1,82 @@
/** /**
* Copyright (C) 2006-2010, 2013-2014 Christian Pierre MOMON * Copyright (C) 2021-2023 Christian Pierre MOMON
* *
* This file is part of Devinsy-utils. * This file is part of Kiss4web.
* *
* Kiss4web is free software: you can redistribute it and/or modify * Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * 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 * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Kiss4web is distributed in the hope that it will be useful, * Kiss4web is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/> * along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/ */
package fr.devinsy.kiss4web; package fr.devinsy.kiss4web;
import java.io.IOException; import java.io.IOException;
import javax.servlet.ServletException; import jakarta.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
/** /**
* * The Class Page.
*/ */
public interface 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 void doIt(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException; 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,420 +0,0 @@
/**
* Copyright (C) 2006-2010, 2013-2014 Christian Pierre MOMON
*
* This file is part of Devinsy-utils.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import fr.devinsy.kiss4web.security.SecurityAgent;
import fr.devinsy.kiss4web.security.User;
/**
*
*/
public class PageManager extends HttpServlet
{
private static final long serialVersionUID = 1983715791417570578L;
private static PageManager instance = null;
protected SecurityAgent securityAgent;
static private org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(PageManager.class);
/**
*
*/
@Override
public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
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() + "]");
String className = buildClassName(request.getPathInfo());
logger.info("className=" + className);
Page page = this.instanciatePage("site." + className);
if (page == null)
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("Unknow page.");
}
else
{
HttpSession session = request.getSession(false);
String login;
if (session == null)
{
login = null;
}
else
{
login = (String) session.getAttribute("login");
}
if (this.securityAgent.checkPermission(request.getPathInfo(), login))
{
page.doIt(request, response);
logger.info("securityAgent say 'permission OK': (" + login + ", " + request.getPathInfo() + ")");
}
else
{
logger.info("securityAgent say 'permission KO': (" + login + ", " + request.getPathInfo() + ")");
if (login == null)
{
response.sendRedirect("/gestion/login.xhtml");
}
else
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html><head></head><body>");
out.println("Permission denied.");
out.println("<form method='get' action='javascript:window.back ();'>");
out.println(" <input type='submit' name='retour' value='Retour' />");
out.println("</form>");
out.println("</body></html>");
}
}
}
}
/**
*
*/
@Override
public void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
{
doGet(request, response);
}
/**
*
*/
@Override
public void init() throws ServletException
{
//
instance = this;
try
{
this.securityAgent = new SecurityAgent(getInitParameter("securityDataPath"));
}
catch (Exception exception)
{
throw new ServletException("SecurityAgent initialization failed.", exception);
}
}
/**
*/
public Page instanciatePage(final String className)
{
Page result;
Class<Page> pageClass = null;
try
{
pageClass = (Class<Page>) Class.forName(className);
}
catch (java.lang.ClassNotFoundException exception)
{
result = null;
}
logger.info("class=" + pageClass);
if (pageClass == null)
{
result = null;
logger.error("Unknow page: (" + className + ")");
}
else
{
try
{
result = pageClass.newInstance();
}
catch (java.lang.InstantiationException exception)
{
logger.error("Can't instanciate page (" + className + ")");
result = null;
}
catch (java.lang.IllegalAccessException exception)
{
logger.error("(2) Can't instanciate page (" + className + ")");
result = null;
}
}
//
return (result);
}
/**
*
*/
public SecurityAgent securityAgent()
{
SecurityAgent result;
result = this.securityAgent;
//
return (result);
}
/**
*
*/
static public 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);
}
/**
*
*/
static public String buildClassName2(final String pathInfo)
{
String result;
if (pathInfo.endsWith(".xhtml"))
{
char[] source = pathInfo.toCharArray();
StringBuffer out = new StringBuffer();
for (char c : source)
{
out.append("[" + c + "]");
}
logger.debug(out.toString());
char[] target = new char[source.length - 7];
int lastStartToken = 0;
for (int nChar = 1; nChar < source.length - 5; nChar++)
{
char charSource = source[nChar];
switch (charSource)
{
case '/':
target[nChar - 1] = '.';
lastStartToken = nChar;
break;
case '.':
target[lastStartToken] = Character.toUpperCase(target[lastStartToken]);
break;
default:
target[nChar - 1] = source[nChar];
}
}
out = new StringBuffer();
for (char c : target)
{
out.append("[" + c + "]");
}
logger.debug(out.toString());
result = new String(target);
}
else if (pathInfo.equals("/"))
{
result = "Accueil";
}
else if (pathInfo.endsWith("/"))
{
char[] source = pathInfo.toCharArray();
StringBuffer out = new StringBuffer();
for (char c : source)
{
out.append("[" + c + "]");
}
logger.debug(out.toString());
char[] target = new char[source.length - 2];
int lastStartToken = 0;
for (int nChar = 1; nChar < source.length - 1; nChar++)
{
char charSource = source[nChar];
switch (charSource)
{
case '/':
target[nChar - 1] = '.';
lastStartToken = nChar + 1;
break;
default:
target[nChar - 1] = source[nChar];
}
}
char[] targetPlus = new char[source.length - lastStartToken];
targetPlus[0] = '.';
targetPlus[1] = Character.toUpperCase(source[lastStartToken]);
int index = 2;
for (int nChar = lastStartToken + 1; nChar < source.length - 1; nChar++)
{
targetPlus[index] = source[nChar];
index += 1;
}
out = new StringBuffer();
for (char c : target)
{
out.append("[" + c + "]");
}
logger.debug(out.toString());
out = new StringBuffer();
for (char c : targetPlus)
{
out.append("[" + c + "]");
}
logger.debug(out.toString());
result = new String(target) + new String(targetPlus);
}
else
{
logger.debug("unknow case");
result = null;
}
//
return (result);
}
/**
*
*/
static public 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);
}
/**
*
*/
static public User getUserFromSession(final HttpServletRequest request)
{
User result;
if (request == null)
{
result = null;
}
else
{
HttpSession session = request.getSession(false);
String login;
if (session == null)
{
result = null;
}
else
{
login = (String) session.getAttribute("login");
result = PageManager.instance().securityAgent().users().getByLogin(login);
}
}
//
return (result);
}
/**
*
*/
public static PageManager instance()
{
return instance;
}
}

View file

@ -1,45 +1,107 @@
/** /**
* Copyright (C) 2006-2010, 2013-2014 Christian Pierre MOMON * Copyright (C) 2006-2024 Christian Pierre MOMON
* *
* This file is part of Devinsy-utils. * This file is part of Kiss4web.
* *
* Kiss4web is free software: you can redistribute it and/or modify * Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * 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 * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Kiss4web is distributed in the hope that it will be useful, * Kiss4web is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/> * along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/ */
package fr.devinsy.kiss4web; package fr.devinsy.kiss4web;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import jakarta.servlet.http.HttpServletResponse;
/** /**
* * The Class Redirector.
*/ */
public class Redirector public class Redirector
{ {
static private final Logger logger = LoggerFactory.getLogger(Redirector.class); private static final Logger logger = LoggerFactory.getLogger(Redirector.class);
public enum Type
{
MOVED_PERMANENTLY(HttpServletResponse.SC_MOVED_PERMANENTLY),
MOVED_TEMPORARILY(HttpServletResponse.SC_MOVED_TEMPORARILY);
private int statusCode;
private Type(final int value)
{
this.statusCode = value;
}
/** /**
* Status code.
* *
* @return the int
*/ */
static public void redirect(final HttpServletResponse response, final String destination) public int statusCode()
{
int result;
result = this.statusCode;
//
return result;
}
}
/**
* Redirect.
*
* @param response
* the response
* @param destination
* the destination
*/
public static void redirect(final HttpServletResponse response, final String 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)
{ {
logger.info("Redirect to <" + destination + ">"); logger.info("Redirect to <" + destination + ">");
response.setHeader("Location", destination); if ((response == null) || (type == null))
response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); {
throw new IllegalArgumentException("Null parameter.");
}
else
{
String target;
if (destination == null)
{
target = "/";
}
else
{
target = destination;
}
response.setHeader("Location", target);
response.setStatus(type.statusCode());
}
} }
} }
// ////////////////////////////////////////////////////////////////////////

View file

@ -1,89 +0,0 @@
/**
* Copyright (C) 2006-2010, 2013-2014 Christian Pierre MOMON
*
* This file is part of Devinsy-utils.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
*/
public class ServletDispatcher extends SimpleServletDispatcher
{
private static final long serialVersionUID = -3471226305721330069L;
static private Logger logger;
// protected Servlets servlets;
/**
*
*/
@Override
public void doIt(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
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() + "]");
String className = pathInfoToClassName(request.getPathInfo());
logger.info("className=" + className);
HttpServlet servlet = instanciateServlet(className);
if (servlet == null)
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html><head></head><body>");
out.println("Unknow page.");
out.println("</body></html>");
out.close();
}
else
{
servlet.service(request, response);
}
}
/**
*
*/
@Override
public void init() throws ServletException
{
super.init();
logger = LoggerFactory.getLogger(this.getClass());
// this.servlets = new Servlets();
}
}

View file

@ -1,67 +0,0 @@
/**
* Copyright (C) 2006-2010, 2013-2014 Christian Pierre MOMON
*
* This file is part of Devinsy-utils.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/
package fr.devinsy.kiss4web;
import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
import fr.devinsy.util.StringList;
/**
*
*/
public class ServletTools
{
/**
*
* @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

@ -1,50 +1,56 @@
/** /**
* Copyright (C) 2006-2010, 2013-2014 Christian Pierre MOMON * Copyright (C) 2006-2023 Christian Pierre MOMON
* *
* This file is part of Devinsy-utils. * This file is part of Kiss4web.
* *
* Kiss4web is free software: you can redistribute it and/or modify * Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * 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 * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Kiss4web is distributed in the hope that it will be useful, * Kiss4web is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Kiss4web. If not, see <http://www.gnu.org/licenses/> * along with Kiss4web. If not, see <http://www.gnu.org/licenses/>
*/ */
package fr.devinsy.kiss4web; package fr.devinsy.kiss4web;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import fr.devinsy.util.StringList; import fr.devinsy.strings.StringList;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
/** /**
* * The Class SimpleSecurityAgent.
*/ */
public class SimpleSecurityAgent public class SimpleSecurityAgent
{ {
static private final Logger logger = LoggerFactory.getLogger(SimpleSecurityAgent.class); private static final Logger logger = LoggerFactory.getLogger(SimpleSecurityAgent.class);
public static final String USERID_LABEL = "securityAgent.userId"; public static final String USERID_LABEL = "securityAgent.userId";
public static final String ACCOUNTID_LABEL = "securityAgent.accountId"; public static final String ACCOUNTID_LABEL = "securityAgent.accountId";
public static final String AUTH_LABEL = "securityAgent.auth"; public static final String AUTH_LABEL = "securityAgent.auth";
private static final int DEFAULT_AUTHENTICATION_DURATION = 60 * 60;
private String userIdLabel; private String userIdLabel;
private String accountIdLabel; private String accountIdLabel;
private String authLabel; private String authLabel;
private String secretKey; private String secretKey;
private static final int DEFAULT_AUTHENTICATION_DURATION = 60 * 60;
private int authenticationDuration; 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) public SimpleSecurityAgent(final String prefix, final String secretKey)
{ {
@ -56,7 +62,11 @@ public class SimpleSecurityAgent
} }
/** /**
* Account id.
* *
* @param request
* the request
* @return the string
*/ */
public String accountId(final HttpServletRequest request) public String accountId(final HttpServletRequest request)
{ {
@ -65,11 +75,15 @@ public class SimpleSecurityAgent
result = (String) CookieHelper.getCookieValue(request, this.accountIdLabel); result = (String) CookieHelper.getCookieValue(request, this.accountIdLabel);
// //
return (result); return result;
} }
/** /**
* Auth.
* *
* @param request
* the request
* @return the string
*/ */
public String auth(final HttpServletRequest request) public String auth(final HttpServletRequest request)
{ {
@ -78,11 +92,15 @@ public class SimpleSecurityAgent
result = (String) CookieHelper.getCookieValue(request, this.authLabel); result = (String) CookieHelper.getCookieValue(request, this.authLabel);
// //
return (result); return result;
} }
/** /**
* This method builds a key from keys and a secret key. * This method builds a key from keys and a secret key.
*
* @param keys
* the keys
* @return the string
*/ */
public String computeAuth(final String... keys) public String computeAuth(final String... keys)
{ {
@ -107,20 +125,52 @@ public class SimpleSecurityAgent
} }
// //
return (result); return result;
} }
/** /**
* Digest with secret.
* *
* @return * @param source
* the source
* @return the string
*/
public String digestWithSecret(final String source)
{
String result;
if (source == null)
{
result = null;
}
else
{
String key = source + this.secretKey;
result = digest(key);
}
//
return result;
}
/**
* Gets the authentication duration.
*
* @return the authentication duration
*/ */
public int getAuthenticationDuration() public int getAuthenticationDuration()
{ {
return authenticationDuration; return this.authenticationDuration;
} }
/** /**
* Check authentication and refresh it (reset countdown). * 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) public boolean isAuthenticated(final HttpServletRequest request, final HttpServletResponse response)
{ {
@ -147,35 +197,17 @@ public class SimpleSecurityAgent
result = false; result = false;
} }
//
return (result);
}
/**
*
* @param source
* @return
*/
public String md5sumWithSecret(final String source)
{
String result;
if (source == null)
{
result = null;
}
else
{
String key = source + this.secretKey;
result = digest(key);
}
// //
return result; return result;
} }
/** /**
* Reset.
* *
* @param request
* the request
* @param response
* the response
*/ */
public void reset(final HttpServletRequest request, final HttpServletResponse response) public void reset(final HttpServletRequest request, final HttpServletResponse response)
{ {
@ -185,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) public void setAuthenticated(final HttpServletRequest request, final HttpServletResponse response, final String accountId, final String userId)
{ {
@ -200,8 +241,10 @@ public class SimpleSecurityAgent
} }
/** /**
* Sets the authentication duration.
* *
* @param duration * @param duration
* the new authentication duration
*/ */
public void setAuthenticationDuration(final int duration) public void setAuthenticationDuration(final int duration)
{ {
@ -209,7 +252,11 @@ public class SimpleSecurityAgent
} }
/** /**
* User id.
* *
* @param request
* the request
* @return the string
*/ */
public String userId(final HttpServletRequest request) public String userId(final HttpServletRequest request)
{ {
@ -218,13 +265,17 @@ public class SimpleSecurityAgent
result = (String) CookieHelper.getCookieValue(request, this.userIdLabel); result = (String) CookieHelper.getCookieValue(request, this.userIdLabel);
// //
return (result); return result;
} }
/** /**
* Digest.
* *
* @param keys
* the keys
* @return the string
*/ */
static public String digest(final String... keys) public static String digest(final String... keys)
{ {
String result; String result;
@ -246,6 +297,6 @@ public class SimpleSecurityAgent
} }
// //
return (result); return result;
} }
} }

View file

@ -1,867 +0,0 @@
/**
* Copyright (C) 2006-2010, 2013-2014 Christian Pierre MOMON
*
* This file is part of Devinsy-utils.
*
* Kiss4web is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.regex.Matcher;
import java.util.regex.Pattern;
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.util.StringList;
/**
* Rename KissDispatcher?
*/
public class SimpleServletDispatcher extends HttpServlet
{
public enum ContentDispositionType
{
ATTACHMENT, INLINE
}
private static final long serialVersionUID = -3471226305721330069L;
static private Logger logger = LoggerFactory.getLogger(SimpleServletDispatcher.class);
static final private Pattern SHORT_REWRITED_URL_CLASS = Pattern.compile("^([^-]+)-.+\\.xhtml$");
static final private Pattern SHORT_REWRITED_URL_PARAMETERS = Pattern.compile("^[^-]+-(.+)\\.xhtml$");
static final private Pattern LONG_REWRITED_URL_CLASS = Pattern.compile("^([^-]+)-/.*$");
// static final protected Pattern LONG_REWRITED_URL_PARAMETERS =
// Pattern.compile("^.+-/(.)+*$");
static final private Pattern REWRITE_PARAMETER = Pattern.compile("[^%\\w\\d]");
static final public int CACHE_AGE = 2 * 60 * 60;
private String webclassesRootPath;
/*
* "Code can be shortest, speedest and memory smallest, but not the three in same time, only two", unknow citation.
*
* Note: characters array avalaible here
* http://fr.wikipedia.org/wiki/Table_des_caract%C3%A8res_Unicode_%280000-0FFF%29
*/
static protected char NONE = (char) 0;
static protected 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' };
/**
*
*
*/
public void dispatch(final HttpServletRequest request, final HttpServletResponse response, final String webClassesRootPath) throws IOException, ServletException
{
long startTime = new Date().getTime();
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 path = request.getRequestURI();
String path = request.getPathInfo();
if (path == null)
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html><head></head><body>");
out.println("Unknow path.");
out.println("</body></html>");
out.close();
}
else if ((!path.endsWith("/")) && (!path.endsWith(".xhtml")) && (!path.contains("-/")))
{
// path = getServletContext().getRealPath("/") +
// request.getRequestURI();
// First, search file in the WebContent root.
path = getServletContext().getRealPath("/") + request.getPathInfo();
logger.debug("path1=" + path);
if (!new File(path).exists())
{
// If file is not in WebContent root, search it in packaged
// classes.
path = getServletContext().getRealPath("/") + "WEB-INF/classes/" + webClassesRootPath.replaceAll("\\.", "/") + request.getPathInfo();
}
logger.debug("path2=" + path);
returnInlineFile(response, new File(path), getServletContext().getMimeType(path));
logger.info("File returned directly [" + path + "] with mimetype [" + getServletContext().getMimeType(path) + "].");
}
else
{
String className = pathInfoToClassName(path, webClassesRootPath);
logger.info("className=[" + className + "]");
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("Unknow page.");
out.println("</body></html>");
out.close();
}
else if (isAuthorized(request, response))
{
servlet.init(this.getServletConfig());
servlet.service(request, response);
}
else
{
/*
* TODO
*
* response.setContentType ("text/html"); PrintWriter
* out = response.getWriter();
*
* out.println ("<html><head></head><body>"); out.println
* ("Not authorized page."); out.println ("</body></html>");
*/
}
}
//
long endTime = new Date().getTime();
logger.debug("TIME: {}ms {}", endTime - startTime, request.getPathInfo());
}
/**
*
*/
@Override
public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
dispatch(request, response, this.webclassesRootPath);
}
/**
* Backward compatibility.
*/
public void doIt(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
dispatch(request, response, this.webclassesRootPath);
}
/**
*
*/
@Override
public void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
{
dispatch(request, response, this.webclassesRootPath);
}
/**
*
*/
@Override
public void init() throws ServletException
{
super.init();
this.webclassesRootPath = getInitParameter("webClassesRootPath");
// Set logger.
String logFilepathname = getInitParameter("log4j-init-file");
if (logFilepathname != null)
{
try
{
System.out.println("Log configuration found (" + 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.");
}
}
/**
*
*/
public boolean isAuthorized(final HttpServletRequest request, final HttpServletResponse response)
{
boolean result;
result = true;
//
return (result);
}
/**
*
*/
static public 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("Unknow page: (" + className + ")");
}
else
{
try
{
result = servletClass.newInstance();
}
catch (java.lang.InstantiationException exception)
{
logger.error("Can't instanciate servlet (" + className + ")");
result = null;
}
catch (java.lang.IllegalAccessException exception)
{
logger.error("(2) Can't instanciate servlet (" + className + ")");
result = null;
}
}
//
return (result);
}
/**
* Extract values from a path.
*
* Example:
*
* <pre>
* "/article-/123/doors/open.xhtml";
* => "123", "doors" and "open".
* </pre>
*/
static public String[] longRewritedUrlParameters(final String path)
{
String[] result;
result = path.substring(path.indexOf("-/") + 2).split("/");
//
return (result);
}
/**
* Convert a path in a class name, using easy 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>
*
*/
static public 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
{
String[] tokens = pathInfo.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];
if (pathInfo.endsWith("/"))
{
name.append(lastToken).append(".").append(lastToken.substring(0, 1).toUpperCase()).append(lastToken.substring(1)).append("_xhtml");
}
else
{
Matcher matcher = SHORT_REWRITED_URL_CLASS.matcher(lastToken);
if (matcher.matches())
{
// Short rewrited URL case.
// logger.debug("group 1=[" + matcher.group(1) +
// "]");
lastToken = matcher.group(1) + ".xhtml";
}
name.append(lastToken.substring(0, 1).toUpperCase()).append(lastToken.substring(1).replace('.', '_'));
}
result = name.toString();
logger.debug("==>[" + tokens[tokens.length - 1] + "]");
}
}
}
logger.info("[" + pathInfo + "] => [" + result + "]");
//
return (result);
}
/**
*
*/
static public 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);
}
/**
*
*/
static public void returnAttachmentFile(final HttpServletResponse response, final File file, final String mimeType) throws IOException
{
returnFile(response, file, mimeType, ContentDispositionType.ATTACHMENT);
}
/**
*
*/
static public 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() + CACHE_AGE * 1000);
response.setHeader("Cache-Control", "max-age=" + 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();
}
}
}
}
/**
*
*/
static public 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();
}
}
}
/**
*
*/
static public void returnInlineFile(final HttpServletResponse response, final File file, final String mimeType) throws IOException
{
returnFile(response, file, mimeType, ContentDispositionType.INLINE);
}
/**
*
*/
static public String[] rewritedUrlParameters(final HttpServletRequest request)
{
String[] result;
result = longRewritedUrlParameters(request.getRequestURI());
//
return (result);
}
/**
* This method gives a way for a long rewriting URL format. Long as in REST.
*
* Sometimes, URL has to be rewrited because we need to put parameter in the
* page name.
*
* Example:
*
* <pre>
* "/good/give_file?id=123&filename=foo.jpg"
* => rewriteShorturl("/good/give_file", "123", "foo.jpg");
* => "/good/give_file-/123/foo.jpg"
* </pre>
*
* Note: "-/" is used to indicate the start of parameters.
*
*/
static public String rewriteLongUrl(final String uri, final String... parameters)
{
String result;
StringList string = new StringList();
string.append(uri).append("-");
if ((parameters == null) || (parameters.length == 0))
{
string.append("/");
}
else
{
for (String parameter : parameters)
{
string.append("/").append(parameter);
}
}
result = string.toString();
//
return (result);
}
/**
*
*
* @param parameter
* @return
*/
static String rewriteParameter(final String parameter)
{
String result;
StringBuffer buffer = new StringBuffer(parameter.length());
char previousCar = NONE;
for (int charIndex = 0; charIndex < parameter.length(); charIndex++)
{
// logger.info("" + charIndex + " " + parameter.charAt(charIndex) +
// " " + (char) tab[parameter.charAt(charIndex)]);
char sourceCar = parameter.charAt(charIndex);
char targetCar;
if (sourceCar > 255)
{
targetCar = '-';
}
else
{
targetCar = (char) rewritingParameterMapping[sourceCar];
}
if (targetCar != NONE)
{
if ((targetCar != '-') || ((targetCar == '-') && (previousCar != '-')))
{
buffer.append(targetCar);
previousCar = targetCar;
}
}
}
if (buffer.charAt(buffer.length() - 1) == '-')
{
buffer.setLength(buffer.length() - 1);
}
result = buffer.toString();
logger.info("[" + parameter + "] -> [" + result + "]");
//
return (result);
}
/**
* This method gives a way for a short rewriting URL format.
*
* Sometimes, URL has to be rewrited because we need to put parameter in the
* page name.
*
* Example:
*
* <pre>
* "/good/article.xhtm?id=123&class=today&title=story's about me"
* => rewriteShorturl("/good/article", "xhtml", "123", "Story's aboute me");
* => "/good/article-123-today-story-s-about-me.xhtml"
* </pre>
*/
static public String rewriteShortUrl(final String uri, final String extension, final String... parameters)
{
String result;
StringList string = new StringList();
string.append(uri);
for (String parameter : parameters)
{
// Not use of String.replaceAll() method in goal to optimize Pattern
// compile action.
// string.append("-").append(REWRITE_PARAMETER.matcher(parameter.toLowerCase()).replaceAll("-"));
string.append("-").append(rewriteParameter(parameter));
}
if ((extension != null) && (extension.length() != 0))
{
string.append(".").append(extension);
}
result = string.toString();
//
return (result);
}
/**
*
*/
static public String shortRewritedUrlParameter(final HttpServletRequest request)
{
String result;
result = shortRewritedUrlParameter(request.getRequestURI());
//
return (result);
}
/**
* Return value of the first parameter.
*/
static public String shortRewritedUrlParameter(final String path)
{
String result;
String[] results = shortRewritedUrlParameters(path);
if ((results == null) || (results.length == 0))
{
result = null;
}
else
{
result = results[0];
}
//
return (result);
}
/**
*
*/
static public String[] shortRewritedUrlParameters(final HttpServletRequest request)
{
String[] result;
result = shortRewritedUrlParameters(request.getRequestURI());
//
return (result);
}
/**
* Extract value from a path. Example: "/article-123.xhtml" => "123".
*/
static public String[] shortRewritedUrlParameters(final String path)
{
String[] result;
Matcher matcher = SHORT_REWRITED_URL_PARAMETERS.matcher(path);
if (matcher.matches())
{
if (matcher.groupCount() != 1)
{
result = null;
}
else
{
result = matcher.group(1).split("-");
}
}
else
{
result = null;
}
//
return (result);
}
}

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

@ -0,0 +1,79 @@
/*
* 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;
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()
{
super();
}
/**
* {@inheritDoc}
*/
@Override
public String getServletClassName(final ServletConfig config, final HttpServletRequest request)
{
String result;
result = "/fr/devinsy/kiss4web/dispatcher/hooks/BlankServlet";
//
return result;
}
/**
* {@inheritDoc}
*/
@Override
public boolean matches(final ServletContext servletContext, final HttpServletRequest request)
{
boolean result;
String urlPath = request.getPathInfo();
if ((urlPath == null) || (urlPath.length() == 0))
{
result = true;
}
else
{
result = false;
}
//
return result;
}
}

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

@ -0,0 +1,76 @@
/*
* 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;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
/**
* The Class DirectHook.
*/
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();
this.targetClassName = targetClassName;
}
/**
* {@inheritDoc}
*/
@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;
result = true;
//
return result;
}
}

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

@ -0,0 +1,80 @@
/*
* 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;
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()
{
super();
}
/**
* {@inheritDoc}
*/
@Override
public String getServletClassName(final ServletConfig config, final HttpServletRequest request)
{
String result;
result = "website." + KissDispatcherUtils.translateToClassName(request.getPathInfo());
//
return result;
}
/**
* {@inheritDoc}
*/
@Override
public boolean matches(final ServletContext servletContext, final HttpServletRequest request)
{
boolean result;
String urlPath = request.getPathInfo();
if ((urlPath != null) && (urlPath.endsWith("/")))
{
result = true;
}
else
{
result = false;
}
//
return result;
}
}

View file

@ -0,0 +1,51 @@
/*
* 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 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
* the request
* @return the servlet
*/
String getServletClassName(ServletConfig config, HttpServletRequest request);
/**
* Matches.
*
* @param servletContext
* the servlet context
* @param request
* the request
* @return true, if successful
*/
boolean matches(final ServletContext servletContext, final HttpServletRequest request);
}

View file

@ -0,0 +1,33 @@
/*
* 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;
/**
* The Class HookCore.
*/
public abstract class HookCore implements Hook
{
/**
* Instantiates a new hook core.
*/
public HookCore()
{
super();
}
}

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

@ -0,0 +1,82 @@
/*
* 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;
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()
{
super();
}
/**
* {@inheritDoc}
*/
@Override
public String getServletClassName(final ServletConfig config, final HttpServletRequest request)
{
String result;
String urlPath = request.getPathInfo();
result = "website." + KissDispatcherUtils.translateToClassName(LongURLRewriter.unrewrite(urlPath));
//
return result;
}
/**
* {@inheritDoc}
*/
@Override
public boolean matches(final ServletContext servletContext, final HttpServletRequest request)
{
boolean result;
String urlPath = request.getPathInfo();
if (LongURLRewriter.matches(urlPath))
{
urlPath = ShortURLRewriter.unrewrite(urlPath);
result = KissDispatcherUtils.isAvailablePath(urlPath);
}
else
{
result = false;
}
//
return result;
}
}

View file

@ -0,0 +1,178 @@
/**
* 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.util.regex.Matcher;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.strings.StringList;
import jakarta.servlet.http.HttpServletRequest;
/**
* The Class LongURLRewriter.
*/
public class LongURLRewriter
{
private static Logger logger = LoggerFactory.getLogger(LongURLRewriter.class);
private final static Pattern LONG_REWRITED_URL_CLASS = Pattern.compile("^([^-]+)-/.*$");
// static final protected Pattern LONG_REWRITED_URL_PARAMETERS =
// Pattern.compile("^.+-/(.)+*$");
private static final Pattern REWRITE_PARAMETER = Pattern.compile("[^%\\w\\d]");
/**
* Matches.
*
* @param urlPath
* the url path
* @return true, if successful
*/
public static boolean matches(final String urlPath)
{
boolean result;
Matcher matcher = LONG_REWRITED_URL_CLASS.matcher(urlPath);
result = matcher.matches();
//
return result;
}
/**
* This method gives a way for a long rewriting URL format. Long as in REST.
*
* Sometimes, URL has to be rewrited because we need to put parameter in the
* page name.
*
* Example:
*
* <pre>
* "/good/give_file?id=123&filename=foo.jpg"
* => rewriteShorturl("/good/give_file", "123", "foo.jpg");
* => "/good/give_file-/123/foo.jpg"
* </pre>
*
* 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)
{
String result;
StringList string = new StringList();
string.append(path).append("-");
if ((parameters == null) || (parameters.length == 0))
{
string.append("/");
}
else
{
for (String parameter : parameters)
{
string.append("/").append(parameter);
}
}
result = string.toString();
//
return result;
}
/**
* This methods unrewrite a pathinfo.
*
* /catalog/article-/123/2016/12/14/resume.xhtml -> /catalog/article.xhtml
*
* @param source
* an URL path.
* @return the string
*/
public static String unrewrite(final String source)
{
String result;
Matcher matcher = LONG_REWRITED_URL_CLASS.matcher(source);
if (matcher.matches())
{
// Short rewrited URL case.
// logger.debug("group 1=[" + matcher.group(1) +
// "]");
result = matcher.group(1) + ".xhtml";
}
else
{
result = null;
}
//
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.
*
* Example:
*
* <pre>
* "/article-/123/doors/open.xhtml";
* => "123", "doors" and "open".
* </pre>
*
* @param source
* an URL path.
* @return the string[]
*/
public static String[] unrewriteParameters(final String source)
{
String[] result;
result = source.substring(source.indexOf("-/") + 2).split("/");
//
return result;
}
}

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");
}
}

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