Bug 558378: [R-Help] Fix accept header of R help server client request
- Add utils to parse media type headers
- Add check of accept header in API servlet
Change-Id: Ia0377ae82d2085b276be0a9f74a4c90a7bc2af29
diff --git a/rhelp/org.eclipse.statet.rhelp.core-tests/.classpath b/rhelp/org.eclipse.statet.rhelp.core-tests/.classpath
new file mode 100644
index 0000000..78c94b4
--- /dev/null
+++ b/rhelp/org.eclipse.statet.rhelp.core-tests/.classpath
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
+ <attributes>
+ <attribute name="annotationpath" value="/org.eclipse.statet/eea/"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins">
+ <attributes>
+ <attribute name="annotationpath" value="/org.eclipse.statet/eea/"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/rhelp/org.eclipse.statet.rhelp.core-tests/.gitignore b/rhelp/org.eclipse.statet.rhelp.core-tests/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/rhelp/org.eclipse.statet.rhelp.core-tests/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/rhelp/org.eclipse.statet.rhelp.core-tests/.project b/rhelp/org.eclipse.statet.rhelp.core-tests/.project
new file mode 100644
index 0000000..60da93d
--- /dev/null
+++ b/rhelp/org.eclipse.statet.rhelp.core-tests/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.statet.rhelp.core-tests</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/rhelp/org.eclipse.statet.rhelp.core-tests/.settings/org.eclipse.core.resources.prefs b/rhelp/org.eclipse.statet.rhelp.core-tests/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..99f26c0
--- /dev/null
+++ b/rhelp/org.eclipse.statet.rhelp.core-tests/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/rhelp/org.eclipse.statet.rhelp.core-tests/.settings/org.eclipse.core.runtime.prefs b/rhelp/org.eclipse.statet.rhelp.core-tests/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..5a0ad22
--- /dev/null
+++ b/rhelp/org.eclipse.statet.rhelp.core-tests/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/rhelp/org.eclipse.statet.rhelp.core-tests/.settings/org.eclipse.jdt.core.prefs b/rhelp/org.eclipse.statet.rhelp.core-tests/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..ea2d0f5
--- /dev/null
+++ b/rhelp/org.eclipse.statet.rhelp.core-tests/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,383 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
+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_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_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=80
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=16
+org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=32
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain=0
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=49
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=80
+org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_module_statements=80
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16
+org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_relational_operator=0
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=85
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_shift_operator=0
+org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_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_type_arguments=0
+org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=80
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=2
+org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_after_package=-2
+org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=1
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=-2
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=2
+org.eclipse.jdt.core.formatter.blank_lines_before_package=-2
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=-2
+org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch=0
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=2
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=false
+org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+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_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=false
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=false
+org.eclipse.jdt.core.formatter.comment.indent_tag_description=true
+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=do not insert
+org.eclipse.jdt.core.formatter.comment.line_length=100
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=false
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not 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_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=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_else_in_if_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=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_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_not_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=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_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case=insert
+org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=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_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=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_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=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_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_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_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=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_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_code_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_method_body_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_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_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.lineSplit=100
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block=0
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block=0
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=-1
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block=-1
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body=-1
+org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=2
+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_switch_statement=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.text_block_indentation=0
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_additive_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=false
+org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_before_relational_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_shift_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
diff --git a/rhelp/org.eclipse.statet.rhelp.core-tests/.settings/org.eclipse.jdt.ui.prefs b/rhelp/org.eclipse.statet.rhelp.core-tests/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..470b007
--- /dev/null
+++ b/rhelp/org.eclipse.statet.rhelp.core-tests/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,139 @@
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+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=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=true
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=false
+cleanup.organize_imports=true
+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=false
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=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=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=true
+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_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=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_lambda=true
+cleanup.use_parentheses_in_expressions=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=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup.use_type_arguments=false
+cleanup.use_unboxing=false
+cleanup_profile=_StatET
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_StatET
+formatter_settings_version=18
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=\#java;\#;\#org.eclipse.statet.jcommons;\#org.eclipse.statet.ecommons;\#org.eclipse.statet;java;javax;com.ibm.icu;org.osgi;org.eclipse;;org.eclipse.statet.jcommons;org.eclipse.statet.ecommons;org.eclipse.statet;
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.keywordthis=true
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/*\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\#\n \# Copyright (c) ${year} ${user} and others.\n \# \n \# This program and the accompanying materials are made available under the\n \# terms of the Eclipse Public License 2.0 which is available at\n \# https\://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0\n \# which is available at https\://www.apache.org/licenses/LICENSE-2.0.\n \# \n \# SPDX-License-Identifier\: EPL-2.0 OR Apache-2.0\n \# \n \# Contributors\:\n \# ${user} - initial API and implementation\n \#\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=*/</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n * \n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="false" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment"/><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="false" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></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=true
+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_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=false
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=false
+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=false
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_modifiers=false
+sp_cleanup.remove_redundant_semicolons=true
+sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_trailing_whitespaces=false
+sp_cleanup.remove_trailing_whitespaces_all=false
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=true
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=false
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=false
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=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=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+sp_cleanup.use_type_arguments=false
diff --git a/rhelp/org.eclipse.statet.rhelp.core-tests/META-INF/MANIFEST.MF b/rhelp/org.eclipse.statet.rhelp.core-tests/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..095e32f
--- /dev/null
+++ b/rhelp/org.eclipse.statet.rhelp.core-tests/META-INF/MANIFEST.MF
@@ -0,0 +1,12 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.statet.rhelp.core.http.tests
+Bundle-Version: 4.1.0.qualifier
+Bundle-Vendor: Eclipse StatET
+Bundle-Name: StatET R-Help - Core - Tests (Incubation)
+Fragment-Host: org.eclipse.statet.rhelp.core
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Import-Package: javax.servlet;version="3.1.0",
+ javax.servlet.http;version="3.1.0",
+ org.junit.jupiter.api;version="5.5.1",
+ org.junit.jupiter.api.function;version="5.5.1"
diff --git a/rhelp/org.eclipse.statet.rhelp.core-tests/about.html b/rhelp/org.eclipse.statet.rhelp.core-tests/about.html
new file mode 100644
index 0000000..f094738
--- /dev/null
+++ b/rhelp/org.eclipse.statet.rhelp.core-tests/about.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>January 1, 2019</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless
+ otherwise indicated below, the Content is provided to you under the terms and conditions of the
+ Eclipse Public License Version 2.0 ("EPL"), or the Apache License, Version 2.0 (AL).
+ A copy of the EPL is available at <a href="https://www.eclipse.org/legal/epl-2.0"
+ >https://www.eclipse.org/legal/epl-2.0</a>. For purposes of the EPL, "Program" will
+ mean the Content. A copy of the AL is available at <a href="https://www.apache.org/licenses/LICENSE-2.0"
+ >https://www.apache.org/licenses/LICENSE-2.0</a>.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is being
+ redistributed by another party ("Redistributor") and different terms and conditions
+ may apply to your use of any object code in the Content. Check the Redistributor's license that
+ was provided with the Content. If no such license exists, contact the Redistributor. Unless
+ otherwise indicated below, the terms and conditions of the EPL or AL still apply to any source
+ code in the Content and such source code may be obtained at <a href="https://www.eclipse.org/"
+ >https://www.eclipse.org</a>.</p>
+
+</body>
+</html>
diff --git a/rhelp/org.eclipse.statet.rhelp.core-tests/build.properties b/rhelp/org.eclipse.statet.rhelp.core-tests/build.properties
new file mode 100644
index 0000000..239dd55
--- /dev/null
+++ b/rhelp/org.eclipse.statet.rhelp.core-tests/build.properties
@@ -0,0 +1,8 @@
+source..= src/
+output..= target/classes/
+javacDefaultEncoding..= UTF-8
+
+bin.includes= META-INF/,\
+ .,\
+ about.html
+src.includes= .settings/org.eclipse.core.resources.prefs
diff --git a/rhelp/org.eclipse.statet.rhelp.core-tests/src/org/eclipse/statet/internal/rhelp/core/http/HttpHeaderTest.java b/rhelp/org.eclipse.statet.rhelp.core-tests/src/org/eclipse/statet/internal/rhelp/core/http/HttpHeaderTest.java
new file mode 100644
index 0000000..cf4b961
--- /dev/null
+++ b/rhelp/org.eclipse.statet.rhelp.core-tests/src/org/eclipse/statet/internal/rhelp/core/http/HttpHeaderTest.java
@@ -0,0 +1,259 @@
+/*=============================================================================#
+ # Copyright (c) 2019, 2020 Stephan Wahlbrink <sw@wahlbrink.eu> and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.rhelp.core.http;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import org.eclipse.statet.jcommons.collections.BasicImMapEntry;
+import org.eclipse.statet.jcommons.collections.ImCollections;
+import org.eclipse.statet.jcommons.collections.IntArrayList;
+import org.eclipse.statet.jcommons.collections.IntList;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
+import org.eclipse.statet.internal.rhelp.core.http.HttpHeaderUtils.MediaTypeEntry;
+import org.eclipse.statet.internal.rhelp.core.http.HttpHeaderUtils.ParseException;
+
+
+@NonNullByDefault
+public class HttpHeaderTest {
+
+
+ public HttpHeaderTest() {
+ }
+
+
+ @Test
+ public void parseMediaTypes_empty() throws ParseException {
+ List<MediaTypeEntry> entries;
+
+ entries= parseMediaTypes("");
+ assertEquals(0, entries.size());
+
+ entries= parseMediaTypes(" ");
+ assertEquals(0, entries.size());
+ }
+
+ @Test
+ public void parseMediaTypes_simple() throws ParseException {
+ List<MediaTypeEntry> entries;
+
+ entries= parseMediaTypes("text/plain, text/html, text/x-dvi, */*");
+ assertMediaTypesEquals(ImCollections.newList(
+ new MediaTypeEntry("text", "plain", 1f, ImCollections.emptyList()),
+ new MediaTypeEntry("text", "html", 1f, ImCollections.emptyList()),
+ new MediaTypeEntry("text", "x-dvi", 1f, ImCollections.emptyList()),
+ new MediaTypeEntry("*", "*", 1f, ImCollections.emptyList())
+ ), entries );
+ }
+
+ @Test
+ public void parseMediaTypes_withQualityFactor() throws ParseException {
+ List<MediaTypeEntry> entries;
+
+ entries= parseMediaTypes("text/plain;q=0.1");
+ assertMediaTypesEquals(ImCollections.newList(
+ new MediaTypeEntry("text", "plain", 0.1f, ImCollections.emptyList())
+ ), entries );
+
+ entries= parseMediaTypes("text/plain; q=0.25");
+ assertMediaTypesEquals(ImCollections.newList(
+ new MediaTypeEntry("text", "plain", 0.25f, ImCollections.emptyList())
+ ), entries );
+
+ entries= parseMediaTypes("text/plain; q=1 ");
+ assertMediaTypesEquals(ImCollections.newList(
+ new MediaTypeEntry("text", "plain", 1f, ImCollections.emptyList())
+ ), entries );
+ }
+
+ @Test
+ public void parseMediaTypes_withQualityFactor_invalid() throws ParseException {
+ Assertions.assertThrows(ParseException.class,
+ () -> parseMediaTypes("text/plain;q") );
+
+ Assertions.assertThrows(ParseException.class,
+ () -> parseMediaTypes("text/plain;q=") );
+
+ Assertions.assertThrows(ParseException.class,
+ () -> parseMediaTypes("text/plain;q=text") );
+ }
+
+ @Test
+ public void parseMediaTypes_withParameter() throws ParseException {
+ List<MediaTypeEntry> entries;
+
+ entries= parseMediaTypes("text/html;level=1");
+ assertMediaTypesEquals(ImCollections.newList(
+ new MediaTypeEntry("text", "html", 1f, ImCollections.newList(
+ new BasicImMapEntry<>("level", "1") ))
+ ), entries );
+
+ entries= parseMediaTypes("application/x.org.eclipse.statet.rhelp-ds; ser=12");
+ assertMediaTypesEquals(ImCollections.newList(
+ new MediaTypeEntry("application", "x.org.eclipse.statet.rhelp-ds", 1f, ImCollections.newList(
+ new BasicImMapEntry<>("ser", "12") ))
+ ), entries );
+
+ entries= parseMediaTypes(" text/html; level=1 ; ext= test ");
+ assertMediaTypesEquals(ImCollections.newList(
+ new MediaTypeEntry("text", "html", 1f, ImCollections.newList(
+ new BasicImMapEntry<>("level", "1"),
+ new BasicImMapEntry<>("ext", "test") ))
+ ), entries );
+ }
+
+ @Test
+ public void parseMediaTypes_precedence_bySpecific() throws ParseException {
+ List<MediaTypeEntry> entries;
+
+ entries= parseMediaTypes("text/*, text/html, text/html;level=1, */*");
+ entries.sort(null);
+ assertMediaTypesEquals(ImCollections.newList(
+ new MediaTypeEntry("text", "html", 1f, ImCollections.newList(
+ new BasicImMapEntry<>("level", "1"))),
+ new MediaTypeEntry("text", "html", 1f, ImCollections.emptyList()),
+ new MediaTypeEntry("text", "*", 1f, ImCollections.emptyList()),
+ new MediaTypeEntry("*", "*", 1f, ImCollections.emptyList())
+ ), entries );
+ }
+
+ @Test
+ public void parseMediaTypes_precedence_byQualityFactor() throws ParseException {
+ List<MediaTypeEntry> entries;
+
+ entries= parseMediaTypes("text/plain;q=0.1, text/html, text/x-dvi;q=0.5");
+ entries.sort(null);
+ assertMediaTypesEquals(ImCollections.newList(
+ new MediaTypeEntry("text", "html", 1f, ImCollections.emptyList()),
+ new MediaTypeEntry("text", "x-dvi", 0.5f, ImCollections.emptyList()),
+ new MediaTypeEntry("text", "plain", 0.1f, ImCollections.emptyList())
+ ), entries );
+ }
+
+ private List<MediaTypeEntry> parseMediaTypes(final String... headers) throws ParseException {
+ final List<MediaTypeEntry> entries= new ArrayList<>();
+ HttpHeaderUtils.parseMediaTypes(Collections.enumeration(Arrays.asList(headers)),
+ null, entries );
+ return entries;
+ }
+
+ private void assertMediaTypesEquals(final List<MediaTypeEntry> expected, final List<MediaTypeEntry> entries) {
+ assertEquals(expected.size(), entries.size(), "count");
+ for (int i= 0; i < expected.size(); i++) {
+ final int i0= i;
+ assertEquals(expected.get(i), entries.get(i),
+ () -> String.format("media types differ at [%1$s] in basic properties", i0) );
+ assertEquals(expected.get(i).getQualityFactor(), entries.get(i).getQualityFactor(), 0f,
+ () -> String.format("media types differ at [%1$s] in qualityFactor ", i0) );
+ }
+ }
+
+
+ @Test
+ public void findFirstValid() {
+ List<MediaTypeEntry> entries;
+ int version;
+
+ entries= ImCollections.newList(
+ new MediaTypeEntry("application", "x.org.eclipse.statet.test", 0.5f, ImCollections.newList(
+ new BasicImMapEntry<>("ver", "3") )),
+ new MediaTypeEntry("application", "x.org.eclipse.statet.test", 0.2f, ImCollections.newList(
+ new BasicImMapEntry<>("ver", "2") )),
+ new MediaTypeEntry("application", "x.org.eclipse.statet.test", 0.1f, ImCollections.newList(
+ new BasicImMapEntry<>("ver", "1") )) );
+ version= HttpHeaderUtils.findFirstValid(entries, "ver", (final int v) -> (v == 1));
+ assertEquals(1, version);
+
+ entries= ImCollections.newList(
+ new MediaTypeEntry("application", "x.org.eclipse.statet.test", 0.5f, ImCollections.newList(
+ new BasicImMapEntry<>("ver", "3") )),
+ new MediaTypeEntry("application", "x.org.eclipse.statet.test", 0.2f, ImCollections.newList(
+ new BasicImMapEntry<>("ver", "2") )),
+ new MediaTypeEntry("application", "x.org.eclipse.statet.test", 0.1f, ImCollections.newList(
+ new BasicImMapEntry<>("ver", "1") )) );
+ version= HttpHeaderUtils.findFirstValid(entries, "ver", (final int v) -> (v == 3));
+ assertEquals(3, version);
+
+ final IntList supportedVersions= new IntArrayList();
+ supportedVersions.add(4);
+ supportedVersions.add(2);
+ entries= ImCollections.newList(
+ new MediaTypeEntry("application", "x.org.eclipse.statet.test", 0.5f, ImCollections.newList(
+ new BasicImMapEntry<>("ver", "3") )),
+ new MediaTypeEntry("application", "x.org.eclipse.statet.test", 0.2f, ImCollections.newList(
+ new BasicImMapEntry<>("ver", "2") )),
+ new MediaTypeEntry("application", "x.org.eclipse.statet.test", 0.1f, ImCollections.newList(
+ new BasicImMapEntry<>("ver", "1") )) );
+ version= HttpHeaderUtils.findFirstValid(entries, "ver", (final int v) -> supportedVersions.contains(v));
+ assertEquals(2, version);
+ }
+
+ @Test
+ public void findFirstValid_withMissingSpec() {
+ List<MediaTypeEntry> entries;
+ int version;
+
+ entries= ImCollections.newList(
+ new MediaTypeEntry("application", "x.org.eclipse.statet.test", 0.5f, ImCollections.newList()),
+ new MediaTypeEntry("application", "x.org.eclipse.statet.test", 0.2f, ImCollections.newList(
+ new BasicImMapEntry<>("ver", "2") )),
+ new MediaTypeEntry("application", "x.org.eclipse.statet.test", 0.1f, ImCollections.newList(
+ new BasicImMapEntry<>("ver", "1") )) );
+ version= HttpHeaderUtils.findFirstValid(entries, "ver", (final int v) -> (v == 1));
+ assertEquals(1, version);
+ }
+
+ @Test
+ public void findFirstValid_withInvalidSpec() {
+ List<MediaTypeEntry> entries;
+ int version;
+
+ entries= ImCollections.newList(
+ new MediaTypeEntry("application", "x.org.eclipse.statet.test", 0.5f, ImCollections.newList(
+ new BasicImMapEntry<>("ver", "") )),
+ new MediaTypeEntry("application", "x.org.eclipse.statet.test", 0.2f, ImCollections.newList(
+ new BasicImMapEntry<>("ver", "x") )),
+ new MediaTypeEntry("application", "x.org.eclipse.statet.test", 0.1f, ImCollections.newList(
+ new BasicImMapEntry<>("ver", "1") )) );
+ version= HttpHeaderUtils.findFirstValid(entries, "ver", (final int v) -> (v == 1));
+ assertEquals(1, version);
+ }
+
+ @Test
+ public void findFirstValid_noValid() {
+ List<MediaTypeEntry> entries;
+ int version;
+
+ entries= ImCollections.newList(
+ new MediaTypeEntry("application", "x.org.eclipse.statet.test", 0.5f, ImCollections.newList(
+ new BasicImMapEntry<>("ver", "3") )),
+ new MediaTypeEntry("application", "x.org.eclipse.statet.test", 0.2f, ImCollections.newList(
+ new BasicImMapEntry<>("ver", "2") )),
+ new MediaTypeEntry("application", "x.org.eclipse.statet.test", 0.1f, ImCollections.newList(
+ new BasicImMapEntry<>("ver", "1") )) );
+ version= HttpHeaderUtils.findFirstValid(entries, "ver", (final int v) -> (v == 4));
+ assertEquals(-1, version);
+ }
+
+
+}
diff --git a/rhelp/org.eclipse.statet.rhelp.core-tests/src/org/eclipse/statet/internal/rhelp/core/server/ServerREnvHelpAccessTest.java b/rhelp/org.eclipse.statet.rhelp.core-tests/src/org/eclipse/statet/internal/rhelp/core/server/ServerREnvHelpAccessTest.java
new file mode 100644
index 0000000..4097894
--- /dev/null
+++ b/rhelp/org.eclipse.statet.rhelp.core-tests/src/org/eclipse/statet/internal/rhelp/core/server/ServerREnvHelpAccessTest.java
@@ -0,0 +1,67 @@
+/*=============================================================================#
+ # Copyright (c) 2019, 2020 Stephan Wahlbrink <sw@wahlbrink.eu> and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.rhelp.core.server;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
+import org.eclipse.statet.internal.rhelp.core.http.HttpHeaderUtils;
+import org.eclipse.statet.internal.rhelp.core.http.HttpHeaderUtils.MediaTypeEntry;
+import org.eclipse.statet.internal.rhelp.core.http.HttpHeaderUtils.ParseException;
+
+
+@NonNullByDefault
+public class ServerREnvHelpAccessTest {
+
+
+ public static String getVersionedDS_AccessHeader() {
+ return ServerREnvHelpAccess.DS_VERSIONED_ACCEPT_HEADER;
+ }
+
+ public static String getModestDS_AccessHeader() {
+ return ServerREnvHelpAccess.DS_MODEST_ACCEPT_HEADER;
+ }
+
+
+ @Test
+ public void DS_VERSIONED_AcceptHeader_valid() throws ParseException {
+ final List<MediaTypeEntry> entries= HttpHeaderUtils.readMediaTypeEntries(Arrays.asList(getVersionedDS_AccessHeader()), null);
+
+ for (final MediaTypeEntry entry : entries) {
+ assertEquals(ServerApi.APPLICATION_MEDIA_TYPE, entry.getType());
+ assertEquals(ServerApi.DS_MEDIA_SUBTYPE, entry.getSubtype());
+ assertNotNull(entry.getParameterValue(ServerApi.DS_SER_VERSION));
+ }
+ }
+
+ @Test
+ public void DS_MODEST_AcceptHeader_valid() throws ParseException {
+ final List<MediaTypeEntry> entries= HttpHeaderUtils.readMediaTypeEntries(Arrays.asList(getModestDS_AccessHeader()), null);
+
+ for (final MediaTypeEntry entry : entries) {
+ assertEquals(ServerApi.APPLICATION_MEDIA_TYPE, entry.getType());
+ assertEquals(ServerApi.DS_MEDIA_SUBTYPE, entry.getSubtype());
+ }
+ }
+
+
+}
diff --git a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/FIO.java b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/DataStream.java
similarity index 93%
rename from rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/FIO.java
rename to rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/DataStream.java
index 5277b77..f57eecb 100644
--- a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/FIO.java
+++ b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/DataStream.java
@@ -32,28 +32,31 @@
import org.eclipse.statet.jcommons.lang.Nullable;
+/**
+ * IO data stream for R help data.
+ */
@NonNullByDefault
-public final class FIO implements AutoCloseable {
+public final class DataStream implements AutoCloseable {
- private static final ThreadLocal<FIO> INSTANCES= new ThreadLocal<FIO>() {
+ private static final ThreadLocal<DataStream> INSTANCES= new ThreadLocal<DataStream>() {
@Override
- protected FIO initialValue() {
- return new FIO();
+ protected DataStream initialValue() {
+ return new DataStream();
}
};
- public static FIO get(final OutputStream out) {
- final FIO io= INSTANCES.get();
+ public static DataStream get(final OutputStream out) {
+ final DataStream io= INSTANCES.get();
io.flags= OUT;
io.out.init(out);
return io;
}
- public static FIO get(final InputStream in) {
- final FIO io= INSTANCES.get();
+ public static DataStream get(final InputStream in) {
+ final DataStream io= INSTANCES.get();
io.flags= IN;
io.in.init(in);
return io;
@@ -123,7 +126,7 @@
}
public void enableCompression() {
- FIO.this.flags |= COMPRESS;
+ DataStream.this.flags |= COMPRESS;
this.out= new DeflaterOutputStream(this.out, this.deflater, 4096);
}
@@ -132,7 +135,7 @@
if (this.out != null) {
super.close();
this.out= null;
- if ((FIO.this.flags & COMPRESS) != 0) {
+ if ((DataStream.this.flags & COMPRESS) != 0) {
this.deflater.reset();
}
}
@@ -157,7 +160,7 @@
}
public void enableCompression() {
- FIO.this.flags |= COMPRESS;
+ DataStream.this.flags |= COMPRESS;
this.in= new InflaterInputStream(this.in, this.inflater, 4096);
}
@@ -166,7 +169,7 @@
if (this.in != null) {
super.close();
this.in= null;
- if ((FIO.this.flags & COMPRESS) != 0) {
+ if ((DataStream.this.flags & COMPRESS) != 0) {
this.inflater.reset();
}
}
@@ -186,8 +189,10 @@
private int flags;
+ private int version;
- public FIO() {
+
+ public DataStream() {
this.bb= ByteBuffer.allocateDirect(BB_LENGTH);
if (this.bb.hasArray()) {
this.mode= MODE_BBARRAY;
@@ -214,6 +219,7 @@
this.out.close();
}
this.flags= 0;
+ this.version= 0;
}
public void enableCompression() {
@@ -228,6 +234,19 @@
}
+ public void writeVersion(final int version) throws IOException {
+ writeInt((this.version= version));
+ }
+
+ public int readVersion() throws IOException {
+ return (this.version= readInt());
+ }
+
+ public int getVersion() {
+ return this.version;
+ }
+
+
private void writeFullyBB(final int bn) throws IOException {
switch (this.mode) {
case MODE_BBARRAY:
diff --git a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/SerUtil.java b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/SerUtil.java
index b26af2a..bfeb262 100644
--- a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/SerUtil.java
+++ b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/SerUtil.java
@@ -51,11 +51,13 @@
public class SerUtil {
- private static final int VERSION_11= 11;
- private static final int VERSION_10= 10;
- private static final int VERSION= VERSION_11;
+ public static final int VERSION_11= 11;
+ public static final int VERSION_10= 10;
+ public static final int CURRENT_VERSION= VERSION_11;
- public static final String READABLE_SERVER= "" + VERSION_11 + ',' + VERSION_10; //$NON-NLS-1$
+ public static final int[] READABLE_VERSIONS= {
+ VERSION_11,
+ VERSION_10 };
private static final int COMPRESS= 1 << 4;
@@ -150,10 +152,10 @@
final Path newFile= directory.resolve(RHELP_SER_FILE + ".new"); //$NON-NLS-1$
Files.deleteIfExists(newFile);
- try (final FIO fio= FIO.get(new BufferedOutputStream(
+ try (final DataStream out= DataStream.get(new BufferedOutputStream(
Files.newOutputStream(newFile, StandardOpenOption.CREATE_NEW) ))) {
- save(help, fio, COMPRESS);
- fio.flush();
+ save(help, out, COMPRESS);
+ out.flush();
}
synchronized (controller.getFileLock()) {
@@ -184,7 +186,7 @@
try (final OutputStream out= new BufferedOutputStream(
Files.newOutputStream(newFile, StandardOpenOption.CREATE_NEW) )) {
- FIO.copy(in, out);
+ DataStream.copy(in, out);
}
synchronized (controller.getFileLock()) {
@@ -213,13 +215,13 @@
return REnvHelpImpl.NOT_AVAILABLE_STAMP;
}
- try (final FIO fio= FIO.get(new BufferedInputStream(
+ try (final DataStream in= DataStream.get(new BufferedInputStream(
Files.newInputStream(serFile), 64 ))) {
- final int version= fio.readInt();
- if (version != VERSION && !canRead(version, rEnvConfig)) {
+ final int version= in.readVersion();
+ if (version != CURRENT_VERSION && !canRead(version, rEnvConfig)) {
return REnvHelpImpl.NOT_AVAILABLE_STAMP;
}
- return fio.readLong();
+ return in.readLong();
}
}
catch (final Throwable e) {
@@ -241,9 +243,9 @@
return null;
}
- try (final FIO fio= FIO.get(new BufferedInputStream(
+ try (final DataStream in= DataStream.get(new BufferedInputStream(
Files.newInputStream(serFile) ))) {
- return load(rEnvConfig, fio);
+ return load(rEnvConfig, in);
}
}
catch (final Throwable e) {
@@ -258,94 +260,94 @@
}
}
- public void save(final REnvHelpImpl help, final FIO fio, final int flags)
+ public void save(final REnvHelpImpl help, final DataStream out, final int flags)
throws IOException {
- fio.writeInt(VERSION);
- fio.writeLong(help.getStamp());
+ out.writeVersion(CURRENT_VERSION);
+ out.writeLong(help.getStamp());
- fio.writeInt(flags);
+ out.writeInt(flags);
if ((flags & COMPRESS) != 0) {
- fio.enableCompression();
+ out.enableCompression();
}
- fio.writeString(help.getDocDir());
+ out.writeString(help.getDocDir());
{ final ImList<DocResource> resources= help.getManuals();
final int count= resources.size();
- fio.writeInt(count);
+ out.writeInt(count);
for (int i= 0; i < count; i++) {
- saveDocResource(resources.get(i), fio);
+ saveDocResource(resources.get(i), out);
}
}
{ final ImList<DocResource> resources= help.getMiscResources();
final int count= resources.size();
- fio.writeInt(count);
+ out.writeInt(count);
for (int i= 0; i < count; i++) {
- saveDocResource(resources.get(i), fio);
+ saveDocResource(resources.get(i), out);
}
}
{ final List<RHelpKeywordGroup> keywordGroups= help.getKeywords();
final int count= keywordGroups.size();
- fio.writeInt(count);
+ out.writeInt(count);
for (int i= 0; i < keywordGroups.size(); i++) {
- saveKeywordGroup(keywordGroups.get(i), fio);
+ saveKeywordGroup(keywordGroups.get(i), out);
}
}
{ final List<RPkgHelp> packages= help.getPkgs();
final int count= packages.size();
- fio.writeInt(count);
+ out.writeInt(count);
for (int i= 0; i < packages.size(); i++) {
- savePackage(packages.get(i), fio);
+ savePackage(packages.get(i), out);
}
}
}
- public REnvHelpImpl load(final REnvHelpConfiguration rEnvConfig, final FIO fio)
+ public REnvHelpImpl load(final REnvHelpConfiguration rEnvConfig, final DataStream in)
throws IOException {
- final int version= fio.readInt();
- if (version != VERSION && !canRead(version, rEnvConfig)) {
+ final int version= in.readVersion();
+ if (version != CURRENT_VERSION && !canRead(version, rEnvConfig)) {
throw new UnsupportedVersionException(version);
}
- final long stamp= fio.readLong();
+ final long stamp= in.readLong();
- final int flags= fio.readInt();
+ final int flags= in.readInt();
if ((flags & COMPRESS) != 0) {
- fio.enableCompression();
+ in.enableCompression();
}
- final String docDir= fio.readString();
+ final String docDir= in.readString();
final ImList<DocResource> manuals;
- { final int count= fio.readInt();
+ { final int count= in.readInt();
final DocResource[] array= new org.eclipse.statet.rhelp.core.DocResource[count];
for (int i= 0; i < count; i++) {
- array[i]= readDocResource(fio);
+ array[i]= readDocResource(in);
}
manuals= ImCollections.newList(array);
}
final ImList<DocResource> miscRes;
- { final int count= fio.readInt();
+ { final int count= in.readInt();
final DocResource[] array= new @NonNull DocResource[count];
for (int i= 0; i < count; i++) {
- array[i]= readDocResource(fio);
+ array[i]= readDocResource(in);
}
miscRes= ImCollections.newList(array);
}
final ImList<RHelpKeywordGroup> keywordGroups;
- { final int count= fio.readInt();
+ { final int count= in.readInt();
final RHelpKeywordGroup[] array= new @NonNull RHelpKeywordGroup[count];
for (int i= 0; i < count; i++) {
- array[i]= loadKeywordGroup(fio);
+ array[i]= loadKeywordGroup(in);
}
keywordGroups= ImCollections.newList(array);
}
final ImList<RPkgHelp> pkgHelps;
- { final int count= fio.readInt();
+ { final int count= in.readInt();
final RPkgHelp[] array= new @NonNull RPkgHelp[count];
for (int i= 0; i < count; i++) {
- array[i]= loadPackage(rEnvConfig, fio);
+ array[i]= loadPackage(rEnvConfig, in);
}
pkgHelps= ImCollections.newList(array);
}
@@ -357,117 +359,117 @@
private void saveDocResource(final DocResource res,
- final FIO fio) throws IOException {
- fio.writeString(res.getTitle());
- fio.writeString(res.getPath());
- fio.writeString(res.getPdfPath());
+ final DataStream out) throws IOException {
+ out.writeString(res.getTitle());
+ out.writeString(res.getPath());
+ out.writeString(res.getPdfPath());
}
- private DocResource readDocResource(final FIO fio) throws IOException {
+ private DocResource readDocResource(final DataStream in) throws IOException {
return new DocResource(
- fio.readNonNullString(),
- fio.readNonNullString(),
- fio.readString() );
+ in.readNonNullString(),
+ in.readNonNullString(),
+ in.readString() );
}
private void saveKeywordGroup(final RHelpKeywordGroup group,
- final FIO fio) throws IOException {
- fio.writeString(group.getLabel());
- fio.writeString(group.getDescription());
+ final DataStream out) throws IOException {
+ out.writeString(group.getLabel());
+ out.writeString(group.getDescription());
final List<RHelpKeyword> keywords= group.getNestedKeywords();
final int count= keywords.size();
- fio.writeInt(count);
+ out.writeInt(count);
for (int i= 0; i < count; i++) {
- saveKeyword(keywords.get(i), fio);
+ saveKeyword(keywords.get(i), out);
}
}
- private RHelpKeywordGroup loadKeywordGroup(final FIO fio) throws IOException {
- final String label= fio.readString();
- final String description= fio.readString();
- final int count= fio.readInt();
+ private RHelpKeywordGroup loadKeywordGroup(final DataStream in) throws IOException {
+ final String label= in.readString();
+ final String description= in.readString();
+ final int count= in.readInt();
final RHelpKeyword[] keywords= new @NonNull RHelpKeyword[count];
for (int i= 0; i < count; i++) {
- keywords[i]= loadKeyword(fio);
+ keywords[i]= loadKeyword(in);
}
return new RHelpKeywordGroupImpl(label, description, ImCollections.newList(keywords));
}
- private void saveKeyword(final RHelpKeyword keyword, final FIO fio)
+ private void saveKeyword(final RHelpKeyword keyword, final DataStream out)
throws IOException {
- fio.writeString(keyword.getKeyword());
- fio.writeString(keyword.getDescription());
+ out.writeString(keyword.getKeyword());
+ out.writeString(keyword.getDescription());
final List<RHelpKeyword> nestedKeywords= keyword.getNestedKeywords();
final int count= nestedKeywords.size();
- fio.writeInt(count);
+ out.writeInt(count);
for (int i= 0; i < nestedKeywords.size(); i++) {
- saveKeyword(nestedKeywords.get(i), fio);
+ saveKeyword(nestedKeywords.get(i), out);
}
}
- private RHelpKeyword loadKeyword(final FIO fio)
+ private RHelpKeyword loadKeyword(final DataStream in)
throws IOException {
- final String keyword= fio.readString();
- final String description= fio.readString();
- final int n= fio.readInt();
+ final String keyword= in.readString();
+ final String description= in.readString();
+ final int n= in.readInt();
final RHelpKeyword[] nestedKeywords= new @NonNull RHelpKeyword[n];
for (int i= 0; i < n; i++) {
- nestedKeywords[i]= loadKeyword(fio);
+ nestedKeywords[i]= loadKeyword(in);
}
return new RHelpKeywordImpl(keyword, description, ImCollections.newList(nestedKeywords));
}
- private void savePackage(final RPkgHelp pkgHelp, final FIO fio)
+ private void savePackage(final RPkgHelp pkgHelp, final DataStream out)
throws IOException {
- savePkgDescription(pkgHelp.getPkgDescription(), fio);
+ savePkgDescription(pkgHelp.getPkgDescription(), out);
final List<RHelpPage> pages= pkgHelp.getPages();
final int nPages= pages.size();
- fio.writeInt(nPages);
+ out.writeInt(nPages);
for (int i= 0; i < nPages; i++) {
- savePage(pages.get(i), fio);
+ savePage(pages.get(i), out);
}
}
- private RPkgHelp loadPackage(final REnvHelpConfiguration rEnvConfig, final FIO fio)
+ private RPkgHelp loadPackage(final REnvHelpConfiguration rEnvConfig, final DataStream in)
throws IOException {
- final RPkgDescription pkgDescription= loadPkgDescription(rEnvConfig, fio);
+ final RPkgDescription pkgDescription= loadPkgDescription(rEnvConfig, in);
- final int nPages= fio.readInt();
+ final int nPages= in.readInt();
final RHelpPage[] pages= new @NonNull RHelpPage[nPages];
final RPkgHelpImpl pkg= new RPkgHelpImpl(pkgDescription, rEnvConfig.getREnv());
for (int i= 0; i < nPages; i++) {
- pages[i]= loadPage(pkg, fio);
+ pages[i]= loadPage(pkg, in);
}
pkg.setPages(ImCollections.newList(pages));
return pkg;
}
private void savePkgDescription(final RPkgDescription pkgDescription,
- final FIO fio) throws IOException {
- fio.writeString(pkgDescription.getName());
- fio.writeString(pkgDescription.getVersion().toString());
- fio.writeString(pkgDescription.getTitle());
- fio.writeString(pkgDescription.getDescription());
- fio.writeString(pkgDescription.getAuthor());
- fio.writeString(pkgDescription.getMaintainer());
- fio.writeString(pkgDescription.getUrl());
- fio.writeString(pkgDescription.getBuilt());
- fio.writeString(pkgDescription.getLibLocation().getDirectory());
+ final DataStream out) throws IOException {
+ out.writeString(pkgDescription.getName());
+ out.writeString(pkgDescription.getVersion().toString());
+ out.writeString(pkgDescription.getTitle());
+ out.writeString(pkgDescription.getDescription());
+ out.writeString(pkgDescription.getAuthor());
+ out.writeString(pkgDescription.getMaintainer());
+ out.writeString(pkgDescription.getUrl());
+ out.writeString(pkgDescription.getBuilt());
+ out.writeString(pkgDescription.getLibLocation().getDirectory());
}
private RPkgDescription loadPkgDescription(final REnvHelpConfiguration rEnvConfig,
- final FIO fio) throws IOException {
- final String name= fio.readNonNullString().intern();
- final String version= fio.readNonNullString();
- final String title= fio.readNonNullString();
- final String description= fio.readNonNullString();
- final String author= fio.readString();
- final String maintainer= fio.readString();
- final String url= fio.readString();
- final String built= fio.readNonNullString();
- final RLibLocation libLocation= getLibLocationSafe(rEnvConfig, fio.readNonNullString());
+ final DataStream in) throws IOException {
+ final String name= in.readNonNullString().intern();
+ final String version= in.readNonNullString();
+ final String title= in.readNonNullString();
+ final String description= in.readNonNullString();
+ final String author= in.readString();
+ final String maintainer= in.readString();
+ final String url= in.readString();
+ final String built= in.readNonNullString();
+ final RLibLocation libLocation= getLibLocationSafe(rEnvConfig, in.readNonNullString());
return new BasicRPkgDescription(name, RNumVersion.create(version),
title, description,
@@ -484,33 +486,33 @@
return libLocation;
}
- private void savePage(final RHelpPage page, final FIO fio)
+ private void savePage(final RHelpPage page, final DataStream out)
throws IOException {
- fio.writeString(page.getName());
+ out.writeString(page.getName());
{ final ImList<String> topics= page.getTopics();
final int nTopics= topics.size();
- fio.writeInt(nTopics);
+ out.writeInt(nTopics);
for (int i= 0; i < nTopics; i++) {
final String topic= topics.get(i);
- fio.writeString((topic == page.getName()) ? null : topic);
+ out.writeString((topic == page.getName()) ? null : topic);
}
}
- fio.writeString(page.getTitle());
+ out.writeString(page.getTitle());
}
- private RHelpPage loadPage(final RPkgHelp pkg, final FIO fio)
+ private RHelpPage loadPage(final RPkgHelp pkg, final DataStream in)
throws IOException {
- final String name= fio.readNonNullString().intern();
+ final String name= in.readNonNullString().intern();
final ImList<String> topics;
- { final int nTopics= fio.readInt();
+ { final int nTopics= in.readInt();
final String[] array= new @NonNull String[nTopics];
for (int i= 0; i < array.length; i++) {
- final String topic= fio.readString();
+ final String topic= in.readString();
array[i]= (topic == null) ? name : topic.intern();
}
topics= ImCollections.newList(array);
}
- final String title= fio.readNonNullString();
+ final String title= in.readNonNullString();
return new RHelpPageImpl(pkg, name, topics, title);
}
diff --git a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/http/BasicMediaType.java b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/http/BasicMediaType.java
new file mode 100644
index 0000000..ec4b4a0
--- /dev/null
+++ b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/http/BasicMediaType.java
@@ -0,0 +1,111 @@
+/*=============================================================================#
+ # Copyright (c) 2019, 2020 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.rhelp.core.http;
+// package org.eclipse.statet.jcommons.io;
+
+import org.eclipse.statet.jcommons.collections.ImList;
+import org.eclipse.statet.jcommons.collections.ImMapEntry;
+import org.eclipse.statet.jcommons.lang.Immutable;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+
+@NonNullByDefault
+public class BasicMediaType implements MediaType, Immutable {
+
+
+ private static String check(final String t) {
+ if (t.length() == 1 && t.charAt(0) == '*') {
+ return WILDCARD;
+ }
+ return t;
+ }
+
+ protected static final int compare(final String t1, final String t2) {
+ if (t1 == WILDCARD) {
+ if (t2 == WILDCARD) {
+ return 0;
+ }
+ else {
+ return 1;
+ }
+ }
+ else if (t2 == WILDCARD) {
+ return -1;
+ }
+ else {
+ return t1.compareTo(t2);
+ }
+ }
+
+
+ private final String type;
+ private final String subtype;
+ private final ImList<? extends ImMapEntry<String, String>> parameters;
+
+
+ public BasicMediaType(final String type, final String subtype,
+ final ImList<? extends ImMapEntry<String, String>> parameters) {
+ this.type= check(type);
+ this.subtype= check(subtype);
+ this.parameters= parameters;
+ }
+
+ @Override
+ public final String getType() {
+ return this.type;
+ }
+
+ @Override
+ public final String getSubtype() {
+ return this.subtype;
+ }
+
+ @Override
+ public ImList<? extends ImMapEntry<String, String>> getParameters() {
+ return this.parameters;
+ }
+
+
+// public boolean includes(final MediaType type) {
+// if (this.type == WILDCARD || this.type.equals(type.getType())) {
+// if (this.subtype == WILDCARD || this.subtype.equals(type.getSubtype())) {
+// return true;
+// }
+// }
+// return false;
+// }
+
+
+ @Override
+ public int hashCode() {
+ return this.type.hashCode() + this.subtype.hashCode() * 31;
+ }
+
+ @Override
+ public boolean equals(final @Nullable Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof MediaType) {
+ final MediaType other= (MediaType)obj;
+ return (this.type.equals(other.getType())
+ && this.subtype.equals(other.getSubtype())
+ && getParameters().equals(other.getParameters()) );
+ }
+ return false;
+ }
+
+}
diff --git a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/http/HttpHeaderUtils.java b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/http/HttpHeaderUtils.java
new file mode 100644
index 0000000..5adfd40
--- /dev/null
+++ b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/http/HttpHeaderUtils.java
@@ -0,0 +1,472 @@
+/*=============================================================================#
+ # Copyright (c) 2019, 2020 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.rhelp.core.http;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.function.BiPredicate;
+import java.util.function.IntPredicate;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+
+import org.eclipse.statet.jcommons.collections.BasicImMapEntry;
+import org.eclipse.statet.jcommons.collections.ImCollections;
+import org.eclipse.statet.jcommons.collections.ImList;
+import org.eclipse.statet.jcommons.collections.ImMapEntry;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+
+@NonNullByDefault
+public class HttpHeaderUtils {
+
+
+ public static final String LOCATION_NAME= "Location"; //$NON-NLS-1$
+
+ public static final String ACCEPT_NAME= "Accept"; //$NON-NLS-1$
+
+ public static final String QUALITY_FACTOR_PARAM_NAME= "q"; //$NON-NLS-1$
+
+
+ public static class MediaTypeEntry extends BasicMediaType implements Comparable<MediaTypeEntry> {
+
+
+ private final float qualityFactor;
+
+
+ public MediaTypeEntry(final String type, final String subtype,
+ final float qualityFactor, final ImList<? extends ImMapEntry<String, String>> extParams) {
+ super(type, subtype, extParams);
+ this.qualityFactor= qualityFactor;
+ }
+
+
+ public float getQualityFactor() {
+ return this.qualityFactor;
+ }
+
+
+ @Override
+ public int compareTo(final MediaTypeEntry o) {
+ { final float diff= this.qualityFactor - o.qualityFactor;
+ if (diff != 0) {
+ return (diff > 0) ? -1 : 1;
+ }
+ }
+ { final int diff= compare(getType(), o.getType());
+ if (diff != 0) {
+ return diff;
+ }
+ }
+ { final int diff= compare(getSubtype(), o.getSubtype());
+ if (diff != 0) {
+ return diff;
+ }
+ }
+ return -(getParameters().size() - o.getParameters().size());
+ }
+
+
+ }
+
+ public static class ParseException extends Exception {
+
+ private static final long serialVersionUID= 1L;
+
+ private final String errorDescription;
+ private final String input;
+ private final int errorOffset;
+
+ public ParseException(final String errorDescription, final String input, final int errorOffset) {
+ super(String.format("Parse error: %1$s at %3$s in:\n%2$s", errorDescription, input, errorOffset));
+ this.errorDescription= errorDescription;
+ this.input= input;
+ this.errorOffset= errorOffset;
+ }
+
+
+ public String getErrorDescription() {
+ return this.errorDescription;
+ }
+
+ public String getInput() {
+ return this.input;
+ }
+
+ public int getErrorOffset() {
+ return this.errorOffset;
+ }
+
+ }
+
+ public static final class HeaderBuilder {
+
+
+ private final StringBuilder sb= new StringBuilder();
+
+
+ public HeaderBuilder() {
+ }
+
+
+ public void newEntry(final String value) {
+ if (this.sb.length() > 0) {
+ this.sb.append(',');
+ }
+ this.sb.append(value);
+ }
+
+ public void newEntry(final String value, final float qValue) {
+ newEntry(value);
+ this.sb.append(';');
+ this.sb.append(QUALITY_FACTOR_PARAM_NAME);
+ this.sb.append('=');
+ this.sb.append(qValue);
+ }
+
+ public void addParameter(final String name, final String value) {
+ this.sb.append(';');
+ this.sb.append(name);
+ this.sb.append('=');
+ this.sb.append(value);
+ }
+
+ public String build() {
+ return this.sb.toString();
+ }
+
+ }
+
+
+ private static class Tokenizer {
+
+ private static boolean isLinearWhitespace(final char c) {
+ switch (c) {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private static boolean isSeparator(final char c) {
+ switch (c) {
+ case '(':
+ case ')':
+ case '<':
+ case '>':
+ case '@':
+ case ',':
+ case ';':
+ case ':':
+ case '\\':
+ case '"':
+ case '/':
+ case '[':
+ case ']':
+ case '?':
+ case '=':
+ case '{':
+ case '}':
+ case ' ':
+ case '\t':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private final String input;
+
+ private int index;
+
+
+ public Tokenizer(final String input) {
+ this.input= input;
+ }
+
+
+ private int consumeWhitespace(int idx) {
+ while (idx < this.input.length() && isLinearWhitespace(this.input.charAt(idx))) {
+ idx++;
+ }
+ return idx;
+ }
+
+ private int consumeToken(int idx) {
+ while (idx < this.input.length()) {
+ final char c= this.input.charAt(idx);
+ if (c > 0x20 && c < 0x7F && !isSeparator(c)) {
+ idx++;
+ }
+ else {
+ break;
+ }
+ }
+ return idx;
+ }
+
+ public void readOperatorAssert(final char c) throws ParseException {
+ int idx= this.index;
+ idx= consumeWhitespace(idx);
+ if (idx < this.input.length() && this.input.charAt(idx) == c) {
+ this.index= idx + 1;
+ return;
+ }
+ throw new ParseException("operator '" + c + "' expected", this.input, idx);
+ }
+
+ public String readTokenAssert() throws ParseException {
+ int idx= this.index;
+ idx= consumeWhitespace(idx);
+ final int start= idx;
+ idx= consumeToken(idx);
+ if (start < idx) {
+ this.index= idx;
+ return this.input.substring(start, idx);
+ }
+ throw new ParseException("token expected", this.input, idx);
+ }
+
+ private String readParamValue(int idx) throws ParseException {
+ if (idx < this.input.length()) {
+ if (this.input.charAt(idx) == '"') {
+ idx++;
+ final int start= idx;
+ int end= -1;
+ while (idx < this.input.length()) {
+ final char c= this.input.charAt(idx);
+ switch (c) {
+ case '"':
+ end= idx;
+ idx++;
+ break;
+ case '\\':
+ idx++;
+ if (idx < this.input.length()) {
+ idx++;
+ }
+ continue;
+ default:
+ idx++;
+ continue;
+ }
+ }
+ this.index= idx;
+ if (end >= 0) {
+ return this.input.substring(start, end);
+ }
+ throw new ParseException("closing quote ('\"') expected", this.input, idx);
+ }
+ else {
+ final int start= idx;
+ idx= consumeToken(idx);
+ this.index= idx;
+ return this.input.substring(start, idx);
+ }
+ }
+ this.index= idx;
+ return "";
+ }
+
+ public String readParamValue() throws ParseException {
+ int idx= this.index;
+ idx= consumeWhitespace(idx);
+ return readParamValue(idx);
+ }
+
+ public void skipParamValue() throws ParseException {
+ int idx= this.index;
+ idx= consumeWhitespace(idx);
+ if (idx < this.input.length()) {
+ if (this.input.charAt(idx) == '"') {
+ idx++;
+ int end= -1;
+ while (idx < this.input.length()) {
+ final char c= this.input.charAt(idx);
+ switch (c) {
+ case '"':
+ end= idx;
+ idx++;
+ break;
+ case '\\':
+ idx++;
+ if (idx < this.input.length()) {
+ idx++;
+ }
+ continue;
+ default:
+ idx++;
+ continue;
+ }
+ }
+ this.index= idx;
+ if (end >= 0) {
+ return;
+ }
+ throw new ParseException("closing quote ('\"') expected", this.input, idx);
+ }
+ else {
+ idx= consumeToken(idx);
+ this.index= idx;
+ return;
+ }
+ }
+ this.index= idx;
+ }
+
+ public float readQValue() throws ParseException {
+ int idx= this.index;
+ idx= consumeWhitespace(idx);
+ final int start= idx;
+ try {
+ idx= consumeToken(idx);
+ this.index= idx;
+ return Float.parseFloat(this.input.substring(start, idx));
+ }
+ catch (final NumberFormatException e) {
+ throw new ParseException("q value (number) expected", this.input, start);
+ }
+ }
+
+ public boolean readNextEntry() {
+ int idx= this.index;
+ idx= consumeWhitespace(idx);
+ if (idx < this.input.length()) {
+ if (this.index == 0) {
+ return true;
+ }
+ if (this.input.charAt(idx) == ',') {
+ this.index= idx + 1;
+ return true;
+ }
+ }
+ this.index= idx;
+ return false;
+ }
+
+ public boolean readNextParam() {
+ int idx= this.index;
+ idx= consumeWhitespace(idx);
+ if (idx < this.input.length() && this.input.charAt(idx) == ';') {
+ this.index= idx + 1;
+ return true;
+ }
+ this.index= idx;
+ return false;
+ }
+
+ public void assertEnd() throws ParseException {
+ int idx= this.index;
+ idx= consumeWhitespace(idx);
+ this.index= idx;
+ if (idx == this.input.length()) {
+ return;
+ }
+ throw new ParseException("EOF expected", this.input, idx);
+ }
+
+ }
+
+ public static List<MediaTypeEntry> readAcceptHeaderEntries(final HttpServletRequest req,
+ final @Nullable BiPredicate<String, String> filter)
+ throws ServletException {
+ try {
+ final List<MediaTypeEntry> entries= new ArrayList<>();
+ final Enumeration<String> headers= req.getHeaders(ACCEPT_NAME);
+ if (headers != null) {
+ parseMediaTypes(headers, filter, entries);
+ }
+ entries.sort(null);
+ return entries;
+ }
+ catch (final ParseException e) {
+ throw new ServletException("Failed to read Accept header of request.", e);
+ }
+ }
+
+ public static List<MediaTypeEntry> readMediaTypeEntries(final Collection<String> headers,
+ final @Nullable BiPredicate<String, String> filter)
+ throws ParseException {
+ final List<MediaTypeEntry> entries= new ArrayList<>();
+ if (!headers.isEmpty()) {
+ parseMediaTypes(Collections.enumeration(headers), filter, entries);
+ }
+ entries.sort(null);
+ return entries;
+ }
+
+ protected final static void parseMediaTypes(final Enumeration<String> headers,
+ final @Nullable BiPredicate<String, String> filter, final List<MediaTypeEntry> entries) throws ParseException {
+ final List<ImMapEntry<String, String>> extParams= new ArrayList<>();
+ while (headers.hasMoreElements()) {
+ final Tokenizer tokenizer= new Tokenizer(headers.nextElement());
+ while (tokenizer.readNextEntry()) {
+ extParams.clear();
+
+ final String type= tokenizer.readTokenAssert();
+ tokenizer.readOperatorAssert('/');
+ final String subtype= tokenizer.readTokenAssert();
+
+ final boolean include= (filter == null || filter.test(type, subtype));
+ float qValue= 1;
+ for (int nParam= 0; tokenizer.readNextParam(); nParam++) {
+ final String paramName= tokenizer.readTokenAssert();
+ tokenizer.readOperatorAssert('=');
+ if (!include) {
+ tokenizer.skipParamValue();
+ continue;
+ }
+ if (nParam == 0 && paramName.equals(QUALITY_FACTOR_PARAM_NAME)) {
+ qValue= tokenizer.readQValue();
+ }
+ else {
+ final String paramValue= tokenizer.readParamValue();
+ extParams.add(new BasicImMapEntry<>(paramName, paramValue));
+ }
+ }
+ entries.add(new MediaTypeEntry(type, subtype, qValue,
+ ImCollections.toList(extParams) ));
+ }
+ tokenizer.assertEnd();
+ }
+ }
+
+
+ public static int findFirstValid(final List<MediaTypeEntry> entries,
+ final String parameterName, final IntPredicate paramPredicate) {
+ for (final MediaTypeEntry entry : entries) {
+ final String vString= entry.getParameterValue(parameterName);
+ if (vString != null) {
+ try {
+ final int v= Integer.parseInt(vString);
+ if (paramPredicate.test(v)) {
+ return v;
+ }
+ }
+ catch (final NumberFormatException e) {}
+ }
+ }
+ return -1;
+ }
+
+}
diff --git a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/http/MediaType.java b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/http/MediaType.java
new file mode 100644
index 0000000..fefb770
--- /dev/null
+++ b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/http/MediaType.java
@@ -0,0 +1,48 @@
+/*=============================================================================#
+ # Copyright (c) 2019, 2020 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.rhelp.core.http;
+//package org.eclipse.statet.jcommons.io;
+
+import java.util.Map;
+
+import org.eclipse.statet.jcommons.collections.ImList;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+
+@NonNullByDefault
+public interface MediaType {
+
+ String WILDCARD= "*";
+
+
+ String getType();
+
+ String getSubtype();
+
+
+ ImList<? extends Map.Entry<String, String>> getParameters();
+
+ default @Nullable String getParameterValue(final String name) {
+ final ImList<? extends Map.Entry<String, String>> parameters= getParameters();
+ for (final Map.Entry<String, String> parameter : parameters) {
+ if (parameter.getKey().equals(name)) {
+ return parameter.getValue();
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/server/JettyREnvHelpAccess.java b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/server/JettyREnvHelpAccess.java
index b220053..da6d7a8 100644
--- a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/server/JettyREnvHelpAccess.java
+++ b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/server/JettyREnvHelpAccess.java
@@ -40,8 +40,6 @@
import org.eclipse.statet.jcommons.status.ProgressMonitor;
import org.eclipse.statet.jcommons.status.StatusException;
-import org.eclipse.statet.internal.rhelp.core.SerUtil;
-
@NonNullByDefault
public class JettyREnvHelpAccess extends ServerREnvHelpAccess {
@@ -77,7 +75,7 @@
throw new ResponseException(message);
}
final String contentType= response.getHeaders().get(HttpHeader.CONTENT_TYPE);
- if (contentType == null || !contentType.startsWith(ServerApi.DS_MIME_TYPE)) {
+ if (contentType == null || !contentType.startsWith(ServerApi.DS_MEDIA_TYPE_STRING)) {
throw new ResponseException(String.format("Unexpected content type: '%1$s'.",
contentType ));
}
@@ -90,7 +88,7 @@
if (eTag != null) {
request.header(HttpHeader.IF_NONE_MATCH, eTag);
}
- request.accept(ServerApi.DS_MIME_TYPE + ';' + ServerApi.DS_SER_VERSION + '=' + SerUtil.READABLE_SERVER);
+ request.accept(DS_VERSIONED_ACCEPT_HEADER);
return doGetDataStream(request, (eTag != null));
}
@@ -103,14 +101,15 @@
request.param(params[i++], params[i++]);
}
request.method(HttpMethod.POST);
- request.content(new BytesContentProvider(ServerApi.DS_MIME_TYPE, requestData));
+ request.content(new BytesContentProvider(ServerApi.DS_MEDIA_TYPE_STRING, requestData));
+
+ request.accept(DS_MODEST_ACCEPT_HEADER);
return doGetDataStream(request, false);
}
private @Nullable InputStream doGetDataStream(final Request request, final boolean notModified)
throws StatusException, ResponseException {
- request.accept(ServerApi.DS_MIME_TYPE);
final InputStreamResponseListener listener= new InputStreamResponseListener();
request.send(listener);
@@ -154,7 +153,7 @@
request.param(params[i++], params[i++]);
}
- request.accept(ServerApi.DS_MIME_TYPE);
+ request.accept(DS_MODEST_ACCEPT_HEADER);
if (timeout != -1) {
request.timeout(timeout, TimeUnit.SECONDS);
}
diff --git a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/server/ServerApi.java b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/server/ServerApi.java
index f4678a1..5425912 100644
--- a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/server/ServerApi.java
+++ b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/server/ServerApi.java
@@ -29,7 +29,9 @@
public static final String API_VERSION_1= "api/v1"; //$NON-NLS-1$
- public static final String DS_MIME_TYPE= "application/x.org.eclipse.statet.rhelp-ds"; //$NON-NLS-1$
+ public static final String APPLICATION_MEDIA_TYPE= "application"; //$NON-NLS-1$
+ public static final String DS_MEDIA_SUBTYPE= "x.org.eclipse.statet.rhelp-ds"; //$NON-NLS-1$
+ public static final String DS_MEDIA_TYPE_STRING= APPLICATION_MEDIA_TYPE + '/' + DS_MEDIA_SUBTYPE;
public static final String DS_SER_VERSION= "ser"; //$NON-NLS-1$
diff --git a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/server/ServerREnvHelpAccess.java b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/server/ServerREnvHelpAccess.java
index 44cbc55..7aeff0b 100644
--- a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/server/ServerREnvHelpAccess.java
+++ b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/internal/rhelp/core/server/ServerREnvHelpAccess.java
@@ -37,12 +37,13 @@
import org.eclipse.statet.jcommons.status.StatusException;
import org.eclipse.statet.jcommons.status.Statuses;
-import org.eclipse.statet.internal.rhelp.core.FIO;
+import org.eclipse.statet.internal.rhelp.core.DataStream;
import org.eclipse.statet.internal.rhelp.core.REnvHelpIndex;
import org.eclipse.statet.internal.rhelp.core.RHelpSearchMatchImpl;
import org.eclipse.statet.internal.rhelp.core.RHelpWebapp;
import org.eclipse.statet.internal.rhelp.core.SerUtil;
import org.eclipse.statet.internal.rhelp.core.SerUtil.Controller;
+import org.eclipse.statet.internal.rhelp.core.http.HttpHeaderUtils;
import org.eclipse.statet.rhelp.core.REnvHelpConfiguration;
import org.eclipse.statet.rhelp.core.RHelpCore;
import org.eclipse.statet.rhelp.core.RHelpPage;
@@ -58,6 +59,18 @@
protected static final String[] NO_PARAMS= new String[0];
+ protected static final String DS_MODEST_ACCEPT_HEADER= ServerApi.DS_MEDIA_TYPE_STRING;
+ protected static final String DS_VERSIONED_ACCEPT_HEADER;
+ static {
+ final HttpHeaderUtils.HeaderBuilder builder= new HttpHeaderUtils.HeaderBuilder();
+ final int[] acceptedVersions= SerUtil.READABLE_VERSIONS;
+ for (int i= 0; i < acceptedVersions.length; i++) {
+ builder.newEntry(ServerApi.DS_MEDIA_TYPE_STRING, (10 - i)/10.0f);
+ builder.addParameter(ServerApi.DS_SER_VERSION, Integer.toString(acceptedVersions[i]));
+ }
+ DS_VERSIONED_ACCEPT_HEADER= builder.build();
+ }
+
private final URI url;
@@ -197,15 +210,15 @@
@Override
public List<RHelpPage> getPagesForTopic(final String topic, final Map<String, RPkgHelp> packageMap,
final int timeout, final @Nullable ProgressMonitor m) throws StatusException {
- try (final FIO fio= FIO.get(new ByteArrayInputStream(getDataStreamBytes(
+ try (final DataStream in= DataStream.get(new ByteArrayInputStream(getDataStreamBytes(
createUrl(createPath(ServerApi.PAGES)), new String[] {
ServerApi.TOPIC_PARAM, topic,
}, timeout, m)))) {
- final int n= fio.readInt();
+ final int n= in.readInt();
final List<RHelpPage> pages= new ArrayList<>(n);
for (int i= 0; i < n; i++) {
- final String pkgName= nonNullAssert(fio.readString());
- final String pageName= nonNullAssert(fio.readString());
+ final String pkgName= nonNullAssert(in.readString());
+ final String pageName= nonNullAssert(in.readString());
final RPkgHelp pkgHelp= packageMap.get(pkgName);
if (pkgHelp != null) {
final RHelpPage page= pkgHelp.getPage(pageName);
@@ -226,13 +239,13 @@
public @Nullable String getHtmlPage(final RPkgHelp pkgHelp, final String pageName,
final @Nullable String queryString,
final int timeout, final @Nullable ProgressMonitor m) throws StatusException {
- try (final FIO fio= FIO.get(new ByteArrayInputStream(getDataStreamBytes(
+ try (final DataStream in= DataStream.get(new ByteArrayInputStream(getDataStreamBytes(
createUrl(createPath(ServerApi.PKGS, pkgHelp.getName(), ServerApi.PAGES, pageName)),
(queryString != null) ? new String[] {
ServerApi.QUERY_STRING_PARAM, queryString,
} : NO_PARAMS,
timeout, m )))) {
- return fio.readString();
+ return in.readString();
}
catch (final NotFoundException e) {
return null;
@@ -250,37 +263,37 @@
final Map<String, RPkgHelp> packageMap,
final RHelpSearchRequestor requestor) throws StatusException {
final ByteArrayOutputStream requestData= new ByteArrayOutputStream();
- try (final FIO fio= FIO.get(requestData)) {
- fio.writeInt(searchQuery.getSearchType());
- fio.writeString(searchQuery.getSearchString());
- fio.writeStringList(searchQuery.getEnabledFields());
- fio.writeStringList(searchQuery.getKeywords());
- fio.writeStringList(searchQuery.getPackages());
+ try (final DataStream out= DataStream.get(requestData)) {
+ out.writeInt(searchQuery.getSearchType());
+ out.writeString(searchQuery.getSearchString());
+ out.writeStringList(searchQuery.getEnabledFields());
+ out.writeStringList(searchQuery.getKeywords());
+ out.writeStringList(searchQuery.getPackages());
}
catch (final Exception e) {
throw onFailed(e);
}
- try (final FIO fio= FIO.get(getDataStream(
+ try (final DataStream in= DataStream.get(getDataStream(
createUrl(createPath(ServerApi.SEARCH)), new String[] {
ServerApi.MAX_FRAGMENTS_PARAM, Integer.toString(requestor.getMaxFragments()),
}, requestData.toByteArray() ))) {
while (true) {
- final byte matchType= fio.readByte();
+ final byte matchType= in.readByte();
switch (matchType) {
case ServerApi.END_MATCH:
return;
case ServerApi.PAGE_MATCH: {
- final String pkgName= fio.readNonNullString();
- final String pageName= fio.readNonNullString();
- final float score= fio.readFloat();
- final int matchCount= fio.readInt();
+ final String pkgName= in.readNonNullString();
+ final String pageName= in.readNonNullString();
+ final float score= in.readFloat();
+ final int matchCount= in.readInt();
final MatchFragment[] fragments;
if (matchCount >= 0) {
- final int nFragments= fio.readInt();
+ final int nFragments= in.readInt();
fragments= new @NonNull MatchFragment[nFragments];
for (int i= 0; i < nFragments; i++) {
- final String field= fio.readNonNullString();
- final String text= fio.readNonNullString();
+ final String field= in.readNonNullString();
+ final String text= in.readNonNullString();
fragments[i]= new RHelpSearchMatchImpl.Fragment(field, text);
}
}
diff --git a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/CustomMimeTypes.java b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/CustomMediaTypeProvider.java
similarity index 74%
rename from rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/CustomMimeTypes.java
rename to rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/CustomMediaTypeProvider.java
index 11b9de1..50a5d29 100644
--- a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/CustomMimeTypes.java
+++ b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/CustomMediaTypeProvider.java
@@ -22,27 +22,27 @@
@NonNullByDefault
-public class CustomMimeTypes implements MimeTypes {
+public class CustomMediaTypeProvider implements MediaTypeProvider {
private final Map<String, String> nameTypes= new HashMap<>();
private final Map<String, String> extTypes= new HashMap<>();
- public CustomMimeTypes() {
+ public CustomMediaTypeProvider() {
}
- public void addName(final String fileName, final String type) {
- this.nameTypes.put(fileName, type);
+ public void addName(final String fileName, final String mediaTypeString) {
+ this.nameTypes.put(fileName, mediaTypeString);
}
- public void addExt(final String fileExt, final String type) {
- this.extTypes.put(fileExt, type);
+ public void addExt(final String fileExt, final String mediaTypeString) {
+ this.extTypes.put(fileExt, mediaTypeString);
}
@Override
- public @Nullable String getMimeType(final String fileName) {
+ public @Nullable String getMediaTypeString(final String fileName) {
String type= this.nameTypes.get(fileName);
if (type == null) {
final int idx= fileName.indexOf('.');
diff --git a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/MimeTypes.java b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/MediaTypeProvider.java
similarity index 89%
rename from rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/MimeTypes.java
rename to rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/MediaTypeProvider.java
index 47c0da9..81f5a3e 100644
--- a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/MimeTypes.java
+++ b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/MediaTypeProvider.java
@@ -19,9 +19,9 @@
@NonNullByDefault
-public interface MimeTypes {
+public interface MediaTypeProvider {
- @Nullable String getMimeType(final String fileName);
+ @Nullable String getMediaTypeString(final String fileName);
}
diff --git a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/RHelpApi1Servlet.java b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/RHelpApi1Servlet.java
index 4fbfe90..c595c5c 100644
--- a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/RHelpApi1Servlet.java
+++ b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/RHelpApi1Servlet.java
@@ -35,9 +35,11 @@
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.jcommons.status.StatusException;
-import org.eclipse.statet.internal.rhelp.core.FIO;
+import org.eclipse.statet.internal.rhelp.core.DataStream;
import org.eclipse.statet.internal.rhelp.core.REnvHelpImpl;
import org.eclipse.statet.internal.rhelp.core.SerUtil;
+import org.eclipse.statet.internal.rhelp.core.http.HttpHeaderUtils;
+import org.eclipse.statet.internal.rhelp.core.http.HttpHeaderUtils.MediaTypeEntry;
import org.eclipse.statet.internal.rhelp.core.server.ServerApi;
import org.eclipse.statet.internal.rhelp.core.server.ServerApi.RequestInfo;
import org.eclipse.statet.rhelp.core.REnvHelp;
@@ -79,11 +81,11 @@
}
- private static final MimeTypes API_MIME_TYPES;
+ private static final MediaTypeProvider API_MEDIA_TYPE_PROVIDER;
static {
- final CustomMimeTypes apiMimeTypes= new CustomMimeTypes();
- apiMimeTypes.addExt("ser", ServerApi.DS_MIME_TYPE); //$NON-NLS-1$
- API_MIME_TYPES= apiMimeTypes;
+ final CustomMediaTypeProvider apiMediaTypes= new CustomMediaTypeProvider();
+ apiMediaTypes.addExt("ser", ServerApi.DS_MEDIA_TYPE_STRING); //$NON-NLS-1$
+ API_MEDIA_TYPE_PROVIDER= apiMediaTypes;
}
@@ -117,8 +119,8 @@
final @Nullable ResourceHandler resourceHandler) {
this.rHelpManager= rHelpManager;
this.resourceHandler= (resourceHandler != null) ? resourceHandler :
- new SimpleResourceHandler(new ServletMimeTypes(getServletContext()));
- this.resourceHandler.setSpecialMimeTypes(API_MIME_TYPES);
+ new SimpleResourceHandler(new ServletMediaTypeProvider(getServletContext()));
+ this.resourceHandler.setSpecialMediaTypes(API_MEDIA_TYPE_PROVIDER);
this.resourceHandler.setCacheControl("max-age=100, must-revalidate"); //$NON-NLS-1$
}
@@ -258,13 +260,22 @@
final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
final REnvHelpImpl help= getEnvHelp(req);
- resp.setContentType(ServerApi.DS_MIME_TYPE);
+ resp.setContentType(ServerApi.DS_MEDIA_TYPE_STRING);
try (final OutputStream out= resp.getOutputStream()) {
- out.write(FIO.encodeLong(help.getStamp()));
+ out.write(DataStream.encodeLong(help.getStamp()));
}
}
+ protected int checkAcceptDS(final HttpServletRequest req) throws ServletException {
+ final List<MediaTypeEntry> entries= HttpHeaderUtils.readAcceptHeaderEntries(req,
+ (final String type, final String subtype) ->
+ (type.equals(ServerApi.APPLICATION_MEDIA_TYPE)
+ && subtype.equals(ServerApi.DS_MEDIA_SUBTYPE) ));
+ return HttpHeaderUtils.findFirstValid(entries, ServerApi.DS_SER_VERSION,
+ (final int v) -> (v == SerUtil.CURRENT_VERSION) );
+ }
+
private void processBasicData(
final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
final REnvHelpConfiguration config= (REnvHelpConfiguration) req.getAttribute(ATTR_RENV_CONFIG);
@@ -284,6 +295,11 @@
}
}
+ final int serVersion= checkAcceptDS(req);
+ if (serVersion < 0) {
+ resp.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE);
+ return;
+ }
final Path file= SerUtil.getBasicDataFilePath(config);
if (file != null && Files.isRegularFile(file)) {
this.resourceHandler.doGet(file, req, resp);
@@ -334,13 +350,13 @@
pages= pkgHelp.getPages();
}
- resp.setContentType(ServerApi.DS_MIME_TYPE);
- try (final FIO fio= FIO.get(resp.getOutputStream())) {
+ resp.setContentType(ServerApi.DS_MEDIA_TYPE_STRING);
+ try (final DataStream out= DataStream.get(resp.getOutputStream())) {
final int n= pages.size();
- fio.writeInt(n);
+ out.writeInt(n);
for (int i= 0; i < n; i++) {
final RHelpPage page= pages.get(i);
- fio.writeString(page.getName());
+ out.writeString(page.getName());
}
}
}
@@ -358,9 +374,9 @@
return;
}
- resp.setContentType(ServerApi.DS_MIME_TYPE);
- try (final FIO fio= FIO.get(resp.getOutputStream())) {
- fio.writeString(html);
+ resp.setContentType(ServerApi.DS_MEDIA_TYPE_STRING);
+ try (final DataStream out= DataStream.get(resp.getOutputStream())) {
+ out.writeString(html);
}
}
@@ -373,14 +389,14 @@
if (topic != null) {
final List<RHelpPage> pages= help.getPagesForTopic(topic, null);
- resp.setContentType(ServerApi.DS_MIME_TYPE);
- try (final FIO fio= FIO.get(resp.getOutputStream())) {
+ resp.setContentType(ServerApi.DS_MEDIA_TYPE_STRING);
+ try (final DataStream out= DataStream.get(resp.getOutputStream())) {
final int n= pages.size();
- fio.writeInt(n);
+ out.writeInt(n);
for (int i= 0; i < n; i++) {
final RHelpPage page= pages.get(i);
- fio.writeString(page.getPackage().getName());
- fio.writeString(page.getName());
+ out.writeString(page.getPackage().getName());
+ out.writeString(page.getName());
}
}
}
@@ -388,13 +404,13 @@
private @Nullable RHelpSearchQuery readRHelpSearchQuery(
final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
- if (req.getContentType() != null && req.getContentType().equals(ServerApi.DS_MIME_TYPE)) {
- try (final FIO fio= FIO.get(req.getInputStream())) {
- final int searchType= fio.readInt();
- final String searchString= fio.readNonNullString();
- final ImList<String >fields= ImCollections.newList(fio.readNonNullStringArray());
- final ImList<String >keywords= ImCollections.newList(fio.readNonNullStringArray());
- final ImList<String >packages= ImCollections.newList(fio.readNonNullStringArray());
+ if (req.getContentType() != null && req.getContentType().equals(ServerApi.DS_MEDIA_TYPE_STRING)) {
+ try (final DataStream in= DataStream.get(req.getInputStream())) {
+ final int searchType= in.readInt();
+ final String searchString= in.readNonNullString();
+ final ImList<String >fields= ImCollections.newList(in.readNonNullStringArray());
+ final ImList<String >keywords= ImCollections.newList(in.readNonNullStringArray());
+ final ImList<String >packages= ImCollections.newList(in.readNonNullStringArray());
return new RHelpSearchQuery(searchType, searchString, fields,
keywords, packages,
getEnv(req) );
@@ -444,9 +460,9 @@
return;
}
- resp.setContentType(ServerApi.DS_MIME_TYPE);
+ resp.setContentType(ServerApi.DS_MEDIA_TYPE_STRING);
resp.flushBuffer();
- try (final FIO fio= FIO.get(resp.getOutputStream())) {
+ try (final DataStream out= DataStream.get(resp.getOutputStream())) {
help.search(searchQuery, new RHelpSearchRequestor() {
@Override
@@ -457,21 +473,21 @@
@Override
public void matchFound(final RHelpSearchMatch match) {
try {
- fio.writeByte(ServerApi.PAGE_MATCH);
+ out.writeByte(ServerApi.PAGE_MATCH);
{ final RHelpPage page= match.getPage();
- fio.writeString(page.getPackage().getName());
- fio.writeString(page.getName());
+ out.writeString(page.getPackage().getName());
+ out.writeString(page.getName());
}
- fio.writeFloat(match.getScore());
- fio.writeInt(match.getMatchCount());
+ out.writeFloat(match.getScore());
+ out.writeInt(match.getMatchCount());
if (match.getMatchCount() >= 0) {
final MatchFragment[] fragments= nonNullAssert(match.getBestFragments());
final int nFragments= fragments.length;
- fio.writeInt(nFragments);
+ out.writeInt(nFragments);
for (int i= 0; i < nFragments; i++) {
final MatchFragment fragment= fragments[i];
- fio.writeString(fragment.getField());
- fio.writeString(fragment.getText());
+ out.writeString(fragment.getField());
+ out.writeString(fragment.getText());
}
}
}
@@ -481,7 +497,7 @@
}
});
- fio.writeInt(ServerApi.END_MATCH);
+ out.writeInt(ServerApi.END_MATCH);
}
catch (final WrappedIOException e) {
throw e.getCause();
diff --git a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/RHelpHttpServlet.java b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/RHelpHttpServlet.java
index 751f427..c8e5f74 100644
--- a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/RHelpHttpServlet.java
+++ b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/RHelpHttpServlet.java
@@ -38,8 +38,6 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.eclipse.jetty.http.HttpHeader;
-
import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
@@ -51,6 +49,7 @@
import org.eclipse.statet.internal.rhelp.core.REnvHelpIndex;
import org.eclipse.statet.internal.rhelp.core.RHelpWebapp;
import org.eclipse.statet.internal.rhelp.core.RHelpWebapp.RequestInfo;
+import org.eclipse.statet.internal.rhelp.core.http.HttpHeaderUtils;
import org.eclipse.statet.internal.rhelp.core.index.RHelpHtmlUtils;
import org.eclipse.statet.internal.rhelp.core.server.ServerClientSupport;
import org.eclipse.statet.rhelp.core.DocResource;
@@ -84,17 +83,17 @@
private static final String ATTR_RENV_CONFIG= "rhelp.renv.config"; //$NON-NLS-1$
- private static final MimeTypes DOC_MIME_TYPES;
+ private static final MediaTypeProvider DOC_MEDIA_TYPES;
static {
- final CustomMimeTypes docMimeTypes= new CustomMimeTypes();
- docMimeTypes.addName("README", "text/plain;charset=iso-8859-1"); //$NON-NLS-1$ //$NON-NLS-2$
- docMimeTypes.addName("COPYING", "text/plain;charset=iso-8859-1"); //$NON-NLS-1$ //$NON-NLS-2$
- docMimeTypes.addName("LICENSE", "text/plain;charset=iso-8859-1"); //$NON-NLS-1$ //$NON-NLS-2$
- docMimeTypes.addName("AUTHORS", "text/plain;charset=iso-8859-1"); //$NON-NLS-1$ //$NON-NLS-2$
- docMimeTypes.addName("THANKS", "text/plain;charset=iso-8859-1"); //$NON-NLS-1$ //$NON-NLS-2$
- docMimeTypes.addName("DESCRIPTION", "text/plain"); //$NON-NLS-1$ //$NON-NLS-2$
- docMimeTypes.addExt("Rnw", "text/plain"); //$NON-NLS-1$ //$NON-NLS-2$
- DOC_MIME_TYPES= docMimeTypes;
+ final CustomMediaTypeProvider docMediaTypes= new CustomMediaTypeProvider();
+ docMediaTypes.addName("README", "text/plain;charset=iso-8859-1"); //$NON-NLS-1$ //$NON-NLS-2$
+ docMediaTypes.addName("COPYING", "text/plain;charset=iso-8859-1"); //$NON-NLS-1$ //$NON-NLS-2$
+ docMediaTypes.addName("LICENSE", "text/plain;charset=iso-8859-1"); //$NON-NLS-1$ //$NON-NLS-2$
+ docMediaTypes.addName("AUTHORS", "text/plain;charset=iso-8859-1"); //$NON-NLS-1$ //$NON-NLS-2$
+ docMediaTypes.addName("THANKS", "text/plain;charset=iso-8859-1"); //$NON-NLS-1$ //$NON-NLS-2$
+ docMediaTypes.addName("DESCRIPTION", "text/plain"); //$NON-NLS-1$ //$NON-NLS-2$
+ docMediaTypes.addExt("Rnw", "text/plain"); //$NON-NLS-1$ //$NON-NLS-2$
+ DOC_MEDIA_TYPES= docMediaTypes;
}
@SuppressWarnings("null")
@@ -187,8 +186,8 @@
this.rHelpManager= rHelpManager;
this.fileResourceHandler= (fileResourceHandler != null) ? fileResourceHandler :
- new SimpleResourceHandler(new ServletMimeTypes(getServletContext()));
- this.fileResourceHandler.setSpecialMimeTypes(DOC_MIME_TYPES);
+ new SimpleResourceHandler(new ServletMediaTypeProvider(getServletContext()));
+ this.fileResourceHandler.setSpecialMediaTypes(DOC_MEDIA_TYPES);
this.fileResourceHandler.setCacheControl("max-age=600, must-revalidate"); //$NON-NLS-1$
this.serverForwardHandler= serverForwardHandler;
@@ -293,7 +292,7 @@
resp.resetBuffer();
resp.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
- resp.setHeader(HttpHeader.LOCATION.asString(), path);
+ resp.setHeader(HttpHeaderUtils.LOCATION_NAME, path);
}
diff --git a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/ResourceHandler.java b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/ResourceHandler.java
index 932f623..5ff406b 100644
--- a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/ResourceHandler.java
+++ b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/ResourceHandler.java
@@ -28,7 +28,7 @@
public interface ResourceHandler {
- void setSpecialMimeTypes(final MimeTypes types);
+ void setSpecialMediaTypes(final MediaTypeProvider types);
void setCacheControl(final String value);
diff --git a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/ServletMimeTypes.java b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/ServletMediaTypeProvider.java
similarity index 83%
rename from rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/ServletMimeTypes.java
rename to rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/ServletMediaTypeProvider.java
index 09d9c38..4e4fca5 100644
--- a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/ServletMimeTypes.java
+++ b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/ServletMediaTypeProvider.java
@@ -21,19 +21,19 @@
@NonNullByDefault
-public class ServletMimeTypes implements MimeTypes {
+public class ServletMediaTypeProvider implements MediaTypeProvider {
private final ServletContext servletContext;
- public ServletMimeTypes(final ServletContext servletContext) {
+ public ServletMediaTypeProvider(final ServletContext servletContext) {
this.servletContext= servletContext;
}
@Override
- public @Nullable String getMimeType(final String fileName) {
+ public @Nullable String getMediaTypeString(final String fileName) {
return this.servletContext.getMimeType(fileName);
}
diff --git a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/SimpleResourceHandler.java b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/SimpleResourceHandler.java
index ee3b02e..c552e02 100644
--- a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/SimpleResourceHandler.java
+++ b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/SimpleResourceHandler.java
@@ -32,29 +32,29 @@
public class SimpleResourceHandler implements ResourceHandler {
- private final MimeTypes defaultMimeTypes;
- private @Nullable MimeTypes specialMimeTypes;
+ private final MediaTypeProvider defaultMediaTypes;
+ private @Nullable MediaTypeProvider specialMediaTypes;
private @Nullable String cacheControl;
- public SimpleResourceHandler(final MimeTypes mimeTypes) {
- this.defaultMimeTypes= mimeTypes;
+ public SimpleResourceHandler(final MediaTypeProvider mediaTypes) {
+ this.defaultMediaTypes= mediaTypes;
}
@Override
- public void setSpecialMimeTypes(final MimeTypes types) {
- this.specialMimeTypes= types;
+ public void setSpecialMediaTypes(final MediaTypeProvider types) {
+ this.specialMediaTypes= types;
}
- private @Nullable String getMimeType(final String fileName) {
+ private @Nullable String getMediaType(final String fileName) {
String type= null;
- if (this.specialMimeTypes != null) {
- type= this.specialMimeTypes.getMimeType(fileName);
+ if (this.specialMediaTypes != null) {
+ type= this.specialMediaTypes.getMediaTypeString(fileName);
}
if (type == null) {
- type= this.defaultMimeTypes.getMimeType(fileName);
+ type= this.defaultMediaTypes.getMediaTypeString(fileName);
}
return type;
}
@@ -71,9 +71,9 @@
in.available();
final byte[] buffer= new byte[1024];
- { final String mimeType= getMimeType(file.getFileName().toString());
- if (mimeType != null) {
- resp.setContentType(mimeType);
+ { final String mediaType= getMediaType(file.getFileName().toString());
+ if (mediaType != null) {
+ resp.setContentType(mediaType);
}
}
{ final String cacheControl= this.cacheControl;
diff --git a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/jetty/JettyRHelpUtils.java b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/jetty/JettyRHelpUtils.java
index 71213d0..8d99120 100644
--- a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/jetty/JettyRHelpUtils.java
+++ b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/jetty/JettyRHelpUtils.java
@@ -23,25 +23,25 @@
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
-import org.eclipse.statet.rhelp.core.http.MimeTypes;
+import org.eclipse.statet.rhelp.core.http.MediaTypeProvider;
import org.eclipse.statet.rhelp.core.http.ResourceHandler;
-import org.eclipse.statet.rhelp.core.http.ServletMimeTypes;
+import org.eclipse.statet.rhelp.core.http.ServletMediaTypeProvider;
@NonNullByDefault
public class JettyRHelpUtils {
- public static MimeTypes getMimeTypes(final ServletContext context) {
- return new ServletMimeTypes(context);
+ public static MediaTypeProvider getMediaTypes(final ServletContext context) {
+ return new ServletMediaTypeProvider(context);
}
- public static ResourceHandler newResourceHandler(final MimeTypes mimeTypes) {
- return new JettyResourceHandler(mimeTypes);
+ public static ResourceHandler newResourceHandler(final MediaTypeProvider mediaTypes) {
+ return new JettyResourceHandler(mediaTypes);
}
public static ResourceHandler newResourceHandler(final ServletContext context) {
- return newResourceHandler(getMimeTypes(context));
+ return newResourceHandler(getMediaTypes(context));
}
diff --git a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/jetty/JettyResourceHandler.java b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/jetty/JettyResourceHandler.java
index 7cddc31..e83a7f0 100644
--- a/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/jetty/JettyResourceHandler.java
+++ b/rhelp/org.eclipse.statet.rhelp.core/src/org/eclipse/statet/rhelp/core/http/jetty/JettyResourceHandler.java
@@ -36,7 +36,7 @@
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
-import org.eclipse.statet.rhelp.core.http.MimeTypes;
+import org.eclipse.statet.rhelp.core.http.MediaTypeProvider;
import org.eclipse.statet.rhelp.core.http.ResourceHandler;
@@ -47,13 +47,13 @@
private static class JettyMimeTypes extends org.eclipse.jetty.http.MimeTypes {
- private final MimeTypes defaultTypes;
+ private final MediaTypeProvider defaultMediaTypes;
- private @Nullable MimeTypes specialTypes;
+ private @Nullable MediaTypeProvider specialMediaTypes;
- public JettyMimeTypes(final MimeTypes mimeTypes) {
- this.defaultTypes= mimeTypes;
+ public JettyMimeTypes(final MediaTypeProvider mimeTypes) {
+ this.defaultMediaTypes= mimeTypes;
}
@Override
@@ -63,11 +63,11 @@
filename= filename.substring(idx + 1);
}
String type= null;
- if (this.specialTypes != null) {
- type= this.specialTypes.getMimeType(filename);
+ if (this.specialMediaTypes != null) {
+ type= this.specialMediaTypes.getMediaTypeString(filename);
}
if (type == null) {
- type= this.defaultTypes.getMimeType(filename);
+ type= this.defaultMediaTypes.getMediaTypeString(filename);
}
if (type == null) {
type= super.getMimeByExtension(filename);
@@ -78,19 +78,19 @@
}
- private final JettyMimeTypes mimeTypes;
+ private final JettyMimeTypes mediaTypes;
- public JettyResourceHandler(final MimeTypes defaultTypes) {
- this.mimeTypes= new JettyMimeTypes(defaultTypes);
- setContentFactory(new ResourceContentFactory(this, this.mimeTypes,
+ public JettyResourceHandler(final MediaTypeProvider defaultTypes) {
+ this.mediaTypes= new JettyMimeTypes(defaultTypes);
+ setContentFactory(new ResourceContentFactory(this, this.mediaTypes,
new CompressedContentFormat[0] ));
}
@Override
- public void setSpecialMimeTypes(final MimeTypes types) {
- this.mimeTypes.specialTypes= types;
+ public void setSpecialMediaTypes(final MediaTypeProvider types) {
+ this.mediaTypes.specialMediaTypes= types;
}
@Override
diff --git a/rhelp/org.eclipse.statet.rhelp.server/pom.xml b/rhelp/org.eclipse.statet.rhelp.server/pom.xml
index 3b756a5..f3b3185 100644
--- a/rhelp/org.eclipse.statet.rhelp.server/pom.xml
+++ b/rhelp/org.eclipse.statet.rhelp.server/pom.xml
@@ -50,6 +50,12 @@
<version>4.1.0-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-client</artifactId>
+ <scope>test</scope>
+ </dependency>
+
</dependencies>
<build>
diff --git a/rhelp/org.eclipse.statet.rhelp.server/src/test/java/org/eclipse/statet/rhelp/server/AbstractDefaultAppTest.java b/rhelp/org.eclipse.statet.rhelp.server/src/test/java/org/eclipse/statet/rhelp/server/AbstractDefaultAppTest.java
new file mode 100644
index 0000000..262e47c
--- /dev/null
+++ b/rhelp/org.eclipse.statet.rhelp.server/src/test/java/org/eclipse/statet/rhelp/server/AbstractDefaultAppTest.java
@@ -0,0 +1,90 @@
+/*=============================================================================#
+ # Copyright (c) 2020 Stephan Wahlbrink <sw@wahlbrink.eu> and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.rhelp.server;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
+
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+import org.eclipse.statet.jcommons.status.Status;
+
+import org.eclipse.statet.rhelp.core.REnvHelp;
+import org.eclipse.statet.rhelp.core.RHelpManager;
+import org.eclipse.statet.rj.renv.core.REnv;
+import org.eclipse.statet.rj.renv.core.REnvConfiguration;
+import org.eclipse.statet.rj.renv.core.REnvManager;
+
+
+@ExtendWith(SpringExtension.class)
+@SpringBootTest(webEnvironment= WebEnvironment.RANDOM_PORT)
+@Import(ContextConfiguration.class)
+@NonNullByDefault
+public abstract class AbstractDefaultAppTest {
+
+
+ @Autowired
+ protected @Nullable REnvManager rEnvManager;
+
+ @Autowired
+ protected @Nullable RHelpManager rHelpManager;
+
+
+ public AbstractDefaultAppTest() {
+ }
+
+
+ @SuppressWarnings("null")
+ protected static <T> T assumeNotNull(final @Nullable T value) {
+ assumeTrue(value != null);
+ return value;
+ }
+
+ @SuppressWarnings("null")
+ protected static REnv assumeREnvValid(final @Nullable REnv rEnv) {
+ assumeTrue(rEnv != null);
+ final REnvConfiguration rEnvConfiguration= rEnv.get(REnvConfiguration.class);
+ assumeTrue(rEnvConfiguration != null
+ && rEnvConfiguration.getValidationStatus().getSeverity() == Status.OK );
+ return rEnv;
+ }
+
+ protected void assumeRHelpAvailable(final String envId) throws InterruptedException {
+ final REnvManager rEnvManager= assumeNotNull(this.rEnvManager);
+ final REnv rEnv= assumeREnvValid(rEnvManager.get(envId, null));
+
+ final RHelpManager rHelpManager= assumeNotNull(this.rHelpManager);
+ final long tStart= System.nanoTime();
+ final long tEnd= tStart + SECONDS.toNanos(5);
+ while (tStart < tEnd) {
+ final REnvHelp rEnvHelp= rHelpManager.getHelp(rEnv);
+ if (rEnvHelp != null) {
+ rEnvHelp.unlock();
+ return;
+ }
+ Thread.sleep(500);
+ }
+ assumeTrue(false, String.format("Help for R env '%1$s' available.", envId));
+ }
+
+}
diff --git a/rhelp/org.eclipse.statet.rhelp.server/src/test/java/org/eclipse/statet/rhelp/server/ApplicationTests.java b/rhelp/org.eclipse.statet.rhelp.server/src/test/java/org/eclipse/statet/rhelp/server/ApplicationTests.java
index 0e5fd42..20c1367 100644
--- a/rhelp/org.eclipse.statet.rhelp.server/src/test/java/org/eclipse/statet/rhelp/server/ApplicationTests.java
+++ b/rhelp/org.eclipse.statet.rhelp.server/src/test/java/org/eclipse/statet/rhelp/server/ApplicationTests.java
@@ -17,21 +17,14 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
-import static org.junit.jupiter.api.Assumptions.assumeTrue;
import java.time.Duration;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.context.annotation.Import;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
-import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.jcommons.runtime.AppEnvironment;
import org.eclipse.statet.jcommons.runtime.CommonsRuntime;
import org.eclipse.statet.jcommons.status.Status;
@@ -43,18 +36,8 @@
import org.eclipse.statet.rj.renv.core.REnvManager;
-@ExtendWith(SpringExtension.class)
-@SpringBootTest
-@Import(ContextConfiguration.class)
@NonNullByDefault
-public class ApplicationTests {
-
-
- @Autowired
- private @Nullable REnvManager rEnvManager;
-
- @Autowired
- private @Nullable RHelpManager rHelpManager;
+public class ApplicationTests extends AbstractDefaultAppTest {
@Test
@@ -94,12 +77,32 @@
@Test
@EnabledIfEnvironmentVariable(named = "STATET_TEST_FILES", matches = ".+")
- public void RHelp_available() {
+ public void RHelp_loadAvailable() {
final REnvManager rEnvManager= assumeNotNull(this.rEnvManager);
final REnv rEnv= assumeREnvValid(rEnvManager.get("default", null));
final RHelpManager rHelpManager= assumeNotNull(this.rHelpManager);
+ assertTimeoutPreemptively(Duration.ofSeconds(10),
+ () -> {
+ while (true) {
+ final REnvHelp rEnvHelp= rHelpManager.getHelp(rEnv);
+ if (rEnvHelp != null) {
+ rEnvHelp.unlock();
+ return;
+ }
+ }
+ });
+ }
+
+ @Test
+ @EnabledIfEnvironmentVariable(named = "STATET_TEST_FILES", matches = ".+")
+ public void RHelp_createNew() {
+ final REnvManager rEnvManager= assumeNotNull(this.rEnvManager);
+ final REnv rEnv= assumeREnvValid(rEnvManager.get("new", null));
+
+ final RHelpManager rHelpManager= assumeNotNull(this.rHelpManager);
+
assertTimeoutPreemptively(Duration.ofMinutes(10),
() -> {
while (true) {
@@ -113,19 +116,4 @@
}
- @SuppressWarnings("null")
- private static <T> T assumeNotNull(final @Nullable T value) {
- assumeTrue(value != null);
- return value;
- }
-
- @SuppressWarnings("null")
- private static REnv assumeREnvValid(final @Nullable REnv rEnv) {
- assumeTrue(rEnv != null);
- final REnvConfiguration rEnvConfiguration= rEnv.get(REnvConfiguration.class);
- assumeTrue(rEnvConfiguration != null
- && rEnvConfiguration.getValidationStatus().getSeverity() == Status.OK );
- return rEnv;
- }
-
}
diff --git a/rhelp/org.eclipse.statet.rhelp.server/src/test/java/org/eclipse/statet/rhelp/server/HttpAccesssTests.java b/rhelp/org.eclipse.statet.rhelp.server/src/test/java/org/eclipse/statet/rhelp/server/HttpAccesssTests.java
new file mode 100644
index 0000000..6d8191f
--- /dev/null
+++ b/rhelp/org.eclipse.statet.rhelp.server/src/test/java/org/eclipse/statet/rhelp/server/HttpAccesssTests.java
@@ -0,0 +1,107 @@
+/*=============================================================================#
+ # Copyright (c) 2020 Stephan Wahlbrink <sw@wahlbrink.eu> and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.rhelp.server;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.eclipse.jetty.client.HttpClient;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
+import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.util.StreamUtils;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.internal.rhelp.core.DataStream;
+import org.eclipse.statet.internal.rhelp.core.REnvHelpImpl;
+import org.eclipse.statet.internal.rhelp.core.SerUtil;
+import org.eclipse.statet.internal.rhelp.core.server.JettyREnvHelpAccess;
+import org.eclipse.statet.internal.rhelp.core.server.ServerApi;
+import org.eclipse.statet.rhelp.core.http.jetty.JettyRHelpUtils;
+
+
+@NonNullByDefault
+public class HttpAccesssTests extends AbstractDefaultAppTest {
+
+
+ protected static class TestHelpAccess extends JettyREnvHelpAccess {
+
+
+ public TestHelpAccess(final URI url, final HttpClient httpClient) throws Exception {
+ super(url, httpClient);
+ }
+
+
+ public byte @Nullable [] loadREnvHelpData(
+ final long currentStamp) throws Exception {
+ try (final InputStream in= getDataStream(
+ createUrl(createPath(ServerApi.BASIC_DATA)),
+ ServerApi.createETag(currentStamp) )) {
+ if (in == null) {
+ return null;
+ }
+ return StreamUtils.copyToByteArray(in);
+ }
+ }
+
+ }
+
+
+ @LocalServerPort
+ private int port;
+
+
+ public HttpAccesssTests() {
+ }
+
+
+ private HttpClient getHttpClient() {
+ final HttpClient httpClient= new HttpClient();
+ httpClient.setExecutor(JettyRHelpUtils.getExecutor());
+ httpClient.setAddressResolutionTimeout(10000);
+ httpClient.setConnectTimeout(10000);
+ return httpClient;
+ }
+
+ private URI getHelpUrl(final String envId) throws URISyntaxException {
+ return new URI("http", null, "localhost", this.port, "/" + envId, null, null);
+ }
+
+
+ @Test
+ @EnabledIfEnvironmentVariable(named = "STATET_TEST_FILES", matches = ".+")
+ public void loadBasicData() throws Exception {
+ assumeRHelpAvailable("default");
+
+ final TestHelpAccess clientSupport= new TestHelpAccess(
+ getHelpUrl("default"), getHttpClient() );
+ final byte[] basicDataSerialized= clientSupport.loadREnvHelpData(REnvHelpImpl.NOT_AVAILABLE_STAMP);
+
+ assertNotNull(basicDataSerialized);
+
+ final DataStream in= DataStream.get(new ByteArrayInputStream(basicDataSerialized));
+ Assertions.assertEquals(SerUtil.CURRENT_VERSION, in.readVersion());
+ }
+
+
+}
diff --git a/rhelp/pom.xml b/rhelp/pom.xml
index 65beeae..9e96aaf 100644
--- a/rhelp/pom.xml
+++ b/rhelp/pom.xml
@@ -32,6 +32,7 @@
<modules>
<module>org.eclipse.statet.rhelp.core</module>
+ <module>org.eclipse.statet.rhelp.core-tests</module>
<module>org.eclipse.statet.rhelp.server</module>