diff --git a/eclipse-language-servers/org.springframework.tooling.ls.integration.repository/category.xml b/eclipse-language-servers/org.springframework.tooling.ls.integration.repository/category.xml
index 72dccc22e..301b36d56 100644
--- a/eclipse-language-servers/org.springframework.tooling.ls.integration.repository/category.xml
+++ b/eclipse-language-servers/org.springframework.tooling.ls.integration.repository/category.xml
@@ -40,14 +40,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -65,7 +93,7 @@
-
+
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/.classpath b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/.classpath
new file mode 100644
index 000000000..eca7bdba8
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/.project b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/.project
new file mode 100644
index 000000000..052901b0a
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/.project
@@ -0,0 +1,28 @@
+
+
+ org.springsource.ide.eclipse.commons.boot.ls
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/.settings/org.eclipse.jdt.core.prefs b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..3e5a4cef4
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,314 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.8
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=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.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=1
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+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_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.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.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=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=false
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_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=80
+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.format_guardian_clause_on_one_line=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=false
+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_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_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=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_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_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_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_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_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_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_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_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_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_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_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.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_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+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_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+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.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/.settings/org.eclipse.jdt.ui.prefs b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 000000000..fe75b53ff
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,56 @@
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_SpringSource Tool Suite
+formatter_settings_version=11
+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=false
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=false
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/.settings/org.eclipse.mylyn.tasks.ui.prefs b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/.settings/org.eclipse.mylyn.tasks.ui.prefs
new file mode 100644
index 000000000..488179572
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/.settings/org.eclipse.mylyn.tasks.ui.prefs
@@ -0,0 +1,4 @@
+#Fri Oct 19 17:41:16 PDT 2007
+eclipse.preferences.version=1
+project.repository.kind=jira
+project.repository.url=https\://jira.springsource.com
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/.settings/org.eclipse.mylyn.team.ui.prefs b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/.settings/org.eclipse.mylyn.team.ui.prefs
new file mode 100644
index 000000000..7632f5e7d
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/.settings/org.eclipse.mylyn.team.ui.prefs
@@ -0,0 +1,3 @@
+#Fri Oct 19 17:41:16 PDT 2007
+commit.comment.template=${task.key}\: ${task.description}
+eclipse.preferences.version=1
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..ac88575ed
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/META-INF/MANIFEST.MF
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Spring Tool Suite Common UI Components
+Bundle-SymbolicName: org.springsource.ide.eclipse.commons.boot.ls;singleton:=true
+Bundle-Version: 4.8.1.qualifier
+Bundle-Vendor: Pivotal Software, Inc.
+Require-Bundle: org.eclipse.core.resources,
+ org.springsource.ide.eclipse.commons.livexp
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-ActivationPolicy: lazy
+Automatic-Module-Name: org.springsource.ide.eclipse.commons.boot.ls
+Export-Package: org.springsource.ide.eclipse.commons.boot.ls.remoteapps
+Import-Package: org.eclipse.core.runtime
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/about.html b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/about.html
new file mode 100644
index 000000000..ae88621cc
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/about.html
@@ -0,0 +1,22 @@
+
+
+
+
+About Eclipse Integration Commons
+
+
+
+
About Eclipse Integration Commons
+
June 30, 2015
+
Abstract
+
The Eclipse Integration Commons project provides components that help
+other projects to implement Eclipse-based tooling.
+
License
+
Pivotal Software, Inc. (“Pivotal”) makes available all content
+in this download ("Content"). Unless otherwise indicated below, the
+Content is provided to you under the terms and conditions of the Eclipse
+Public License Version 1.0 ("EPL"). A copy of the EPL is available in
+the file called license.txt. For purposes of the EPL, "Program" will
+mean the Content.
+
+
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/build.properties b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/build.properties
new file mode 100644
index 000000000..20aab766d
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/build.properties
@@ -0,0 +1,8 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ about.html,\
+ plugin.xml
+src.includes = about.html
+
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/plugin.xml b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/plugin.xml
new file mode 100644
index 000000000..c90b9f208
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/plugin.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/pom.xml b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/pom.xml
new file mode 100644
index 000000000..d747b9ba1
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/pom.xml
@@ -0,0 +1,35 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot.ide
+ org.springframework.boot.ide.servers
+ 4.8.1-SNAPSHOT
+ ../pom.xml
+
+
+ org.springsource.ide.eclipse.commons.boot.ls
+ eclipse-plugin
+ org.springsource.ide.eclipse.commons.boot.ls
+
+
+
+
+ org.eclipse.tycho
+ tycho-p2-plugin
+ ${tycho-version}
+
+
+ second-generate-p2-metadata
+
+ p2-metadata
+
+ verify
+
+
+
+
+
+
+
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/schema/org.springsource.ide.eclipse.commons.boot.ls.remoteapps.RemoteBootAppsDataHolder.Contributor.exsd b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/schema/org.springsource.ide.eclipse.commons.boot.ls.remoteapps.RemoteBootAppsDataHolder.Contributor.exsd
new file mode 100644
index 000000000..1c6ff228c
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/schema/org.springsource.ide.eclipse.commons.boot.ls.remoteapps.RemoteBootAppsDataHolder.Contributor.exsd
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+ [Enter description of this extension point.]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [Enter the first release in which this extension point appears.]
+
+
+
+
+
+
+
+
+ [Enter extension point usage example here.]
+
+
+
+
+
+
+
+
+ [Enter API information here.]
+
+
+
+
+
+
+
+
+ [Enter information about supplied implementation of this extension point.]
+
+
+
+
+
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/src/org/springsource/ide/eclipse/commons/boot/ls/remoteapps/ExentionPointLoader.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/src/org/springsource/ide/eclipse/commons/boot/ls/remoteapps/ExentionPointLoader.java
new file mode 100644
index 000000000..246d581c9
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/src/org/springsource/ide/eclipse/commons/boot/ls/remoteapps/ExentionPointLoader.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.boot.ls.remoteapps;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.Platform;
+import org.springsource.ide.eclipse.commons.livexp.util.Log;
+
+public class ExentionPointLoader {
+
+
+ @SuppressWarnings("unchecked")
+ public static List load(Class contributionType) {
+ String extensionPointId = contributionType.getCanonicalName();
+ List constributions = new ArrayList<>();
+ for (IConfigurationElement ce : Platform.getExtensionRegistry().getConfigurationElementsFor(extensionPointId)) {
+ try {
+ Object contribution = ce.createExecutableExtension("class");
+ if (!contributionType.isInstance(contribution)) {
+ throw new IllegalStateException("Invalid contribution to extension point "+extensionPointId);
+ } else {
+ constributions.add((T) contribution);
+ }
+ } catch (Exception e) {
+ Log.log(e);
+ }
+ }
+ return constributions;
+ }
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/src/org/springsource/ide/eclipse/commons/boot/ls/remoteapps/RemoteBootAppsDataHolder.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/src/org/springsource/ide/eclipse/commons/boot/ls/remoteapps/RemoteBootAppsDataHolder.java
new file mode 100644
index 000000000..66a0ed6a3
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.boot.ls/src/org/springsource/ide/eclipse/commons/boot/ls/remoteapps/RemoteBootAppsDataHolder.java
@@ -0,0 +1,260 @@
+/*******************************************************************************
+ * Copyright (c) 2017, 2020 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.boot.ls.remoteapps;
+
+import java.util.List;
+import java.util.function.Supplier;
+
+import org.springsource.ide.eclipse.commons.livexp.core.LiveSets;
+import org.springsource.ide.eclipse.commons.livexp.core.ObservableSet;
+
+/**
+ * A RemoteAppsDataHolder provides the means to connect providers of RemoteAppData
+ * with consumers of RemoteAppData. At present there is one consumer and three producers.
+ *
+ * The single consumer is the Spring Boot Language Server eclipse plugin. It uses remote app data
+ * to scrape live (hover, bean etc.) information from remote boot processes.
+ *
+ * The three producers of the information are:
+ *
+ * a) the "Remote Boot Apps" preferences page (which is defined in the language server
+ * plugin and allows for users to manually enter information.
+ *
+ * b) the BootDashBoard cloudfoundry plugin, which contributes information automatically
+ * when boot apps are deployed to cf from boot dash with JMX tunnelling enabled.
+ * c) BootDashBoard itself via GenericRemoteAppElement framework. This provides remote app
+ * data automatically, for elements that support JMX connections.
+ *
+ * Note: it would be more logical if this class was defined inside boot.ls plugin, (since it
+ * is the (only) consumer of the data). But because of how
+ * STS 4 and STS 3 components are currently being built, it is not possible for STS 3 components
+ * to depend directly on STS 4 components. It is however possible for STS 4 to depend on
+ * STS 3 components. I.e. boot.ls can depend on boot.dashboard but not vice-versa.
+ * This is why {@link RemoteBootAppsDataHolder}
+ * 'extension point' is defined here, allowing boot.dash and spring.boot.ls to both access
+ * the api and contribute and/or consume remote-app data.
+ *
+ * @author Kris De Volder
+ */
+public class RemoteBootAppsDataHolder {
+
+ private static RemoteBootAppsDataHolder DEFAULT;
+
+ public synchronized static RemoteBootAppsDataHolder getDefault() {
+ if (DEFAULT==null) {
+ DEFAULT = new RemoteBootAppsDataHolder(() -> ExentionPointLoader.load(RemoteBootAppsDataHolder.Contributor.class));
+ }
+ return DEFAULT;
+ }
+
+ /**
+ * Json serialization-friendly data class
+ */
+ public static class RemoteAppData {
+ private String jmxurl;
+ private String host;
+ private String urlScheme = "https";
+ private String port = "443";
+ private boolean keepChecking = true;
+ //keepChecking defaults to true. Boot dash automatic remote apps should override this explicitly.
+ //Reason. All other 'sources' of remote apps are 'manual' and we want them to default to
+ //'keepChecking' even if the user doesn't set this to true manually.
+ private String processId = null;
+ private String processName = null;
+
+ public RemoteAppData() {
+ }
+
+ public RemoteAppData(String jmxurl, String host) {
+ super();
+ this.jmxurl = jmxurl;
+ this.host = host;
+ }
+
+ public String getJmxurl() {
+ return jmxurl;
+ }
+
+ public void setJmxurl(String jmxurl) {
+ this.jmxurl = jmxurl;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public String getUrlScheme() {
+ return urlScheme;
+ }
+
+ public void setUrlScheme(String urlScheme) {
+ this.urlScheme = urlScheme;
+ }
+
+ public String getPort() {
+ return port;
+ }
+
+ public void setPort(String port) {
+ this.port = port;
+ }
+
+ public boolean isKeepChecking() {
+ return keepChecking;
+ }
+
+ public void setKeepChecking(boolean keepChecking) {
+ this.keepChecking = keepChecking;
+ }
+
+ public String getProcessId() {
+ return processId;
+ }
+
+ public void setProcessId(String processId) {
+ this.processId = processId;
+ }
+
+ public String getProcessName() {
+ return processName;
+ }
+
+ public void setProcessName(String processName) {
+ this.processName = processName;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((host == null) ? 0 : host.hashCode());
+ result = prime * result + ((jmxurl == null) ? 0 : jmxurl.hashCode());
+ result = prime * result + (keepChecking ? 1231 : 1237);
+ result = prime * result + ((port == null) ? 0 : port.hashCode());
+ result = prime * result + ((processId == null) ? 0 : processId.hashCode());
+ result = prime * result + ((urlScheme == null) ? 0 : urlScheme.hashCode());
+ result = prime * result + ((processId == null) ? 0 : processId.hashCode());
+ result = prime * result + ((processName == null) ? 0 : processName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ RemoteAppData other = (RemoteAppData) obj;
+ if (host == null) {
+ if (other.host != null) {
+ return false;
+ }
+ } else if (!host.equals(other.host)) {
+ return false;
+ }
+ if (jmxurl == null) {
+ if (other.jmxurl != null) {
+ return false;
+ }
+ } else if (!jmxurl.equals(other.jmxurl)) {
+ return false;
+ }
+ if (keepChecking != other.keepChecking) {
+ return false;
+ }
+ if (port == null) {
+ if (other.port != null) {
+ return false;
+ }
+ } else if (!port.equals(other.port)) {
+ return false;
+ }
+ if (processId == null) {
+ if (other.processId != null) {
+ return false;
+ }
+ } else if (!processId.equals(other.processId)) {
+ return false;
+ }
+ if (processName == null) {
+ if (other.processName != null) {
+ return false;
+ }
+ } else if (!processName.equals(other.processName)) {
+ return false;
+ }
+ if (urlScheme == null) {
+ if (other.urlScheme != null) {
+ return false;
+ }
+ } else if (!urlScheme.equals(other.urlScheme)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "RemoteAppData [jmxurl=" + jmxurl + ", host=" + host + ", urlScheme=" + urlScheme + ", port=" + port
+ + ", keepChecking=" + keepChecking + ", processId=" + processId + ", processName=" + processName + "]";
+ }
+
+ }
+
+ /**
+ * A producer of remote RemoteAppData can contribute its data by injecting a bean
+ * that implements this interface (via {@link SimpleDIContext}.
+ */
+ public interface Contributor {
+ ObservableSet getRemoteApps();
+ }
+
+ /**
+ * Computes the union of all Contributors.
+ */
+ private final ObservableSet union;
+
+ public RemoteBootAppsDataHolder(Supplier> contributions) {
+ union = union(contributions.get());
+ }
+
+ public static ObservableSet union(List contributors) {
+ if (contributors.isEmpty()) {
+ return LiveSets.emptySet(RemoteAppData.class);
+ } else if (contributors.size()==1) {
+ return contributors.get(0).getRemoteApps();
+ } else {
+ ObservableSet union = contributors.get(0).getRemoteApps();
+ for (int i = 1; i < contributors.size(); i++) {
+ union = LiveSets.union(union, contributors.get(i).getRemoteApps());
+ }
+ return union;
+ }
+ }
+
+ /**
+ * A consumer of RemoteAppData uses this method to obtain data
+ * and/or listen for changes to the data.
+ */
+ public ObservableSet getRemoteApps() {
+ return union;
+ }
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/.classpath b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/.classpath
new file mode 100644
index 000000000..eca7bdba8
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/.project b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/.project
new file mode 100644
index 000000000..bc025c92c
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/.project
@@ -0,0 +1,39 @@
+
+
+ org.springsource.ide.eclipse.commons.core
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+
+
+
+ 1373409305025
+
+ 14
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-projectRelativePath-matches-false-false-target
+
+
+
+
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/.settings/org.eclipse.jdt.core.prefs b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..0e156a7fa
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,357 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
+org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.8
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=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.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=1
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+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_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.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.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=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=false
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_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=80
+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.format_guardian_clause_on_one_line=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=false
+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_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_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=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_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_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_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_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_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_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_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_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_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_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_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.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_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+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_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+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.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/.settings/org.eclipse.jdt.ui.prefs b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 000000000..9d420de10
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,56 @@
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_SpringSource Tool Suite
+formatter_settings_version=11
+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=false
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=false
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=false
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/.settings/org.eclipse.mylyn.tasks.ui.prefs b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/.settings/org.eclipse.mylyn.tasks.ui.prefs
new file mode 100644
index 000000000..488179572
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/.settings/org.eclipse.mylyn.tasks.ui.prefs
@@ -0,0 +1,4 @@
+#Fri Oct 19 17:41:16 PDT 2007
+eclipse.preferences.version=1
+project.repository.kind=jira
+project.repository.url=https\://jira.springsource.com
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/.settings/org.eclipse.mylyn.team.ui.prefs b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/.settings/org.eclipse.mylyn.team.ui.prefs
new file mode 100644
index 000000000..7632f5e7d
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/.settings/org.eclipse.mylyn.team.ui.prefs
@@ -0,0 +1,3 @@
+#Fri Oct 19 17:41:16 PDT 2007
+commit.comment.template=${task.key}\: ${task.description}
+eclipse.preferences.version=1
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..40208bf5b
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/META-INF/MANIFEST.MF
@@ -0,0 +1,40 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: SpringSource Tool Suite (Core)
+Bundle-SymbolicName: org.springsource.ide.eclipse.commons.core;singleton:=true
+Bundle-Version: 4.8.1.qualifier
+Bundle-Activator: org.springsource.ide.eclipse.commons.internal.core.CorePlugin
+Bundle-Vendor: Pivotal Software, Inc.
+Require-Bundle: org.eclipse.core.resources,
+ org.eclipse.mylyn.commons.net;bundle-version="[3.3.0,4.0.0)",
+ org.eclipse.equinox.p2.core;resolution:=optional,
+ org.eclipse.equinox.p2.repository;resolution:=optional,
+ org.eclipse.jdt.core,
+ org.eclipse.jdt.launching,
+ org.eclipse.wst.common.project.facet.core,
+ org.apache.commons.collections,
+ org.apache.log4j,
+ org.eclipse.platform,
+ org.springsource.ide.eclipse.commons.frameworks.core;bundle-version="3.5.0",
+ org.springsource.ide.eclipse.commons.jdk_tools;resolution:=optional,
+ org.eclipse.text,
+ org.springsource.ide.eclipse.commons.livexp,
+ org.eclipse.debug.core,
+ org.eclipse.jface
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Export-Package: org.springsource.ide.eclipse.commons.core,
+ org.springsource.ide.eclipse.commons.core.preferences,
+ org.springsource.ide.eclipse.commons.core.process,
+ org.springsource.ide.eclipse.commons.core.pstore,
+ org.springsource.ide.eclipse.commons.core.templates,
+ org.springsource.ide.eclipse.commons.core.util,
+ org.springsource.ide.eclipse.commons.internal.core,
+ org.springsource.ide.eclipse.commons.internal.core.commandhistory,
+ org.springsource.ide.eclipse.commons.internal.core.net
+Import-Package: org.eclipse.core.runtime,
+ org.eclipse.core.runtime.jobs,
+ org.eclipse.core.runtime.preferences,
+ org.eclipse.osgi.util,
+ org.osgi.framework,
+ org.osgi.service.prefs
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/about.html b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/about.html
new file mode 100644
index 000000000..ae88621cc
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/about.html
@@ -0,0 +1,22 @@
+
+
+
+
+About Eclipse Integration Commons
+
+
+
+
About Eclipse Integration Commons
+
June 30, 2015
+
Abstract
+
The Eclipse Integration Commons project provides components that help
+other projects to implement Eclipse-based tooling.
+
License
+
Pivotal Software, Inc. (“Pivotal”) makes available all content
+in this download ("Content"). Unless otherwise indicated below, the
+Content is provided to you under the terms and conditions of the Eclipse
+Public License Version 1.0 ("EPL"). A copy of the EPL is available in
+the file called license.txt. For purposes of the EPL, "Program" will
+mean the Content.
+
+
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/build.properties b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/build.properties
new file mode 100644
index 000000000..101ae799c
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/build.properties
@@ -0,0 +1,7 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ about.html,\
+ plugin.xml
+src.includes = about.html
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/plugin.xml b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/plugin.xml
new file mode 100644
index 000000000..e808ee60a
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/plugin.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/pom.xml b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/pom.xml
new file mode 100644
index 000000000..9da2ab8dc
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/pom.xml
@@ -0,0 +1,50 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot.ide
+ org.springframework.boot.ide.servers
+ 4.8.1-SNAPSHOT
+ ../pom.xml
+
+
+ org.springsource.ide.eclipse.commons.core
+ eclipse-plugin
+ org.springsource.ide.eclipse.commons.core
+
+
+
+
+ org.eclipse.tycho
+ tycho-p2-plugin
+ ${tycho-version}
+
+
+ second-generate-p2-metadata
+
+ p2-metadata
+
+ verify
+
+
+
+
+ org.eclipse.tycho
+ tycho-compiler-plugin
+
+
+
+ jdk
+ tools.jar
+ ${java.version}
+ system
+ ${java.home}/../lib/tools.jar
+
+
+
+
+
+
+
+
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/schema/resources.exsd b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/schema/resources.exsd
new file mode 100644
index 000000000..c717ac343
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/schema/resources.exsd
@@ -0,0 +1,160 @@
+
+
+
+
+
+
+
+
+ [Enter description of this extension point.]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [Enter the first release in which this extension point appears.]
+
+
+
+
+
+
+
+
+ [Enter extension point usage example here.]
+
+
+
+
+
+
+
+
+ [Enter API information here.]
+
+
+
+
+
+
+
+
+ [Enter information about supplied implementation of this extension point.]
+
+
+
+
+
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/CommandHistoryProvider.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/CommandHistoryProvider.java
new file mode 100644
index 000000000..bf68b133b
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/CommandHistoryProvider.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.springsource.ide.eclipse.commons.internal.core.CorePlugin;
+import org.springsource.ide.eclipse.commons.internal.core.commandhistory.CommandHistory;
+
+
+/**
+ * Provides access to {@link ICommandHistory} implementations.
+ * @author Christian Dupuis
+ * @author Kris De Volder
+ * @since 2.5.0
+ */
+public class CommandHistoryProvider {
+
+ private static final Map COMMAND_HISTORIES = new HashMap();
+
+ public static synchronized ICommandHistory getCommandHistory(String historyId, String natureId) {
+ String key = getKey(historyId, natureId);
+ if (COMMAND_HISTORIES.containsKey(key)) {
+ return COMMAND_HISTORIES.get(key);
+ }
+ else {
+ try {
+ CommandHistory commandHistory = new CommandHistory(historyId, natureId, true);
+ COMMAND_HISTORIES.put(key, commandHistory);
+ return commandHistory;
+ }
+ catch (CoreException e) {
+ CorePlugin.log(
+ "Warning: couldn't get persistent command history, using non-persistent history instead", e);
+ return new CommandHistory(historyId, natureId);
+ }
+ }
+ }
+
+ private static String getKey(String historyId, String natureId) {
+ Assert.isNotNull(historyId);
+ Assert.isNotNull(natureId);
+ return new StringBuilder().append(historyId).append("_").append(natureId).toString();
+ }
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/CoreUtil.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/CoreUtil.java
new file mode 100644
index 000000000..177798edd
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/CoreUtil.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core;
+
+import java.util.Properties;
+
+import org.eclipse.core.runtime.Assert;
+
+/**
+ * @author Steffen Pingel
+ */
+public class CoreUtil {
+
+ /**
+ * Replaces placeholders in text with values from
+ * properties. Placeholders use the following format:
+ * ${key}. If the key is not found in properties
+ * the placeholder is retained.
+ *
+ * @param text the text
+ * @param properties key value pairs for substitution
+ * @return the substituted text
+ */
+ public static String substitute(String text, Properties properties) {
+ Assert.isNotNull(text);
+ Assert.isNotNull(properties);
+ String[] segments = text.split("\\$\\{");
+ StringBuffer sb = new StringBuffer(text.length());
+ sb.append(segments[0]);
+ for (int i = 1; i < segments.length; i++) {
+ String segment = segments[i];
+ String substitution = null;
+ int brace = segment.indexOf('}');
+ if (brace > 0) {
+ String keyword = segment.substring(0, brace);
+ substitution = properties.getProperty(keyword);
+ }
+
+ if (substitution != null) {
+ sb.append(substitution);
+ sb.append(segment.substring(brace + 1));
+ }
+ else {
+ sb.append("${");
+ sb.append(segment);
+ }
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/Entry.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/Entry.java
new file mode 100644
index 000000000..1f4d03ce3
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/Entry.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core;
+
+import java.io.Serializable;
+
+/**
+ * @author Andrew Eisenberg
+ * @author Christian Dupuis
+ * @author Kris De Volder
+ * @since 2.5.0
+ */
+public class Entry implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String command;
+
+ private final String project;
+
+ public Entry(String command, String project) {
+ super();
+ this.command = command;
+ this.project = project;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ Entry other = (Entry) obj;
+ if (command == null) {
+ if (other.command != null) {
+ return false;
+ }
+ }
+ else if (!command.equals(other.command)) {
+ return false;
+ }
+ if (project == null) {
+ if (other.project != null) {
+ return false;
+ }
+ }
+ else if (!project.equals(other.project)) {
+ return false;
+ }
+ return true;
+ }
+
+ public String getCommand() {
+ return command;
+ }
+
+ public String getMenuLabel() {
+ return getCommand().trim() + " (" + getProject().trim() + ")";
+ }
+
+ public String getProject() {
+ return project;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((command == null) ? 0 : command.hashCode());
+ result = prime * result + ((project == null) ? 0 : project.hashCode());
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Entry(" + command + ", " + project + ")";
+ }
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/FileUtil.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/FileUtil.java
new file mode 100644
index 000000000..c6c9837fd
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/FileUtil.java
@@ -0,0 +1,192 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2018 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.channels.FileChannel;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+import org.osgi.framework.Bundle;
+import org.springsource.ide.eclipse.commons.internal.core.CorePlugin;
+
+
+/**
+ * @author Steffen Pingel
+ * @author Leo Dos Santos
+ * @author Christian Dupuis
+ * @author Kris De Volder
+ */
+public class FileUtil {
+
+ private static final int MAX_FILE_SIZE = 1024 * 1024;
+
+ public static final int BUFFER_SIZE = 4096;
+
+ public static void copyDirectory(File sourceDirectory, File targetDirectory, IProgressMonitor monitor)
+ throws CoreException {
+ File[] files = sourceDirectory.listFiles();
+ if (files != null) {
+ for (File sourceFile : files) {
+ File targetFile = new File(targetDirectory, sourceFile.getName());
+ if (sourceFile.isDirectory()) {
+ targetFile.mkdir();
+ copyDirectory(sourceFile, targetFile, monitor);
+ }
+ else {
+ copyFile(sourceFile, targetFile, monitor);
+ }
+ }
+ }
+ }
+
+ public static void copyFile(File sourceFile, File targetFile, IProgressMonitor monitor) throws CoreException {
+ try {
+ monitor.beginTask("Copying file", (int) sourceFile.length());
+
+ FileInputStream in = new FileInputStream(sourceFile);
+ try {
+ writeToFile(in, targetFile, monitor);
+ }
+ finally {
+ in.close();
+ }
+ }
+ catch (IOException e) {
+ throw new CoreException(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, "Could not copy file from "
+ + sourceFile + " to " + targetFile, e));
+ }
+ finally {
+ monitor.done();
+ }
+ }
+
+ public static void writeToFile(InputStream in, File targetFile, IProgressMonitor monitor)
+ throws FileNotFoundException, IOException {
+ FileOutputStream out = new FileOutputStream(targetFile);
+ try {
+ int len;
+ byte[] buffer = new byte[BUFFER_SIZE];
+ while ((len = in.read(buffer)) > 0) {
+ Policy.checkCancelled(monitor);
+
+ out.write(buffer, 0, len);
+ monitor.worked(len);
+ }
+ }
+ finally {
+ out.close();
+ }
+ }
+
+ public static File getFile(Bundle bundle, String filename) throws CoreException {
+ URL url = bundle.getResource(filename);
+ if (url == null) {
+ throw new CoreException(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, "Could not locate file: "
+ + filename, new FileNotFoundException()));
+ }
+
+ try {
+ return new File(FileLocator.toFileURL(url).getPath());
+ }
+ catch (Exception e) {
+ throw new CoreException(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, "Could not locate file: "
+ + filename, e));
+ }
+ }
+
+ public static File getFile(Plugin plugin, String filename) throws CoreException {
+ return getFile(plugin.getBundle(), filename);
+ }
+
+ public static String readFile(File sourceFile, IProgressMonitor monitor) throws CoreException {
+ long length = sourceFile.length();
+ if (length > MAX_FILE_SIZE) {
+ throw new CoreException(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, "File \"" + sourceFile
+ + "\" is too large"));
+ }
+
+ try {
+ monitor.beginTask("Reading file", (int) length);
+
+ FileReader in = new FileReader(sourceFile);
+ try {
+ StringBuilder sb = new StringBuilder((int) length);
+ int len;
+ char[] buffer = new char[BUFFER_SIZE];
+ while ((len = in.read(buffer)) > 0) {
+ Policy.checkCancelled(monitor);
+
+ sb.append(buffer, 0, len);
+ monitor.worked(len);
+ }
+ return sb.toString();
+ }
+ finally {
+ in.close();
+ }
+ }
+ catch (IOException e) {
+ throw new CoreException(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, "Could not read file \""
+ + sourceFile + "\"", e));
+ }
+ finally {
+ monitor.done();
+ }
+ }
+
+ private static String[] BINARY_EXTENSIONS = new String[] { "jar", "gif", "jpg", "jpeg", ".class", "png" };
+
+ public static void copy(File source, File target) throws IOException {
+ FileInputStream sourceOutStream = new FileInputStream(source);
+ FileOutputStream targetOutStream = new FileOutputStream(target);
+ FileChannel sourceChannel = sourceOutStream.getChannel();
+ FileChannel targetChannel = targetOutStream.getChannel();
+ sourceChannel.transferTo(0, sourceChannel.size(), targetChannel);
+ sourceChannel.close();
+ targetChannel.close();
+ sourceOutStream.close();
+ targetOutStream.close();
+ }
+
+ public static boolean isBinaryFile(File file) {
+ String extension = FileUtil.getExtension(file);
+ if (extension != null) {
+ for (String binaryExtension : BINARY_EXTENSIONS) {
+ if (binaryExtension.equals(extension)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public static String getExtension(File file) {
+ String fileName = file.getName();
+ int extensionIndex = fileName.lastIndexOf('.');
+ if (extensionIndex == -1) {
+ return null;
+ }
+ return fileName.substring(extensionIndex + 1);
+ }
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/HttpUtil.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/HttpUtil.java
new file mode 100644
index 000000000..6bc9e3da0
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/HttpUtil.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.osgi.util.NLS;
+import org.springsource.ide.eclipse.commons.core.util.IOUtil;
+import org.springsource.ide.eclipse.commons.internal.core.CorePlugin;
+import org.springsource.ide.eclipse.commons.internal.core.net.HttpClientTransportService;
+import org.springsource.ide.eclipse.commons.internal.core.net.ITransportService;
+import org.springsource.ide.eclipse.commons.internal.core.net.P2TransportService;
+
+/**
+ * Provides helper methods for downloading files.
+ * @author Steffen Pingel
+ */
+public class HttpUtil {
+
+ private static ITransportService transport;
+
+ public static IStatus download(String url, File archiveFile, File targetDirectory, IProgressMonitor monitor) {
+ return download(url, archiveFile, targetDirectory, null, monitor);
+ }
+
+ public static IStatus download(String url, File archiveFile, File targetDirectory, String prefix,
+ IProgressMonitor monitor) {
+
+ if (monitor.isCanceled()) {
+ return Status.CANCEL_STATUS;
+ }
+
+ SubMonitor progress = SubMonitor.convert(monitor, 100);
+
+ targetDirectory.mkdirs();
+
+ // download archive file
+ try {
+ try {
+ OutputStream out = new BufferedOutputStream(new FileOutputStream(archiveFile));
+ try {
+ HttpUtil.download(new URI(url), out, progress.newChild(70));
+ }
+ catch (CoreException e) {
+ return new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, NLS.bind(
+ "I/O error while retrieving data: {0}", e.getMessage()), e);
+ }
+ catch (URISyntaxException e) {
+ return new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, NLS.bind("Invalid URL: {0}", url), e);
+ }
+ finally {
+ out.close();
+ }
+ }
+ catch (IOException e) {
+ return new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, "I/O error while retrieving data", e);
+ }
+
+ // extract archive file
+ try {
+ URL fileUrl = archiveFile.toURI().toURL();
+ ZipFileUtil.unzip(fileUrl, targetDirectory, prefix, progress.newChild(30));
+ if (targetDirectory.listFiles().length <= 0) {
+ String message = NLS.bind("Zip file {0} appears to be empty", archiveFile);
+ return new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, message);
+ }
+ }
+ catch (IOException e) {
+ return new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, "Error while extracting archive", e);
+ }
+ }
+ finally {
+ archiveFile.delete();
+ }
+ return Status.OK_STATUS;
+ }
+
+ public static void download(URI uri, OutputStream out, IProgressMonitor monitor) throws CoreException {
+ String protocol = uri.getScheme();
+ if ("file".equals(protocol)) {
+ // Yes. it is a bit strange that HttpUtil knows how to read from
+ // file url. But it is just easier that
+ // way. Don't need to special case file urls in other places.
+ // We should consider renaming this class but it has the potential
+ // of breaking a lot of dependencies.
+ File f = new File(uri);
+ FileInputStream contents = null;
+ try {
+ contents = new FileInputStream(f);
+ byte[] buf = new byte[40 * 1024];
+ int read;
+ while ((read = contents.read(buf)) >= 0) {
+ // read = -1 means EOF
+ // read == 0 probably is impossible but handle it anyway.
+ if (read > 0) {
+ out.write(buf, 0, read);
+ }
+ }
+ }
+ catch (IOException e) {
+ throw new CoreException(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, e.getMessage(), e));
+ }
+ finally {
+ try {
+ if (contents != null) {
+ contents.close();
+ }
+ }
+ catch (IOException e) {
+ }
+ }
+ }
+ else {
+ getTransport().download(uri, out, monitor);
+ }
+ }
+
+ public static long getLastModified(URI location, IProgressMonitor monitor) throws CoreException {
+ return getTransport().getLastModified(location, monitor);
+ }
+
+ public static synchronized ITransportService getTransport() {
+ if (transport == null) {
+ if (Platform.isRunning()) {
+ try {
+ transport = new P2TransportService();
+ }
+ catch (ClassNotFoundException e) {
+ // fall back to HttpClientTransport
+ }
+ }
+ if (transport == null) {
+ transport = new HttpClientTransportService();
+ }
+ }
+ return transport;
+ }
+
+ public static InputStream stream(URI uri, IProgressMonitor monitor) throws CoreException {
+ return getTransport().stream(uri, monitor);
+ }
+
+ public static void ping(URI uri) throws MalformedURLException, IOException, CoreException {
+ URLConnection connection = uri.toURL().openConnection();
+ connection.setConnectTimeout(500);
+ InputStream input = connection.getInputStream();
+ IOUtil.consume(input);
+ }
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/ICommandHistory.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/ICommandHistory.java
new file mode 100644
index 000000000..9a0b87716
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/ICommandHistory.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core;
+
+import java.util.List;
+
+/**
+ * @author Christian Dupuis
+ * @author Kris De Volder
+ * @since 2.5.0
+ */
+public interface ICommandHistory {
+
+ /**
+ * The default value for maxSize.
+ */
+ int DEFAULT_MAX_SIZE = 100;
+
+ void add(Entry entry);
+
+ void clear();
+
+ Entry getLast();
+
+ List getRecentValid(int limit);
+
+ boolean isEmpty();
+
+ int size();
+
+ Iterable validEntries();
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/JdtUtils.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/JdtUtils.java
new file mode 100644
index 000000000..b9f4a3976
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/JdtUtils.java
@@ -0,0 +1,944 @@
+// COPIED from spring-ide org.springframework.ide.eclipse.core.java.JdtUtils
+/*******************************************************************************
+ * Copyright (c) 2012 - 2013 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IField;
+import org.eclipse.jdt.core.IImportDeclaration;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaModel;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.ITypeParameter;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTParser;
+import org.eclipse.jdt.core.dom.ASTVisitor;
+import org.eclipse.jdt.launching.JavaRuntime;
+import org.springsource.ide.eclipse.commons.internal.core.CorePlugin;
+
+
+/**
+ * Utility class that provides several helper methods for working with Eclipse's
+ * JDT.
+ * @author Christian Dupuis
+ * @author Martin Lippert
+ * @author Leo Dos Santos
+ * @since 2.0
+ */
+public class JdtUtils {
+
+ public static final String CLASS_FILE_EXTENSION = ".class";
+
+ public static final String GROOVY_FILE_EXTENSION = ".groovy";
+
+ public static final String JAVA_FILE_EXTENSION = ".java";
+
+ private static final String AJDT_CLASS = "org.eclipse.ajdt.core.javaelements.AJCompilationUnitManager";
+
+ private static final String AJDT_NATURE = "org.eclipse.ajdt.ui.ajnature";
+
+ private static final String CLASSPATH_FILENAME = ".classpath";
+
+ private static final boolean IS_AJDT_PRESENT = isAjdtPresent();
+
+ /** Suffix for array class names: "[]" */
+ private static final String ARRAY_SUFFIX = "[]";
+
+ /**
+ * Creates specified Java project.
+ */
+ public static IJavaProject createJavaProject(String projectName, IProgressMonitor monitor) throws CoreException {
+ IProject project = SpringCoreUtils.createProject(projectName, null, monitor);
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ if (!project.hasNature(JavaCore.NATURE_ID)) {
+ SpringCoreUtils.addProjectNature(project, JavaCore.NATURE_ID, monitor);
+ }
+ IJavaProject jproject = JavaCore.create(project);
+ // append JRE entry
+ jproject.setRawClasspath(new IClasspathEntry[] { getJreVariableEntry() }, monitor);
+ jproject.setOutputLocation(project.getFullPath(), monitor);
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ return jproject;
+ }
+
+ /**
+ * Checks if the given type implements/extends
+ * className.
+ */
+ // public static boolean doesImplement(IResource resource, IType type,
+ // String className) {
+ // if (resource == null || type == null || className == null) {
+ // return false;
+ // }
+ // if (className.startsWith("java.") || className.startsWith("javax.")) {
+ // try {
+ // ClassLoader cls = getClassLoader(resource.getProject(), null);
+ // Class> typeClass = cls.loadClass(type.getFullyQualifiedName('$'));
+ // Class> interfaceClass = cls.loadClass(className);
+ // return typeClass.equals(interfaceClass) ||
+ // interfaceClass.isAssignableFrom(typeClass);
+ // }
+ // catch (Throwable e) {
+ // // ignore this and fall back to JDT does implement checks
+ // }
+ // }
+ // return doesImplementWithJdt(resource, type, className);
+ // }
+
+ // public static IType getAjdtType(IProject project, String className) {
+ // IJavaProject javaProject = getJavaProject(project);
+ // if (IS_AJDT_PRESENT && javaProject != null && className != null) {
+ //
+ // try {
+ // IType type = null;
+ //
+ // // First look for the type in the project
+ // if (isAjdtProject(project)) {
+ // type = AjdtUtils.getAjdtType(project, className);
+ // if (type != null) {
+ // return type;
+ // }
+ // }
+ //
+ // // Then look for the type in the referenced Java projects
+ // for (IProject refProject : project.getReferencedProjects()) {
+ // if (isAjdtProject(refProject)) {
+ // type = AjdtUtils.getAjdtType(refProject, className);
+ // if (type != null) {
+ // return type;
+ // }
+ // }
+ // }
+ // }
+ // catch (CoreException e) {
+ // StatusHandler.log(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID,
+ // "Error getting Java type '"
+ // + className + "'", e));
+ // }
+ // }
+ // return null;
+ // }
+
+ public static List getAllDependingJavaProjects(IJavaProject project) {
+ List javaProjects = new ArrayList();
+ IJavaModel model = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot());
+ if (model != null) {
+ try {
+ String[] names = project.getRequiredProjectNames();
+ IJavaProject[] projects = model.getJavaProjects();
+ for (IJavaProject project2 : projects) {
+ for (String name2 : names) {
+ String name = project2.getProject().getName();
+ if (name.equals(name2)) {
+ javaProjects.add(project2);
+ }
+ }
+ }
+ }
+ catch (JavaModelException exception) {
+ }
+ }
+ return javaProjects;
+ }
+
+ /**
+ * Creates a Set of {@link URL}s from the OSGi bundle class path manifest
+ * entry.
+ */
+ // public static Set getBundleClassPath(String bundleId) {
+ // Set paths = new HashSet();
+ // try {
+ // Bundle bundle = Platform.getBundle(bundleId);
+ // if (bundle != null) {
+ // String bundleClassPath = (String) bundle.getHeaders()
+ // .get(org.osgi.framework.Constants.BUNDLE_CLASSPATH);
+ // if (bundleClassPath != null) {
+ // String[] classPathEntries =
+ // StringUtils.delimitedListToStringArray(bundleClassPath, ",");
+ // for (String classPathEntry : classPathEntries) {
+ // if (".".equals(classPathEntry.trim())) {
+ // paths.add(FileLocator.toFileURL(bundle.getEntry("/")));
+ // }
+ // else {
+ // paths.add(FileLocator.toFileURL(new URL(bundle.getEntry("/"), "/" +
+ // classPathEntry.trim())));
+ // }
+ // }
+ // }
+ // else {
+ // paths.add(FileLocator.toFileURL(bundle.getEntry("/")));
+ // }
+ // }
+ // }
+ // catch (MalformedURLException e) {
+ // StatusHandler
+ // .log(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID,
+ // "An error occurred getting classpath", e));
+ // }
+ // catch (IOException e) {
+ // StatusHandler
+ // .log(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID,
+ // "An error occurred getting classpath", e));
+ // }
+ // return paths;
+ // }
+
+ /**
+ * @since 2.6.0
+ */
+ public static IJavaElement getByHandle(String handle) {
+ // if (IS_AJDT_PRESENT) {
+ // return AjdtUtils.getByHandle(handle);
+ // }
+ // else {
+ return JavaCore.create(handle);
+ // }
+ }
+
+ /**
+ * Create a {@link ClassLoader} from the class path configuration of the
+ * given project.
+ * @param project the {@link IProject}
+ * @param useParentClassLoader true if the current OSGi class loader should
+ * be used as parent class loader for the constructed class loader.
+ * @return {@link ClassLoader} instance constructed from the
+ * project's build path configuration
+ */
+ // public static ClassLoader getClassLoader(IProject project, ClassLoader
+ // parentClassLoader) {
+ // return ProjectClassLoaderCache.getClassLoader(project,
+ // parentClassLoader);
+ // }
+ //
+ // public static void removeClassLoaderEntryFromCache(IProject project) {
+ // ProjectClassLoaderCache.removeClassLoaderEntryFromCache(project);
+ // }
+ //
+ // public static IMethod getConstructor(IType type, Class[] parameterTypes)
+ // {
+ // String[] parameterTypesAsString =
+ // getParameterTypesAsStringArray(parameterTypes);
+ // return getConstructor(type, parameterTypesAsString);
+ // }
+
+ // public static IMethod getConstructor(IType type, String[] parameterTypes)
+ // {
+ // try {
+ // Set methods = Introspector.getAllConstructors(type);
+ // for (IMethod method : methods) {
+ // if (method.getParameterTypes().length == parameterTypes.length) {
+ // String[] methodParameterTypes = getParameterTypesAsStringArray(method);
+ // if (Arrays.deepEquals(parameterTypes, methodParameterTypes)) {
+ // return method;
+ // }
+ // }
+ // }
+ // }
+ // catch (JavaModelException e) {
+ // }
+ // return null;
+ // }
+
+ // public static IField getField(IType type, String fieldName, String
+ // parameterType) {
+ // try {
+ // Set methods = Introspector.getAllFields(type);
+ // for (IField field : methods) {
+ // if (field.getElementName().equals(fieldName)) {
+ // return field;
+ // }
+ // }
+ // }
+ // catch (JavaModelException e) {
+ // }
+ // return null;
+ // }
+
+ /**
+ * Returns a flat list of all interfaces and super types for the given
+ * {@link IType}.
+ */
+ // public static List getFlatListOfClassAndInterfaceNames(IType
+ // parameterType, IType type) {
+ // List requiredTypes = new ArrayList();
+ // if (parameterType != null) {
+ // do {
+ // try {
+ // requiredTypes.add(parameterType.getFullyQualifiedName());
+ // String[] interfaceNames = parameterType.getSuperInterfaceNames();
+ // for (String interfaceName : interfaceNames) {
+ // if (interfaceName != null) {
+ // if (type.isBinary()) {
+ // requiredTypes.add(interfaceName);
+ // }
+ // String resolvedName = resolveClassName(interfaceName, type);
+ // if (resolvedName != null) {
+ // requiredTypes.add(resolvedName);
+ // }
+ // }
+ // }
+ // parameterType = Introspector.getSuperType(parameterType);
+ // }
+ // catch (JavaModelException e) {
+ // }
+ // } while (parameterType != null &&
+ // !parameterType.getFullyQualifiedName().equals(Object.class.getName()));
+ // }
+ // return requiredTypes;
+ // }
+
+ /**
+ * Returns the corresponding Java project or null a for given
+ * project.
+ * @param project the project the Java project is requested for
+ * @return the requested Java project or null if the Java
+ * project is not defined or the project is not accessible
+ */
+ public static IJavaProject getJavaProject(IProject project) {
+ if (project.isAccessible()) {
+ try {
+ if (project.hasNature(JavaCore.NATURE_ID)) {
+ return (IJavaProject) project.getNature(JavaCore.NATURE_ID);
+ }
+ }
+ catch (CoreException e) {
+ StatusHandler.log(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID,
+ "Error getting Java project for project '" + project.getName() + "'", e));
+ }
+ }
+ return null;
+ }
+
+ public static IJavaProject getJavaProject(IResource config) {
+ IJavaProject project = JavaCore.create(config.getProject());
+ return project;
+ }
+
+ /**
+ * Returns the corresponding Java type for given full-qualified class name.
+ * @param project the JDT project the class belongs to
+ * @param className the full qualified class name of the requested Java type
+ * @return the requested Java type or null if the class is not defined or
+ * the project is not accessible
+ */
+ public static IType getJavaType(IProject project, String className) {
+ IJavaProject javaProject = JdtUtils.getJavaProject(project);
+ if (className != null) {
+ // For inner classes replace '$' by '.'
+ int pos = className.lastIndexOf('$');
+ if (pos > 0) {
+ className = className.replace('$', '.');
+ }
+ try {
+ IType type = null;
+ // First look for the type in the Java project
+ if (javaProject != null) {
+ // TODO CD not sure why we need
+ type = javaProject.findType(className, new NullProgressMonitor());
+ // type = javaProject.findType(className);
+ if (type != null) {
+ return type;
+ }
+ }
+
+ // Then look for the type in the referenced Java projects
+ for (IProject refProject : project.getReferencedProjects()) {
+ IJavaProject refJavaProject = JdtUtils.getJavaProject(refProject);
+ if (refJavaProject != null) {
+ type = refJavaProject.findType(className);
+ if (type != null) {
+ return type;
+ }
+ }
+ }
+
+ // fall back and try to locate the class using AJDT
+ // TODO: uncomment this call
+ // return getAjdtType(project, className);
+ }
+ catch (CoreException e) {
+ StatusHandler.log(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, "Error getting Java type '"
+ + className + "'", e));
+ }
+ }
+
+ return null;
+ }
+
+ public static final IType getJavaTypeForMethodReturnType(IMethod method, IType contextType) {
+ try {
+ return JdtUtils.getJavaTypeFromSignatureClassName(method.getReturnType(), contextType);
+ }
+ catch (JavaModelException e) {
+ }
+ return null;
+ }
+
+ public static IType getJavaTypeFromSignatureClassName(String className, IType contextType) {
+ if (contextType == null || className == null) {
+ return null;
+ }
+ try {
+ return JdtUtils.getJavaType(contextType.getJavaProject().getProject(),
+ JdtUtils.resolveClassNameBySignature(className, contextType));
+ }
+ catch (IllegalArgumentException e) {
+ // do Nothing
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static final List getJavaTypesForMethodParameterTypes(IMethod method, IType contextType) {
+ if (method == null || method.getParameterTypes() == null || method.getParameterTypes().length == 0) {
+ return Collections.EMPTY_LIST;
+ }
+ List parameterTypes = new ArrayList(method.getParameterTypes().length);
+ String[] parameterTypeNames = method.getParameterTypes();
+ for (String parameterTypeName : parameterTypeNames) {
+ parameterTypes.add(JdtUtils.getJavaTypeFromSignatureClassName(parameterTypeName, contextType));
+ }
+ return parameterTypes;
+ }
+
+ public static IClasspathEntry getJreVariableEntry() {
+ return JavaRuntime.getDefaultJREContainerEntry();
+ }
+
+ public static int getLineNumber(IJavaElement element) {
+ if (element != null && element instanceof IMethod) {
+ try {
+ IMethod method = (IMethod) element;
+ int lines = 0;
+ if (method.getDeclaringType() != null && method.getDeclaringType().getCompilationUnit() != null) {
+ String targetsource = method.getDeclaringType().getCompilationUnit().getSource();
+ if (targetsource != null) {
+ String sourceuptomethod = targetsource.substring(0, method.getNameRange().getOffset());
+
+ char[] chars = new char[sourceuptomethod.length()];
+ sourceuptomethod.getChars(0, sourceuptomethod.length(), chars, 0);
+ for (char element0 : chars) {
+ if (element0 == '\n') {
+ lines++;
+ }
+ }
+ return new Integer(lines + 1);
+ }
+ }
+ }
+ catch (JavaModelException e) {
+ }
+ }
+ else if (element != null && element instanceof IType && ((IType) element).getCompilationUnit() != null) {
+ try {
+ IType type = (IType) element;
+ int lines = 0;
+ String targetsource = type.getCompilationUnit().getSource();
+ if (targetsource != null) {
+ String sourceuptomethod = targetsource.substring(0, type.getNameRange().getOffset());
+
+ char[] chars = new char[sourceuptomethod.length()];
+ sourceuptomethod.getChars(0, sourceuptomethod.length(), chars, 0);
+ for (char element0 : chars) {
+ if (element0 == '\n') {
+ lines++;
+ }
+ }
+ return new Integer(lines + 1);
+ }
+ }
+ catch (JavaModelException e) {
+ }
+ }
+ else if (element != null && element instanceof IField) {
+ try {
+ IField type = (IField) element;
+ int lines = 0;
+ ICompilationUnit cu = type.getCompilationUnit();
+ if (cu != null) {
+ String targetsource = cu.getSource();
+ if (targetsource != null) {
+ String sourceuptomethod = targetsource.substring(0, type.getNameRange().getOffset());
+
+ char[] chars = new char[sourceuptomethod.length()];
+ sourceuptomethod.getChars(0, sourceuptomethod.length(), chars, 0);
+ for (char element0 : chars) {
+ if (element0 == '\n') {
+ lines++;
+ }
+ }
+ return new Integer(lines + 1);
+ }
+ }
+ }
+ catch (JavaModelException e) {
+ }
+ }
+ return new Integer(-1);
+ }
+
+ // public static IMethod getMethod(IType type, String methodName, Class[]
+ // parameterTypes) {
+ // String[] parameterTypesAsString =
+ // getParameterTypesAsStringArray(parameterTypes);
+ // return getMethod(type, methodName, parameterTypesAsString);
+ // }
+
+ // public static IMethod getMethod(IType type, String methodName, String[]
+ // parameterTypes) {
+ // int index = methodName.indexOf('(');
+ // if (index >= 0) {
+ // methodName = methodName.substring(0, index);
+ // }
+ // try {
+ // Set methods = Introspector.getAllMethods(type);
+ // for (IMethod method : methods) {
+ // if (method.getElementName().equals(methodName)
+ // && method.getParameterTypes().length == parameterTypes.length) {
+ // String[] methodParameterTypes = getParameterTypesAsStringArray(method);
+ // if (Arrays.deepEquals(parameterTypes, methodParameterTypes)) {
+ // return method;
+ // }
+ // }
+ // }
+ //
+ // return Introspector.findMethod(type, methodName, parameterTypes.length,
+ // Public.YES, Static.DONT_CARE);
+ // }
+ // catch (JavaModelException e) {
+ // }
+ // return null;
+ // }
+
+ public static String getMethodName(IMethod method) {
+ // Special support Ajdt intertype declarations
+ String methodName = method.getElementName();
+ int index = methodName.lastIndexOf('.');
+ if (index > 0) {
+ methodName = methodName.substring(index + 1);
+ }
+ return methodName;
+ }
+
+ public static String[] getParameterTypesString(IMethod method) {
+ try {
+ String[] parameterQualifiedTypes = Signature.getParameterTypes(method.getSignature());
+ int length = parameterQualifiedTypes == null ? 0 : parameterQualifiedTypes.length;
+ String[] parameterPackages = new String[length];
+ for (int i = 0; i < length; i++) {
+ parameterQualifiedTypes[i] = parameterQualifiedTypes[i].replace('/', '.');
+ parameterPackages[i] = Signature.getSignatureSimpleName(parameterQualifiedTypes[i]);
+ }
+ return parameterPackages;
+ }
+ catch (IllegalArgumentException e) {
+ }
+ catch (JavaModelException e) {
+ }
+ return null;
+ }
+
+ public static String getParentName(IMethod method) {
+ // Special support Ajdt intertype declarations
+ String methodName = method.getElementName();
+ int index = methodName.lastIndexOf('.');
+ if (index > 0) {
+ return methodName.substring(0, index);
+ }
+ else {
+ return method.getParent().getElementName();
+ }
+ }
+
+ // public static IProjectClassLoaderSupport
+ // getProjectClassLoaderSupport(IProject je, ClassLoader parentClassLoader)
+ // {
+ // return new DefaultProjectClassLoaderSupport(je, parentClassLoader);
+ // }
+
+ public static String getPropertyNameFromMethodName(IMethod method) {
+ // Special support Ajdt intertype declarations
+ String methodName = method.getElementName();
+ int index = methodName.lastIndexOf('.');
+ if (index > 0) {
+ methodName = methodName.substring(index + 1);
+ }
+ String replaceText = methodName.substring("set".length());
+ if (replaceText != null) {
+ replaceText = java.beans.Introspector.decapitalize(replaceText);
+ }
+ return replaceText;
+ }
+
+ public static String getReturnTypeString(IMethod method, boolean classTypesOnly) {
+ try {
+ String qualifiedReturnType = Signature.getReturnType(method.getSignature());
+ if (!classTypesOnly || qualifiedReturnType.startsWith("L") || qualifiedReturnType.startsWith("Q")) {
+ return Signature.getSignatureSimpleName(qualifiedReturnType.replace('/', '.'));
+ }
+ }
+ catch (IllegalArgumentException e) {
+ }
+ catch (JavaModelException e) {
+ }
+ return null;
+ }
+
+ public static IResource getSourceResource(IResource classFile) {
+ try {
+ if (isJavaProject(classFile) && classFile.getName().endsWith(CLASS_FILE_EXTENSION)) {
+ IPath classFilePath = classFile.getFullPath();
+ String classFileName = null;
+
+ IJavaProject project = getJavaProject(classFile);
+ IPath defaultOutput = project.getOutputLocation();
+
+ if (defaultOutput.isPrefixOf(classFilePath)) {
+ classFileName = classFilePath.removeFirstSegments(defaultOutput.segmentCount()).toString();
+ }
+ else {
+ for (IClasspathEntry entry : project.getRawClasspath()) {
+ if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ IPath output = entry.getOutputLocation();
+ if (output != null) {
+ if (classFilePath.isPrefixOf(output)) {
+ classFileName = classFilePath.removeFirstSegments(output.segmentCount()).toString();
+ }
+ }
+ }
+ }
+ }
+
+ if (classFileName != null) {
+ // Replace file extension
+ String sourceFileName = classFileName.replace(".class", ".java");
+ for (IClasspathEntry entry : project.getRawClasspath()) {
+ if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ IPath path = entry.getPath().append(sourceFileName).removeFirstSegments(1);
+ IResource resource = project.getProject().findMember(path);
+ if (resource != null) {
+ return resource;
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (JavaModelException e) {
+ }
+ return null;
+ }
+
+ public static boolean isAjdtPresent() {
+ try {
+ Class.forName(AJDT_CLASS);
+ return true;
+ }
+ catch (ClassNotFoundException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns true if given resource's project is a ADJT project.
+ */
+ public static boolean isAjdtProject(IResource resource) {
+ return SpringCoreUtils.hasNature(resource, AJDT_NATURE);
+ }
+
+ /**
+ * Determines if the resource under question is the .classpath
+ * file of a {@link IJavaProject}.
+ */
+ public static boolean isClassPathFile(IResource resource) {
+ String classPathFileName = resource.getProject().getFullPath().append(CLASSPATH_FILENAME).toString();
+ return resource.getFullPath().toString().equals(classPathFileName);
+ }
+
+ /**
+ * Returns true if given resource's project is a Java project.
+ */
+ public static boolean isJavaProject(IResource resource) {
+ return SpringCoreUtils.hasNature(resource, JavaCore.NATURE_ID);
+ }
+
+ // public static boolean isTypeAjdtElement(IType type) {
+ // if (IS_AJDT_PRESENT) {
+ // return AjdtUtils.isTypeAjdtElement(type);
+ // }
+ // return false;
+ // }
+
+ public static boolean isTypeGroovyElement(IType type) {
+ // TODO CD verify following check with Groovy Eclipse
+ ICompilationUnit cu = type.getCompilationUnit();
+ if (cu != null && cu.getResource() != null) {
+ return cu.getResource().getName().endsWith(GROOVY_FILE_EXTENSION);
+ }
+ else if (cu != null) {
+ try {
+ IResource resource = cu.getUnderlyingResource();
+ if (resource != null) {
+ return resource.getName().endsWith(GROOVY_FILE_EXTENSION);
+ }
+ }
+ catch (JavaModelException e) {
+ // ignore
+ }
+ }
+ return false;
+ }
+
+ public static String resolveClassName(String className, IType type) {
+ if (className == null || type == null) {
+ return className;
+ }
+ // replace binary $ inner class name syntax with . for source level
+ className = className.replace('$', '.');
+ String dotClassName = new StringBuilder().append('.').append(className).toString();
+
+ IProject project = type.getJavaProject().getProject();
+
+ try {
+ // Special handling for some well-know classes
+ if (className.startsWith("java.lang") && getJavaType(project, className) != null) {
+ return className;
+ }
+
+ // Check if the class is imported
+ if (!type.isBinary()) {
+
+ // Strip className to first segment to support
+ // ReflectionUtils.MethodCallback
+ int ix = className.lastIndexOf('.');
+ String firstClassNameSegment = className;
+ if (ix > 0) {
+ firstClassNameSegment = className.substring(0, ix);
+ }
+
+ // Iterate the imports
+ for (IImportDeclaration importDeclaration : type.getCompilationUnit().getImports()) {
+ String importName = importDeclaration.getElementName();
+ // Wildcard imports -> check if the package + className is a
+ // valid type
+ if (importDeclaration.isOnDemand()) {
+ String newClassName = new StringBuilder(importName.substring(0, importName.length() - 1))
+ .append(className).toString();
+ if (getJavaType(project, newClassName) != null) {
+ return newClassName;
+ }
+ }
+ // Concrete import matching .className at the end -> check
+ // if type exists
+ else if (importName.endsWith(dotClassName) && getJavaType(project, importName) != null) {
+ return importName;
+ }
+ // Check if className is multi segmented
+ // (ReflectionUtils.MethodCallback)
+ // -> check if the first segment
+ else if (!className.equals(firstClassNameSegment)) {
+ if (importName.endsWith(firstClassNameSegment)) {
+ String newClassName = new StringBuilder(importName.substring(0,
+ importName.lastIndexOf('.') + 1)).append(className).toString();
+ if (getJavaType(project, newClassName) != null) {
+ return newClassName;
+ }
+ }
+ }
+ }
+ }
+
+ // Check if the class is in the same package as the type
+ String packageName = type.getPackageFragment().getElementName();
+ String newClassName = new StringBuilder(packageName).append(dotClassName).toString();
+ if (getJavaType(project, newClassName) != null) {
+ return newClassName;
+ }
+
+ // Check if the className is sufficient (already fully-qualified)
+ if (getJavaType(project, className) != null) {
+ return className;
+ }
+
+ // Check if the class is coming from the java.lang
+ newClassName = new StringBuilder("java.lang").append(dotClassName).toString();
+ if (getJavaType(project, newClassName) != null) {
+ return newClassName;
+ }
+
+ // Fall back to full blown resolution
+ String[][] fullInter = type.resolveType(className);
+ if (fullInter != null && fullInter.length > 0) {
+ return fullInter[0][0] + "." + fullInter[0][1];
+ }
+ }
+ catch (JavaModelException e) {
+ StatusHandler.log(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, "An error occurred resolving class name",
+ e));
+ }
+
+ return className;
+ }
+
+ public static String resolveClassNameBySignature(String className, IType type) {
+ className = Signature.toString(className).replace('$', '.');
+ return resolveClassName(className, type);
+ }
+
+ public static void visitTypeAst(IType type, ASTVisitor visitor) {
+ if (type != null && type.getCompilationUnit() != null) {
+ ASTParser parser = ASTParser.newParser(AST.JLS3);
+ parser.setSource(type.getCompilationUnit());
+ parser.setResolveBindings(true);
+ ASTNode node = parser.createAST(new NullProgressMonitor());
+ node.accept(visitor);
+ }
+ }
+
+ // private static boolean doesImplementWithJdt(IResource resource, IType
+ // type, String className) {
+ // IType interfaceType = getJavaType(resource.getProject(), className);
+ // if (type != null && interfaceType != null) {
+ // try {
+ // IType[] subTypes =
+ // SuperTypeHierarchyCache.getTypeHierarchy(interfaceType)
+ // .getAllSubtypes(interfaceType);
+ // if (subTypes != null) {
+ // for (IType subType : subTypes) {
+ // if (subType.equals(type)) {
+ // return true;
+ // }
+ // }
+ // }
+ // }
+ // catch (JavaModelException ex) {
+ // StatusHandler.log(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID,
+ // "An error occurred resolving subtypes", ex));
+ // }
+ // }
+ // return false;
+ // }
+
+ // private static String[] getParameterTypesAsStringArray(Class[]
+ // parameterTypes) {
+ // String[] parameterTypesAsString = new String[parameterTypes.length];
+ // for (int i = 0; i < parameterTypes.length; i++) {
+ // parameterTypesAsString[i] =
+ // ClassUtils.getQualifiedName(parameterTypes[i]);
+ // }
+ // return parameterTypesAsString;
+ // }
+
+ private static String[] getParameterTypesAsStringArray(IMethod method) {
+ Set typeParameterNames = new HashSet();
+ try {
+ for (ITypeParameter param : method.getDeclaringType().getTypeParameters()) {
+ typeParameterNames.add(param.getElementName());
+ }
+ for (ITypeParameter param : method.getTypeParameters()) {
+ typeParameterNames.add(param.getElementName());
+ }
+ }
+ catch (JavaModelException e) {
+ }
+ String[] parameterTypesAsString = new String[method.getParameterTypes().length];
+ for (int i = 0; i < method.getParameterTypes().length; i++) {
+ String parameterTypeString = Signature.getElementType(method.getParameterTypes()[i]);
+ boolean isArray = !parameterTypeString.equals(method.getParameterTypes()[i]);
+
+ String parameterType = resolveClassNameBySignature(parameterTypeString, method.getDeclaringType());
+ if (typeParameterNames.contains(parameterType)) {
+ parameterTypesAsString[i] = Object.class.getName() + (isArray ? ARRAY_SUFFIX : "");
+ }
+ else {
+ parameterTypesAsString[i] = parameterType + (isArray ? ARRAY_SUFFIX : "");
+ }
+ }
+ return parameterTypesAsString;
+ }
+
+ // static class DefaultProjectClassLoaderSupport implements
+ // IProjectClassLoaderSupport {
+ //
+ // private ClassLoader classLoader;
+ //
+ // private ClassLoader weavingClassLoader;
+ //
+ // public DefaultProjectClassLoaderSupport(IProject javaProject, ClassLoader
+ // parentClassLoader) {
+ // setupClassLoaders(javaProject, parentClassLoader);
+ // }
+ //
+ // public void executeCallback(IProjectClassLoaderAwareCallback callback)
+ // throws Throwable {
+ // try {
+ // activateWeavingClassLoader();
+ // callback.doWithActiveProjectClassLoader();
+ // }
+ // finally {
+ // recoverClassLoader();
+ // }
+ // }
+ //
+ // public ClassLoader getProjectClassLoader() {
+ // return this.weavingClassLoader;
+ // }
+ //
+ // /**
+ // * Activates the weaving class loader as thread context classloader.
+ // *
+ // * Use {@link #recoverClassLoader()} to recover the original thread
+ // * context classloader
+ // */
+ // private void activateWeavingClassLoader() {
+ // Thread.currentThread().setContextClassLoader(weavingClassLoader);
+ // }
+ //
+ // private void recoverClassLoader() {
+ // Thread.currentThread().setContextClassLoader(classLoader);
+ // }
+ //
+ // private void setupClassLoaders(IProject project, ClassLoader
+ // parentClassLoader) {
+ // classLoader = Thread.currentThread().getContextClassLoader();
+ // weavingClassLoader = ProjectClassLoaderCache.getClassLoader(project,
+ // parentClassLoader);
+ // }
+ // }
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/MarkerUtils.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/MarkerUtils.java
new file mode 100644
index 000000000..6669315f7
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/MarkerUtils.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 Spring IDE Developers
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Spring IDE Developers - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.springsource.ide.eclipse.commons.internal.core.CorePlugin;
+
+/**
+ * Some {@link IMarker} helper methods.
+ * @author Torsten Juergeleit
+ * @author Christian Dupuis
+ */
+public final class MarkerUtils {
+
+ public static final String ORIGINATING_RESOURCE_KEY = "originatingResource";
+
+ public static final String ELEMENT_ID_KEY = "elementId";
+
+ public static int getHighestSeverityFromMarkersInRange(IResource resource, String markerId,
+ int startLine, int endLine) {
+ int severity = -1;
+ if (resource != null) {
+ for (IMarker marker : getAllMarkersInRange(resource, markerId, startLine, endLine)) {
+ int sev = marker.getAttribute(IMarker.SEVERITY, -1);
+ if (sev == IMarker.SEVERITY_WARNING) {
+ severity = sev;
+ }
+ else if (sev == IMarker.SEVERITY_ERROR) {
+ severity = sev;
+ break;
+ }
+ }
+ }
+ return severity;
+ }
+
+ public static Set getAllMarkersInRange(IResource resource, String markerId, int startLine, int endLine) {
+ Set foundMarkers = new HashSet();
+ if (resource != null) {
+ try {
+ IMarker[] markers = resource.findMarkers(markerId, true,
+ IResource.DEPTH_INFINITE);
+ for (IMarker marker : markers) {
+ if (startLine == -1 || isMarkerInRange(marker, startLine, endLine)) {
+ foundMarkers.add(marker);
+ }
+ }
+ }
+ catch (CoreException e) {
+ // ignore
+ }
+ }
+ return foundMarkers;
+ }
+
+ public static boolean isMarkerInRange(IMarker marker, int startLine, int endLine)
+ throws CoreException {
+ if (startLine >= 0 && endLine >= startLine && marker.isSubtypeOf(IMarker.TEXT)) {
+ int line = marker.getAttribute(IMarker.LINE_NUMBER, -1);
+ return (line >= startLine && line <= endLine);
+ }
+ return false;
+ }
+
+ /**
+ * Removes all {@link IMarker markers} with the given id (including the
+ * inherited ones) from given {@link IResource} and it's members that if the
+ * marker has an attribute under the key named
+ * {@link #ORIGINATING_RESOURCE_KEY} attribute that matches the given
+ * {@link IResource#getFullPath()}.
+ */
+ public static void deleteAllMarkers(IResource resource, String id) {
+ if (resource != null && resource.isAccessible()) {
+ try {
+ IMarker[] markers = resource.findMarkers(id, true,
+ IResource.DEPTH_ONE);
+ for (IMarker marker : markers) {
+// if (originatingResourceValue.equals(marker
+// .getAttribute(ORIGINATING_RESOURCE_KEY))) {
+ marker.delete();
+// }
+ }
+ }
+ catch (CoreException e) {
+ CorePlugin.log(e);
+ }
+ }
+ }
+
+ /**
+ * Removes all {@link IMarker markers} with given id (including the
+ * inherited ones) from given {@link IResource} and it's members.
+ */
+ public static void deleteMarkers(IResource resource, String id) {
+ if (resource != null && resource.isAccessible()) {
+ try {
+ resource.deleteMarkers(id, true, IResource.DEPTH_INFINITE);
+ }
+ catch (CoreException e) {
+ CorePlugin.log(e);
+ }
+ }
+ }
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/PatternUtils.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/PatternUtils.java
new file mode 100644
index 000000000..23aefe009
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/PatternUtils.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 Spring IDE Developers
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Spring IDE Developers - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core;
+
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+/**
+ * @author Torsten Juergeleit
+ * @author Christian Dupuis
+ */
+public final class PatternUtils {
+
+ private PatternUtils() {
+ // Not for instantiation
+ }
+
+ /**
+ * Creates a pattern element from the pattern string which is either a
+ * reg-ex expression or of wildcard format ('*' matches any character and
+ * '?' matches one character).
+ * @param pattern the search pattern
+ * @param isCaseSensitive set to true to create a case
+ * insensitve pattern
+ * @param isRegexSearch true if the passed string is a reg-ex
+ * pattern
+ * @throws PatternSyntaxException
+ */
+ public static Pattern createPattern(String pattern,
+ boolean isCaseSensitive, boolean isRegexSearch)
+ throws PatternSyntaxException {
+ if (!isRegexSearch) {
+ pattern = toRegExFormat(pattern);
+ }
+ if (!isCaseSensitive) {
+ return Pattern.compile(pattern, Pattern.CASE_INSENSITIVE |
+ Pattern.UNICODE_CASE | Pattern.MULTILINE);
+ }
+ return Pattern.compile(pattern, Pattern.MULTILINE);
+ }
+
+ /**
+ * Converts wildcard format ('*' and '?') to reg-ex format.
+ */
+ private static String toRegExFormat(String pattern) {
+ StringBuffer regex = new StringBuffer(pattern.length());
+ boolean escaped = false;
+ boolean quoting = false;
+ for (int i = 0; i < pattern.length(); i++) {
+ char c = pattern.charAt(i);
+ if (c == '*' && !escaped) {
+ if (quoting) {
+ regex.append("\\E");
+ quoting = false;
+ }
+ regex.append(".*");
+ escaped = false;
+ continue;
+ } else if (c == '?' && !escaped) {
+ if (quoting) {
+ regex.append("\\E");
+ quoting = false;
+ }
+ regex.append(".");
+ escaped = false;
+ continue;
+ } else if (c == '\\' && !escaped) {
+ escaped = true;
+ continue;
+ } else if (c == '\\' && escaped) {
+ escaped = false;
+ if (quoting) {
+ regex.append("\\E");
+ quoting = false;
+ }
+ regex.append("\\\\");
+ continue;
+ }
+ if (!quoting) {
+ regex.append("\\Q");
+ quoting = true;
+ }
+ if (escaped && c != '*' && c != '?' && c != '\\') {
+ regex.append('\\');
+ }
+ regex.append(c);
+ escaped = c == '\\';
+ }
+ if (quoting) {
+ regex.append("\\E");
+ }
+ return regex.toString();
+ }
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/Policy.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/Policy.java
new file mode 100644
index 000000000..1901ec304
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/Policy.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+
+/**
+ * @author Steffen Pingel
+ * @author Leo Dos Santos
+ * @author Christian Dupuis
+ */
+public class Policy {
+
+ public static boolean TEST_MODE;
+
+ static {
+ String application = System.getProperty("eclipse.application", ""); //$NON-NLS-1$ //$NON-NLS-2$
+ if (application.length() > 0) {
+ TEST_MODE = application.endsWith("testapplication") || application.endsWith("uitest"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ public static void checkCancelled(IProgressMonitor monitor) {
+ if (monitor != null && monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ }
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/ResourceProvider.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/ResourceProvider.java
new file mode 100644
index 000000000..91ea6ae23
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/ResourceProvider.java
@@ -0,0 +1,344 @@
+/*******************************************************************************
+ * Copyright (c) 2012 - 2014 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.osgi.util.NLS;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
+import org.osgi.service.prefs.BackingStoreException;
+import org.springsource.ide.eclipse.commons.internal.core.CorePlugin;
+
+/**
+ * Provides access to externalized resources such as urls. Resources are
+ * specified through an extension point.
+ *
+ * @author Steffen Pingel
+ * @author Christian Dupuis
+ */
+public class ResourceProvider {
+
+ public static final String RECORD_SEPARATOR_PATTERN = "[\\r\\n\\s]";
+
+ public static final String FIELD_SEPARATOR = "|";
+
+ public static final String FIELD_SEPARATOR_PATTERN = "\\|";
+
+ public static final String RECORD_SEPARATOR = "\n";
+
+ public static class Property {
+
+ public String type;
+
+ private String id;
+
+ private String label;
+
+ private String defaultValue;
+
+ private boolean multiValue;
+
+ private boolean userConfigurable;
+
+ private String contributedValue;
+
+ private final ResourceProvider provider;
+
+ private Property(ResourceProvider provider) {
+ this.provider = provider;
+ }
+
+ public String getDefaultValue() {
+ String value = contributedValue;
+ if (value == null) {
+ value = defaultValue;
+ }
+ return value;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public String getValue() {
+ String value = provider.getPreferences().get(id, null);
+ if (value == null) {
+ value = contributedValue;
+ }
+ if (value == null) {
+ value = defaultValue;
+ }
+ return value;
+ }
+
+ public boolean isMultiValue() {
+ return multiValue;
+ }
+
+ public boolean isUserConfigurable() {
+ return userConfigurable;
+ }
+
+ public void setValue(String value) {
+ provider.getPreferences().put(id, value);
+ try {
+ provider.getPreferences().flush();
+ } catch (BackingStoreException e) {
+ StatusHandler.log(new Status(IStatus.ERROR,
+ CorePlugin.PLUGIN_ID,
+ "Error occured while saving preferences", e));
+ }
+ }
+
+ }
+
+ private static class ExtensionPointReader {
+
+ private static final String ATTRIBUTE_ID = "id";
+
+ private static final String ATTRIBUTE_VALUE = "value";
+
+ private static final String ATTRIBUTE_LABEL = "label";
+
+ private static final String ATTRIBUTE_TYPE = "type";
+
+ private static final String ATTRIBUTE_MULTI_VALUE = "multiValue";
+
+ private static final String ATTRIBUTE_DEFAULT_VALUE = "defaultValue";
+
+ private static final String ATTRIBUTE_USER_CONFIGURABLE = "userConfigurable";
+
+ private static final String ELEMENT_URL = "url";
+
+ private static final String ELEMENT_PROPERTY = "propertyDefinition";
+
+ private static final String EXTENSION_ID_REFERENCES = "com.springsource.sts.core.resources";
+
+ private final Map valueByKey = new HashMap();
+
+ private final Map propertyById = new HashMap();
+
+ public void read(ResourceProvider resourceProvider) {
+ IExtensionRegistry registry = Platform.getExtensionRegistry();
+ IExtensionPoint extensionPoint = registry
+ .getExtensionPoint(EXTENSION_ID_REFERENCES);
+ IExtension[] extensions = extensionPoint.getExtensions();
+
+ // read property definitions
+ for (IExtension extension : extensions) {
+ IConfigurationElement[] elements = extension
+ .getConfigurationElements();
+ for (IConfigurationElement element : elements) {
+ if (element.getName().compareTo(ELEMENT_PROPERTY) == 0) {
+ Property p = new Property(resourceProvider);
+ p.id = element.getAttribute(ATTRIBUTE_ID);
+ p.label = element.getAttribute(ATTRIBUTE_LABEL);
+ p.defaultValue = element
+ .getAttribute(ATTRIBUTE_DEFAULT_VALUE);
+ p.multiValue = Boolean.parseBoolean(element
+ .getAttribute(ATTRIBUTE_MULTI_VALUE));
+ p.userConfigurable = Boolean.parseBoolean(element
+ .getAttribute(ATTRIBUTE_USER_CONFIGURABLE));
+ p.type = element.getAttribute(ATTRIBUTE_TYPE);
+ propertyById.put(p.id, p);
+ }
+ }
+ }
+
+ // read contributed definitions
+ for (IExtension extension : extensions) {
+ IConfigurationElement[] elements = extension
+ .getConfigurationElements();
+ for (IConfigurationElement element : elements) {
+ if (element.getName().compareTo(ELEMENT_URL) == 0) {
+ String key = element.getAttribute(ATTRIBUTE_ID);
+ String value = element.getAttribute(ATTRIBUTE_VALUE);
+ valueByKey.put(key, value);
+
+ Property p = propertyById.get(key);
+ if (p == null) {
+ // property was not defined explicitly
+ p = new Property(resourceProvider);
+ p.id = key;
+ p.label = "";
+ propertyById.put(p.id, p);
+ }
+ p.contributedValue = value;
+ }
+ }
+ }
+ }
+
+ }
+
+ private final IEclipsePreferences preferences;
+
+ private static ResourceProvider instance = new ResourceProvider();
+
+ public static ResourceProvider getInstance() {
+ return instance;
+ }
+
+ public static String getUrl(String key) {
+ return getUrls(key)[0];
+ }
+
+ public static String[] getUrls(String key) {
+ String[] urls = parseUrls(key, instance.getValue(key));
+ String[] defaultUrls = parseUrls(key, instance.getDefaultValue(key));
+
+ Set cleanableUrls = new HashSet<>();
+ for (String url : defaultUrls) {
+ if (url.startsWith("https:")) {
+ cleanableUrls.add("http:"+url.substring(6));
+ } else if (url.startsWith("http:")) {
+ cleanableUrls.add(url);
+ }
+ }
+
+ for (int i = 0; i < urls.length; i++) {
+ String url = urls[i];
+ if (cleanableUrls.contains(url)) {
+ urls[i] = "https:"+url.substring(5);
+ }
+ }
+ return urls;
+ }
+
+ private static String[] parseUrls(String key, String value) {
+ if (value == null) {
+ throw new RuntimeException(NLS.bind(
+ "No URL found for key: ''{0}''", key));
+ }
+ if (value.isEmpty()) {
+ return new String[0];
+ }
+
+ // Post process the urls to replace UUID and version number placeholders
+ if (value.contains("%UUID%")) {
+ value = value.replace("%UUID%", CorePlugin.getUUID());
+ }
+ if (value.contains("%VERSION%") || value.contains("%SHORT_VERSION%")) {
+ Bundle bundle = CorePlugin.getDefault().getBundle();
+ Version version = new Version((String) bundle.getHeaders().get(
+ "Bundle-Version")); //$NON-NLS-1$
+ value = value.replace("%VERSION%", version.toString());
+ value = value.replace("%SHORT_VERSION%", version.getMajor() + "."
+ + version.getMinor());
+ }
+ String[] values = value.split(RECORD_SEPARATOR_PATTERN);
+ return discardLocationNames(values);
+ }
+
+ private static String[] discardLocationNames(String[] values) {
+ for (int i = 0; i < values.length; i++) {
+ String nameUrlString = values[i];
+ String[] nameUrlStrings = nameUrlString
+ .split(FIELD_SEPARATOR_PATTERN);
+ if (nameUrlStrings.length == 2) {
+ String url = nameUrlStrings[1];
+ values[i] = url;
+ }
+ }
+ return values;
+ }
+
+ private final Map propertyById;
+
+ private final List listeners;
+
+ private ResourceProvider() {
+ this.listeners = new CopyOnWriteArrayList();
+ this.preferences = new InstanceScope().getNode(CorePlugin.PLUGIN_ID);
+ this.preferences
+ .addPreferenceChangeListener(new IPreferenceChangeListener() {
+ public void preferenceChange(PreferenceChangeEvent event) {
+ Property p = propertyById.get(event.getKey());
+ if (p != null) {
+ for (PropertyChangeListener listener : listeners) {
+ listener.propertyChange(new PropertyChangeEvent(
+ ResourceProvider.this, p.id, event
+ .getOldValue(), event
+ .getNewValue()));
+ }
+ }
+ }
+ });
+
+ DefaultScope.INSTANCE.getNode(CorePlugin.PLUGIN_ID).addPreferenceChangeListener(new IPreferenceChangeListener() {
+ @Override
+ public void preferenceChange(PreferenceChangeEvent event) {
+ Property p = propertyById.get(event.getKey());
+ if (p != null) {
+ p.defaultValue = (String)event.getNewValue();
+ }
+ }
+ });
+
+ ExtensionPointReader reader = new ExtensionPointReader();
+ reader.read(this);
+ this.propertyById = reader.propertyById;
+ }
+
+ public void addPropertyChangeListener(PropertyChangeListener listener) {
+ listeners.add(listener);
+ }
+
+ public IEclipsePreferences getPreferences() {
+ return preferences;
+ }
+
+ public Collection getProperties() {
+ return Collections.unmodifiableCollection(propertyById.values());
+ }
+
+ public Property getProperty(String id) {
+ return propertyById.get(id);
+ }
+
+ public void removePropertyChangeListener(PropertyChangeListener listener) {
+ listeners.remove(listener);
+ }
+
+ private String getValue(String key) {
+ Property p = propertyById.get(key);
+ return (p != null) ? p.getValue() : null;
+ }
+
+ private String getDefaultValue(String key) {
+ Property p = propertyById.get(key);
+ return (p != null) ? p.getDefaultValue() : null;
+ }
+
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/SpringCorePreferences.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/SpringCorePreferences.java
new file mode 100644
index 000000000..1d52d2f89
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/SpringCorePreferences.java
@@ -0,0 +1,104 @@
+// COPIED from spring-ide org.springframework.ide.eclipse.core.SpringCorePreferences
+/*******************************************************************************
+ * Copyright (c) 2012 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.osgi.service.prefs.BackingStoreException;
+import org.springsource.ide.eclipse.commons.internal.core.CorePlugin;
+
+
+/**
+ * @author Christian Dupuis
+ * @since 2.0
+ */
+public class SpringCorePreferences {
+
+ /** The identifier for enablement of project versus workspace settings */
+ public static final String PROJECT_PROPERTY_ID = "enable.project.preferences";
+
+ private final String propertyNamespace;
+
+ private final IEclipsePreferences preferences;
+
+ private SpringCorePreferences(IProject project, String qualifier) {
+ this.propertyNamespace = qualifier + '.';
+ this.preferences = getEclipsePreferences(project, qualifier);
+ }
+
+ // public static SpringCorePreferences getProjectPreferences(IProject
+ // project) {
+ // return getProjectPreferences(project, SpringCore.PLUGIN_ID);
+ // }
+
+ public static SpringCorePreferences getProjectPreferences(IProject project, String qualifier) {
+ return new SpringCorePreferences(project, qualifier);
+ }
+
+ public static SpringCorePreferences getPluginPreferences(String qualifier) {
+ return new SpringCorePreferences(null, qualifier);
+ }
+
+ private IEclipsePreferences getEclipsePreferences(IProject project, String qualifier) {
+ IScopeContext context = project!=null
+ ? new ProjectScope(project)
+ : InstanceScope.INSTANCE;
+ IEclipsePreferences node = context.getNode(qualifier);
+ return node;
+ }
+
+ public void putString(String key, String value) {
+ if (key == null || value == null) {
+ return;
+ }
+ try {
+ this.preferences.put(propertyNamespace + key, value);
+ this.preferences.flush();
+ }
+ catch (BackingStoreException e) {
+ StatusHandler.log(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, "An error occurred updating preferences",
+ e));
+ }
+ }
+
+ public void putBoolean(String key, boolean value) {
+ if (key == null) {
+ return;
+ }
+ try {
+ this.preferences.putBoolean(propertyNamespace + key, value);
+ this.preferences.flush();
+ }
+ catch (BackingStoreException e) {
+ StatusHandler.log(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, "An error occurred updating preferences",
+ e));
+ }
+ }
+
+ public String getString(String key, String defaultValue) {
+ return this.preferences.get(propertyNamespace + key, defaultValue);
+ }
+
+ public boolean getBoolean(String key, boolean defaultValue) {
+ return this.preferences.getBoolean(propertyNamespace + key, defaultValue);
+ }
+
+ public IEclipsePreferences getProjectPreferences() {
+ return this.preferences;
+ }
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/SpringCoreUtils.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/SpringCoreUtils.java
new file mode 100644
index 000000000..0b68a1cd3
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/SpringCoreUtils.java
@@ -0,0 +1,809 @@
+// COPIED from spring-ide org.springframework.ide.eclipse.core.SpringCoreUtils
+/*******************************************************************************
+ * Copyright (c) 2012, 2013 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.commons.lang.StringUtils;
+import org.eclipse.core.resources.ICommand;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IPathVariableManager;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.wst.common.project.facet.core.FacetedProjectFramework;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+import org.springsource.ide.eclipse.commons.internal.core.CorePlugin;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * Some helper methods.
+ * @author Torsten Juergeleit
+ * @author Christian Dupuis
+ * @author Martin Lippert
+ */
+public final class SpringCoreUtils {
+
+ /**
+ * File name of OSGi bundle manifests
+ * @since 2.0.5
+ */
+ public static String BUNDLE_MANIFEST_FILE = "MANIFEST.MF";
+
+ /**
+ * Folder name of OSGi bundle manifests directories
+ * @since 2.0.5
+ */
+ public static String BUNDLE_MANIFEST_FOLDER = "META-INF";
+
+ /** New placeholder string for Spring 3 EL support */
+ public static final String EL_PLACEHOLDER_PREFIX = "#{";
+
+ /** URL file schema */
+ public static final String FILE_SCHEME = "file";
+
+ public static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+ public static final String PLACEHOLDER_PREFIX = "${";
+
+ public static final String PLACEHOLDER_SUFFIX = "}";
+
+ public static final String SOURCE_CONTROL_SCHEME = "sourcecontrol";
+
+ private static final String DEPLOY_PATH = "deploy-path";
+
+ private static boolean DOCUMENT_BUILDER_ERROR = false;
+
+ private static final Object DOCUMENT_BUILDER_LOCK = new Object();
+
+ private static XPathExpression EXPRESSION;
+
+ private static boolean SAX_PARSER_ERROR = false;
+
+ private static final Object SAX_PARSER_LOCK = new Object();
+
+ private static final String SOURCE_PATH = "source-path";
+
+ private static final String XPATH_EXPRESSION = "//project-modules/wb-module/wb-resource";
+
+ private static final String SPRING_BUILDER_ID = "org.springframework.ide.eclipse.core.springbuilder";
+
+ private static final String MARKER_ID = "org.springframework.ide.eclipse.core.problemmarker";
+
+ public static final String NATURE_ID = "org.springframework.ide.eclipse.core.springnature";
+
+ static {
+ try {
+ XPathFactory newInstance = XPathFactory.newInstance();
+ XPath xpath = newInstance.newXPath();
+ EXPRESSION = xpath.compile(XPATH_EXPRESSION);
+ }
+ catch (XPathExpressionException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Adds given builder to specified project.
+ */
+ public static void addProjectBuilder(IProject project, String builderID, IProgressMonitor monitor)
+ throws CoreException {
+ IProjectDescription desc = project.getDescription();
+ ICommand builderCommand = getProjectBuilderCommand(desc, builderID);
+ if (builderCommand == null) {
+
+ // Add a new build spec
+ ICommand command = desc.newCommand();
+ command.setBuilderName(builderID);
+
+ // Commit the spec change into the project
+ addProjectBuilderCommand(desc, command);
+ project.setDescription(desc, monitor);
+ }
+ }
+
+ /**
+ * Adds (or updates) a builder in given project description.
+ */
+ public static void addProjectBuilderCommand(IProjectDescription description, ICommand command) throws CoreException {
+ ICommand[] oldCommands = description.getBuildSpec();
+ ICommand oldBuilderCommand = getProjectBuilderCommand(description, command.getBuilderName());
+ ICommand[] newCommands;
+ if (oldBuilderCommand == null) {
+
+ // Add given builder to the end of the builder list
+ newCommands = new ICommand[oldCommands.length + 1];
+ System.arraycopy(oldCommands, 0, newCommands, 0, oldCommands.length);
+ newCommands[oldCommands.length] = command;
+ }
+ else {
+
+ // Replace old builder with given new one
+ for (int i = 0, max = oldCommands.length; i < max; i++) {
+ if (oldCommands[i] == oldBuilderCommand) {
+ oldCommands[i] = command;
+ break;
+ }
+ }
+ newCommands = oldCommands;
+ }
+ description.setBuildSpec(newCommands);
+ }
+
+ /**
+ * Adds given nature as first nature to specified project.
+ */
+ public static void addProjectNature(IProject project, String nature, IProgressMonitor monitor) throws CoreException {
+ if (project != null && nature != null) {
+ if (!project.hasNature(nature)) {
+ IProjectDescription desc = project.getDescription();
+ String[] oldNatures = desc.getNatureIds();
+ String[] newNatures = new String[oldNatures.length + 1];
+ newNatures[0] = nature;
+ if (oldNatures.length > 0) {
+ System.arraycopy(oldNatures, 0, newNatures, 1, oldNatures.length);
+ }
+ desc.setNatureIds(newNatures);
+ project.setDescription(desc, monitor);
+ }
+ }
+ }
+
+ /**
+ * Triggers a build of the given {@link IProject} instance, but only the
+ * Spring builder
+ * @param project the project to build
+ */
+ public static void buildProject(IProject project) {
+ buildProject(project, SPRING_BUILDER_ID);
+ }
+
+ /**
+ * Triggers a build of the given {@link IProject} instance with a full build
+ * and all builders
+ * @param project the project to build
+ */
+ public static void buildFullProject(IProject project) {
+ buildProject(project, null);
+ }
+
+ /**
+ * Triggers a build of the given {@link IProject} instance, but only the
+ * Spring builder
+ * @param project the project to build
+ * @param builderID the ID of the specific builder that should be executed
+ * on the project
+ * @since 3.2.0
+ */
+ public static void buildProject(IProject project, String builderID) {
+ if (ResourcesPlugin.getWorkspace().isAutoBuilding()) {
+ scheduleBuildInBackground(project, ResourcesPlugin.getWorkspace().getRuleFactory().buildRule(),
+ new Object[] { ResourcesPlugin.FAMILY_AUTO_BUILD }, builderID);
+ }
+ }
+
+ /**
+ * Creates given folder and (if necessary) all of it's parents.
+ */
+ public static void createFolder(IFolder folder, IProgressMonitor monitor) throws CoreException {
+ if (!folder.exists()) {
+ IContainer parent = folder.getParent();
+ if (parent instanceof IFolder) {
+ createFolder((IFolder) parent, monitor);
+ }
+ folder.create(true, true, monitor);
+ }
+ }
+
+ /**
+ * Creates specified simple project.
+ */
+ public static IProject createProject(String projectName, IProjectDescription description, IProgressMonitor monitor)
+ throws CoreException {
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ IProject project = root.getProject(projectName);
+ if (!project.exists()) {
+ if (description == null) {
+ project.create(monitor);
+ }
+ else {
+ project.create(description, monitor);
+ }
+ }
+ else {
+ project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
+ }
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ if (!project.isOpen()) {
+ project.open(monitor);
+ }
+ return project;
+ }
+
+ /**
+ * Finds the first line separator used by the given text.
+ * @return "\n" or "\r" or "\r\n",
+ * or null if none found
+ * @since 2.2.2
+ */
+ public static String findLineSeparator(char[] text) {
+ // find the first line separator
+ int length = text.length;
+ if (length > 0) {
+ char nextChar = text[0];
+ for (int i = 0; i < length; i++) {
+ char currentChar = nextChar;
+ nextChar = i < length - 1 ? text[i + 1] : ' ';
+ switch (currentChar) {
+ case '\n':
+ return "\n"; //$NON-NLS-1$
+ case '\r':
+ return nextChar == '\n' ? "\r\n" : "\r"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ }
+ // not found
+ return null;
+ }
+
+ /**
+ * Returns the specified adapter for the given object or null
+ * if adapter is not supported.
+ */
+ @SuppressWarnings("unchecked")
+ public static T getAdapter(Object object, Class adapter) {
+ if (object != null && adapter != null) {
+ if (adapter.isAssignableFrom(object.getClass())) {
+ return (T) object;
+ }
+ if (object instanceof IAdaptable) {
+ return (T) ((IAdaptable) object).getAdapter(adapter);
+ }
+ }
+ return null;
+ }
+
+ public static IFile getDeploymentDescriptor(IProject project) {
+ if (SpringCoreUtils.hasProjectFacet(project, "jst.web")) {
+ IFile settingsFile = project.getFile(".settings/org.eclipse.wst.common.component");
+ if (settingsFile.exists()) {
+ try {
+ NodeList nodes = (NodeList) EXPRESSION
+ .evaluate(parseDocument(settingsFile), XPathConstants.NODESET);
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Element element = (Element) nodes.item(i);
+ if ("/".equals(element.getAttribute(DEPLOY_PATH))) {
+ String path = element.getAttribute(SOURCE_PATH);
+ if (path != null) {
+ IFile deploymentDescriptor = project.getFile(new Path(path).append("WEB-INF").append(
+ "web.xml"));
+ if (deploymentDescriptor.exists()) {
+ return deploymentDescriptor;
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e) {
+ StatusHandler.log(new Status(IStatus.WARNING, CorePlugin.PLUGIN_ID, 1, e.getMessage(), e));
+ }
+ }
+ }
+ return null;
+ }
+
+ public static DocumentBuilder getDocumentBuilder() {
+ try {
+ DocumentBuilderFactory documentBuilderFactory = getDocumentBuilderFactory();
+ documentBuilderFactory.setExpandEntityReferences(false);
+ return documentBuilderFactory.newDocumentBuilder();
+ }
+ catch (Exception e) {
+ StatusHandler.log(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, "Error creating DocumentBuilder", e));
+ }
+ return null;
+ }
+
+ public static DocumentBuilderFactory getDocumentBuilderFactory() {
+ if (!DOCUMENT_BUILDER_ERROR) {
+ try {
+ // this might fail on IBM J9; therefore trying only once and
+ // then falling back to
+ // OSGi service reference as it should be
+ return DocumentBuilderFactory.newInstance();
+ }
+ catch (Exception e) {
+ StatusHandler.log(new Status(IStatus.INFO, CorePlugin.PLUGIN_ID,
+ "Error creating DocumentBuilderFactory. Switching to OSGi service reference."));
+ DOCUMENT_BUILDER_ERROR = true;
+ }
+ }
+
+ BundleContext bundleContext = CorePlugin.getDefault().getBundle().getBundleContext();
+ ServiceReference reference = bundleContext.getServiceReference(DocumentBuilderFactory.class.getName());
+ if (reference != null) {
+ try {
+ synchronized (DOCUMENT_BUILDER_LOCK) {
+ return (DocumentBuilderFactory) bundleContext.getService(reference);
+ }
+ }
+ catch (Exception e) {
+ StatusHandler.log(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID,
+ "Error creating DocumentBuilderFactory", e));
+ }
+ finally {
+ bundleContext.ungetService(reference);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the line separator found in the given text. If it is null, or not
+ * found return the line delimiter for the given project. If the project is
+ * null, returns the line separator for the workspace. If still null, return
+ * the system line separator.
+ * @since 2.2.2
+ */
+ public static String getLineSeparator(String text, IProject project) {
+ String lineSeparator = null;
+
+ // line delimiter in given text
+ if (text != null && text.length() != 0) {
+ lineSeparator = findLineSeparator(text.toCharArray());
+ if (lineSeparator != null) {
+ return lineSeparator;
+ }
+ }
+
+ // line delimiter in project preference
+ IScopeContext[] scopeContext;
+ if (project != null) {
+ scopeContext = new IScopeContext[] { new ProjectScope(project) };
+ lineSeparator = Platform.getPreferencesService().getString(Platform.PI_RUNTIME,
+ Platform.PREF_LINE_SEPARATOR, null, scopeContext);
+ if (lineSeparator != null) {
+ return lineSeparator;
+ }
+ }
+
+ // line delimiter in workspace preference
+ scopeContext = new IScopeContext[] { new InstanceScope() };
+ lineSeparator = Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR,
+ null, scopeContext);
+ if (lineSeparator != null) {
+ return lineSeparator;
+ }
+
+ // system line delimiter
+ return LINE_SEPARATOR;
+ }
+
+ /**
+ * Returns specified builder from given project description.
+ */
+ public static ICommand getProjectBuilderCommand(IProjectDescription description, String builderID)
+ throws CoreException {
+ ICommand[] commands = description.getBuildSpec();
+ for (int i = commands.length - 1; i >= 0; i--) {
+ if (commands[i].getBuilderName().equals(builderID)) {
+ return commands[i];
+ }
+ }
+ return null;
+ }
+
+ public static IPath getProjectLocation(IProject project) {
+ return (project.getRawLocation() != null ? project.getRawLocation() : project.getLocation());
+ }
+
+ public static URI getResourceURI(IResource resource) {
+ if (resource != null) {
+ URI uri = resource.getRawLocationURI();
+ if (uri == null) {
+ uri = resource.getLocationURI();
+ }
+ if (uri != null) {
+ String scheme = uri.getScheme();
+ if (FILE_SCHEME.equalsIgnoreCase(scheme)) {
+ return uri;
+ }
+ else if (SOURCE_CONTROL_SCHEME.equals(scheme)) {
+ // special case of Rational Team Concert
+ IPath path = resource.getLocation();
+ File file = path.toFile();
+ if (file.exists()) {
+ return file.toURI();
+ }
+ }
+ else {
+ IPathVariableManager variableManager = ResourcesPlugin.getWorkspace().getPathVariableManager();
+ return variableManager.resolveURI(uri);
+ }
+ }
+ }
+ return null;
+ }
+
+ public static SAXParser getSaxParser() {
+ if (!SAX_PARSER_ERROR) {
+ try {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ SAXParser parser = factory.newSAXParser();
+ return parser;
+ }
+ catch (Exception e) {
+ StatusHandler.log(new Status(IStatus.INFO, CorePlugin.PLUGIN_ID,
+ "Error creating SaxParserFactory. Switching to OSGI service reference."));
+ SAX_PARSER_ERROR = true;
+ }
+ }
+
+ BundleContext bundleContext = CorePlugin.getDefault().getBundle().getBundleContext();
+ ServiceReference reference = bundleContext.getServiceReference(SAXParserFactory.class.getName());
+ if (reference != null) {
+ try {
+ synchronized (SAX_PARSER_LOCK) {
+ SAXParserFactory factory = (SAXParserFactory) bundleContext.getService(reference);
+ return factory.newSAXParser();
+ }
+ }
+ catch (Exception e) {
+ StatusHandler
+ .log(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, "Error creating SaxParserFactory", e));
+ }
+ finally {
+ bundleContext.ungetService(reference);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns a list of all projects with the Spring project nature.
+ */
+ public static Set getSpringProjects() {
+ Set projects = new LinkedHashSet();
+ for (IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
+ if (isSpringProject(project)) {
+ projects.add(project);
+ }
+ }
+ return projects;
+ }
+
+ /**
+ * Returns true if given resource's project has the given nature.
+ */
+ public static boolean hasNature(IResource resource, String natureId) {
+ if (resource != null && resource.isAccessible()) {
+ IProject project = resource.getProject();
+ if (project != null) {
+ try {
+ return project.hasNature(natureId);
+ }
+ catch (CoreException e) {
+ StatusHandler.log(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID,
+ "An error occurred inspecting project nature", e));
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if given text contains a placeholder, e.g.
+ * ${beansRef} .
+ */
+ public static boolean hasPlaceHolder(String text) {
+ if (text == null || StringUtils.isBlank(text)) {
+ return false;
+ }
+ int pos = text.indexOf(PLACEHOLDER_PREFIX);
+ int elPos = text.indexOf(EL_PLACEHOLDER_PREFIX);
+ return ((pos != -1 || elPos != -1) && text.indexOf(PLACEHOLDER_SUFFIX, pos) != -1);
+ }
+
+ public static boolean hasProjectFacet(IResource resource, String facetId) {
+ if (resource != null && resource.isAccessible()) {
+ try {
+ return JdtUtils.isJavaProject(resource)
+ && FacetedProjectFramework.hasProjectFacet(resource.getProject(), facetId);
+ }
+ catch (CoreException e) {
+ // TODO CD handle exception
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if Eclipse's runtime bundle has the same or a newer than
+ * given version.
+ */
+ public static boolean isEclipseSameOrNewer(int majorVersion, int minorVersion) {
+ Bundle bundle = Platform.getBundle(Platform.PI_RUNTIME);
+ if (bundle != null) {
+ String versionString = (String) bundle.getHeaders().get(org.osgi.framework.Constants.BUNDLE_VERSION);
+ try {
+ Version version = new Version(versionString);
+ int major = version.getMajor();
+ if (major > majorVersion) {
+ return true;
+ }
+ if (major == majorVersion) {
+ int minor = version.getMinor();
+ if (minor >= minorVersion) {
+ return true;
+ }
+ }
+ }
+ catch (IllegalArgumentException e) {
+ // ignore this exception as this can't occur in pratice
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks if the given {@link IResource} is a OSGi bundle manifest.
+ *
+ * Note: only the name and last segment of the folder name are checked.
+ * @since 2.0.5
+ */
+ public static boolean isManifest(IResource resource) {
+ // check if it is a MANIFEST.MF file in META-INF
+ if (resource != null
+ // && resource.isAccessible()
+ && resource.getType() == IResource.FILE && resource.getName().equals(BUNDLE_MANIFEST_FILE)
+ && resource.getParent() != null && resource.getParent().getProjectRelativePath() != null
+ && resource.getParent().getProjectRelativePath().lastSegment() != null
+ && resource.getParent().getProjectRelativePath().lastSegment().equals(BUNDLE_MANIFEST_FOLDER)) {
+
+ // check if the manifest is not in an output folder
+ IPath filePath = resource.getFullPath();
+ IJavaProject javaProject = JdtUtils.getJavaProject(resource);
+ if (javaProject != null) {
+ try {
+ IPath defaultOutputLocation = javaProject.getOutputLocation();
+ if (defaultOutputLocation != null && defaultOutputLocation.isPrefixOf(filePath)) {
+ return false;
+ }
+ for (IClasspathEntry entry : javaProject.getRawClasspath()) {
+ if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ IPath outputLocation = entry.getOutputLocation();
+ if (outputLocation != null && outputLocation.isPrefixOf(filePath)) {
+ return false;
+ }
+ }
+ }
+ }
+ catch (JavaModelException e) {
+ // don't care here
+ }
+ return true;
+ }
+ else {
+ // if the project is not a java project -> it is the manifest
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if given resource's project is a Spring project.
+ */
+ public static boolean isSpringProject(IResource resource) {
+ return hasNature(resource, NATURE_ID);
+ }
+
+ /**
+ * Returns true if Eclipse's runtime bundle has the same or a newer than
+ * given version.
+ */
+ public static boolean isVersionSameOrNewer(String versionString, int majorVersion, int minorVersion,
+ int microVersion) {
+ return new Version(versionString).compareTo(new Version(majorVersion, minorVersion, microVersion)) >= 0;
+ }
+
+ public static Document parseDocument(IFile deploymentDescriptor) {
+ try {
+ if (getResourceURI(deploymentDescriptor) != null) {
+ return parseDocument(getResourceURI(deploymentDescriptor));
+ }
+ return getDocumentBuilder().parse(new InputSource(deploymentDescriptor.getContents()));
+ }
+ catch (SAXException e) {
+ throw new RuntimeException(e);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ catch (CoreException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Document parseDocument(URI deploymentDescriptor) {
+ try {
+ return getDocumentBuilder().parse(deploymentDescriptor.toString());
+ }
+ catch (SAXException e) {
+ throw new RuntimeException(e);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Removes given builder from specified project.
+ */
+ public static void removeProjectBuilder(IProject project, String builderID, IProgressMonitor monitor)
+ throws CoreException {
+ if (project != null && builderID != null) {
+ IProjectDescription desc = project.getDescription();
+ ICommand[] commands = desc.getBuildSpec();
+ for (int i = commands.length - 1; i >= 0; i--) {
+ if (commands[i].getBuilderName().equals(builderID)) {
+ ICommand[] newCommands = new ICommand[commands.length - 1];
+ System.arraycopy(commands, 0, newCommands, 0, i);
+ System.arraycopy(commands, i + 1, newCommands, i, commands.length - i - 1);
+ // Commit the spec change into the project
+ desc.setBuildSpec(newCommands);
+ project.setDescription(desc, monitor);
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes given nature from specified project.
+ */
+ public static void removeProjectNature(IProject project, String nature, IProgressMonitor monitor)
+ throws CoreException {
+ if (project != null && nature != null) {
+ if (project.exists() && project.hasNature(nature)) {
+
+ // first remove all problem markers (including the
+ // inherited ones) from Spring beans project
+ if (nature.equals(NATURE_ID)) {
+ project.deleteMarkers(MARKER_ID, true, IResource.DEPTH_INFINITE);
+ }
+
+ // now remove project nature
+ IProjectDescription desc = project.getDescription();
+ String[] oldNatures = desc.getNatureIds();
+ String[] newNatures = new String[oldNatures.length - 1];
+ int newIndex = oldNatures.length - 2;
+ for (int i = oldNatures.length - 1; i >= 0; i--) {
+ if (!oldNatures[i].equals(nature)) {
+ newNatures[newIndex--] = oldNatures[i];
+ }
+ }
+ desc.setNatureIds(newNatures);
+ project.setDescription(desc, monitor);
+ }
+ }
+ }
+
+ /**
+ * Verify that file can safely be modified; eventually checkout the file
+ * from source code control.
+ * @return true if resource can be modified
+ * @since 2.2.9
+ */
+ public static boolean validateEdit(IFile... files) {
+ for (IFile file : files) {
+ if (!file.exists()) {
+ return false;
+ }
+ }
+ IStatus status = ResourcesPlugin.getWorkspace().validateEdit(files, IWorkspace.VALIDATE_PROMPT);
+ if (status.isOK()) {
+ return true;
+ }
+ return false;
+ }
+
+ private static void scheduleBuildInBackground(final IProject project, ISchedulingRule rule,
+ final Object[] jobFamilies, final String builderID) {
+ Job job = new Job("Building workspace") {
+
+ @Override
+ public boolean belongsTo(Object family) {
+ if (jobFamilies == null || family == null) {
+ return false;
+ }
+ for (Object jobFamilie : jobFamilies) {
+ if (family.equals(jobFamilie)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public IStatus run(IProgressMonitor monitor) {
+ try {
+ if (builderID != null) {
+ project.build(IncrementalProjectBuilder.FULL_BUILD, builderID, null, monitor);
+ }
+ else {
+ project.build(IncrementalProjectBuilder.FULL_BUILD, monitor);
+ }
+ return Status.OK_STATUS;
+ }
+ catch (CoreException e) {
+ return new Status(Status.ERROR, CorePlugin.PLUGIN_ID, 1, "Error during build of project ["
+ + project.getName() + "]", e);
+ }
+ }
+ };
+ if (rule != null) {
+ job.setRule(rule);
+ }
+ job.setPriority(Job.BUILD);
+ job.schedule();
+ }
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/StatusHandler.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/StatusHandler.java
new file mode 100644
index 000000000..c914efcdc
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/StatusHandler.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core;
+
+import org.eclipse.core.runtime.ILog;
+import org.eclipse.core.runtime.IStatus;
+import org.springsource.ide.eclipse.commons.internal.core.CorePlugin;
+
+
+/**
+ * @author Steffen Pingel
+ * @author Leo Dos Santos
+ * @author Christian Dupuis
+ */
+public class StatusHandler {
+
+ public static void log(IStatus status) {
+ CorePlugin plugin = CorePlugin.getDefault();
+ if (plugin!=null) {
+ ILog log = plugin.getLog();
+ if (log!=null) {
+ log.log(status);
+ }
+ }
+ }
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/ZipFileUtil.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/ZipFileUtil.java
new file mode 100644
index 000000000..bbda98c4a
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/ZipFileUtil.java
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2018 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.file.Path;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipInputStream;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.springsource.ide.eclipse.commons.core.process.StandardProcessRunner;
+import org.springsource.ide.eclipse.commons.core.util.OsUtils;
+
+
+/**
+ * @author Steffen Pingel
+ * @author Leo Dos Santos
+ * @author Christian Dupuis
+ * @author Kris De Volder
+ * @since 2.0
+ */
+public class ZipFileUtil {
+
+ /**
+ * This Zip utility doesn't know how to extract file permission correctly
+ * from zip files (does Java ZipEntry even provide this info? It seems
+ * not!).
+ *
+ * To remedy this problem, clients can provide their own logic for setting
+ * permissions they may care about. A subclass of PermissionSetter is used
+ * to determine the permission setting logic.
+ *
+ * @author Kris De Volder
+ *
+ * @since 2.8
+ */
+ public static abstract class PermissionSetter {
+
+ /**
+ * Called after a file was succesfully extracted from the zip archive.
+ * @throws IOException
+ */
+ public abstract void fileUnzipped(ZipEntry entry, File entryFile) throws IOException;
+
+ /**
+ * A permission setter that does nothing.
+ */
+ public static final PermissionSetter NULL = new PermissionSetter() {
+ @Override
+ public void fileUnzipped(ZipEntry entry, File entryFile) {
+ // Do nothing
+ }
+ };
+
+ /**
+ * Creates an executable permission setter based on a list of file
+ * extensions.
+ *
+ * Any file ending with the extension will be made executable.
+ */
+ public static PermissionSetter executableExtensions(final String... exts) {
+ if (OsUtils.isWindows()) {
+ // It may be ok to do nothing for windows? (note: not tested!)
+ return NULL;
+ }
+ else {
+ // Assume we are unix if not Windows (Mac OS X is ok)
+ return new PermissionSetter() {
+ @Override
+ public void fileUnzipped(ZipEntry entry, File entryFile) throws IOException {
+ for (String ext : exts) {
+ if (entryFile.getName().endsWith(ext)) {
+ // This only works with Java 6:
+ // entryFile.setExecutable(true);
+
+ // This only works on Unix:
+ StandardProcessRunner runner = new StandardProcessRunner();
+ try {
+ runner.run(new File("."), "chmod", "a+x", entryFile.toString());
+ }
+ catch (InterruptedException e) {
+ // Restore the interrupted status (see
+ // https://www.ibm.com/developerworks/java/library/j-jtp05236/index.html)
+ Thread.currentThread().interrupt();
+ }
+ return; // No sense making a file executable
+ // more than once.
+ }
+ }
+ }
+ };
+ }
+ }
+
+ }
+
+ private static final int BUFFER_SIZE = 512 * 1024;
+
+ public static void unzip(URL source, File targetFile, IProgressMonitor monitor) throws IOException {
+ unzip(source, targetFile, null, monitor);
+ }
+
+ public static void unzip(URL source, File targetFile, String prefix, IProgressMonitor monitor) throws IOException {
+ unzip(source, targetFile, prefix, PermissionSetter.NULL, monitor);
+ }
+
+ public static void unzip(URL source, File targetFile, String prefix, PermissionSetter permsetter,
+ IProgressMonitor monitor) throws IOException {
+ if (monitor == null) {
+ monitor = new NullProgressMonitor();
+ }
+ try {
+ monitor.beginTask("Extracting " + source.getFile(), IProgressMonitor.UNKNOWN);
+
+ byte[] buffer = new byte[BUFFER_SIZE];
+ ZipInputStream zipIn = new ZipInputStream(source.openStream());
+ Path normalizedTargetFilePath = targetFile.toPath().normalize();
+ try {
+ ZipEntry entry;
+ while ((entry = zipIn.getNextEntry()) != null) {
+ String name = entry.getName();
+ if (prefix != null && name.startsWith(prefix)) {
+ name = name.substring(prefix.length());
+ if (name.length() > 1) {
+ // cut off separator
+ name = name.substring(1);
+ }
+ }
+
+ Policy.checkCancelled(monitor);
+ monitor.subTask(name);
+ File entryFile = new File(targetFile, name);
+ /*
+ * Ensure the outputdir + name doesn't leave the outputdir.
+ */
+ if (!entryFile.toPath().normalize().startsWith(normalizedTargetFilePath)) {
+ throw new ZipException("The file " + name
+ + " is trying to leave the target output directory of " + targetFile);
+ }
+ if (entry.isDirectory()) {
+ entryFile.mkdirs();
+ }
+ else {
+ entryFile.getParentFile().mkdirs();
+ FileOutputStream out = new FileOutputStream(entryFile);
+ try {
+ int len;
+ while ((len = zipIn.read(buffer)) >= 0) {
+ Policy.checkCancelled(monitor);
+ out.write(buffer, 0, len);
+ }
+ }
+ finally {
+ out.close();
+ }
+ long modTime = entry.getTime();
+ if (modTime > 0) {
+ entryFile.setLastModified(modTime);
+ }
+ permsetter.fileUnzipped(entry, entryFile);
+ }
+ }
+ }
+ finally {
+ zipIn.close();
+ }
+ }
+ finally {
+ monitor.done();
+ }
+ }
+
+ public static void unzip(File zipFile, File unzipDir, IProgressMonitor monitor) throws MalformedURLException, IOException {
+ unzip(zipFile.toURI().toURL(), unzipDir, monitor);
+ }
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/preferences/GlobalPreferenceEnhancer.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/preferences/GlobalPreferenceEnhancer.java
new file mode 100644
index 000000000..21430b6e4
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/preferences/GlobalPreferenceEnhancer.java
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core.preferences;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.osgi.service.prefs.BackingStoreException;
+import org.springsource.ide.eclipse.commons.internal.core.CorePlugin;
+
+public class GlobalPreferenceEnhancer {
+
+ // JDT ui constants
+ private static final String JDT_UI_BUNDLE_ID = "org.eclipse.jdt.ui";
+
+ // org.eclipse.jdt.ui.PreferenceConstants.CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVA
+ private static final String CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVA = "content_assist_autoactivation_triggers_java";
+
+ // org.eclipse.jdt.ui.PreferenceConstants.CODEASSIST_AUTOACTIVATION_DELAY
+ private static final String CODEASSIST_AUTOACTIVATION_DELAY = "content_assist_autoactivation_delay";
+
+ // org.eclipse.jdt.ui.PreferenceConstants.EDITOR_ESCAPE_STRINGS
+ private static final String EDITOR_ESCAPE_STRINGS = "escape¥Strings";
+
+ // org.eclipse.jdt.ui.PreferenceConstants.EDITOR_SMART_PASTE
+ private static final String EDITOR_SMART_PASTE = "smartPaste";
+
+ // org.eclipse.jdt.ui.PreferenceConstants.EDITOR_SMART_TAB
+ private static final String EDITOR_SMART_TAB = "smart_tab";
+
+ // org.eclipse.jdt.ui.PreferenceConstants.EDITOR_SMART_BACKSPACE
+ private static final String EDITOR_SMART_BACKSPACE = "smart_backspace";
+
+ // org.eclipse.jdt.ui.PreferenceConstants.EDITOR_SMART_OPENING_BRACE
+ private static final String EDITOR_SMART_OPENING_BRACE = "smart_opening_brace";
+
+ // org.eclipse.jdt.ui.PreferenceConstants.EDITOR_SMART_SEMICOLON
+ private static final String EDITOR_SMART_SEMICOLON = "smart_semicolon";
+
+ // M2E constants
+ private static final String M2E_CORE_BUNDLE_ID = "org.eclipse.m2e.core";
+
+ // org.eclipse.m2e.core.internal.preferences.MavenPreferenceConstants.P_HIDE_FOLDERS_OF_NESTED_PROJECTS
+ private static final String P_HIDE_FOLDERS_OF_NESTED_PROJECTS = "eclipse.m2.hideFoldersOfNestedProjects";
+
+ // org.eclipse.m2e.core.internal.preferences.MavenPreferenceConstants.P_DEFAULT_POM_EDITOR_PAGE
+ private static final String P_DEFAULT_POM_EDITOR_PAGE = "eclipse.m2.defaultPomEditorPage";
+
+ // org.eclipse.m2e.core.internal.preferences.MavenPreferenceConstants.P_UPDATE_INDEXES
+ private static final String P_UPDATE_INDEXES = "eclipse.m2.updateIndexes";
+
+ // jdt core constatnts
+ private static final String JDT_CORE_BUNDLE_ID = "org.eclipse.jdt.core";
+
+ // org.eclipse.jdt.core.JavaCore.COMPILER_PB_NON_NLS_STRING_LITERAL
+ private static final String COMPILER_PB_NON_NLS_STRING_LITERAL = "org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral";
+
+ public void enhanceAllPreferences() {
+ enhanceM2EPreferences();
+ enhanceJDTPreferences();
+ }
+
+ public void enhanceM2EPreferences() {
+ IEclipsePreferences m2eCorePrefs = InstanceScope.INSTANCE.getNode(M2E_CORE_BUNDLE_ID);
+ if (m2eCorePrefs != null) {
+ m2eCorePrefs.putBoolean(P_HIDE_FOLDERS_OF_NESTED_PROJECTS, true);
+ m2eCorePrefs.putBoolean(P_DEFAULT_POM_EDITOR_PAGE, true);
+ m2eCorePrefs.putBoolean(P_UPDATE_INDEXES, false);
+ try {
+ m2eCorePrefs.flush();
+ }
+ catch (BackingStoreException e) {
+ handleException(e);
+ }
+ }
+ }
+
+ public void enhanceJDTPreferences() {
+ IEclipsePreferences jdtCorePrefs = InstanceScope.INSTANCE.getNode(JDT_CORE_BUNDLE_ID);
+ if (jdtCorePrefs != null) {
+ jdtCorePrefs.put(COMPILER_PB_NON_NLS_STRING_LITERAL, "ignore");
+
+ try {
+ jdtCorePrefs.flush();
+ }
+ catch (BackingStoreException e) {
+ handleException(e);
+ }
+ }
+
+ IEclipsePreferences jdtUiPrefs = InstanceScope.INSTANCE.getNode(JDT_UI_BUNDLE_ID);
+ if (jdtUiPrefs != null) {
+ jdtUiPrefs.putBoolean(EDITOR_SMART_PASTE, true);
+ jdtUiPrefs.putBoolean(EDITOR_ESCAPE_STRINGS, true);
+ jdtUiPrefs.putInt(CODEASSIST_AUTOACTIVATION_DELAY, 40);
+ //jdtUiPrefs.put(CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVA, "_.abcdefghijklmnopqrstuvwxyz");
+ jdtUiPrefs.putBoolean(EDITOR_SMART_SEMICOLON, true);
+ jdtUiPrefs.putBoolean(EDITOR_SMART_OPENING_BRACE, true);
+ jdtUiPrefs.putBoolean(EDITOR_SMART_BACKSPACE, true);
+ jdtUiPrefs.putBoolean(EDITOR_SMART_TAB, true);
+
+ // org.eclipse.jdt.ui.PreferenceConstants.CODEASSIST_FAVORITE_STATIC_MEMBERS
+ // disable for now until we figure out the best things to include
+ // here;
+ // it is a semi-colon separateted list where each element looks like
+ // a static import statement
+ // jdtUiPrefs.put("content_assist_favorite_static_members",
+ // "org.eclipse.jdt.internal.ui.javaeditor.IJavaEditorActionConstants.*");
+
+ try {
+ jdtUiPrefs.flush();
+ }
+ catch (BackingStoreException e) {
+ handleException(e);
+ }
+ }
+ }
+
+ public void undoAll() {
+ undoJDTEnhance();
+ undoM2EEnhance();
+ }
+
+ public void undoJDTEnhance() {
+ IEclipsePreferences jdtCorePrefs = InstanceScope.INSTANCE.getNode(JDT_CORE_BUNDLE_ID);
+ if (jdtCorePrefs != null) {
+ jdtCorePrefs.remove(COMPILER_PB_NON_NLS_STRING_LITERAL);
+
+ try {
+ jdtCorePrefs.flush();
+ }
+ catch (BackingStoreException e) {
+ handleException(e);
+ }
+ }
+
+ IEclipsePreferences jdtUiPrefs = InstanceScope.INSTANCE.getNode(JDT_UI_BUNDLE_ID);
+ if (jdtUiPrefs != null) {
+ jdtUiPrefs.remove(EDITOR_SMART_PASTE);
+ jdtUiPrefs.remove(EDITOR_ESCAPE_STRINGS);
+ jdtUiPrefs.remove(CODEASSIST_AUTOACTIVATION_DELAY);
+ jdtUiPrefs.remove(CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVA);
+ jdtUiPrefs.remove(EDITOR_SMART_SEMICOLON);
+ jdtUiPrefs.remove(EDITOR_SMART_OPENING_BRACE);
+ jdtUiPrefs.remove(EDITOR_SMART_BACKSPACE);
+ jdtUiPrefs.remove(EDITOR_SMART_TAB);
+
+ try {
+ jdtUiPrefs.flush();
+ }
+ catch (BackingStoreException e) {
+ handleException(e);
+ }
+ }
+ }
+
+ public void undoM2EEnhance() {
+ IEclipsePreferences m2eCorePrefs = InstanceScope.INSTANCE.getNode(M2E_CORE_BUNDLE_ID);
+ if (m2eCorePrefs != null) {
+ m2eCorePrefs.remove(P_HIDE_FOLDERS_OF_NESTED_PROJECTS);
+ m2eCorePrefs.remove(P_DEFAULT_POM_EDITOR_PAGE);
+ m2eCorePrefs.remove(P_UPDATE_INDEXES);
+ try {
+ m2eCorePrefs.flush();
+ }
+ catch (BackingStoreException e) {
+ handleException(e);
+ }
+ }
+ }
+
+ private void handleException(BackingStoreException e) {
+ CorePlugin.getDefault().getLog()
+ .log(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, e.getLocalizedMessage(), e));
+ }
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/preferences/StsProperties.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/preferences/StsProperties.java
new file mode 100644
index 000000000..1033f9ea9
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/preferences/StsProperties.java
@@ -0,0 +1,181 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2020 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core.preferences;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Properties;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.springsource.ide.eclipse.commons.internal.core.CorePlugin;
+
+/**
+ * An instance of this class provides a mechanism to retrieve String properties.
+ * This is similar to a Java system properties. However it has support for reading these
+ * properties from a fixed url. This allows us to change the properties after release.
+ *
+ * Properties in this class can come from several different sources, listed here in
+ * decreasing order of priority:
+ *
+ * 1) Java System properties (set via -Dmy.prop.name=value) in STS.ini
+ * (properties set this way override anything else).
+ * 2) default values hard-coded in this class.
+ * (used only if property was not set via either 1 or 2).
+ *
+ * @since 3.4.M1
+ * @since 3.8.4 : no more reading props from url. Only hard-coded or system props used (too many
+ * issues with the network accesses blocking UI thread.)
+ *
+ * @author Kris De Volder
+ */
+public class StsProperties {
+
+
+ //Note: there is also a class called 'ResourceProvider'.. which reads various properties
+ // from eclipse extension points. This is different because the STSProperties themselves
+ // are read from an external url.
+ //The ResourceProvider only allows properties to defined by extensions contained in plugins
+ // installed into the Ecliple platform.
+
+ /**
+ * This class is a singleton. This holds the instance once created.
+ */
+ private static StsProperties instance = null;
+
+ public static StsProperties getInstance(IProgressMonitor mon) {
+ if (instance==null) {
+ StsProperties newInstance = new StsProperties(mon);
+ instance = newInstance;
+ }
+ return instance;
+ }
+
+ private final Properties props;
+
+ private StsProperties(IProgressMonitor mon) {
+ mon.beginTask("Read Sts Properties", 11);
+ try {
+ props = createProperties();
+ } finally {
+ mon.done();
+ }
+ }
+
+ protected Properties createProperties() {
+ Properties props = new Properties();
+
+ // Default properties (guarantees certain properties have a value no
+ // matter what).
+
+ props.put("spring.site.url", "https://spring.io");
+ props.put("spring.initializr.json.url", "https://start.spring.io");
+
+ //Urls used in the dashboard. For each XXX.url=... property, if
+ // - XXX.url.label is defined that label will be used for the corresponding
+ // dashboard tab instead of the html page title (title tends to be too long).
+ // - XXX.url.external is defined that url will always be openened in an external browser.
+
+ //Docs
+ props.put("spring.docs.url", "https://spring.io/docs");
+ props.put("spring.docs.url.label", "Spring Docs");
+ props.put("spring.docs.url.external", "false");
+
+ //Blog
+ props.put("spring.blog.url", "https://spring.io/blog");
+ props.put("spring.blog.url.label", "Blog");
+ props.put("spring.blog.url.external", "false");
+
+ //Tracker:
+ props.put("sts.tracker.url", "https://github.com/spring-projects/spring-ide/issues");
+ props.put("sts.tracker.url.label", "Issues");
+ props.put("sts.tracker.url.external", "true");
+
+ //New and Noteworthy
+ props.put("sts.nan.url", "https://static.springsource.org/sts/nan/latest/NewAndNoteworthy.html");
+ props.put("sts.nan.url.label", "New and Noteworthy");
+ props.put("sts.nan.url.external", "false");
+
+ //Forum:
+ props.put("sts.forum.url", "https://forum.springsource.org/forumdisplay.php?32-SpringSource-Tool-Suite");
+ props.put("sts.forum.url.label", "Forum");
+ props.put("sts.forum.url.external", "false");
+
+ //Guides
+ props.put("spring.guides.url", "https://spring.io/guides");
+ props.put("spring.guides.url.label", "Guides");
+ props.put("spring.guides.url.external", "true");
+
+ //Spring boot runtime
+ props.put("spring.boot.install.url", "https://repo.spring.io/release/org/springframework/boot/spring-boot-cli/2.1.15.RELEASE/spring-boot-cli-2.1.15.RELEASE-bin.zip");
+ //Discovery url for spring reference app
+ props.put("spring.reference.app.discovery.url", "https://raw.github.com/kdvolder/spring-reference-apps-meta/master/reference-apps.json");
+
+ //Url for webservice that generates typegraph for spring boot jar type content assist
+ props.put("spring.boot.typegraph.url", "https://aetherial.cfapps.io/boot/typegraph");
+
+ //Default version of spring boot, assumed when we need a version but can't determine it from the classpath of the project.
+ //Typically this should point to the latest version of spring-boot (the one used by spring-initialzr app).
+ props.put("spring.boot.default.version", "2.1.15.RELEASE");
+ props.put("spring.boot.cloud.default.version", "2.1.0.RELEASE");
+
+ return props;
+ }
+
+ /**
+ * Procudes names of properties that have explicitly been set, either from properties file
+ * or by the explicitly provided defaults. More precisely this does not return
+ * properties simply inherited from Java system properties.
+ */
+ public Collection getExplicitProperties() {
+ ArrayList keys = new ArrayList();
+ for (Object string : props.keySet()) {
+ if (string instanceof String) {
+ keys.add((String) string);
+ }
+ }
+ return keys;
+ }
+
+ public String get(String key) {
+ String value = System.getProperty(key);
+ if (value == null) {
+ value = props.getProperty(key);
+ }
+ return value;
+ }
+
+ public boolean get(String key, boolean deflt) {
+ String value = get(key);
+ if (value!=null) {
+ return Boolean.valueOf(value);
+ }
+ return deflt;
+ }
+
+ public static StsProperties getInstance() {
+ return getInstance(new NullProgressMonitor());
+ }
+
+ public URL url(String prop) {
+ String s = get(prop);
+ try {
+ if (s!=null) {
+ return new URL(get(prop));
+ }
+ } catch (Exception e) {
+ CorePlugin.log(e);
+ }
+ return null;
+ }
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/process/OutputWriter.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/process/OutputWriter.java
new file mode 100644
index 000000000..e46892c7c
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/process/OutputWriter.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core.process;
+
+/**
+ * @author Christian Dupuis
+ * @author Steffen Pingel
+ * @since 2.5.2
+ */
+public interface OutputWriter {
+
+ void write(String line);
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/process/ProcessRunner.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/process/ProcessRunner.java
new file mode 100644
index 000000000..d84216b59
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/process/ProcessRunner.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core.process;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author Christian Dupuis
+ * @author Steffen Pingel
+ * @since 2.5.2
+ */
+public interface ProcessRunner {
+
+ int run(File workingDir, String... command) throws IOException, InterruptedException;
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/process/StandardProcessRunner.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/process/StandardProcessRunner.java
new file mode 100644
index 000000000..f2c7afe58
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/process/StandardProcessRunner.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core.process;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * @author Christian Dupuis
+ * @author Steffen Pingel
+ * @since 2.5.2
+ */
+public final class StandardProcessRunner implements ProcessRunner {
+
+ private static final String[] ENVIRONMENT = new String[] {
+ String.format("JAVA_HOME=%s", System.getProperty("java.home")),
+ String.format("PATH=%s", System.getenv("PATH")),
+ String.format("USERDOMAIN=%s", System.getenv("USERDOMAIN")),
+ String.format("USERNAME=%s", System.getenv("USERNAME")),
+ String.format("USERPROFILE=%s", System.getenv("USERPROFILE")) };
+
+ private final OutputWriter[] standardOutputWriters;
+
+ private final OutputWriter[] standardErrorWriters;
+
+ public StandardProcessRunner() {
+ this(new OutputWriter[0], new OutputWriter[0]);
+ }
+
+ public StandardProcessRunner(OutputWriter standardOutputWriter, OutputWriter standardErrorWriter) {
+ this(new OutputWriter[] { standardOutputWriter }, new OutputWriter[] { standardErrorWriter });
+ }
+
+ public StandardProcessRunner(OutputWriter[] standardOutputWriters, OutputWriter[] standardErrorWriters) {
+ this.standardOutputWriters = standardOutputWriters;
+ this.standardErrorWriters = standardErrorWriters;
+ }
+
+ public int run(File workingDir, String... command) throws IOException, InterruptedException {
+ Process process;
+
+ if (command.length == 1) {
+ process = Runtime.getRuntime().exec(command[0], ENVIRONMENT, workingDir);
+ }
+ else {
+ process = Runtime.getRuntime().exec(command, ENVIRONMENT, workingDir);
+ }
+
+ CountDownLatch latch = new CountDownLatch(2);
+ new Thread(new StreamReader(process.getInputStream(), this.standardOutputWriters, latch)).start();
+ new Thread(new StreamReader(process.getErrorStream(), this.standardErrorWriters, latch)).start();
+
+ int returnCode = process.waitFor();
+ latch.await();
+
+ return returnCode;
+ }
+
+ private static final class StreamReader implements Runnable {
+
+ private final BufferedReader input;
+
+ private final OutputWriter[] outputs;
+
+ private final CountDownLatch latch;
+
+ public StreamReader(InputStream input, OutputWriter[] outputs, CountDownLatch latch) {
+ this.input = new BufferedReader(new InputStreamReader(input));
+ this.outputs = outputs;
+ this.latch = latch;
+ }
+
+ public void run() {
+ try {
+ String line = null;
+ while ((line = this.input.readLine()) != null) {
+ for (OutputWriter output : this.outputs) {
+ output.write(line);
+ }
+ }
+ }
+ catch (IOException e) {
+ }
+ finally {
+ try {
+ if (this.input != null) {
+ this.input.close();
+ }
+ }
+ catch (IOException e) {
+ }
+ finally {
+ this.latch.countDown();
+ }
+ }
+ }
+ }
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/process/SystemErrOutputWriter.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/process/SystemErrOutputWriter.java
new file mode 100644
index 000000000..6ca9a03a3
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/process/SystemErrOutputWriter.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core.process;
+
+/**
+ * @author Christian Dupuis
+ * @author Steffen Pingel
+ * @since 2.5.2
+ */
+public class SystemErrOutputWriter implements OutputWriter {
+
+ public void write(String line) {
+ System.err.println(line);
+ }
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/process/SystemOutOutputWriter.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/process/SystemOutOutputWriter.java
new file mode 100644
index 000000000..231f43adc
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/process/SystemOutOutputWriter.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Pivotal Software, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core.process;
+
+/**
+ * @author Christian Dupuis
+ * @author Steffen Pingel
+ * @since 2.5.2
+ */
+public final class SystemOutOutputWriter implements OutputWriter {
+
+ public void write(String line) {
+ System.out.println(line);
+ }
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/pstore/IPropertyStore.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/pstore/IPropertyStore.java
new file mode 100644
index 000000000..3ab3eb5d2
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/pstore/IPropertyStore.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core.pstore;
+
+/**
+ * An instance of this provides a way to store and retrieve
+ * properties. The properties are persisted somehow.
+ *
+ * This interface is deliberately kept very sparse so as to be
+ * 'easy' to implement. Its an interface meant for implementors.
+ *
+ * If you are a client you can an wrap instance of this interface
+ * into a {@link PropertyStoreApi} for a more convenient api
+ * with more operations.
+ *
+ * @author Kris De Volder
+ */
+public interface IPropertyStore {
+ String get(String key);
+ void put(String key, String value) throws Exception;
+}
\ No newline at end of file
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/pstore/IScopedPropertyStore.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/pstore/IScopedPropertyStore.java
new file mode 100644
index 000000000..d223bef9e
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/pstore/IScopedPropertyStore.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core.pstore;
+
+/**
+ * An instance of this provides a way to store and retrieve
+ * properties associated with some 'scope' object of type T.
+ *
+ * The properties are persisted somehow.
+ */
+public interface IScopedPropertyStore {
+ String get(T scope, String key);
+ void put(T scope, String key, String value) throws Exception;
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/pstore/InMemoryPropertyStore.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/pstore/InMemoryPropertyStore.java
new file mode 100644
index 000000000..775bbab6f
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/pstore/InMemoryPropertyStore.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core.pstore;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Kris De Volder
+ */
+public class InMemoryPropertyStore implements IPropertyStore {
+
+ private Map props = new HashMap<>();
+
+ @Override
+ public synchronized String get(String key) {
+ return props.get(key);
+ }
+
+ @Override
+ public synchronized void put(String key, String value) throws Exception {
+ props.put(key, value);
+ }
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/pstore/PreferenceBasedStore.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/pstore/PreferenceBasedStore.java
new file mode 100644
index 000000000..0e3e696b5
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/pstore/PreferenceBasedStore.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core.pstore;
+
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+
+/**
+ * An abstract base class to create {@link IScopedPropertyStore} that uses
+ * {@link IEclipsePreferences} to persist properties.
+ */
+public abstract class PreferenceBasedStore implements IScopedPropertyStore {
+
+ protected abstract IEclipsePreferences createPrefs(T element);
+
+ @Override
+ public String get(T p, String k) {
+ IEclipsePreferences prefs = createPrefs(p);
+ return prefs.get(k, null);
+ }
+
+ @Override
+ public void put(T element, String key, String value) throws Exception {
+ IEclipsePreferences prefs = createPrefs(element);
+ if (value==null) {
+ prefs.remove(key);
+ } else {
+ prefs.put(key, value);
+ }
+ prefs.flush();
+ }
+
+}
diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/pstore/PropertyFileStore.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/pstore/PropertyFileStore.java
new file mode 100644
index 000000000..b39747768
--- /dev/null
+++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/pstore/PropertyFileStore.java
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springsource.ide.eclipse.commons.core.pstore;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.AclEntry;
+import java.nio.file.attribute.AclEntryPermission;
+import java.nio.file.attribute.AclEntryType;
+import java.nio.file.attribute.AclFileAttributeView;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.UserPrincipal;
+import java.nio.file.attribute.UserPrincipalLookupService;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Properties;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.springsource.ide.eclipse.commons.core.util.OsUtils;
+import org.springsource.ide.eclipse.commons.livexp.util.Log;
+
+/**
+ * Implementation of IPropertyStore backed by a .properties file.
+ * The properties file is 'private'. I.e. it is created such that only
+ * the onwer of the file is allowed access to it.
+ */
+public class PropertyFileStore implements IPropertyStore {
+
+ final private File file;
+ final private Properties props = new Properties();
+
+ Job flushProperties = new Job("Save private properties") {
+
+ boolean errorLogged = false;
+
+ {
+ setSystem(true);
+ }
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ try {
+ createFileIfNeeded(file);
+ try (OutputStream out = new FileOutputStream(file)) {
+ props.store(out, "Private properties");
+ }
+ } catch (IOException e) {
+ if (!errorLogged) {
+ errorLogged = true; //complaining once about failure to store props is enough!
+ Log.log(e);
+ }
+ }
+ return Status.OK_STATUS;
+ }
+ };
+
+ protected void createFileIfNeeded(File f) throws IOException {
+ if (!f.exists()) {
+ createFile(f);
+ setPermissions(f);
+ }
+ }
+
+ protected void setPermissions(File f) throws IOException {
+ if (OsUtils.isWindows()) {
+ setWindowsPerissions(f);
+ } else {
+ setUnixPermissions(f);
+ }
+ }
+
+ protected void setWindowsPerissions(File f) throws IOException {
+ Path file = f.toPath();
+ AclFileAttributeView aclAttr = Files.getFileAttributeView(file, AclFileAttributeView.class);
+
+ UserPrincipalLookupService upls = file.getFileSystem().getUserPrincipalLookupService();
+ UserPrincipal user = upls.lookupPrincipalByName(System.getProperty("user.name"));
+ AclEntry.Builder builder = AclEntry.newBuilder();
+ builder.setPermissions( EnumSet.allOf(AclEntryPermission.class));
+// This was here before but it seems not enough to actually allow reading the file:
+// builder.setPermissions( EnumSet.of(
+// AclEntryPermission.READ_DATA,
+// AclEntryPermission.WRITE_DATA,
+// AclEntryPermission.APPEND_DATA,
+// AclEntryPermission.READ_ACL,
+// AclEntryPermission.WRITE_ACL,
+// AclEntryPermission.READ_ATTRIBUTES,
+// AclEntryPermission.WRITE_ATTRIBUTES,
+// AclEntryPermission.READ_NAMED_ATTRS,
+// AclEntryPermission.WRITE_NAMED_ATTRS,
+// AclEntryPermission.DELETE
+// ));
+ builder.setPrincipal(user);
+ builder.setType(AclEntryType.ALLOW);
+ aclAttr.setAcl(Collections.singletonList(builder.build()));
+ }
+
+ protected void setUnixPermissions(File f) throws IOException {
+ Files.setPosixFilePermissions(file.toPath(), EnumSet.of(
+ PosixFilePermission.OWNER_READ,
+ PosixFilePermission.OWNER_WRITE)
+ );
+ }
+
+ protected void createFile(File f) throws IOException {
+ if (f.getParentFile() != null) {
+ f.getParentFile().mkdirs();
+ }
+ f.createNewFile();
+ }
+
+ public PropertyFileStore(File file) {
+ this.file = file;
+ try {
+ if (file.exists()) {
+ try (InputStream in = new FileInputStream(file)) {
+ props.load(in);
+ }
+ }
+ } catch (IOException e) {
+ //Log and move on. This is not 'critical'. Maybe the file is corrupt and will be overwritten
+ // or something else is wrong and we won't be able to persist props. But at least
+ //props will be working in memory.
+ Log.log(e);
+ }
+ }
+
+ @Override
+ public synchronized String get(String key) {
+ return props.getProperty(key);
+ }
+
+ @Override
+ public void put(String key, String value) throws Exception {
+ Object oldValue = nullPut(key, value);
+ if (!Objects.equals(oldValue, value)) {
+ flushProperties.schedule();
+ }
+ }
+
+ private Object nullPut(String key, String value) {
+ if (value==null) {
+ return props.remove(key);
+ } else {
+ return props.put(key, value);
+ }
+ }
+
+ public boolean isEmpty() {
+ return props.isEmpty();
+ }
+
+ /**
+ * Blocks the current thread until all dirty data has been written to disk. This meant for testing purposes.
+ * E.g. a test that wants to check contents of the backing file after performing ops on the store.
+ */
+ public void sync() throws InterruptedException {
+ flushProperties.join();
+ }
+
+ /**
+ * Convert the contents currently in the store into a Map. Mainly meant for testing purposes to easily compare
+ * the map contents to expected contents. Not thread safe. Test code is expected to call this at a time
+ * when the work on the map is 'done'.
+ */
+ public Map asMap() {
+ Map builder = new HashMap<>();
+ for (Entry