diff options
author | Eugene Tarassov | 2011-11-11 18:51:51 +0000 |
---|---|---|
committer | Eugene Tarassov | 2011-11-11 18:51:51 +0000 |
commit | 9587c5ddf0b78aa00883d5cac15ce23dd116df9e (patch) | |
tree | d1f1e47b0fb5950ba40881d82f2c4a5f3bb1cfca /plugins/org.eclipse.tcf.debug.ui | |
parent | f8bdfbc8174a8255d41b8e03183aab2205304243 (diff) | |
download | org.eclipse.tcf-9587c5ddf0b78aa00883d5cac15ce23dd116df9e.tar.gz org.eclipse.tcf-9587c5ddf0b78aa00883d5cac15ce23dd116df9e.tar.xz org.eclipse.tcf-9587c5ddf0b78aa00883d5cac15ce23dd116df9e.zip |
TCF Java package names changed: org.eclipse.tm.tcf.* -> org.eclipse.tcf.*
Diffstat (limited to 'plugins/org.eclipse.tcf.debug.ui')
137 files changed, 23393 insertions, 0 deletions
diff --git a/plugins/org.eclipse.tcf.debug.ui/.classpath b/plugins/org.eclipse.tcf.debug.ui/.classpath new file mode 100644 index 000000000..8e321c38f --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/.classpath @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry excluding="**/.svn/**" kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"> + <accessrules> + <accessrule kind="accessible" pattern="org/eclipse/debug/**/provisional/**"/> + </accessrules> + </classpathentry> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/plugins/org.eclipse.tcf.debug.ui/.project b/plugins/org.eclipse.tcf.debug.ui/.project new file mode 100644 index 000000000..5ea738022 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/.project @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.tm.tcf.debug.ui</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> + <filteredResources> + <filter> + <id>1311579666882</id> + <name></name> + <type>10</type> + <matcher> + <id>org.eclipse.ui.ide.multiFilter</id> + <arguments>1.0-name-matches-false-false-target</arguments> + </matcher> + </filter> + </filteredResources> +</projectDescription> diff --git a/plugins/org.eclipse.tcf.debug.ui/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.tcf.debug.ui/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..35fc6d403 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,299 @@ +#Wed Oct 05 10:00:20 PDT 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch,.svn/
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5
+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_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_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_method_declaration=0
+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_resources_in_try=80
+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.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_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=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_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=8
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=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=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_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_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_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_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_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_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=true
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=true
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=true
+org.eclipse.jdt.core.formatter.lineSplit=180
+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=space
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
diff --git a/plugins/org.eclipse.tcf.debug.ui/.settings/org.eclipse.jdt.ui.prefs b/plugins/org.eclipse.tcf.debug.ui/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 000000000..903e1082e --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,4 @@ +#Wed Oct 05 09:55:18 PDT 2011
+eclipse.preferences.version=1
+formatter_profile=_Java STD
+formatter_settings_version=12
diff --git a/plugins/org.eclipse.tcf.debug.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.tcf.debug.ui/META-INF/MANIFEST.MF new file mode 100644 index 000000000..493ed16fa --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/META-INF/MANIFEST.MF @@ -0,0 +1,35 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.tm.tcf.debug.ui;singleton:=true +Bundle-Version: 0.5.0.qualifier +Bundle-Activator: org.eclipse.tm.internal.tcf.debug.ui.Activator +Bundle-Vendor: %providerName +Bundle-Localization: plugin +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.ui.ide, + org.eclipse.ui.console, + org.eclipse.ui.workbench.texteditor, + org.eclipse.text, + org.eclipse.jface.text, + org.eclipse.debug.core, + org.eclipse.debug.ui, + org.eclipse.tm.tcf.debug, + com.jcraft.jsch;bundle-version="0.1.37", + org.eclipse.jsch.core;bundle-version="1.1.100", + org.eclipse.jsch.ui;bundle-version="1.1.100", + org.eclipse.core.filesystem;bundle-version="1.3.0" +Import-Package: org.eclipse.core.expressions, + org.eclipse.tm.tcf.core;version="0.4.0", + org.eclipse.tm.tcf.protocol;version="0.5.0", + org.eclipse.tm.tcf.services;version="0.5.0", + org.eclipse.tm.tcf.ssl;version="0.4.0", + org.eclipse.tm.tcf.util;version="0.4.0" +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-ActivationPolicy: lazy +Eclipse-LazyStart: true +Export-Package: org.eclipse.tm.internal.tcf.debug.ui.adapters, + org.eclipse.tm.internal.tcf.debug.ui.commands;x-friends:="org.eclipse.tm.tcf.cdt.ui", + org.eclipse.tm.internal.tcf.debug.ui.launch, + org.eclipse.tm.internal.tcf.debug.ui.model;x-friends:="org.eclipse.tm.tcf.cdt.ui" diff --git a/plugins/org.eclipse.tcf.debug.ui/about.html b/plugins/org.eclipse.tcf.debug.ui/about.html new file mode 100644 index 000000000..6c5b3615b --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/about.html @@ -0,0 +1,28 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/> +<title>About</title> +</head> +<body lang="EN-US"> +<h2>About This Content</h2> + +<p>January 10, 2008</p> +<h3>License</h3> + +<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. +For purposes of the EPL, "Program" will mean the Content.</p> + +<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p> + +</body> +</html>
\ No newline at end of file diff --git a/plugins/org.eclipse.tcf.debug.ui/agent/get-os-tag b/plugins/org.eclipse.tcf.debug.ui/agent/get-os-tag new file mode 100644 index 000000000..3ab5d23fe --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/agent/get-os-tag @@ -0,0 +1,19 @@ +#!/bin/sh + +OPSYS=`uname -o 2>/dev/null || uname -s` + +if [ $OPSYS = Cygwin ] ; then + echo cygwin +elif [ $OPSYS = GNU/Linux ] ; then + if [ -e /etc/fedora-release ] ; then + echo fc`rpm -q --queryformat='%{VERSION}\n' fedora-release 2>/dev/null` + elif [ -e /etc/redhat-release ] ; then + echo rh`sed -e 's/^.*release //' -e 's/ .*$//' -e 's/\\./_/g' </etc/redhat-release` + elif [ -e /etc/mandrake-release ] ; then + echo mdk + elif [ -e /etc/SuSE-release ] ; then + echo suse + fi +fi + + diff --git a/plugins/org.eclipse.tcf.debug.ui/build.properties b/plugins/org.eclipse.tcf.debug.ui/build.properties new file mode 100644 index 000000000..39c4c9da1 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/build.properties @@ -0,0 +1,20 @@ +############################################################################### +# Copyright (c) 2010 Wind River Systems, Inc. and others. +# 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 +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Wind River Systems - initial API and implementation +############################################################################### +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + about.html,\ + plugin.properties,\ + icons/,\ + agent/ +src.includes = about.html diff --git a/plugins/org.eclipse.tcf.debug.ui/icons/arguments_tab.gif b/plugins/org.eclipse.tcf.debug.ui/icons/arguments_tab.gif Binary files differnew file mode 100644 index 000000000..44660b5f0 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/icons/arguments_tab.gif diff --git a/plugins/org.eclipse.tcf.debug.ui/icons/attribute.gif b/plugins/org.eclipse.tcf.debug.ui/icons/attribute.gif Binary files differnew file mode 100644 index 000000000..0f0769269 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/icons/attribute.gif diff --git a/plugins/org.eclipse.tcf.debug.ui/icons/brkp_ovr.gif b/plugins/org.eclipse.tcf.debug.ui/icons/brkp_ovr.gif Binary files differnew file mode 100644 index 000000000..5f5f0ab99 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/icons/brkp_ovr.gif diff --git a/plugins/org.eclipse.tcf.debug.ui/icons/casttotype_co.gif b/plugins/org.eclipse.tcf.debug.ui/icons/casttotype_co.gif Binary files differnew file mode 100644 index 000000000..b04de7e29 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/icons/casttotype_co.gif diff --git a/plugins/org.eclipse.tcf.debug.ui/icons/memory-map.gif b/plugins/org.eclipse.tcf.debug.ui/icons/memory-map.gif Binary files differnew file mode 100644 index 000000000..b48083118 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/icons/memory-map.gif diff --git a/plugins/org.eclipse.tcf.debug.ui/icons/path.gif b/plugins/org.eclipse.tcf.debug.ui/icons/path.gif Binary files differnew file mode 100644 index 000000000..13ce11b14 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/icons/path.gif diff --git a/plugins/org.eclipse.tcf.debug.ui/icons/refresh.gif b/plugins/org.eclipse.tcf.debug.ui/icons/refresh.gif Binary files differnew file mode 100644 index 000000000..049cac696 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/icons/refresh.gif diff --git a/plugins/org.eclipse.tcf.debug.ui/icons/showasarray_co.gif b/plugins/org.eclipse.tcf.debug.ui/icons/showasarray_co.gif Binary files differnew file mode 100644 index 000000000..233e52a4a --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/icons/showasarray_co.gif diff --git a/plugins/org.eclipse.tcf.debug.ui/icons/signals.gif b/plugins/org.eclipse.tcf.debug.ui/icons/signals.gif Binary files differnew file mode 100644 index 000000000..34823ea7b --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/icons/signals.gif diff --git a/plugins/org.eclipse.tcf.debug.ui/icons/target_tab.gif b/plugins/org.eclipse.tcf.debug.ui/icons/target_tab.gif Binary files differnew file mode 100644 index 000000000..e9df7b871 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/icons/target_tab.gif diff --git a/plugins/org.eclipse.tcf.debug.ui/icons/tcf.gif b/plugins/org.eclipse.tcf.debug.ui/icons/tcf.gif Binary files differnew file mode 100644 index 000000000..3198679ae --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/icons/tcf.gif diff --git a/plugins/org.eclipse.tcf.debug.ui/icons/thread_not_active.gif b/plugins/org.eclipse.tcf.debug.ui/icons/thread_not_active.gif Binary files differnew file mode 100644 index 000000000..d1a859622 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/icons/thread_not_active.gif diff --git a/plugins/org.eclipse.tcf.debug.ui/icons/var_aggr.gif b/plugins/org.eclipse.tcf.debug.ui/icons/var_aggr.gif Binary files differnew file mode 100644 index 000000000..d261b6887 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/icons/var_aggr.gif diff --git a/plugins/org.eclipse.tcf.debug.ui/icons/var_pointer.gif b/plugins/org.eclipse.tcf.debug.ui/icons/var_pointer.gif Binary files differnew file mode 100644 index 000000000..961873ea9 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/icons/var_pointer.gif diff --git a/plugins/org.eclipse.tcf.debug.ui/icons/var_simple.gif b/plugins/org.eclipse.tcf.debug.ui/icons/var_simple.gif Binary files differnew file mode 100644 index 000000000..9ea61ad1f --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/icons/var_simple.gif diff --git a/plugins/org.eclipse.tcf.debug.ui/plugin.properties b/plugins/org.eclipse.tcf.debug.ui/plugin.properties new file mode 100644 index 000000000..693faaef4 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/plugin.properties @@ -0,0 +1,55 @@ +############################################################################### +# Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. +# 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 +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Wind River Systems - initial implementation +############################################################################### +pluginName = TCF/Eclipse Debugger Integration UI (Incubation) +providerName = Eclipse CDT + +preferencePage.name = Target Communication + +debugCurrentInstructionPointer = Debug Current Instruction Pointer +debugCallStack = Debug Call Stack +debugBreakpointInstance = Breakpoint + +DebuggerActionSet.label = TCF Debugger + +commands.category.name = TCF Debugger +commands.category.desc = TCF Debugger Commands + +Signals.label = Signals... +MemoryMap.label = Symbol Files... +ViewMemory.label = View Memory +WatchInExpressions.label = Watch In Expressions +Refresh.label = Refresh +UpdatePolicy.label = Update Policy + +CastToType.label=Cast To Type... +CastToType.tooltip=Cast Expression To Type +RestoreDefaultType.label=Restore Original Type +RestoreDefaultType.tooltip=Restore Original Type Of Expression +CastToArray.label=Display As Array... +CastToArray.tooltip=Display Expression As Array + +ReverseExecutionCategory.name=Reverse execution +ReverseExecutionCategory.description=Reverse execution control commands + +BackInto.label=Back Into +BackInto.tooltip=Back Into +BackInto.description=Step back into +BackOver.label=Back Over +BackOver.tooltip=Back Over +BackOver.description=Step back over +BackReturn.label=Back Return +BackReturn.tooltip=Back Return +BackReturn.description=Run backwards until return +BackResume.label=Run Backwards +BackResume.tooltip=Run Backwards +BackResume.description=Run backwards + +propertyPage.name = Debug Element diff --git a/plugins/org.eclipse.tcf.debug.ui/plugin.xml b/plugins/org.eclipse.tcf.debug.ui/plugin.xml new file mode 100644 index 000000000..3927a0dc4 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/plugin.xml @@ -0,0 +1,631 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?eclipse version="3.2"?> +<!-- + Copyright (c) 2010, 2011 Wind River Systems, Inc. and others. + 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 + http://www.eclipse.org/legal/epl-v10.html + + Contributors: + Wind River Systems - initial API and implementation + --> + +<plugin> + + <extension-point id="launch_context" name="TCF Launch Context" schema="schema/launch_context.exsd"/> + + <extension point="org.eclipse.tm.tcf.startup"/> + + <extension + id="org.eclipse.tm.tcf.debug.ui.adapters" + point="org.eclipse.core.runtime.adapters"> + <factory + class="org.eclipse.tm.internal.tcf.debug.ui.adapters.TCFLaunchAdapterFactory" + adaptableType="org.eclipse.tm.internal.tcf.debug.model.TCFLaunch"> + <adapter type="org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider"/> + <adapter type="org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider"/> + <adapter type="org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory"/> + <adapter type="org.eclipse.debug.ui.contexts.ISuspendTrigger"/> + </factory> + <factory + class="org.eclipse.tm.internal.tcf.debug.ui.adapters.TCFNodeAdapterFactory" + adaptableType="org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode"> + <adapter type="org.eclipse.debug.ui.actions.IToggleBreakpointsTarget"/> + <adapter type="org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension"/> + <adapter type="org.eclipse.ui.views.properties.IPropertySource"/> + </factory> + </extension> + + <extension point="org.eclipse.debug.ui.debugModelPresentations"> + <debugModelPresentation + class = "org.eclipse.tm.internal.tcf.debug.ui.model.TCFModelPresentation" + id = "org.eclipse.tm.tcf.debug"> + </debugModelPresentation> + </extension> + + <extension point="org.eclipse.debug.ui.launchConfigurationTypeImages"> + <launchConfigurationTypeImage + icon="icons/tcf.gif" + configTypeID="org.eclipse.tm.tcf.debug.LaunchConfigurationType" + id="org.eclipse.tm.tcf.debug.LaunchConfigurationTypeImage"> + </launchConfigurationTypeImage> + </extension> + + <extension point="org.eclipse.debug.ui.launchConfigurationTabGroups"> + <launchConfigurationTabGroup + type="org.eclipse.tm.tcf.debug.LaunchConfigurationType" + description="Run or debug a program using Target Communication Framework" + class="org.eclipse.tm.internal.tcf.debug.ui.launch.TCFTabGroup" + id="org.eclipse.tm.tcf.debug.LaunchConfigurationTabGroup"> + </launchConfigurationTabGroup> + </extension> + + <extension point="org.eclipse.core.expressions.propertyTesters"> + <propertyTester + namespace="org.eclipse.tm.tcf.launch" + properties="isExecutable,areUpdatePoliciesSupported" + type="org.eclipse.core.runtime.IAdaptable" + class="org.eclipse.tm.internal.tcf.debug.ui.launch.TCFPropertyTester" + id="org.eclipse.tm.tcf.launch.PropertyTester"> + </propertyTester> + </extension> + + <extension point="org.eclipse.debug.ui.launchShortcuts"> + <shortcut + label="TCF Application" + icon="icons/tcf.gif" + helpContextId="org.eclipse.tm.tcf.debug.ui.shortcut_tcf_application" + modes="run, debug" + class="org.eclipse.tm.internal.tcf.debug.ui.launch.TCFLaunchShortcut" + description="Launch an application using Target Communication Framework (TCF)" + id="org.eclipse.tm.tcf.debug.ui.TCFShortcut"> + <description + description="Runs an application using Target Communication Framework (TCF)" + mode="run"> + </description> + <description + description="Debugs an application using Target Communication Framework (TCF)" + mode="debug"> + </description> + <contextualLaunch> + <enablement> + <with variable="selection"> + <count value="1"/> + <iterate> + <test + forcePluginActivation="true" + property="org.eclipse.tm.tcf.launch.isExecutable"/> + </iterate> + </with> + </enablement> + </contextualLaunch> + <configurationType + id="org.eclipse.tm.tcf.debug.LaunchConfigurationType"> + </configurationType> + </shortcut> + </extension> + + <extension + point="org.eclipse.ui.contexts"> + <context + name="Debugging using Target Communication Framework" + description="Debugging using Target Communication Framework" + id="org.eclipse.tm.tcf.debug.ui.debugging" + parentId="org.eclipse.debug.ui.debugging"> + </context> + </extension> + + <extension + point="org.eclipse.ui.views"> + <view + name="TCF Trace" + icon="icons/tcf.gif" + category="org.eclipse.debug.ui" + class="org.eclipse.tm.internal.tcf.debug.ui.trace.TraceView" + id="org.eclipse.tm.tcf.TraceView"> + </view> + </extension> + + <extension + point="org.eclipse.ui.perspectiveExtensions"> + <perspectiveExtension + targetID="org.eclipse.debug.ui.DebugPerspective"> + <view + relative="org.eclipse.ui.console.ConsoleView" + relationship="stack" + visible="false" + id="org.eclipse.tm.tcf.TraceView"> + </view> + </perspectiveExtension> + </extension> + + <extension point="org.eclipse.ui.editors.annotationTypes"> + <type + name="org.eclipse.tm.tcf.debug.top_frame"> + </type> + <type + name="org.eclipse.tm.tcf.debug.stack_frame"> + </type> + <type + name="org.eclipse.tm.tcf.debug.breakpoint_instance"> + </type> + </extension> + + <extension point="org.eclipse.ui.editors.markerAnnotationSpecification"> + <specification + annotationImageProvider="org.eclipse.tm.internal.tcf.debug.ui.model.TCFAnnotationImageProvider" + annotationType="org.eclipse.tm.tcf.debug.top_frame" + colorPreferenceKey="currentIPColor" + colorPreferenceValue="198,219,174" + highlightPreferenceKey="currentIPHighlight" + highlightPreferenceValue="true" + label="%debugCurrentInstructionPointer" + overviewRulerPreferenceKey="currentIPOverviewRuler" + overviewRulerPreferenceValue="true" + presentationLayer="6" + textPreferenceKey="currentIPIndication" + textPreferenceValue="false" + verticalRulerPreferenceKey="currentIPVerticalRuler" + verticalRulerPreferenceValue="true"> + </specification> + <specification + annotationImageProvider="org.eclipse.tm.internal.tcf.debug.ui.model.TCFAnnotationImageProvider" + annotationType="org.eclipse.tm.tcf.debug.stack_frame" + colorPreferenceKey="secondaryIPColor" + colorPreferenceValue="219,235,204" + highlightPreferenceKey="secondaryIPHighlight" + highlightPreferenceValue="true" + label="%debugCallStack" + overviewRulerPreferenceKey="secondaryIPOverviewRuler" + overviewRulerPreferenceValue="true" + presentationLayer="6" + textPreferenceKey="secondaryIPIndication" + textPreferenceValue="false" + verticalRulerPreferenceKey="secondaryIPVerticalRuler" + verticalRulerPreferenceValue="true"> + </specification> + <specification + annotationImageProvider="org.eclipse.tm.internal.tcf.debug.ui.model.TCFAnnotationImageProvider" + annotationType="org.eclipse.tm.tcf.debug.breakpoint_instance" + colorPreferenceKey="breakpointInstanceColor" + colorPreferenceValue="100,200,204" + highlightPreferenceKey="breakpointInstanceHighlight" + highlightPreferenceValue="false" + label="%debugBreakpointInstance" + overviewRulerPreferenceKey="breakpointInstanceRuler" + overviewRulerPreferenceValue="true" + presentationLayer="5" + textPreferenceKey="breakpointInstanceIndication" + textPreferenceValue="false" + verticalRulerPreferenceKey="breakpointInstanceVerticalRuler" + verticalRulerPreferenceValue="true"> + </specification> + </extension> + + <extension point="org.eclipse.debug.ui.detailPaneFactories"> + <detailFactories + class="org.eclipse.tm.internal.tcf.debug.ui.model.TCFDetailPaneFactory" + id="org.eclipse.tm.tcf.debug.DetailPaneFactory"> + <enablement> + <with variable="selection"> + <iterate> + <or> + <instanceof value="org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode"/> + </or> + </iterate> + </with> + </enablement> + </detailFactories> + </extension> + + <extension point="org.eclipse.ui.popupMenus"> + <!-- TCFLaunch popup menu contributions --> + <objectContribution + id="org.eclipse.tm.tcf.debug.ui.TCFLaunch" + objectClass="org.eclipse.tm.internal.tcf.debug.model.TCFLaunch"> + <action + id="org.eclipse.tm.tcf.debug.ui.actions.Signals" + class="org.eclipse.tm.internal.tcf.debug.ui.commands.SignalsCommand" + icon="icons/signals.gif" + label="%Signals.label" + menubarPath="additions"> + <enablement> + <pluginState + value="activated" + id="org.eclipse.tm.tcf.debug.ui"> + </pluginState> + </enablement> + </action> + </objectContribution> + + <!-- TCFNode popup menu contributions --> + <objectContribution + id="org.eclipse.tm.tcf.debug.ui.TCFNode" + objectClass="org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode"> + <action + id="org.eclipse.tm.tcf.debug.ui.actions.Signals" + class="org.eclipse.tm.internal.tcf.debug.ui.commands.SignalsCommand" + icon="icons/signals.gif" + label="%Signals.label" + menubarPath="additions"> + <enablement> + <pluginState + value="activated" + id="org.eclipse.tm.tcf.debug.ui"> + </pluginState> + </enablement> + </action> + <action + id="org.eclipse.tm.tcf.debug.ui.actions.MemoryMap" + class="org.eclipse.tm.internal.tcf.debug.ui.commands.MemoryMapCommand" + icon="icons/memory-map.gif" + label="%MemoryMap.label" + menubarPath="additions"> + <enablement> + <pluginState + value="activated" + id="org.eclipse.tm.tcf.debug.ui"> + </pluginState> + </enablement> + </action> + <action + id="org.eclipse.tm.tcf.debug.ui.actions.Refresh" + class="org.eclipse.tm.internal.tcf.debug.ui.commands.RefreshCommand" + icon="icons/refresh.gif" + label="%Refresh.label" + menubarPath="additions"> + <enablement> + <pluginState + value="activated" + id="org.eclipse.tm.tcf.debug.ui"> + </pluginState> + </enablement> + </action> + </objectContribution> + + <!-- TCFNodeExpression popup menu contributions --> + <objectContribution + id="org.eclipse.tm.tcf.debug.ui.TCFNodeExpression" + objectClass="org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExpression"> + <action + id="org.eclipse.tm.tcf.debug.ui.actions.ViewMemory" + class="org.eclipse.tm.internal.tcf.debug.ui.commands.ViewMemoryCommand" + label="%ViewMemory.label" + menubarPath="variableGroup"> + <enablement> + <pluginState + value="activated" + id="org.eclipse.tm.tcf.debug.ui"> + </pluginState> + </enablement> + </action> + </objectContribution> + + <!-- ICastToType popup menu contributions --> + <objectContribution + id="org.eclipse.tm.tcf.debug.ui.CastToType" + objectClass="org.eclipse.tm.internal.tcf.debug.ui.model.ICastToType"> + <action + label="%RestoreDefaultType.label" + helpContextId="restore_default_type_action_context" + tooltip="%RestoreDefaultType.tooltip" + class="org.eclipse.tm.internal.tcf.debug.ui.commands.RestoreDefaultTypeCommand" + menubarPath="variableGroup" + enablesFor="1" + id="org.eclipse.tm.tcf.debug.ui.commands.RestoreDefaultType"> + <enablement> + <pluginState + value="activated" + id="org.eclipse.tm.tcf.debug.ui"> + </pluginState> + </enablement> + </action> + <action + label="%CastToType.label" + icon="icons/casttotype_co.gif" + helpContextId="cast_to_type_action_context" + tooltip="%CastToType.tooltip" + class="org.eclipse.tm.internal.tcf.debug.ui.commands.CastToTypeCommand" + menubarPath="variableGroup" + enablesFor="1" + id="org.eclipse.tm.tcf.debug.ui.commands.CastToType"> + <enablement> + <pluginState + value="activated" + id="org.eclipse.tm.tcf.debug.ui"> + </pluginState> + </enablement> + </action> + <action + label="%CastToArray.label" + icon="icons/showasarray_co.gif" + helpContextId="cast_to_array_action_context" + tooltip="%CastToArray.tooltip" + class="org.eclipse.tm.internal.tcf.debug.ui.commands.CastToArrayCommand" + menubarPath="variableGroup" + enablesFor="1" + id="org.eclipse.tm.tcf.debug.ui.commands.CastToArray"> + <enablement> + <pluginState + value="activated" + id="org.eclipse.tm.tcf.debug.ui"> + </pluginState> + </enablement> + </action> + </objectContribution> + + <!-- IWatchInExpressions --> + <objectContribution + id="org.eclipse.tm.tcf.debug.ui.WatchInExpressions" + objectClass="org.eclipse.tm.internal.tcf.debug.ui.model.IWatchInExpressions"> + <action + id="org.eclipse.tm.tcf.debug.ui.actions.WatchInExpressions" + class="org.eclipse.tm.internal.tcf.debug.ui.commands.WatchInExpressionsCommand" + label="%WatchInExpressions.label" + menubarPath="additions"> + <enablement> + <pluginState + value="activated" + id="org.eclipse.tm.tcf.debug.ui"> + </pluginState> + </enablement> + </action> + </objectContribution> + </extension> + + <extension + point="org.eclipse.ui.commands"> + <category + name="%commands.category.name" + description="%commands.category.desc" + id="org.eclipse.tm.tcf.debug.ui.commands"> + </category> + <command + categoryId="org.eclipse.tm.tcf.debug.ui.commands" + defaultHandler="org.eclipse.tm.internal.tcf.debug.ui.commands.RefreshHandler" + id="org.eclipse.tm.tcf.debug.ui.commands.refresh" + name="%Refresh.label"/> + </extension> + + <extension point="org.eclipse.ui.handlers"> + <handler + class="org.eclipse.tm.internal.tcf.debug.ui.commands.RefreshHandler" + commandId="org.eclipse.ui.file.refresh"> + <activeWhen> + <and> + <with variable="activeContexts"> + <iterate ifEmpty="false" operator="or"> + <equals value="org.eclipse.tm.tcf.debug.ui.debugging"/> + </iterate> + </with> + <with variable="activePart"> + <test property="org.eclipse.tm.tcf.launch.areUpdatePoliciesSupported"/> + </with> + </and> + </activeWhen> + </handler> + </extension> + + <extension + point="org.eclipse.ui.menus"> + <!-- Registers View --> + <menuContribution + locationURI="toolbar:org.eclipse.debug.ui.RegisterView?after=additions"> + <command + commandId="org.eclipse.tm.tcf.debug.ui.commands.refresh" + icon="icons/refresh.gif" + id="org.eclipse.tm.tcf.debug.ui.commands.refresh.registers" + label="%Refresh.label" + style="push"> + <visibleWhen checkEnabled="false"> + <with variable="activeContexts"> + <iterate ifEmpty="false" operator="or"> + <equals value="org.eclipse.tm.tcf.debug.ui.debugging"/> + </iterate> + </with> + </visibleWhen> + </command> + </menuContribution> + <menuContribution + locationURI="menu:org.eclipse.debug.ui.RegisterView?after=additions"> + <menu + label="%UpdatePolicy.label" + id="org.eclipse.tm.tcf.debug.ui.commands.update.policy.registers"> + <visibleWhen checkEnabled="false"> + <with variable="activeContexts"> + <iterate ifEmpty="false" operator="or"> + <equals value="org.eclipse.tm.tcf.debug.ui.debugging"/> + </iterate> + </with> + </visibleWhen> + <dynamic + id="org.eclipse.tm.tcf.debug.ui.commands.update.policy.registers.menu" + class="org.eclipse.tm.internal.tcf.debug.ui.commands.UpdatePolicyMenu"/> + </menu> + </menuContribution> + <!-- Variables View --> + <menuContribution + locationURI="toolbar:org.eclipse.debug.ui.VariableView?after=additions"> + <command + commandId="org.eclipse.tm.tcf.debug.ui.commands.refresh" + icon="icons/refresh.gif" + id="org.eclipse.tm.tcf.debug.ui.commands.refresh.variables" + label="%Refresh.label" + style="push"> + <visibleWhen checkEnabled="false"> + <with variable="activeContexts"> + <iterate ifEmpty="false" operator="or"> + <equals value="org.eclipse.tm.tcf.debug.ui.debugging"/> + </iterate> + </with> + </visibleWhen> + </command> + </menuContribution> + <menuContribution + locationURI="menu:org.eclipse.debug.ui.VariableView?after=additions"> + <menu + label="%UpdatePolicy.label" + id="org.eclipse.tm.tcf.debug.ui.commands.update.policy.variables"> + <visibleWhen checkEnabled="false"> + <with variable="activeContexts"> + <iterate ifEmpty="false" operator="or"> + <equals value="org.eclipse.tm.tcf.debug.ui.debugging"/> + </iterate> + </with> + </visibleWhen> + <dynamic + id="org.eclipse.tm.tcf.debug.ui.commands.update.policy.variables.menu" + class="org.eclipse.tm.internal.tcf.debug.ui.commands.UpdatePolicyMenu"/> + </menu> + </menuContribution> + <!-- Expressions View --> + <menuContribution + locationURI="toolbar:org.eclipse.debug.ui.ExpressionView?after=additions"> + <command + commandId="org.eclipse.tm.tcf.debug.ui.commands.refresh" + icon="icons/refresh.gif" + id="org.eclipse.tm.tcf.debug.ui.commands.refresh.expressions" + label="%Refresh.label" + style="push"> + <visibleWhen checkEnabled="false"> + <with variable="activeContexts"> + <iterate ifEmpty="false" operator="or"> + <equals value="org.eclipse.tm.tcf.debug.ui.debugging"/> + </iterate> + </with> + </visibleWhen> + </command> + </menuContribution> + <menuContribution + locationURI="menu:org.eclipse.debug.ui.ExpressionView?after=additions"> + <menu + label="%UpdatePolicy.label" + id="org.eclipse.tm.tcf.debug.ui.commands.update.policy.expressions"> + <visibleWhen checkEnabled="false"> + <with variable="activeContexts"> + <iterate ifEmpty="false" operator="or"> + <equals value="org.eclipse.tm.tcf.debug.ui.debugging"/> + </iterate> + </with> + </visibleWhen> + <dynamic + id="org.eclipse.tm.tcf.debug.ui.commands.update.policy.expressions.menu" + class="org.eclipse.tm.internal.tcf.debug.ui.commands.UpdatePolicyMenu"/> + </menu> + </menuContribution> + <!-- Modules View --> + <menuContribution + locationURI="toolbar:org.eclipse.debug.ui.ModuleView?after=additions"> + <command + commandId="org.eclipse.tm.tcf.debug.ui.commands.refresh" + icon="icons/refresh.gif" + id="org.eclipse.tm.tcf.debug.ui.commands.refresh.modules" + label="%Refresh.label" + style="push"> + <visibleWhen checkEnabled="false"> + <with variable="activeContexts"> + <iterate ifEmpty="false" operator="or"> + <equals value="org.eclipse.tm.tcf.debug.ui.debugging"/> + </iterate> + </with> + </visibleWhen> + </command> + </menuContribution> + <menuContribution + locationURI="menu:org.eclipse.debug.ui.ModuleView?after=additions"> + <menu + label="%UpdatePolicy.label" + id="org.eclipse.tm.tcf.debug.ui.commands.update.policy.modules"> + <visibleWhen checkEnabled="false"> + <with variable="activeContexts"> + <iterate ifEmpty="false" operator="or"> + <equals value="org.eclipse.tm.tcf.debug.ui.debugging"/> + </iterate> + </with> + </visibleWhen> + <dynamic + id="org.eclipse.tm.tcf.debug.ui.commands.update.policy.modules.menu" + class="org.eclipse.tm.internal.tcf.debug.ui.commands.UpdatePolicyMenu"/> + </menu> + </menuContribution> + <!-- Memory View --> + <menuContribution + locationURI="toolbar:org.eclipse.debug.ui.MemoryView?after=additions"> + <command + commandId="org.eclipse.tm.tcf.debug.ui.commands.refresh" + icon="icons/refresh.gif" + id="org.eclipse.tm.tcf.debug.ui.commands.refresh.memory" + label="%Refresh.label" + style="push"> + <visibleWhen checkEnabled="false"> + <with variable="activeContexts"> + <iterate ifEmpty="false" operator="or"> + <equals value="org.eclipse.tm.tcf.debug.ui.debugging"/> + </iterate> + </with> + </visibleWhen> + </command> + </menuContribution> + <menuContribution + locationURI="menu:org.eclipse.debug.ui.MemoryView?after=additions"> + <menu + label="%UpdatePolicy.label" + id="org.eclipse.tm.tcf.debug.ui.commands.update.policy.memory"> + <visibleWhen checkEnabled="false"> + <with variable="activeContexts"> + <iterate ifEmpty="false" operator="or"> + <equals value="org.eclipse.tm.tcf.debug.ui.debugging"/> + </iterate> + </with> + </visibleWhen> + <dynamic + id="org.eclipse.tm.tcf.debug.ui.commands.update.policy.memory.menu" + class="org.eclipse.tm.internal.tcf.debug.ui.commands.UpdatePolicyMenu"/> + </menu> + </menuContribution> + </extension> + + <extension + point="org.eclipse.debug.ui.memoryRenderings"> + <renderingBindings + defaultIds="org.eclipse.debug.ui.rendering.raw_memory" + primaryId="org.eclipse.debug.ui.rendering.raw_memory" + renderingIds="org.eclipse.debug.ui.rendering.raw_memory,org.eclipse.debug.ui.rendering.ascii,org.eclipse.debug.ui.rendering.signedint,org.eclipse.debug.ui.rendering.unsignedint,org.eclipse.debug.ui.rendering.hexint"> + <enablement> + <instanceof value="org.eclipse.tm.internal.tcf.debug.ui.model.TCFMemoryBlockRetrieval$MemoryBlock"/> + </enablement> + </renderingBindings> + </extension> + + <extension point="org.eclipse.debug.ui.debugModelContextBindings"> + <modelContextBinding + contextId="org.eclipse.tm.tcf.debug.ui.debugging" + debugModelId="org.eclipse.tm.tcf.debug"/> + </extension> + + <extension point="org.eclipse.ui.propertyPages"> + <page class="org.eclipse.tm.internal.tcf.debug.ui.properties.TCFPropertyPage" + id="org.eclipse.tcf.debug.node.propertyPage" + name="%propertyPage.name"> + <filter name="debugModelId" value="org.eclipse.tm.tcf.debug"/> + <enabledWhen> + <instanceof value="org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode"/> + </enabledWhen> + </page> + </extension> + + <extension + point="org.eclipse.ui.preferencePages"> + <page + category="org.eclipse.debug.ui.DebugPreferencePage" + class="org.eclipse.tm.internal.tcf.debug.ui.preferences.TCFDebugPreferencePage" + id="org.eclipse.tm.internal.tcf.debug.ui.preferences" + name="%preferencePage.name"> + </page> + </extension> + + <extension point="org.eclipse.core.runtime.preferences"> + <initializer class="org.eclipse.tm.internal.tcf.debug.ui.preferences.TCFPreferencesInitializer"/> + </extension> +</plugin> diff --git a/plugins/org.eclipse.tcf.debug.ui/pom.xml b/plugins/org.eclipse.tcf.debug.ui/pom.xml new file mode 100644 index 000000000..b38e7fcf3 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/pom.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" + xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.eclipse.tcf</groupId> + <artifactId>tcf-parent</artifactId> + <version>0.5.0-SNAPSHOT</version> + <relativePath>../../pom.xml</relativePath> + </parent> + + <version>0.5.0-SNAPSHOT</version> + <artifactId>org.eclipse.tm.tcf.debug.ui</artifactId> + <packaging>eclipse-plugin</packaging> +</project> diff --git a/plugins/org.eclipse.tcf.debug.ui/schema/launch_context.exsd b/plugins/org.eclipse.tcf.debug.ui/schema/launch_context.exsd new file mode 100644 index 000000000..473255026 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/schema/launch_context.exsd @@ -0,0 +1,72 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!-- Schema file written by PDE --> +<schema targetNamespace="org.eclipse.tm.tcf"> +<annotation> + <appInfo> + <meta.schema plugin="org.eclipse.tm.tcf.debug.ui" id="launch_context" name="TCF Launch Context"/> + </appInfo> + <documentation> + This extension point is used to register plugins + that want to extends TCF Launch Configuration functionality. + </documentation> + +</annotation> + + <element name="extension"> + <complexType> + <sequence> + <element ref="class" minOccurs="0" maxOccurs="unbounded"/> + </sequence> + <attribute name="point" type="string" use="required"> + <annotation> + <documentation> + a fully qualified identifier of the target extension point + </documentation> + </annotation> + </attribute> + <attribute name="id" type="string"> + <annotation> + <documentation> + an optional identifier of the extension instance + </documentation> + </annotation> + </attribute> + <attribute name="name" type="string"> + <annotation> + <documentation> + an optional name of the extension instance + </documentation> + </annotation> + </attribute> + </complexType> + </element> + + <element name="class"> + <complexType> + <attribute name="name" type="string"> + <annotation> + <documentation> + Class should implement ILaunchContext interface + </documentation> + </annotation> + </attribute> + </complexType> + </element> + + <annotation> + <appInfo> + <meta.section type="apiInfo"/> + </appInfo> + <documentation> + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="implementation"/> + </appInfo> + <documentation> + </documentation> + </annotation> + +</schema> diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/Activator.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/Activator.java new file mode 100644 index 000000000..ae58135e7 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/Activator.java @@ -0,0 +1,127 @@ +/******************************************************************************* + * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFAnnotationManager; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModelManager; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + public static final String PLUGIN_ID = "org.eclipse.tm.tcf.debug.ui"; + + private static final Object lock = new Object(); + + private static Activator plugin; + private static TCFModelManager model_manager; + private static TCFAnnotationManager annotation_manager; + + public void start(BundleContext context) throws Exception { + synchronized (lock) { + super.start(context); + plugin = this; + Protocol.invokeLater(new Runnable() { + public void run() { + if (model_manager == null) { + model_manager = new TCFModelManager(); + } + } + }); + } + } + + public void stop(BundleContext context) throws Exception { + Protocol.invokeAndWait(new Runnable() { + public void run() { + if (model_manager != null) { + model_manager.dispose(); + model_manager = null; + } + if (annotation_manager != null) { + annotation_manager.dispose(); + annotation_manager = null; + } + } + }); + synchronized (lock) { + plugin = null; + super.stop(context); + } + } + + /** + * Returns the shared instance + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + + /** + * Returns the shared TCFModelManager instance + * @return the shared TCFModelManager instance + */ + public static TCFModelManager getModelManager() { + assert Protocol.isDispatchThread(); + if (model_manager == null) model_manager = new TCFModelManager(); + return model_manager; + } + + /** + * Returns the shared TCFAnnotationManager instance + * @return the shared TCFAnnotationManager instance + */ + public static TCFAnnotationManager getAnnotationManager() { + assert Protocol.isDispatchThread(); + if (annotation_manager == null) annotation_manager = new TCFAnnotationManager(); + return annotation_manager; + } + + /** + * Send error message into Eclipse log. + * @param msg - error message test + * @param err - exception + */ + public static void log(String msg, Throwable err) { + synchronized (lock) { + if (plugin == null || plugin.getLog() == null) { + err.printStackTrace(); + } + else { + plugin.getLog().log(new Status(IStatus.ERROR, + plugin.getBundle().getSymbolicName(), IStatus.OK, msg, err)); + } + } + } + + /** + * Send error message into Eclipse log. + * @param err - exception + */ + public static void log(Throwable err) { + synchronized (lock) { + if (plugin == null || plugin.getLog() == null) { + err.printStackTrace(); + } + else { + plugin.getLog().log(new Status(IStatus.ERROR, + plugin.getBundle().getSymbolicName(), IStatus.OK, "Unhandled exception in TCF UI", err)); + } + } + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/ImageCache.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/ImageCache.java new file mode 100644 index 000000000..76d445be0 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/ImageCache.java @@ -0,0 +1,150 @@ +/******************************************************************************* + * Copyright (c) 2008, 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui; + +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.resource.CompositeImageDescriptor; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.Point; +import org.eclipse.ui.PlatformUI; +import org.osgi.framework.Bundle; + +public class ImageCache { + + public static final String + IMG_TCF = "icons/tcf.gif", + IMG_TARGET_TAB = "icons/target_tab.gif", + IMG_TARGET_WIZARD = "icons/full/wizban/debug_wiz.png", + IMG_ARGUMENTS_TAB = "icons/arguments_tab.gif", + IMG_ATTRIBUTE = "icons/attribute.gif", + IMG_PATH = "icons/path.gif", + + IMG_THREAD_TERMINATED = "icons/full/obj16/threadt_obj.gif", + IMG_THREAD_SUSPENDED = "icons/full/obj16/threads_obj.gif", + IMG_THREAD_RUNNNIG = "icons/full/obj16/thread_obj.gif", + IMG_THREAD_NOT_ACTIVE = "icons/thread_not_active.gif", + IMG_THREAD_UNKNOWN_STATE = "icons/thread_not_active.gif", + + IMG_PROCESS_TERMINATED = "icons/full/obj16/debugtt_obj.gif", + IMG_PROCESS_SUSPENDED = "icons/full/obj16/debugts_obj.gif", + IMG_PROCESS_RUNNING = "icons/full/obj16/debugt_obj.gif", + + IMG_REGISTER = "icons/full/obj16/genericregister_obj.gif", + + IMG_VARIABLE = "icons/var_simple.gif", + IMG_VARIABLE_POINTER = "icons/var_pointer.gif", + IMG_VARIABLE_AGGREGATE = "icons/var_aggr.gif", + + IMG_SIGNALS = "icons/signals.gif", + IMG_MEMORY_MAP = "icons/memory-map.gif", + + IMG_ARRAY_PARTITION = "icons/full/obj16/arraypartition_obj.gif", + + IMG_STACK_FRAME_SUSPENDED = "icons/full/obj16/stckframe_obj.gif", + IMG_STACK_FRAME_RUNNING = "icons/full/obj16/stckframe_running_obj.gif", + + IMG_BREAKPOINT_ENABLED = "icons/full/obj16/brkp_obj.gif", + IMG_BREAKPOINT_DISABLED = "icons/full/obj16/brkpd_obj.gif", + IMG_BREAKPOINT_INSTALLED = "icons/ovr16/installed_ovr.gif", + IMG_BREAKPOINT_CONDITIONAL = "icons/ovr16/conditional_ovr.gif", + IMG_BREAKPOINT_WARNING = "icons/ovr16/warning_ovr.gif", + IMG_BREAKPOINT_ERROR = "icons/ovr16/error_ovr.gif", + IMG_BREAKPOINT_OVERLAY = "icons/brkp_ovr.gif"; + + private static final Map<String,ImageDescriptor> desc_cache = new HashMap<String,ImageDescriptor>(); + private static final Map<ImageDescriptor,Image> image_cache = new HashMap<ImageDescriptor,Image>(); + private static final Map<String,Map<ImageDescriptor,ImageDescriptor>> overlay_cache = + new HashMap<String,Map<ImageDescriptor,ImageDescriptor>>(); + + public static synchronized ImageDescriptor getImageDescriptor(String name) { + if (name == null) return null; + ImageDescriptor descriptor = desc_cache.get(name); + if (descriptor == null) { + Bundle bundle = Platform.getBundle(Activator.PLUGIN_ID); + if (bundle != null){ + URL url = FileLocator.find(bundle, new Path(name), null); + if (url != null) descriptor = ImageDescriptor.createFromURL(url); + } + if (descriptor == null) { + bundle = Platform.getBundle("org.eclipse.debug.ui"); + if (bundle != null){ + URL url = FileLocator.find(bundle, new Path(name), null); + if (url != null) descriptor = ImageDescriptor.createFromURL(url); + } + } + if (descriptor == null) { + bundle = Platform.getBundle("org.eclipse.cdt.debug.ui"); + if (bundle != null){ + URL url = FileLocator.find(bundle, new Path(name), null); + if (url != null) descriptor = ImageDescriptor.createFromURL(url); + } + } + if (descriptor == null) { + descriptor = PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(name); + } + if (descriptor == null) { + descriptor = ImageDescriptor.getMissingImageDescriptor(); + } + desc_cache.put(name, descriptor); + } + return descriptor; + } + + public static synchronized ImageDescriptor addOverlay(ImageDescriptor descriptor, String name) { + return addOverlay(descriptor, name, 0, 0); + } + + public static synchronized ImageDescriptor addOverlay( + ImageDescriptor descriptor, String name, final int x, final int y) { + if (descriptor == null || name == null) return descriptor; + String key = name + ':' + x + ':' + y; + Map<ImageDescriptor,ImageDescriptor> map = overlay_cache.get(key); + if (map == null) overlay_cache.put(key, map = new HashMap<ImageDescriptor,ImageDescriptor>()); + ImageDescriptor res = map.get(descriptor); + if (res != null) return res; + final ImageData base = descriptor.getImageData(); + final ImageData overlay = getImageDescriptor(name).getImageData(); + res = new CompositeImageDescriptor() { + @Override + protected void drawCompositeImage(int width, int height) { + drawImage(base, 0, 0); + drawImage(overlay, x, y); + } + @Override + protected Point getSize() { + return new Point(base.width, base.height); + } + }; + map.put(descriptor, res); + return res; + } + + public static synchronized Image getImage(ImageDescriptor desc) { + Image image = image_cache.get(desc); + if (image == null) { + image = desc.createImage(); + image_cache.put(desc, image); + } + return image; + } + + public static synchronized Image getImage(String name) { + return getImage(getImageDescriptor(name)); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/adapters/TCFLaunchAdapterFactory.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/adapters/TCFLaunchAdapterFactory.java new file mode 100644 index 000000000..7bb5dc9b9 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/adapters/TCFLaunchAdapterFactory.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.adapters; + +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory; +import org.eclipse.debug.ui.contexts.ISuspendTrigger; +import org.eclipse.tm.internal.tcf.debug.model.TCFLaunch; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.tcf.util.TCFTask; + + +public class TCFLaunchAdapterFactory implements IAdapterFactory { + + private static final Class<?>[] adapter_list = { + IElementLabelProvider.class, + IElementContentProvider.class, + IModelProxyFactory.class, + ISuspendTrigger.class, + }; + + private static final IElementLabelProvider launch_label_provider = new TCFLaunchLabelProvider(); + + @SuppressWarnings("rawtypes") + public Object getAdapter(final Object from, final Class to) { + if (from instanceof TCFLaunch) { + if (to == IElementLabelProvider.class) return launch_label_provider; + return new TCFTask<Object>() { + public void run() { + TCFLaunch launch = (TCFLaunch)from; + TCFModel model = Activator.getModelManager().getModel(launch); + if (model != null && to.isInstance(model)) { + done(model); + return; + } + done(null); + } + }.getE(); + } + return null; + } + + @SuppressWarnings("rawtypes") + public Class[] getAdapterList() { + return adapter_list; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/adapters/TCFLaunchLabelProvider.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/adapters/TCFLaunchLabelProvider.java new file mode 100644 index 000000000..701cfecfc --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/adapters/TCFLaunchLabelProvider.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2008, 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.adapters; + +import java.util.Collection; +import java.util.Map; + +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider; +import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.tm.internal.tcf.debug.model.TCFLaunch; +import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.tcf.services.IProcesses; + +class TCFLaunchLabelProvider implements IElementLabelProvider { + + public void update(ILabelUpdate[] updates) { + for (int i = 0; i < updates.length; i++) { + ILabelUpdate result = updates[i]; + final TCFLaunch launch = (TCFLaunch)result.getElement(); + ImageDescriptor image = DebugUITools.getDefaultImageDescriptor(launch); + if (image == null) image = ImageCache.getImageDescriptor(ImageCache.IMG_TCF); + result.setImageDescriptor(image, 0); + String status = ""; + if (launch.isConnecting()) { + status = "Connecting"; + } + else if (launch.isDisconnected()) { + status = "Disconnected"; + } + String peer_name = launch.getPeerName(); + if (peer_name != null) { + if (status.length() == 0) status = peer_name; + else status = peer_name + ": " + status; + } + if (status.length() > 0) status = " (" + status + ")"; + Throwable error = launch.getError(); + if (error != null) { + status += ": " + TCFModel.getErrorMessage(error, false); + result.setForeground(new RGB(255, 0, 0), 0); + } + else if (launch.isExited()) { + status += ": Exited"; + int code = launch.getExitCode(); + if (code > 0) status += ", exit code " + code; + if (code < 0) { + status += ", signal " + (-code); + Collection<Map<String,Object>> sigs = launch.getSignalList(); + if (sigs != null) { + for (Map<String,Object> m : sigs) { + Number num = (Number)m.get(IProcesses.SIG_CODE); + if (num == null) continue; + if (num.intValue() != -code) continue; + String s = (String)m.get(IProcesses.SIG_NAME); + if (s == null) continue; + status += " (" + s + ")"; + break; + } + } + } + } + String name = "?"; + ILaunchConfiguration cfg = launch.getLaunchConfiguration(); + if (cfg != null) name = cfg.getName(); + result.setLabel(name + status, 0); + result.done(); + } + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/adapters/TCFNodeAdapterFactory.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/adapters/TCFNodeAdapterFactory.java new file mode 100644 index 000000000..e426c6174 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/adapters/TCFNodeAdapterFactory.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.adapters; + +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.debug.ui.actions.IToggleBreakpointsTarget; +import org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension; +import org.eclipse.tm.internal.tcf.debug.ui.commands.BreakpointCommand; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.ui.views.properties.IPropertySource; + + +public class TCFNodeAdapterFactory implements IAdapterFactory { + + private static final Class<?>[] adapter_list = { + IToggleBreakpointsTarget.class, + IToggleBreakpointsTargetExtension.class, + IPropertySource.class, + }; + + private final BreakpointCommand breakpoint_command = new BreakpointCommand(); + + @SuppressWarnings("rawtypes") + public Object getAdapter(Object obj, Class cls) { + if (obj instanceof TCFNode) { + if (cls == IToggleBreakpointsTarget.class) return breakpoint_command; + if (cls == IToggleBreakpointsTargetExtension.class) return breakpoint_command; + if (cls == IPropertySource.class) return new TCFNodePropertySource((TCFNode) obj); + } + return null; + } + + @SuppressWarnings("rawtypes") + public Class[] getAdapterList() { + return adapter_list; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/adapters/TCFNodePropertySource.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/adapters/TCFNodePropertySource.java new file mode 100644 index 000000000..918090087 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/adapters/TCFNodePropertySource.java @@ -0,0 +1,191 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.adapters; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; +import org.eclipse.tm.internal.tcf.debug.model.TCFSourceRef; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext.MemoryRegion; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeStackFrame; +import org.eclipse.tm.tcf.protocol.JSON; +import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.services.IStackTrace; +import org.eclipse.tm.tcf.util.TCFDataCache; +import org.eclipse.tm.tcf.util.TCFTask; +import org.eclipse.ui.views.properties.IPropertyDescriptor; +import org.eclipse.ui.views.properties.IPropertySource; +import org.eclipse.ui.views.properties.PropertyDescriptor; + +/** + * Adapts TCFNode to IPropertySource. + */ +public class TCFNodePropertySource implements IPropertySource { + + private final TCFNode fNode; + private final Map<String, Object> fProperties = new HashMap<String, Object>(); + private IPropertyDescriptor[] fDescriptors; + + public TCFNodePropertySource(TCFNode node) { + fNode = node; + } + + public Object getEditableValue() { + return null; + } + + public IPropertyDescriptor[] getPropertyDescriptors() { + if (fDescriptors == null) { + try { + final List<IPropertyDescriptor> descriptors = new ArrayList<IPropertyDescriptor>(); + fDescriptors = new TCFTask<IPropertyDescriptor[]>(fNode.getChannel()) { + public void run() { + if (fNode instanceof TCFNodeExecContext) { + getExecContextDescriptors((TCFNodeExecContext) fNode); + } else if (fNode instanceof TCFNodeStackFrame) { + getFrameDescriptors((TCFNodeStackFrame) fNode); + } else { + done(descriptors.toArray(new IPropertyDescriptor[descriptors.size()])); + } + } + + private void getFrameDescriptors(TCFNodeStackFrame frameNode) { + TCFDataCache<IStackTrace.StackTraceContext> ctx_cache = frameNode.getStackTraceContext(); + TCFDataCache<TCFSourceRef> line_info_cache = frameNode.getLineInfo(); + if (!validateAll(ctx_cache, line_info_cache)) return; + IStackTrace.StackTraceContext ctx = ctx_cache.getData(); + if (ctx != null) { + Map<String, Object> props = ctx.getProperties(); + for (String key : props.keySet()) { + Object value = props.get(key); + if (value instanceof Number) { + value = toHexAddrString((Number) value); + } + addDescriptor("Context", key, value); + } + } + TCFSourceRef sourceRef = line_info_cache.getData(); + if (sourceRef != null) { + if (sourceRef.area != null) { + addDescriptor("Source", "Directory", sourceRef.area.directory); + addDescriptor("Source", "File", sourceRef.area.file); + addDescriptor("Source", "Line", sourceRef.area.start_line); + } + if (sourceRef.error != null) { + addDescriptor("Source", "Error", sourceRef.error); + } + } + done(descriptors.toArray(new IPropertyDescriptor[descriptors.size()])); + } + private void getExecContextDescriptors(TCFNodeExecContext exeNode) { + TCFDataCache<IRunControl.RunControlContext> ctx_cache = exeNode.getRunContext(); + TCFDataCache<TCFContextState> state_cache = exeNode.getState(); + TCFDataCache<MemoryRegion[]> mem_map_cache = exeNode.getMemoryMap(); + if (!validateAll(ctx_cache, state_cache, mem_map_cache)) return; + IRunControl.RunControlContext ctx = ctx_cache.getData(); + if (ctx != null) { + Map<String, Object> props = ctx.getProperties(); + for (String key : props.keySet()) { + Object value = props.get(key); + if (value instanceof Number) { + value = toHexAddrString((Number) value); + } + addDescriptor("Context", key, value); + } + } + TCFContextState state = state_cache.getData(); + if (state != null) { + addDescriptor("State", "Suspended", state.is_suspended); + if (state.is_suspended) { + addDescriptor("State", "Suspend reason", state.suspend_reason); + addDescriptor("State", "PC", toHexAddrString(new BigInteger(state.suspend_pc))); + } + addDescriptor("State", "Active", !exeNode.isNotActive()); + } + MemoryRegion[] mem_map = mem_map_cache.getData(); + if (mem_map != null && mem_map.length > 0) { + int idx = 0; + for (MemoryRegion region : mem_map) { + Map<String, Object> props = region.region.getProperties(); + for (String key : props.keySet()) { + Object value = props.get(key); + if (value instanceof Number) { + value = toHexAddrString((Number) value); + } + addDescriptor("MemoryRegion["+idx+']', key, value); + } + idx++; + } + } + done(descriptors.toArray(new IPropertyDescriptor[descriptors.size()])); + } + private void addDescriptor(String category, String key, Object value) { + String id = category + '.' + key; + PropertyDescriptor desc = new PropertyDescriptor(id, key); + desc.setCategory(category); + descriptors.add(desc); + fProperties.put(id, value); + } + boolean validateAll(TCFDataCache<?> ... caches) { + TCFDataCache<?> pending = null; + for (TCFDataCache<?> cache : caches) { + if (!cache.validate()) { + pending = cache; + } + } + if (pending != null) { + pending.wait(this); + return false; + } + return true; + } + }.get(5, TimeUnit.SECONDS); + } + catch (Exception e) { + Activator.log("Error retrieving property data", e); + fDescriptors = new IPropertyDescriptor[0]; + } + } + return fDescriptors; + } + + public Object getPropertyValue(final Object id) { + return fProperties.get(id); + } + + public boolean isPropertySet(Object id) { + return false; + } + + public void resetPropertyValue(Object id) { + } + + public void setPropertyValue(Object id, Object value) { + } + + private static String toHexAddrString(Number num) { + BigInteger n = JSON.toBigInteger(num); + String s = n.toString(16); + int sz = s.length() > 8 ? 16 : 8; + int l = sz - s.length(); + if (l < 0) l = 0; + if (l > 16) l = 16; + return "0x0000000000000000".substring(0, 2 + l) + s; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/AbstractActionDelegate.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/AbstractActionDelegate.java new file mode 100644 index 000000000..d46939ca3 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/AbstractActionDelegate.java @@ -0,0 +1,164 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import java.util.ArrayList; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Event; +import org.eclipse.tm.internal.tcf.debug.model.TCFLaunch; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.tcf.util.TCFTask; +import org.eclipse.ui.IActionDelegate2; +import org.eclipse.ui.IObjectActionDelegate; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; + +public abstract class AbstractActionDelegate +implements IViewActionDelegate, IActionDelegate2, IWorkbenchWindowActionDelegate, IObjectActionDelegate { + + private IAction action; + private IViewPart view; + private IWorkbenchWindow window; + private ISelection selection; + + public void init(IAction action) { + this.action = action; + } + + public void init(IViewPart view) { + this.view = view; + } + + public void init(IWorkbenchWindow window) { + this.window = window; + } + + public void dispose() { + action = null; + view = null; + window = null; + } + + public void setActivePart(IAction action, IWorkbenchPart part) { + this.action = action; + view = null; + if (part instanceof IViewPart) view = (IViewPart)part; + window = part.getSite().getWorkbenchWindow(); + } + + public void run(IAction action) { + IAction action0 = this.action; + try { + this.action = action; + run(); + } + finally { + this.action = action0; + } + } + + public void runWithEvent(IAction action, Event event) { + run(action); + } + + public void selectionChanged(IAction action, ISelection selection) { + this.selection = selection; + IAction action0 = this.action; + try { + this.action = action; + selectionChanged(); + } + finally { + this.action = action0; + } + } + + public IAction getAction() { + return action; + } + + public IViewPart getView() { + return view; + } + + public IWorkbenchWindow getWindow() { + if (view != null) return view.getSite().getWorkbenchWindow(); + if (window != null) return window; + return null; + } + + public ISelection getSelection() { + return selection; + } + + public TCFNode getSelectedNode() { + if (selection instanceof IStructuredSelection) { + final Object o = ((IStructuredSelection)selection).getFirstElement(); + if (o instanceof TCFNode) return (TCFNode)o; + if (o instanceof TCFLaunch) { + return new TCFTask<TCFNode>() { + public void run() { + TCFLaunch launch = (TCFLaunch)o; + TCFModel model = Activator.getModelManager().getModel(launch); + if (model != null) { + done(model.getRootNode()); + } + else { + done(null); + } + } + }.getE(); + } + } + return null; + } + + public TCFNode[] getSelectedNodes() { + ArrayList<TCFNode> list = new ArrayList<TCFNode>(); + if (selection instanceof IStructuredSelection) { + IStructuredSelection s = (IStructuredSelection)selection; + if (s.size() > 0) { + for (final Object o : s.toArray()) { + if (o instanceof TCFNode) { + list.add((TCFNode)o); + } + else if (o instanceof TCFLaunch) { + list.add(new TCFTask<TCFNode>() { + public void run() { + TCFLaunch launch = (TCFLaunch)o; + TCFModel model = Activator.getModelManager().getModel(launch); + if (model != null) { + done(model.getRootNode()); + } + else { + done(null); + } + } + }.getE()); + } + } + } + } + return list.toArray(new TCFNode[list.size()]); + } + + protected abstract void selectionChanged(); + + protected abstract void run(); +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/BackIntoCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/BackIntoCommand.java new file mode 100644 index 000000000..15bbe73c3 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/BackIntoCommand.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.commands.IDebugCommandRequest; +import org.eclipse.tm.internal.tcf.debug.actions.TCFActionStepInto; +import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; +import org.eclipse.tm.internal.tcf.debug.model.TCFSourceRef; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeStackFrame; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.util.TCFDataCache; + +public class BackIntoCommand extends StepCommand { + + private static class StepStateMachine extends TCFActionStepInto { + + private final IDebugCommandRequest monitor; + private final Runnable done; + private final TCFNodeExecContext node; + + StepStateMachine(TCFModel model, IDebugCommandRequest monitor, + IRunControl.RunControlContext ctx, boolean src_step, Runnable done) { + super(model.getLaunch(), ctx, src_step, true); + this.monitor = monitor; + this.done = done; + node = (TCFNodeExecContext)model.getNode(ctx.getID()); + } + + @Override + protected TCFDataCache<TCFContextState> getContextState() { + if (node == null) return null; + return node.getState(); + } + + @Override + protected TCFDataCache<TCFSourceRef> getLineInfo() { + TCFNodeStackFrame frame = node.getStackTrace().getTopFrame(); + if (frame == null) return null; + return frame.getLineInfo(); + } + + @Override + protected TCFDataCache<?> getStackTrace() { + return node.getStackTrace(); + } + + @Override + protected void exit(Throwable error) { + if (exited) return; + super.exit(error); + if (error != null && node.getChannel().getState() == IChannel.STATE_OPEN) { + monitor.setStatus(new Status(IStatus.ERROR, + Activator.PLUGIN_ID, 0, "Cannot step: " + error.getLocalizedMessage(), error)); + } + done.run(); + } + } + + public BackIntoCommand(TCFModel model) { + super(model); + } + + @Override + protected boolean canExecute(IRunControl.RunControlContext ctx) { + if (ctx == null) return false; + if (ctx.canResume(IRunControl.RM_REVERSE_STEP_INTO_LINE)) return true; + if (ctx.canResume(IRunControl.RM_REVERSE_STEP_INTO)) return true; + return false; + } + + @Override + protected void execute(final IDebugCommandRequest monitor, final IRunControl.RunControlContext ctx, + boolean src_step, final Runnable done) { + new StepStateMachine(model, monitor, ctx, src_step, done); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/BackOverCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/BackOverCommand.java new file mode 100644 index 000000000..35e4af1e8 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/BackOverCommand.java @@ -0,0 +1,109 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.commands.IDebugCommandRequest; +import org.eclipse.tm.internal.tcf.debug.actions.TCFActionStepOver; +import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; +import org.eclipse.tm.internal.tcf.debug.model.TCFSourceRef; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeStackFrame; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.services.IBreakpoints; +import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.services.IStackTrace.StackTraceContext; +import org.eclipse.tm.tcf.util.TCFDataCache; + +public class BackOverCommand extends StepCommand { + + private static class StepStateMachine extends TCFActionStepOver { + + private final IDebugCommandRequest monitor; + private final Runnable done; + private final TCFNodeExecContext node; + private TCFNodeStackFrame frame; + + StepStateMachine(TCFModel model, IDebugCommandRequest monitor, + IRunControl.RunControlContext ctx, + boolean src_step, Runnable done) { + super(model.getLaunch(), ctx, src_step, true); + this.monitor = monitor; + this.done = done; + node = (TCFNodeExecContext)model.getNode(ctx.getID()); + } + + @Override + protected TCFDataCache<TCFContextState> getContextState() { + if (node == null) return null; + return node.getState(); + } + + @Override + protected TCFDataCache<TCFSourceRef> getLineInfo() { + if (frame == null) frame = node.getStackTrace().getTopFrame(); + if (frame == null) return null; + return frame.getLineInfo(); + } + + @Override + protected TCFDataCache<StackTraceContext> getStackFrame() { + if (frame == null) frame = node.getStackTrace().getTopFrame(); + if (frame == null) return null; + return frame.getStackTraceContext(); + } + + @Override + protected int getStackFrameIndex() { + if (frame == null) frame = node.getStackTrace().getTopFrame(); + if (frame == null) return 0; + return frame.getFrameNo(); + } + + @Override + protected TCFDataCache<?> getStackTrace() { + return node.getStackTrace(); + } + + @Override + protected void exit(Throwable error) { + if (exited) return; + super.exit(error); + if (error != null && node.getChannel().getState() == IChannel.STATE_OPEN) { + monitor.setStatus(new Status(IStatus.ERROR, + Activator.PLUGIN_ID, 0, "Cannot step: " + error.getLocalizedMessage(), error)); + } + done.run(); + } + } + + public BackOverCommand(TCFModel model) { + super(model); + } + + @Override + protected boolean canExecute(IRunControl.RunControlContext ctx) { + if (ctx == null) return false; + if (ctx.canResume(IRunControl.RM_REVERSE_STEP_OVER_LINE)) return true; + if (ctx.canResume(IRunControl.RM_REVERSE_STEP_OVER)) return true; + if (ctx.canResume(IRunControl.RM_REVERSE_STEP_INTO) && model.getLaunch().getService(IBreakpoints.class) != null) return true; + return false; + } + + @Override + protected void execute(final IDebugCommandRequest monitor, final IRunControl.RunControlContext ctx, + boolean src_step, final Runnable done) { + new StepStateMachine(model, monitor, ctx, src_step, done); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/BackResumeCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/BackResumeCommand.java new file mode 100644 index 000000000..051883bc8 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/BackResumeCommand.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.commands.IDebugCommandRequest; +import org.eclipse.tm.internal.tcf.debug.actions.TCFAction; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IErrorReport; +import org.eclipse.tm.tcf.protocol.IToken; +import org.eclipse.tm.tcf.services.IRunControl; + +public class BackResumeCommand extends StepCommand { + + public BackResumeCommand(TCFModel model) { + super(model); + } + + @Override + protected boolean canExecute(IRunControl.RunControlContext ctx) { + return ctx.canResume(IRunControl.RM_REVERSE_RESUME); + } + + @Override + protected void execute(final IDebugCommandRequest monitor, + final IRunControl.RunControlContext ctx, boolean src_step, final Runnable done) { + new TCFAction(model.getLaunch(), ctx.getID()) { + public void run() { + ctx.resume(IRunControl.RM_REVERSE_RESUME, 1, new IRunControl.DoneCommand() { + public void doneCommand(IToken token, Exception error) { + if (error != null && model.getChannel().getState() == IChannel.STATE_OPEN) { + if (error instanceof IErrorReport) { + IErrorReport r = (IErrorReport)error; + if (r.getErrorCode() == IErrorReport.TCF_ERROR_ALREADY_RUNNING) { + done(); + return; + } + } + launch.removeContextActions(getContextID()); + monitor.setStatus(new Status(IStatus.ERROR, + Activator.PLUGIN_ID, IStatus.OK, "Cannot resume: " + error.getLocalizedMessage(), error)); + } + done(); + } + }); + } + public void done() { + super.done(); + done.run(); + } + }; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/BackReturnCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/BackReturnCommand.java new file mode 100644 index 000000000..604a131f0 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/BackReturnCommand.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.commands.IDebugCommandRequest; +import org.eclipse.tm.internal.tcf.debug.actions.TCFActionStepOut; +import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeStackFrame; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.services.IBreakpoints; +import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.services.IStackTrace.StackTraceContext; +import org.eclipse.tm.tcf.util.TCFDataCache; + +public class BackReturnCommand extends StepCommand { + + private static class StepStateMachine extends TCFActionStepOut { + + private final IDebugCommandRequest monitor; + private final Runnable done; + private final TCFNodeExecContext node; + private TCFNodeStackFrame frame; + + StepStateMachine(TCFModel model, IDebugCommandRequest monitor, + IRunControl.RunControlContext ctx, Runnable done) { + super(model.getLaunch(), ctx, true); + this.monitor = monitor; + this.done = done; + node = (TCFNodeExecContext)model.getNode(ctx.getID()); + } + + @Override + protected TCFDataCache<TCFContextState> getContextState() { + if (node == null) return null; + return node.getState(); + } + + @Override + protected TCFDataCache<StackTraceContext> getStackFrame() { + if (frame == null) frame = node.getStackTrace().getTopFrame(); + if (frame == null) return null; + return frame.getStackTraceContext(); + } + + @Override + protected int getStackFrameIndex() { + if (frame == null) frame = node.getStackTrace().getTopFrame(); + if (frame == null) return 0; + return frame.getFrameNo(); + } + + @Override + protected TCFDataCache<?> getStackTrace() { + return node.getStackTrace(); + } + + @Override + protected void exit(Throwable error) { + if (exited) return; + super.exit(error); + if (error != null && node.getChannel().getState() == IChannel.STATE_OPEN) { + monitor.setStatus(new Status(IStatus.ERROR, + Activator.PLUGIN_ID, 0, "Cannot step: " + error.getLocalizedMessage(), error)); + } + done.run(); + } + } + + public BackReturnCommand(TCFModel model) { + super(model); + } + + @Override + protected boolean canExecute(IRunControl.RunControlContext ctx) { + if (ctx == null) return false; + if (ctx.canResume(IRunControl.RM_REVERSE_STEP_OUT)) return true; + if (!ctx.hasState()) return false; + if (ctx.canResume(IRunControl.RM_REVERSE_RESUME) && model.getLaunch().getService(IBreakpoints.class) != null) return true; + return false; + } + + @Override + protected void execute(final IDebugCommandRequest monitor, final IRunControl.RunControlContext ctx, + boolean src_step, final Runnable done) { + new StepStateMachine(model, monitor, ctx, done); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/BreakpointCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/BreakpointCommand.java new file mode 100644 index 000000000..83fd1ffe8 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/BreakpointCommand.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import java.math.BigInteger; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.tm.internal.tcf.debug.model.TCFBreakpoint; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeStackFrame; +import org.eclipse.tm.tcf.services.IBreakpoints; +import org.eclipse.tm.tcf.util.TCFDataCache; +import org.eclipse.tm.tcf.util.TCFTask; +import org.eclipse.ui.IWorkbenchPart; + + +public class BreakpointCommand implements IToggleBreakpointsTargetExtension { + + public boolean canToggleBreakpoints(IWorkbenchPart part, ISelection selection) { + if (selection.isEmpty()) return false; + final Object obj = ((IStructuredSelection)selection).getFirstElement(); + return new TCFTask<Boolean>() { + public void run() { + TCFDataCache<BigInteger> addr_cache = null; + if (obj instanceof TCFNodeExecContext) addr_cache = ((TCFNodeExecContext)obj).getAddress(); + if (obj instanceof TCFNodeStackFrame) addr_cache = ((TCFNodeStackFrame)obj).getAddress(); + if (addr_cache != null) { + if (!addr_cache.validate(this)) return; + done(addr_cache.getData() != null); + } + else { + done(false); + } + } + }.getE(); + } + + public void toggleBreakpoints(IWorkbenchPart part, ISelection selection) { + if (selection.isEmpty()) return; + final Object obj = ((IStructuredSelection)selection).getFirstElement(); + new TCFTask<Object>() { + public void run() { + TCFDataCache<BigInteger> addr_cache = null; + if (obj instanceof TCFNodeExecContext) addr_cache = ((TCFNodeExecContext)obj).getAddress(); + if (obj instanceof TCFNodeStackFrame) addr_cache = ((TCFNodeStackFrame)obj).getAddress(); + if (addr_cache != null) { + if (!addr_cache.validate(this)) return; + BigInteger addr = addr_cache.getData(); + if (addr != null) { + Map<String,Object> m = new HashMap<String,Object>(); + m.put(IBreakpoints.PROP_ENABLED, Boolean.TRUE); + m.put(IBreakpoints.PROP_LOCATION, addr.toString()); + TCFBreakpoint.createFromTCFProperties(m); + } + } + done(null); + } + }.getE(); + } + + public boolean canToggleLineBreakpoints(IWorkbenchPart part, ISelection selection) { + return false; + } + + public void toggleLineBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException { + // TODO: breakpoint command: toggle line breakpoint + } + + public boolean canToggleMethodBreakpoints(IWorkbenchPart part, ISelection selection) { + return false; + } + + public void toggleMethodBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException { + } + + public boolean canToggleWatchpoints(IWorkbenchPart part, ISelection selection) { + return false; + } + + public void toggleWatchpoints(IWorkbenchPart part, ISelection selection) throws CoreException { + // TODO: breakpoint command: toggle watchpoint + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/CastToArrayCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/CastToArrayCommand.java new file mode 100644 index 000000000..3f2e9db95 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/CastToArrayCommand.java @@ -0,0 +1,142 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; +import org.eclipse.tm.internal.tcf.debug.ui.model.ICastToType; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.tcf.services.ISymbols; +import org.eclipse.tm.tcf.util.TCFDataCache; +import org.eclipse.tm.tcf.util.TCFTask; +import org.eclipse.ui.IWorkbenchWindow; + +public class CastToArrayCommand extends AbstractActionDelegate { + + private class CastToTypeInputValidator implements IInputValidator { + + public CastToTypeInputValidator() { + } + + public String isValid(String new_text) { + try { + if (new_text.length() == 0) return ""; + int i = Integer.parseInt(new_text); + if (i < 1) return "Array length must be >= 1"; + } + catch (Exception x) { + return "Invalid number"; + } + return null; + } + } + + private class CastToTypeDialog extends InputDialog { + + public CastToTypeDialog(Shell shell, String initial_value) { + super(shell, "Cast To Array", "Enter array length", + initial_value, new CastToTypeInputValidator() ); + } + + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setImage(ImageCache.getImage(ImageCache.IMG_TCF)); + } + } + + @Override + protected void run() { + final TCFNode node = getCastToTypeNode(); + if (node == null) return; + IWorkbenchWindow window = Activator.getDefault().getWorkbench().getActiveWorkbenchWindow(); + if (window == null) return; + final String base_type_name = getBaseTypeName(); + if (base_type_name == null) return; + CastToTypeDialog dialog = new CastToTypeDialog(window.getShell(), node.getModel().getCastToType(node.getID())); + if (dialog.open() != Window.OK) return; + final String new_type = dialog.getValue().trim(); + Protocol.invokeLater(new Runnable() { + public void run() { + node.getModel().setCastToType(node.getID(), base_type_name + "[" + new_type + "]"); + } + }); + } + + private String getBaseTypeName() { + final TCFNode node = getCastToTypeNode(); + if (node == null) return null; + return new TCFTask<String>(node.getChannel()) { + public void run() { + TCFDataCache<ISymbols.Symbol> type_cache = ((ICastToType)node).getType(); + if (!type_cache.validate(this)) return; + ISymbols.Symbol type_data = type_cache.getData(); + if (type_data == null || type_data.getTypeClass() != ISymbols.TypeClass.pointer) { + done(null); + } + else { + String ptrs = "****"; + for (int i = 0; i <= ptrs.length(); i++) { + TCFDataCache<ISymbols.Symbol> base_type_cache = node.getModel().getSymbolInfoCache(type_data.getBaseTypeID()); + if (!base_type_cache.validate(this)) return; + ISymbols.Symbol base_type_data = base_type_cache.getData(); + if (base_type_data == null) { + done(null); + return; + } + else { + if (base_type_data.getName() != null) { + done(base_type_data.getName() + ptrs.substring(0, i)); + return; + } + else if (base_type_data.getTypeClass() == ISymbols.TypeClass.pointer) { + type_data = base_type_data; + } + else if (!base_type_data.getID().equals(base_type_data.getTypeID())) { + // modified type without name, like "volatile int" + base_type_cache = node.getModel().getSymbolInfoCache(base_type_data.getTypeID()); + if (!base_type_cache.validate(this)) return; + base_type_data = base_type_cache.getData(); + if (base_type_data != null && base_type_data.getName() != null) { + done(base_type_data.getName() + ptrs.substring(0, i)); + } + else { + done(null); + } + return; + } + else { + done(null); + return; + } + } + } + } + } + }.getE(); + } + + @Override + protected void selectionChanged() { + getAction().setEnabled(getBaseTypeName() != null); + } + + private TCFNode getCastToTypeNode() { + TCFNode node = getSelectedNode(); + if (node instanceof ICastToType) return node; + return null; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/CastToTypeCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/CastToTypeCommand.java new file mode 100644 index 000000000..48e7bdb98 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/CastToTypeCommand.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; +import org.eclipse.tm.internal.tcf.debug.ui.model.ICastToType; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.ui.IWorkbenchWindow; + +public class CastToTypeCommand extends AbstractActionDelegate { + + private class CastToTypeInputValidator implements IInputValidator { + + public CastToTypeInputValidator() { + } + + public String isValid(String new_text) { + return null; + } + } + + private class CastToTypeDialog extends InputDialog { + + public CastToTypeDialog(Shell shell, String initial_value) { + super(shell, "Cast To Type", "Enter type name", + initial_value, new CastToTypeInputValidator() ); + } + + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setImage(ImageCache.getImage(ImageCache.IMG_TCF)); + } + } + + @Override + protected void run() { + final TCFNode node = getCastToTypeNode(); + if (node == null) return; + IWorkbenchWindow window = Activator.getDefault().getWorkbench().getActiveWorkbenchWindow(); + if (window == null) return; + CastToTypeDialog dialog = new CastToTypeDialog(window.getShell(), node.getModel().getCastToType(node.getID())); + if (dialog.open() != Window.OK) return; + final String new_type = dialog.getValue().trim(); + Protocol.invokeLater(new Runnable() { + public void run() { + node.getModel().setCastToType(node.getID(), new_type); + } + }); + } + + @Override + protected void selectionChanged() { + getAction().setEnabled(getCastToTypeNode() != null); + } + + private TCFNode getCastToTypeNode() { + TCFNode node = getSelectedNode(); + if (node instanceof ICastToType) return node; + return null; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/DisconnectCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/DisconnectCommand.java new file mode 100644 index 000000000..eb79092f8 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/DisconnectCommand.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.commands.IDebugCommandRequest; +import org.eclipse.debug.core.commands.IDisconnectHandler; +import org.eclipse.debug.core.commands.IEnabledStateRequest; +import org.eclipse.tm.internal.tcf.debug.model.TCFError; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFRunnable; + + +public class DisconnectCommand implements IDisconnectHandler { + + private final TCFModel model; + + public DisconnectCommand(TCFModel model) { + this.model = model; + } + + public void canExecute(final IEnabledStateRequest monitor) { + new TCFRunnable(monitor) { + public void run() { + monitor.setEnabled(model.getLaunch().canDisconnect()); + monitor.setStatus(Status.OK_STATUS); + done(); + } + }; + } + + public boolean execute(final IDebugCommandRequest monitor) { + new TCFRunnable(monitor) { + public void run() { + try { + model.getLaunch().closeChannel(); + monitor.setStatus(Status.OK_STATUS); + } + catch (Throwable x) { + monitor.setStatus(new TCFError(x).getStatus()); + } + done(); + } + }; + return false; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/DropToFrameCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/DropToFrameCommand.java new file mode 100644 index 000000000..b4efec179 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/DropToFrameCommand.java @@ -0,0 +1,197 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import java.util.Map; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.commands.IDebugCommandRequest; +import org.eclipse.debug.core.commands.IDropToFrameHandler; +import org.eclipse.debug.core.commands.IEnabledStateRequest; +import org.eclipse.tm.internal.tcf.debug.actions.TCFActionStepOut; +import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeStackFrame; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFRunnable; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.services.IBreakpoints; +import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.services.IRunControl.RunControlContext; +import org.eclipse.tm.tcf.services.IStackTrace.StackTraceContext; +import org.eclipse.tm.tcf.util.TCFDataCache; + +/** + * Drop-to-frame command handler for TCF. + */ +public class DropToFrameCommand implements IDropToFrameHandler { + + private static class StepStateMachine extends TCFActionStepOut { + + private final IDebugCommandRequest monitor; + private final Runnable done; + private final TCFNodeExecContext node; + private final TCFNodeStackFrame frame; + + StepStateMachine(TCFModel model, IDebugCommandRequest monitor, + IRunControl.RunControlContext ctx, TCFNodeStackFrame frame, Runnable done) { + super(model.getLaunch(), ctx, false); + this.monitor = monitor; + this.done = done; + this.frame = frame; + this.node = (TCFNodeExecContext)frame.getParent(); + } + + @Override + protected TCFDataCache<TCFContextState> getContextState() { + return node.getState(); + } + + @Override + protected TCFDataCache<StackTraceContext> getStackFrame() { + return frame.getStackTraceContext(); + } + + @Override + protected int getStackFrameIndex() { + return frame.getFrameNo(); + } + + @Override + protected TCFDataCache<?> getStackTrace() { + return node.getStackTrace(); + } + + protected void exit(Throwable error) { + exit(error, "Drop To Frame"); + } + + @Override + protected void exit(Throwable error, String reason) { + if (exited) return; + super.exit(error, reason); + if (error != null && node.getChannel().getState() == IChannel.STATE_OPEN) { + monitor.setStatus(new Status(IStatus.ERROR, + Activator.PLUGIN_ID, 0, "Cannot drop to frame: " + error.getLocalizedMessage(), error)); + } + if (aborted) { + monitor.setStatus(Status.CANCEL_STATUS); + } + done.run(); + } + } + + private final TCFModel model; + + public DropToFrameCommand(TCFModel tcfModel) { + model = tcfModel; + } + + public void canExecute(final IEnabledStateRequest request) { + final Object[] elements = request.getElements(); + if (elements.length != 1 || !(elements[0] instanceof TCFNodeStackFrame)) { + request.setEnabled(false); + request.done(); + return; + } + final TCFNodeStackFrame frameNode = (TCFNodeStackFrame) elements[0]; + new TCFRunnable(request) { + public void run() { + if (frameNode.getFrameNo() < 1) { + request.setEnabled(false); + done(); + return; + } + TCFNodeExecContext exeNode = (TCFNodeExecContext) frameNode.getParent(); + TCFDataCache<IRunControl.RunControlContext> ctx_cache = exeNode.getRunContext(); + if (!ctx_cache.validate(this)) { + return; + } + IRunControl.RunControlContext ctx = ctx_cache.getData(); + if (!canStepOut(ctx)) { + request.setEnabled(false); + done(); + return; + } + int action_cnt = model.getLaunch().getContextActionsCount(ctx.getID()); + if (action_cnt > 0 || !canStepOut(ctx)) { + request.setEnabled(false); + done(); + return; + } + TCFDataCache<TCFContextState> state_cache = exeNode.getState(); + if (!state_cache.validate(this)) { + return; + } + TCFContextState state_data = state_cache.getData(); + request.setEnabled(state_data != null && state_data.is_suspended); + done(); + } + + private boolean canStepOut(RunControlContext ctx) { + if (ctx == null) return false; + if (ctx.canResume(IRunControl.RM_STEP_OUT)) return true; + if (!ctx.hasState()) return false; + if (ctx.canResume(IRunControl.RM_RESUME) && model.getLaunch().getService(IBreakpoints.class) != null) return true; + return false; + } + }; + } + + public boolean execute(final IDebugCommandRequest request) { + final Object[] elements = request.getElements(); + if (elements.length != 1 || !(elements[0] instanceof TCFNodeStackFrame)) { + request.setStatus(Status.CANCEL_STATUS); + request.done(); + return false; + } + final TCFNodeStackFrame frameNode = (TCFNodeStackFrame) elements[0]; + new TCFRunnable(request) { + public void run() { + int frameNo = frameNode.getFrameNo(); + if (frameNo < 1) { + request.setStatus(Status.CANCEL_STATUS); + done(); + return; + } + TCFNodeExecContext exeNode = (TCFNodeExecContext) frameNode.getParent(); + TCFDataCache<IRunControl.RunControlContext> ctx_cache = exeNode.getRunContext(); + if (!ctx_cache.validate(this)) return; + TCFDataCache<TCFContextState> state_cache = exeNode.getState(); + if (!state_cache.validate(this)) return; + TCFContextState state_data = state_cache.getData(); + if (state_data == null || !state_data.is_suspended) { + request.setStatus(Status.CANCEL_STATUS); + done(); + } + if (!exeNode.getStackTrace().validate(this)) return; + Map<String, TCFNode> stack = exeNode.getStackTrace().getData(); + for (TCFNode node : stack.values()) { + TCFNodeStackFrame frame_to_step_out = (TCFNodeStackFrame) node; + if (frame_to_step_out.getFrameNo() == frameNo - 1) { + new StepStateMachine(model, request, ctx_cache.getData(), frame_to_step_out, new Runnable() { + public void run() { + request.done(); + } + }); + return; + } + } + request.setStatus(Status.CANCEL_STATUS); + done(); + } + }; + return false; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/MemoryMapCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/MemoryMapCommand.java new file mode 100644 index 000000000..098eb50dd --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/MemoryMapCommand.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeArrayPartition; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExpression; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeLaunch; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeModule; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeRegister; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeStackFrame; +import org.eclipse.tm.tcf.services.IMemory; +import org.eclipse.tm.tcf.util.TCFDataCache; +import org.eclipse.tm.tcf.util.TCFTask; + +public class MemoryMapCommand extends AbstractActionDelegate { + + private static boolean isValidNode(final TCFNode n) { + if (n instanceof TCFNodeLaunch) return true; + if (n instanceof TCFNodeExecContext) { + return new TCFTask<Boolean>(n.getChannel()) { + public void run() { + TCFDataCache<TCFNodeExecContext> mem_cache = n.getModel().searchMemoryContext(n); + if (mem_cache == null) { + done(false); + return; + } + if (!mem_cache.validate(this)) return; + TCFNodeExecContext mem_node = mem_cache.getData(); + if (mem_node == null) { + done(false); + return; + } + TCFDataCache<TCFNodeExecContext> syms_cache = mem_node.getSymbolsNode(); + if (!syms_cache.validate(this)) return; + TCFNodeExecContext syms_node = syms_cache.getData(); + if (syms_node == null) { + done(false); + return; + } + TCFDataCache<IMemory.MemoryContext> ctx_cache = syms_node.getMemoryContext(); + if (!ctx_cache.validate(this)) return; + done(ctx_cache.getData() != null); + } + }.getE(); + } + if (n instanceof TCFNodeStackFrame) return true; + if (n instanceof TCFNodeExpression) return true; + if (n instanceof TCFNodeArrayPartition) return true; + if (n instanceof TCFNodeRegister) return true; + if (n instanceof TCFNodeModule) return true; + return false; + } + + protected void selectionChanged() { + getAction().setEnabled(isValidNode(getSelectedNode())); + } + + protected void run() { + TCFNode node = getSelectedNode(); + if (!isValidNode(node)) return; + Shell shell = getWindow().getShell(); + try { + new MemoryMapDialog(shell, node).open(); + } + catch (Throwable x) { + MessageBox mb = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK); + mb.setText("Cannot open Symbol Files dialog"); + mb.setMessage(TCFModel.getErrorMessage(x, true)); + mb.open(); + } + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/MemoryMapDialog.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/MemoryMapDialog.java new file mode 100644 index 000000000..c8e450a7e --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/MemoryMapDialog.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; + +class MemoryMapDialog extends Dialog { + + private final TCFNode node; + private final ILaunchConfiguration cfg; + private MemoryMapWidget widget; + private Button ok_button; + + MemoryMapDialog(Shell parent, TCFNode node) { + super(parent); + this.node = node; + cfg = node.getModel().getLaunch().getLaunchConfiguration(); + setShellStyle(getShellStyle() | SWT.RESIZE); + } + + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText("Symbol Files"); + shell.setImage(ImageCache.getImage(ImageCache.IMG_MEMORY_MAP)); + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + ok_button = createButton(parent, IDialogConstants.OK_ID, "&OK", true); + ok_button.setEnabled(widget != null && widget.getMemoryMapID() != null); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite)super.createDialogArea(parent); + widget = new MemoryMapWidget(composite, node); + widget.loadData(cfg); + if (ok_button != null) ok_button.setEnabled(widget.getMemoryMapID() != null); + composite.setSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); + return composite; + } + + @Override + protected void okPressed() { + try { + ILaunchConfigurationWorkingCopy copy = cfg.getWorkingCopy(); + if (widget.saveData(copy)) copy.doSave(); + super.okPressed(); + } + catch (Throwable x) { + MessageBox mb = new MessageBox(getShell(), SWT.ICON_ERROR | SWT.OK); + mb.setText("Cannot update memory map"); + mb.setMessage(TCFModel.getErrorMessage(x, true)); + mb.open(); + } + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/MemoryMapItemDialog.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/MemoryMapItemDialog.java new file mode 100644 index 000000000..39a314963 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/MemoryMapItemDialog.java @@ -0,0 +1,303 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import java.math.BigInteger; +import java.util.Map; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.tcf.protocol.JSON; +import org.eclipse.tm.tcf.services.IMemoryMap; + +class MemoryMapItemDialog extends Dialog { + + private final Map<String,Object> props; + private final boolean enable_editing; + private final Image image; + + private Text addr_text; + private Text size_text; + private Text offset_text; + private Text file_text; + private Button rd_button; + private Button wr_button; + private Button ex_button; + + MemoryMapItemDialog(Shell parent, Image image, Map<String,Object> props, boolean enable_editing) { + super(parent); + this.image = image; + this.props = props; + this.enable_editing = enable_editing; + } + + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText("Symbol File"); + shell.setImage(image); + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + createButton(parent, IDialogConstants.OK_ID, "&OK", true); + updateButtons(); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite)super.createDialogArea(parent); + createFileNameFields(composite); + createPropsFields(composite); + setData(); + composite.setSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); + return composite; + } + + private void createFileNameFields(Composite parent) { + Font font = parent.getFont(); + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(3, false); + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Label file_label = new Label(composite, SWT.WRAP); + file_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + file_label.setFont(font); + file_label.setText("File name:"); + + file_text = new Text(composite, SWT.SINGLE | SWT.BORDER); + file_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + file_text.setFont(font); + file_text.setEditable(enable_editing); + + file_text.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + updateButtons(); + } + }); + + Button button = new Button(composite, SWT.PUSH); + button.setFont(font); + button.setText("..."); + button.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + button.setEnabled(enable_editing); + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + FileDialog file_dialog = new FileDialog(getShell(), SWT.NONE); + file_dialog.setFileName(file_text.getText()); + String path = file_dialog.open(); + if (path != null) file_text.setText(path); + } + }); + } + + private void createPropsFields(Composite parent) { + Font font = parent.getFont(); + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + createTextFields(composite); + createFlagsGroup(composite); + } + + private void createTextFields(Composite parent) { + Font font = parent.getFont(); + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + composite.setFont(font); + composite.setLayout(layout); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.widthHint = 250; + composite.setLayoutData(gd); + + Label addr_label = new Label(composite, SWT.WRAP); + addr_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + addr_label.setFont(font); + addr_label.setText("Address:"); + + addr_text = new Text(composite, SWT.SINGLE | SWT.BORDER); + addr_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + addr_text.setFont(font); + addr_text.setEditable(enable_editing); + + Label size_label = new Label(composite, SWT.WRAP); + size_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + size_label.setFont(font); + size_label.setText("Size:"); + + size_text = new Text(composite, SWT.SINGLE | SWT.BORDER); + size_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + size_text.setFont(font); + size_text.setEditable(enable_editing); + + Label offset_label = new Label(composite, SWT.WRAP); + offset_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + offset_label.setFont(font); + offset_label.setText("File offset:"); + + offset_text = new Text(composite, SWT.SINGLE | SWT.BORDER); + offset_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + offset_text.setFont(font); + offset_text.setEditable(enable_editing); + } + + private void createFlagsGroup(Composite parent) { + Font font = parent.getFont(); + + Group group = new Group(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.verticalSpacing = 0; + layout.numColumns = 1; + group.setLayout(layout); + group.setLayoutData(new GridData(GridData.FILL_BOTH)); + group.setFont(font); + group.setText("Flags"); + + rd_button = new Button(group, SWT.CHECK); + rd_button.setFont(font); + rd_button.setText("Data read"); + rd_button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + rd_button.setEnabled(enable_editing); + + wr_button = new Button(group, SWT.CHECK); + wr_button.setFont(font); + wr_button.setText("Data write"); + wr_button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + wr_button.setEnabled(enable_editing); + + ex_button = new Button(group, SWT.CHECK); + ex_button.setFont(font); + ex_button.setText("Instructions read"); + ex_button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + ex_button.setEnabled(enable_editing); + } + + private String toHex(Number n) { + if (n == null) return null; + BigInteger x = JSON.toBigInteger(n); + String s = x.toString(16); + int l = 16 - s.length(); + if (l < 0) l = 0; + if (l > 16) l = 16; + return "0x0000000000000000".substring(0, 2 + l) + s; + } + + private void setText(Text text, String str) { + if (str == null) str = ""; + text.setText(str); + } + + private void setData() { + setText(addr_text, toHex((Number)props.get(IMemoryMap.PROP_ADDRESS))); + setText(size_text, toHex((Number)props.get(IMemoryMap.PROP_SIZE))); + if (props.get(IMemoryMap.PROP_SECTION_NAME) != null) { + setText(offset_text, (String)props.get(IMemoryMap.PROP_SECTION_NAME)); + } + else { + setText(offset_text, toHex((Number)props.get(IMemoryMap.PROP_OFFSET))); + } + setText(file_text, (String)props.get(IMemoryMap.PROP_FILE_NAME)); + int flags = 0; + Number n = (Number)props.get(IMemoryMap.PROP_FLAGS); + if (n != null) flags = n.intValue(); + rd_button.setSelection((flags & IMemoryMap.FLAG_READ) != 0); + wr_button.setSelection((flags & IMemoryMap.FLAG_WRITE) != 0); + ex_button.setSelection((flags & IMemoryMap.FLAG_EXECUTE) != 0); + updateButtons(); + } + + private void getNumber(Text text, String key) { + String s = text.getText().trim(); + if (s == null || s.length() == 0) { + props.remove(key); + } + else if (s.startsWith("0x")) { + props.put(key, new BigInteger(s.substring(2), 16)); + } + else { + props.put(key, new BigInteger(s)); + } + } + + private void getText(Text text, String key) { + String s = text.getText().trim(); + if (s == null || s.length() == 0) { + props.remove(key); + } + else { + props.put(key, s); + } + } + + private void getData() { + getNumber(addr_text, IMemoryMap.PROP_ADDRESS); + getNumber(size_text, IMemoryMap.PROP_SIZE); + if (offset_text.getText().startsWith(".")) { + props.put(IMemoryMap.PROP_SECTION_NAME, offset_text.getText()); + props.remove(IMemoryMap.PROP_OFFSET); + } + else { + getNumber(offset_text, IMemoryMap.PROP_OFFSET); + props.remove(IMemoryMap.PROP_SECTION_NAME); + } + getText(file_text, IMemoryMap.PROP_FILE_NAME); + int flags = 0; + if (rd_button.getSelection()) flags |= IMemoryMap.FLAG_READ; + if (wr_button.getSelection()) flags |= IMemoryMap.FLAG_WRITE; + if (ex_button.getSelection()) flags |= IMemoryMap.FLAG_EXECUTE; + props.put(IMemoryMap.PROP_FLAGS, flags); + } + + private void updateButtons() { + Button btn = getButton(IDialogConstants.OK_ID); + if (btn != null && file_text != null) btn.setEnabled(!enable_editing || file_text.getText().trim().length() > 0); + } + + @Override + protected void okPressed() { + if (enable_editing) { + try { + getData(); + } + catch (Throwable x) { + MessageBox mb = new MessageBox(getShell(), SWT.ICON_ERROR | SWT.OK); + mb.setText("Invalid data"); + mb.setMessage(TCFModel.getErrorMessage(x, true)); + mb.open(); + return; + } + } + super.okPressed(); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/MemoryMapWidget.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/MemoryMapWidget.java new file mode 100644 index 000000000..7db194fde --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/MemoryMapWidget.java @@ -0,0 +1,632 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITableColorProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.tm.internal.tcf.debug.launch.TCFLaunchDelegate; +import org.eclipse.tm.internal.tcf.debug.model.TCFMemoryRegion; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFChildren; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeLaunch; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.JSON; +import org.eclipse.tm.tcf.services.IMemory; +import org.eclipse.tm.tcf.services.IMemoryMap; +import org.eclipse.tm.tcf.util.TCFDataCache; +import org.eclipse.tm.tcf.util.TCFTask; + +public class MemoryMapWidget { + + + private static final int + SIZING_TABLE_WIDTH = 700, + SIZING_TABLE_HEIGHT = 300; + + private static final String[] column_names = { + "File", + "Address", + "Size", + "Flags", + "File offset/section", + }; + + private final TCFModel model; + private final IChannel channel; + private final TCFNode selection; + + private Combo ctx_text; + private Table map_table; + private TableViewer table_viewer; + private Runnable update_map_buttons; + private final Map<String,ArrayList<IMemoryMap.MemoryRegion>> org_maps = + new HashMap<String,ArrayList<IMemoryMap.MemoryRegion>>(); + private final Map<String,ArrayList<IMemoryMap.MemoryRegion>> cur_maps = + new HashMap<String,ArrayList<IMemoryMap.MemoryRegion>>(); + private final ArrayList<IMemoryMap.MemoryRegion> target_map = + new ArrayList<IMemoryMap.MemoryRegion>(); + private final HashMap<String,TCFNodeExecContext> target_map_nodes = + new HashMap<String,TCFNodeExecContext>(); + private TCFNodeExecContext selected_mem_map_node; + private IMemory.MemoryContext mem_ctx; + private ILaunchConfiguration cfg; + private final HashSet<String> loaded_files = new HashSet<String>(); + private String selected_mem_map_id; + + private final IStructuredContentProvider content_provider = new IStructuredContentProvider() { + + public Object[] getElements(Object input) { + ArrayList<IMemoryMap.MemoryRegion> res = new ArrayList<IMemoryMap.MemoryRegion>(); + ArrayList<IMemoryMap.MemoryRegion> lst = cur_maps.get((String)input); + if (lst != null) res.addAll(lst); + res.addAll(target_map); + return res.toArray(); + } + + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + }; + + private class MapLabelProvider extends LabelProvider implements ITableLabelProvider, ITableColorProvider { + + public Image getColumnImage(Object element, int column) { + return null; + } + + public String getColumnText(Object element, int column) { + TCFMemoryRegion r = (TCFMemoryRegion)element; + switch (column) { + case 0: + return r.getFileName(); + case 1: + case 2: + { + BigInteger x = column == 1 ? r.addr : r.size; + if (x == null) return ""; + String s = x.toString(16); + int sz = 0; + if (mem_ctx != null) sz = mem_ctx.getAddressSize() * 2; + int l = sz - s.length(); + if (l < 0) l = 0; + if (l > 16) l = 16; + return "0x0000000000000000".substring(0, 2 + l) + s; + } + case 3: + { + int n = r.getFlags(); + StringBuffer bf = new StringBuffer(); + if ((n & IMemoryMap.FLAG_READ) != 0) bf.append('r'); + if ((n & IMemoryMap.FLAG_WRITE) != 0) bf.append('w'); + if ((n & IMemoryMap.FLAG_EXECUTE) != 0) bf.append('x'); + return bf.toString(); + } + case 4: + { + Number n = r.getOffset(); + if (n != null) { + BigInteger x = JSON.toBigInteger(n); + String s = x.toString(16); + int l = 16 - s.length(); + if (l < 0) l = 0; + if (l > 16) l = 16; + return "0x0000000000000000".substring(0, 2 + l) + s; + } + String s = r.getSectionName(); + if (s != null) return s; + return ""; + } + } + return ""; + } + + public Color getBackground(Object element, int columnIndex) { + return map_table.getBackground(); + } + + public Color getForeground(Object element, int columnIndex) { + TCFMemoryRegion r = (TCFMemoryRegion)element; + if (r.getProperties().get(IMemoryMap.PROP_ID) != null) { + String fnm = r.getFileName(); + if (fnm != null && loaded_files.contains(fnm)) { + return map_table.getDisplay().getSystemColor(SWT.COLOR_DARK_GREEN); + } + return map_table.getDisplay().getSystemColor(SWT.COLOR_DARK_BLUE); + } + return map_table.getForeground(); + } + + public String getText(Object element) { + return element.toString(); + } + } + + public MemoryMapWidget(Composite composite, TCFNode node) { + if (node != null) { + model = node.getModel(); + channel = node.getChannel(); + selection = node; + } + else { + model = null; + channel = null; + selection = null; + } + createContextText(composite); + createMemoryMapTable(composite); + } + + public String getMemoryMapID() { + return selected_mem_map_id; + } + + private void createContextText(Composite parent) { + Font font = parent.getFont(); + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Label props_label = new Label(composite, SWT.WRAP); + props_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + props_label.setFont(font); + props_label.setText("&Debug context:"); + + ctx_text = new Combo(composite, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY); + ctx_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + ctx_text.setFont(font); + ctx_text.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + selected_mem_map_id = ctx_text.getText(); + selected_mem_map_node = target_map_nodes.get(selected_mem_map_id); + loadTargetMemoryMap(); + table_viewer.setInput(selected_mem_map_id); + if (selected_mem_map_id.length() == 0) selected_mem_map_id = null; + update_map_buttons.run(); + } + }); + } + + private void createMemoryMapTable(Composite parent) { + Font font = parent.getFont(); + + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_BOTH)); + + map_table = new Table(composite, + SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION | + SWT.H_SCROLL | SWT.V_SCROLL); + map_table.setFont(font); + GridData data = new GridData(GridData.FILL_BOTH); + data.widthHint = SIZING_TABLE_WIDTH; + data.heightHint = SIZING_TABLE_HEIGHT; + map_table.setLayoutData(data); + + int w = SIZING_TABLE_WIDTH / (column_names.length + 12); + for (int i = 0; i < column_names.length; i++) { + final TableColumn column = new TableColumn(map_table, SWT.LEAD, i); + column.setMoveable(false); + column.setText(column_names[i]); + switch (i) { + case 0: + column.setWidth(w * 10); + break; + case 1: + case 2: + case 4: + column.setWidth(w * 2); + break; + default: + column.setWidth(w); + break; + } + } + map_table.setHeaderVisible(true); + map_table.setLinesVisible(true); + map_table.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetDefaultSelected(SelectionEvent e) { + IMemoryMap.MemoryRegion r = (IMemoryMap.MemoryRegion)((IStructuredSelection) + table_viewer.getSelection()).getFirstElement(); + if (r == null) return; + editRegion(r); + } + @Override + public void widgetSelected(SelectionEvent e) { + update_map_buttons.run(); + } + }); + + table_viewer = new TableViewer(map_table); + table_viewer.setUseHashlookup(true); + table_viewer.setColumnProperties(column_names); + + table_viewer.setContentProvider(content_provider); + + table_viewer.setLabelProvider(new MapLabelProvider()); + + createMapButtons(composite); + } + + private void createMapButtons(Composite parent) { + Font font = parent.getFont(); + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL)); + Menu menu = new Menu(map_table); + SelectionAdapter sel_adapter = null; + + final Button button_add = new Button(composite, SWT.PUSH); + button_add.setText("&Add..."); + button_add.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + button_add.addSelectionListener(sel_adapter = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + String id = ctx_text.getText(); + if (id == null || id.length() == 0) return; + Map<String,Object> props = new HashMap<String,Object>(); + Image image = ImageCache.getImage(ImageCache.IMG_MEMORY_MAP); + if (new MemoryMapItemDialog(map_table.getShell(), image, props, true).open() == Window.OK) { + props.put(IMemoryMap.PROP_ID, id); + ArrayList<IMemoryMap.MemoryRegion> lst = cur_maps.get(id); + if (lst == null) cur_maps.put(id, lst = new ArrayList<IMemoryMap.MemoryRegion>()); + lst.add(new TCFMemoryRegion(props)); + table_viewer.refresh(); + } + } + }); + final MenuItem item_add = new MenuItem(menu, SWT.PUSH); + item_add.setText("&Add..."); + item_add.addSelectionListener(sel_adapter); + + final Button button_edit = new Button(composite, SWT.PUSH); + button_edit.setText("E&dit..."); + button_edit.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + button_edit.addSelectionListener(sel_adapter = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + IMemoryMap.MemoryRegion r = (IMemoryMap.MemoryRegion)((IStructuredSelection) + table_viewer.getSelection()).getFirstElement(); + if (r == null) return; + editRegion(r); + } + }); + final MenuItem item_edit = new MenuItem(menu, SWT.PUSH); + item_edit.setText("E&dit..."); + item_edit.addSelectionListener(sel_adapter); + + final Button button_remove = new Button(composite, SWT.PUSH); + button_remove.setText("&Remove"); + button_remove.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + button_remove.addSelectionListener(sel_adapter = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + String id = ctx_text.getText(); + if (id == null || id.length() == 0) return; + IMemoryMap.MemoryRegion r = (IMemoryMap.MemoryRegion)((IStructuredSelection) + table_viewer.getSelection()).getFirstElement(); + if (r == null) return; + ArrayList<IMemoryMap.MemoryRegion> lst = cur_maps.get(id); + if (lst != null && lst.remove(r)) table_viewer.refresh(); + } + }); + final MenuItem item_remove = new MenuItem(menu, SWT.PUSH); + item_remove.setText("&Remove"); + item_remove.addSelectionListener(sel_adapter); + + map_table.setMenu(menu); + + update_map_buttons = new Runnable() { + public void run() { + IMemoryMap.MemoryRegion r = (IMemoryMap.MemoryRegion)((IStructuredSelection) + table_viewer.getSelection()).getFirstElement(); + boolean manual = r != null && r.getProperties().get(IMemoryMap.PROP_ID) != null; + button_add.setEnabled(selected_mem_map_id != null); + button_edit.setEnabled(r != null); + button_remove.setEnabled(manual); + item_add.setEnabled(selected_mem_map_id != null); + item_edit.setEnabled(r != null); + item_remove.setEnabled(manual); + } + }; + update_map_buttons.run(); + } + + private void editRegion(IMemoryMap.MemoryRegion r) { + String id = ctx_text.getText(); + if (id == null || id.length() == 0) return; + Map<String,Object> props = r.getProperties(); + boolean enable_editing = props.get(IMemoryMap.PROP_ID) != null; + if (enable_editing) props = new HashMap<String,Object>(props); + Image image = ImageCache.getImage(ImageCache.IMG_MEMORY_MAP); + if (new MemoryMapItemDialog(map_table.getShell(), image, props, enable_editing).open() == Window.OK && enable_editing) { + ArrayList<IMemoryMap.MemoryRegion> lst = cur_maps.get(id); + if (lst != null) { + int n = lst.indexOf(r); + if (n >= 0) { + lst.set(n, new TCFMemoryRegion(props)); + table_viewer.refresh(); + } + } + } + } + + private void readMemoryMapAttribute() { + cur_maps.clear(); + try { + new TCFTask<Boolean>() { + public void run() { + try { + TCFLaunchDelegate.getMemMapsAttribute(cur_maps, cfg); + done(true); + } + catch (Exception e) { + error(e); + } + } + }.get(); + } + catch (Exception x) { + Activator.log("Invalid launch cofiguration attribute", x); + } + } + + private void writeMemoryMapAttribute(ILaunchConfigurationWorkingCopy copy) throws Exception { + String s = null; + final ArrayList<IMemoryMap.MemoryRegion> lst = new ArrayList<IMemoryMap.MemoryRegion>(); + for (ArrayList<IMemoryMap.MemoryRegion> x : cur_maps.values()) lst.addAll(x); + if (lst.size() > 0) { + s = new TCFTask<String>() { + public void run() { + try { + done(JSON.toJSON(lst)); + } + catch (IOException e) { + error(e); + } + } + }.getIO(); + } + copy.setAttribute(TCFLaunchDelegate.ATTR_MEMORY_MAP, s); + } + + public void loadData(ILaunchConfiguration cfg) { + this.cfg = cfg; + cur_maps.clear(); + org_maps.clear(); + loadTargetMemoryNodes(); + readMemoryMapAttribute(); + for (String id : cur_maps.keySet()) { + org_maps.put(id, new ArrayList<IMemoryMap.MemoryRegion>(cur_maps.get(id))); + } + // Update controls + String map_id = getSelectedMemoryNode(); + HashSet<String> ids = new HashSet<String>(target_map_nodes.keySet()); + if (map_id != null) ids.add(map_id); + ids.addAll(cur_maps.keySet()); + String[] arr = ids.toArray(new String[ids.size()]); + Arrays.sort(arr); + ctx_text.removeAll(); + for (String id : arr) ctx_text.add(id); + if (map_id == null && arr.length > 0) map_id = arr[0]; + if (map_id == null) map_id = ""; + ctx_text.setText(map_id); + } + + private String getSelectedMemoryNode() { + if (channel == null || channel.getState() != IChannel.STATE_OPEN) return null; + try { + return new TCFTask<String>(channel) { + public void run() { + TCFDataCache<TCFNodeExecContext> mem_cache = model.searchMemoryContext(selection); + if (mem_cache == null) { + error(new Exception("Context does not provide memory access")); + return; + } + if (!mem_cache.validate(this)) return; + if (mem_cache.getError() != null) { + error(mem_cache.getError()); + return; + } + String id = null; + TCFNodeExecContext mem_node = mem_cache.getData(); + if (mem_node != null) { + TCFDataCache<TCFNodeExecContext> syms_cache = mem_node.getSymbolsNode(); + if (!syms_cache.validate(this)) return; + TCFNodeExecContext syms_node = syms_cache.getData(); + if (syms_node != null) { + TCFDataCache<IMemory.MemoryContext> mem_ctx = syms_node.getMemoryContext(); + if (!mem_ctx.validate(this)) return; + if (mem_ctx.getData() != null) { + if (syms_node.getModel().getLaunch().isMemoryMapPreloadingSupported()) { + TCFDataCache<String> name_cache = syms_node.getFullName(); + if (!name_cache.validate(this)) return; + id = name_cache.getData(); + } + else { + id = mem_ctx.getData().getName(); + } + if (id == null) id = syms_node.getID(); + } + } + } + done(id); + } + }.get(); + } + catch (Exception x) { + if (channel.getState() != IChannel.STATE_OPEN) return null; + Activator.log("Cannot get selected memory node", x); + return null; + } + } + + private void loadTargetMemoryNodes() { + target_map_nodes.clear(); + if (channel == null || channel.getState() != IChannel.STATE_OPEN) return; + try { + new TCFTask<Boolean>(channel) { + public void run() { + TCFNodeLaunch n = model.getRootNode(); + if (!collectMemoryNodes(n.getFilteredChildren())) return; + done(true); + } + private boolean collectMemoryNodes(TCFChildren children) { + if (!children.validate(this)) return false; + Map<String,TCFNode> m = children.getData(); + if (m != null) { + for (TCFNode n : m.values()) { + if (n instanceof TCFNodeExecContext) { + TCFNodeExecContext exe = (TCFNodeExecContext)n; + if (!collectMemoryNodes(exe.getChildren())) return false; + TCFDataCache<TCFNodeExecContext> syms_cache = exe.getSymbolsNode(); + if (!syms_cache.validate(this)) return false; + TCFNodeExecContext syms_node = syms_cache.getData(); + if (syms_node != null) { + TCFDataCache<IMemory.MemoryContext> mem_ctx = syms_node.getMemoryContext(); + if (!mem_ctx.validate(this)) return false; + if (mem_ctx.getData() != null) { + String id = null; + if (syms_node.getModel().getLaunch().isMemoryMapPreloadingSupported()) { + TCFDataCache<String> name_cache = syms_node.getFullName(); + if (!name_cache.validate(this)) return false; + id = name_cache.getData(); + } + else { + id = mem_ctx.getData().getName(); + } + if (id == null) id = syms_node.getID(); + target_map_nodes.put(id, syms_node); + } + } + } + } + } + return true; + } + }.get(); + } + catch (Exception x) { + if (channel.getState() != IChannel.STATE_OPEN) return; + Activator.log("Cannot load target memory context info", x); + } + } + + private void loadTargetMemoryMap() { + loaded_files.clear(); + target_map.clear(); + mem_ctx = null; + if (channel == null || channel.getState() != IChannel.STATE_OPEN) return; + try { + new TCFTask<Boolean>(channel) { + public void run() { + if (selected_mem_map_node != null && !selected_mem_map_node.isDisposed()) { + TCFDataCache<IMemory.MemoryContext> mem_cache = selected_mem_map_node.getMemoryContext(); + if (!mem_cache.validate(this)) return; + if (mem_cache.getError() != null) { + error(mem_cache.getError()); + return; + } + mem_ctx = mem_cache.getData(); + TCFDataCache<TCFNodeExecContext.MemoryRegion[]> map_cache = selected_mem_map_node.getMemoryMap(); + if (!map_cache.validate(this)) return; + if (map_cache.getError() != null) { + error(map_cache.getError()); + return; + } + if (map_cache.getData() != null) { + for (TCFNodeExecContext.MemoryRegion m : map_cache.getData()) { + Map<String,Object> props = m.region.getProperties(); + if (props.get(IMemoryMap.PROP_ID) != null) { + String fnm = m.region.getFileName(); + if (fnm != null) loaded_files.add(fnm); + } + else { + target_map.add(new TCFMemoryRegion(props)); + } + } + } + } + done(true); + } + }.get(); + } + catch (Exception x) { + if (channel.getState() != IChannel.STATE_OPEN) return; + Activator.log("Cannot load target memory map", x); + } + } + + public boolean saveData(ILaunchConfigurationWorkingCopy copy) throws Exception { + boolean loaded_files_ok = true; + if (selected_mem_map_id != null) { + ArrayList<IMemoryMap.MemoryRegion> lst = cur_maps.get(selected_mem_map_id); + if (lst != null) { + for (IMemoryMap.MemoryRegion r : lst) { + String fnm = r.getFileName(); + if (fnm != null && !loaded_files.contains(fnm)) loaded_files_ok = false; + } + if (lst.size() == 0) cur_maps.remove(selected_mem_map_id); + } + } + if (!loaded_files_ok || !org_maps.equals(cur_maps)) { + writeMemoryMapAttribute(copy); + return true; + } + return false; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/RefreshCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/RefreshCommand.java new file mode 100644 index 000000000..ac52e4fa2 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/RefreshCommand.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.debug.ui.IDebugView; +import org.eclipse.debug.ui.memory.IMemoryRenderingSite; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.tcf.util.TCFDataCache; +import org.eclipse.tm.tcf.util.TCFTask; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPartSite; + +public class RefreshCommand extends AbstractActionDelegate { + + @Override + protected void selectionChanged() { + getAction().setEnabled(getRootNode() != null); + } + + @Override + protected void run() { + final TCFNode node = getRootNode(); + if (node == null) return; + new TCFTask<Object>(node.getChannel()) { + public void run() { + IViewPart part = getView(); + TCFModel model = node.getModel(); + TCFNode ref_node = node; + if (part instanceof IMemoryRenderingSite) { + // Search memory node + TCFDataCache<TCFNodeExecContext> mem_cache = model.searchMemoryContext(node); + if (mem_cache == null) { + done(null); + return; + } + if (!mem_cache.validate(this)) return; + ref_node = mem_cache.getData(); + } + if (ref_node != null) { + ref_node.refresh(part); + if (model.clearLock(part)) { + model.setLock(part); + } + } + done(null); + } + }.getE(); + } + + private TCFNode getRootNode() { + IViewPart view = getView(); + if (view == null) return null; + IWorkbenchPartSite site = view.getSite(); + if (site != null && IDebugUIConstants.ID_DEBUG_VIEW.equals(site.getId())) { + TCFNode n = getSelectedNode(); + if (n == null) return null; + return n.getModel().getRootNode(); + } + if (site != null && IDebugUIConstants.ID_MEMORY_VIEW.equals(site.getId())) { + ISelection selection = DebugUITools.getDebugContextManager().getContextService( + site.getWorkbenchWindow()).getActiveContext(); + if (selection instanceof IStructuredSelection) { + Object obj = ((IStructuredSelection)selection).getFirstElement(); + if (obj instanceof TCFNode) return (TCFNode)obj; + } + } + if (view instanceof IDebugView) { + Object input = ((IDebugView)view).getViewer().getInput(); + if (input instanceof TCFNode) return (TCFNode)input; + } + return null; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/RefreshHandler.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/RefreshHandler.java new file mode 100644 index 000000000..6658ec5da --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/RefreshHandler.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.debug.ui.IDebugView; +import org.eclipse.debug.ui.memory.IMemoryRenderingSite; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.tcf.util.TCFDataCache; +import org.eclipse.tm.tcf.util.TCFTask; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchPartSite; +import org.eclipse.ui.handlers.HandlerUtil; + +public class RefreshHandler extends AbstractHandler { + + public Object execute(ExecutionEvent event) throws ExecutionException { + Object input = null; + final IWorkbenchPart part = HandlerUtil.getActivePart(event); + if (part instanceof IMemoryRenderingSite) { + IWorkbenchPartSite site = part.getSite(); + if (site != null) { + ISelection selection = DebugUITools.getDebugContextManager().getContextService( + site.getWorkbenchWindow()).getActiveContext(); + if (selection instanceof IStructuredSelection) { + input = ((IStructuredSelection)selection).getFirstElement(); + } + } + } + else if (part instanceof IDebugView) { + IWorkbenchPartSite site = part.getSite(); + if (site != null && IDebugUIConstants.ID_DEBUG_VIEW.equals(site.getId())) { + ISelection selection = HandlerUtil.getCurrentSelection(event); + if (selection instanceof IStructuredSelection) { + Object obj = ((IStructuredSelection)selection).getFirstElement(); + if (obj instanceof TCFNode) input = ((TCFNode)obj).getModel().getRootNode(); + } + } + else { + input = ((IDebugView)part).getViewer().getInput(); + } + } + if (input instanceof TCFNode) { + final TCFNode node = (TCFNode)input; + return new TCFTask<Object>(node.getChannel()) { + public void run() { + TCFModel model = node.getModel(); + TCFNode ref_node = node; + if (part instanceof IMemoryRenderingSite) { + // Search memory node + TCFDataCache<TCFNodeExecContext> mem_cache = model.searchMemoryContext(node); + if (mem_cache == null) { + done(null); + return; + } + if (!mem_cache.validate(this)) return; + ref_node = mem_cache.getData(); + } + if (ref_node != null) { + ref_node.refresh(part); + if (model.clearLock(part)) { + model.setLock(part); + } + } + done(null); + } + }.getE(); + } + return null; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/RestoreDefaultTypeCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/RestoreDefaultTypeCommand.java new file mode 100644 index 000000000..6be58e590 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/RestoreDefaultTypeCommand.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.tm.internal.tcf.debug.ui.model.ICastToType; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.tcf.protocol.Protocol; + +public class RestoreDefaultTypeCommand extends AbstractActionDelegate { + + @Override + protected void run() { + final TCFNode node = getCastToTypeNode(); + if (node == null) return; + Protocol.invokeLater(new Runnable() { + public void run() { + node.getModel().setCastToType(node.getID(), null); + } + }); + } + + @Override + protected void selectionChanged() { + TCFNode node = getCastToTypeNode(); + getAction().setEnabled(node != null && node.getModel().getCastToType(node.getID()) != null); + } + + private TCFNode getCastToTypeNode() { + TCFNode node = getSelectedNode(); + if (node instanceof ICastToType) return node; + return null; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/ResumeCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/ResumeCommand.java new file mode 100644 index 000000000..5400baae8 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/ResumeCommand.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.commands.IDebugCommandRequest; +import org.eclipse.debug.core.commands.IResumeHandler; +import org.eclipse.tm.internal.tcf.debug.actions.TCFAction; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IErrorReport; +import org.eclipse.tm.tcf.protocol.IToken; +import org.eclipse.tm.tcf.services.IRunControl; + + +public class ResumeCommand extends StepCommand implements IResumeHandler { + + public ResumeCommand(TCFModel model) { + super(model); + } + + @Override + protected boolean canExecute(IRunControl.RunControlContext ctx) { + return ctx.canResume(IRunControl.RM_RESUME); + } + + @Override + protected void execute(final IDebugCommandRequest monitor, + final IRunControl.RunControlContext ctx, boolean src_step, final Runnable done) { + new TCFAction(model.getLaunch(), ctx.getID()) { + public void run() { + ctx.resume(IRunControl.RM_RESUME, 1, new IRunControl.DoneCommand() { + public void doneCommand(IToken token, Exception error) { + if (error != null && model.getChannel().getState() == IChannel.STATE_OPEN) { + if (error instanceof IErrorReport) { + IErrorReport r = (IErrorReport)error; + if (r.getErrorCode() == IErrorReport.TCF_ERROR_ALREADY_RUNNING) { + done(); + return; + } + } + launch.removeContextActions(getContextID()); + monitor.setStatus(new Status(IStatus.ERROR, + Activator.PLUGIN_ID, IStatus.OK, "Cannot resume: " + error.getLocalizedMessage(), error)); + } + done(); + } + }); + } + public void done() { + super.done(); + done.run(); + } + }; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/SignalsCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/SignalsCommand.java new file mode 100644 index 000000000..05dc7a6c3 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/SignalsCommand.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExpression; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeLaunch; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeModule; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeStackFrame; + +public class SignalsCommand extends AbstractActionDelegate { + + private static boolean isValidNode(TCFNode n) { + if (n instanceof TCFNodeLaunch) return true; + if (n instanceof TCFNodeExecContext) return true; + if (n instanceof TCFNodeStackFrame) return true; + if (n instanceof TCFNodeExpression) return true; + if (n instanceof TCFNodeModule) return true; + return false; + } + + protected void selectionChanged() { + TCFNode n = getSelectedNode(); + getAction().setEnabled(isValidNode(n)); + } + + protected void run() { + TCFNode n = getSelectedNode(); + if (isValidNode(n)) { + Shell shell = getWindow().getShell(); + try { + new SignalsDialog(shell, n).open(); + } + catch (Throwable x) { + MessageBox mb = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK); + mb.setText("Cannot open Signals dialog"); + mb.setMessage(TCFModel.getErrorMessage(x, true)); + mb.open(); + } + } + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/SignalsDialog.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/SignalsDialog.java new file mode 100644 index 000000000..eae7a5e9d --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/SignalsDialog.java @@ -0,0 +1,438 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Map; + +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.tm.internal.tcf.debug.launch.TCFLaunchDelegate; +import org.eclipse.tm.internal.tcf.debug.model.TCFLaunch; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFChildren; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext.SignalMask; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IToken; +import org.eclipse.tm.tcf.services.IProcesses; +import org.eclipse.tm.tcf.util.TCFDataCache; +import org.eclipse.tm.tcf.util.TCFTask; + +class SignalsDialog extends Dialog { + + private static final int + SIZING_TABLE_WIDTH = 800, + SIZING_TABLE_HEIGHT = 300; + + private static final String[] column_names = { + "Code", + "Name", + "Description", + "Don't stop", + "Don't pass", + "Pending" + }; + + private static class Signal extends SignalMask { + + Signal(Map<String,Object> m) { + props = m; + } + + Signal(SignalMask m) { + props = m.getProperties(); + dont_stop = m.isDontStop(); + dont_pass = m.isDontPass(); + pending = m.isPending(); + } + + void setDontStop(boolean b) { + dont_stop = b; + } + + void setDontPass(boolean b) { + dont_pass = b; + } + + void setPending(boolean b) { + pending = b; + } + } + + private Table signal_table; + private TableViewer table_viewer; + private Map<Number,Signal> org_signals; + private Signal[] cur_signals; + + private final TCFModel model; + private final IChannel channel; + private final TCFNode selection; + + private TCFNodeExecContext node; + + private final IStructuredContentProvider content_provider = new IStructuredContentProvider() { + + public Object[] getElements(Object input) { + return cur_signals; + } + + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + }; + + private static class SignalLabelProvider extends LabelProvider implements ITableLabelProvider { + + final Image img_rs = ImageCache.getImage("icons/full/elcl16/resume_co.gif"); + final Image img_dl = ImageCache.getImage("icons/full/elcl16/rem_co.gif"); + final Image img_en = ImageCache.getImage("icons/full/elcl16/enabled_co.gif"); + final Image img_ds = ImageCache.getImage("icons/full/elcl16/disabled_co.gif"); + + public Image getColumnImage(Object element, int column) { + SignalMask s = (SignalMask)element; + switch (column) { + case 3: + return s.isDontStop() ? img_rs : img_ds; + case 4: + return s.isDontPass() ? img_dl : img_ds; + case 5: + return s.isPending() ? img_en : img_ds; + } + return null; + } + + public String getColumnText(Object element, int column) { + SignalMask s = (SignalMask)element; + switch (column) { + case 0: + long n = s.getCode().longValue(); + if (n < 32) return Long.toString(n); + String q = Long.toHexString(n); + if (q.length() < 8) q = "00000000".substring(q.length()) + q; + return "0x" + q; + case 1: + return (String)s.getProperties().get(IProcesses.SIG_NAME); + case 2: + return (String)s.getProperties().get(IProcesses.SIG_DESCRIPTION); + } + return ""; + } + + public String getText(Object element) { + return element.toString(); + } + } + + SignalsDialog(Shell parent, TCFNode node) { + super(parent); + model = node.getModel(); + channel = node.getChannel(); + selection = node; + } + + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText("Signals"); + shell.setImage(ImageCache.getImage(ImageCache.IMG_SIGNALS)); + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + createButton(parent, IDialogConstants.OK_ID, "&OK", true); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite)super.createDialogArea(parent); + + createSignalTable(composite); + + composite.setSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); + return composite; + } + + private void createSignalTable(Composite parent) { + Font font = parent.getFont(); + Label props_label = new Label(parent, SWT.WRAP); + props_label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + props_label.setFont(font); + props_label.setText("&Signals:"); + + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1)); + + signal_table = new Table(composite, + SWT.SINGLE | SWT.BORDER | + SWT.H_SCROLL | SWT.V_SCROLL); + signal_table.setFont(font); + GridData data = new GridData(GridData.FILL_BOTH); + data.widthHint = SIZING_TABLE_WIDTH; + data.heightHint = SIZING_TABLE_HEIGHT; + signal_table.setLayoutData(data); + + int w = SIZING_TABLE_WIDTH / (column_names.length + 5); + for (int i = 0; i < column_names.length; i++) { + final TableColumn column = new TableColumn(signal_table, SWT.LEAD, i); + column.setMoveable(false); + column.setText(column_names[i]); + switch (i) { + case 0: + column.setWidth(w * 2); + break; + case 1: + case 2: + column.setWidth(w * 3); + break; + default: + column.setWidth(w); + break; + } + } + signal_table.setHeaderVisible(true); + signal_table.setLinesVisible(true); + signal_table.addMouseListener(new MouseListener() { + + public void mouseDoubleClick(MouseEvent e) { + } + + public void mouseDown(MouseEvent e) { + int count = signal_table.getColumnCount(); + for (int row = 0; row < signal_table.getItemCount(); row++) { + for (int col = 0; col < count; col++) { + TableItem item = signal_table.getItem(row); + if (item.getBounds(col).contains(e.x, e.y)) { + if (row < 0 || row >= cur_signals.length) break; + Signal s = cur_signals[row]; + switch (col) { + case 3: + s.setDontStop(!s.isDontStop()); + break; + case 4: + s.setDontPass(!s.isDontPass()); + break; + case 5: + if (node == null) break; + if (s.isPending()) { + // Cannot clear a signal that is already generated + Signal x = org_signals.get(s.getIndex()); + if (x != null && x.isPending()) break; + } + s.setPending(!s.isPending()); + break; + } + table_viewer.refresh(s); + break; + } + } + } + } + + public void mouseUp(MouseEvent e) { + } + }); + + table_viewer = new TableViewer(signal_table); + table_viewer.setUseHashlookup(true); + table_viewer.setColumnProperties(column_names); + + cur_signals = new TCFTask<Signal[]>(channel) { + public void run() { + TCFNode n = selection; + while (n != null && !(n instanceof TCFNodeExecContext)) n = n.getParent(); + node = (TCFNodeExecContext)n; + if (node == null) { + TCFLaunch launch = model.getLaunch(); + Collection<Map<String,Object>> sigs = launch.getSignalList(); + if (sigs == null) { + done(new Signal[0]); + } + else { + int i = 0; + int no_stop = 0; + int no_pass = 0; + Signal[] arr = new Signal[sigs.size()]; + try { + ILaunchConfiguration cfg = launch.getLaunchConfiguration(); + String dont_stop = cfg.getAttribute(TCFLaunchDelegate.ATTR_SIGNALS_DONT_STOP, ""); + String dont_pass = cfg.getAttribute(TCFLaunchDelegate.ATTR_SIGNALS_DONT_PASS, ""); + if (dont_stop.length() > 0) no_stop = Integer.parseInt(dont_stop, 16); + if (dont_pass.length() > 0) no_pass = Integer.parseInt(dont_pass, 16); + } + catch (Exception x) { + Activator.log("Invalid launch cofiguration attribute", x); + } + for (Map<String,Object> m : sigs) { + Signal s = arr[i++] = new Signal(m); + Number num = s.getIndex(); + int j = num == null ? 0 : 1 << num.intValue(); + s.setDontStop((no_stop & j) != 0); + s.setDontPass((no_pass & j) != 0); + } + done(arr); + } + } + else { + TCFDataCache<SignalMask[]> dc = node.getSignalMask(); + if (!dc.validate(this)) return; + if (dc.getError() != null) { + error(dc.getError()); + } + else if (dc.getData() == null) { + done(new Signal[0]); + } + else { + int i = 0; + Signal[] arr = new Signal[dc.getData().length]; + for (SignalMask m : dc.getData()) arr[i++] = new Signal(m); + done(arr); + } + } + } + }.getE(); + org_signals = new HashMap<Number,Signal>(); + for (Signal m : cur_signals) org_signals.put(m.getIndex(), new Signal(m)); + table_viewer.setContentProvider(content_provider); + + table_viewer.setLabelProvider(new SignalLabelProvider()); + table_viewer.setInput(this); + } + + @Override + protected void okPressed() { + try { + boolean set_mask = false; + int dont_stop_set = 0; + int dont_pass_set = 0; + final LinkedList<Number> send_list = new LinkedList<Number>(); + for (Signal s : cur_signals) { + Number index = s.getIndex(); + Signal x = org_signals.get(index); + if (!set_mask) set_mask = x == null || x.isDontStop() != s.isDontStop() || x.isDontPass() != s.isDontPass(); + if (s.isDontStop()) dont_stop_set |= 1 << index.intValue(); + if (s.isDontPass()) dont_pass_set |= 1 << index.intValue(); + if ((x == null || !x.isPending()) && s.isPending()) send_list.add(s.getCode()); + } + if (set_mask) { + TCFLaunch launch = model.getLaunch(); + ILaunchConfigurationWorkingCopy cfg = launch.getLaunchConfiguration().getWorkingCopy(); + cfg.setAttribute(TCFLaunchDelegate.ATTR_SIGNALS_DONT_STOP, Integer.toHexString(dont_stop_set)); + cfg.setAttribute(TCFLaunchDelegate.ATTR_SIGNALS_DONT_PASS, Integer.toHexString(dont_pass_set)); + cfg.doSave(); + final int dont_stop = dont_stop_set; + final int dont_pass = dont_pass_set; + new TCFTask<Boolean>(channel) { + final HashSet<IToken> cmds = new HashSet<IToken>(); + final LinkedList<TCFNodeExecContext> nodes = new LinkedList<TCFNodeExecContext>(); + TCFDataCache<?> pending; + public void run() { + nodes.clear(); + pending = null; + addNodes(model.getRootNode().getChildren()); + if (pending != null) { + pending.wait(this); + } + else { + while (nodes.size() > 0) { + TCFNodeExecContext exe = nodes.removeFirst(); + exe.getSignalMask().reset(); + IProcesses prs = channel.getRemoteService(IProcesses.class); + cmds.add(prs.setSignalMask(exe.getID(), dont_stop, dont_pass, new IProcesses.DoneCommand() { + public void doneCommand(IToken token, Exception error) { + cmds.remove(token); + if (isDone()) return; + if (error != null) error(error); + if (cmds.size() == 0) done(Boolean.TRUE); + } + })); + } + } + } + private void addNodes(TCFChildren children) { + if (!children.validate()) { + pending = children; + } + else { + Map<String,TCFNode> map = children.getData(); + if (map != null) { + for (TCFNode n : map.values()) { + TCFNodeExecContext exe = (TCFNodeExecContext)n; + addNodes(exe.getChildren()); + nodes.add(exe); + } + } + } + } + }.getE(); + } + if (send_list.size() > 0 && node != null) { + new TCFTask<Boolean>(channel) { + public void run() { + node.getSignalMask().reset(); + final IProcesses prs = channel.getRemoteService(IProcesses.class); + prs.signal(node.getID(), send_list.removeFirst().longValue(), new IProcesses.DoneCommand() { + public void doneCommand(IToken token, Exception error) { + if (error != null) { + error(error); + } + else if (send_list.isEmpty()) { + done(Boolean.TRUE); + } + else { + node.getSignalMask().reset(); + prs.signal(node.getID(), send_list.removeFirst().longValue(), this); + } + } + }); + } + }.getE(); + } + } + catch (Throwable x) { + model.showMessageBox("Cannot update signals state", x); + return; + } + super.okPressed(); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/StepCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/StepCommand.java new file mode 100644 index 000000000..824b6ea7b --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/StepCommand.java @@ -0,0 +1,127 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.commands.IDebugCommandHandler; +import org.eclipse.debug.core.commands.IDebugCommandRequest; +import org.eclipse.debug.core.commands.IEnabledStateRequest; +import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFRunnable; +import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.util.TCFDataCache; + +abstract class StepCommand implements IDebugCommandHandler { + + private static final int MAX_ACTION_CNT = 4; + + protected final TCFModel model; + + public StepCommand(TCFModel model) { + this.model = model; + } + + protected abstract boolean canExecute(IRunControl.RunControlContext ctx); + + protected abstract void execute(IDebugCommandRequest monitor, + IRunControl.RunControlContext ctx, boolean src_step, Runnable done); + + private boolean getContextSet(boolean exec, Object[] elements, Set<IRunControl.RunControlContext> set, Runnable done) { + for (int i = 0; i < elements.length; i++) { + TCFNode node = null; + if (elements[i] instanceof TCFNode) node = (TCFNode)elements[i]; + else node = model.getRootNode(); + while (node != null && !node.isDisposed()) { + IRunControl.RunControlContext ctx = null; + if (node instanceof TCFNodeExecContext) { + TCFDataCache<IRunControl.RunControlContext> cache = ((TCFNodeExecContext)node).getRunContext(); + if (!cache.validate(done)) return false; + ctx = cache.getData(); + } + if (ctx == null) { + node = node.getParent(); + } + else { + if (!canExecute(ctx)) break; + int action_cnt = model.getLaunch().getContextActionsCount(ctx.getID()); + if (exec && action_cnt >= MAX_ACTION_CNT) break; + if (action_cnt > 0) { + set.add(ctx); + } + else { + if (ctx.isContainer()) { + TCFNodeExecContext.ChildrenStateInfo s = new TCFNodeExecContext.ChildrenStateInfo(); + if (!((TCFNodeExecContext)node).hasSuspendedChildren(s, done)) return false; + if (s.suspended || s.not_active) set.add(ctx); + } + if (ctx.hasState()) { + TCFDataCache<TCFContextState> state_cache = ((TCFNodeExecContext)node).getState(); + if (!state_cache.validate(done)) return false; + TCFContextState state_data = state_cache.getData(); + if (state_data != null && state_data.is_suspended) set.add(ctx); + } + } + break; + } + } + } + return true; + } + + public final void canExecute(final IEnabledStateRequest monitor) { + new TCFRunnable(monitor) { + public void run() { + if (done) return; + if (!monitor.isCanceled()) { + Set<IRunControl.RunControlContext> set = new HashSet<IRunControl.RunControlContext>(); + if (!getContextSet(false, monitor.getElements(), set, this)) return; + monitor.setEnabled(set.size() > 0); + monitor.setStatus(Status.OK_STATUS); + } + done(); + } + }; + } + + public final boolean execute(final IDebugCommandRequest monitor) { + new TCFRunnable(monitor) { + public void run() { + if (done) return; + Set<IRunControl.RunControlContext> set = new HashSet<IRunControl.RunControlContext>(); + if (!getContextSet(true, monitor.getElements(), set, this)) return; + if (set.size() == 0) { + monitor.setStatus(Status.OK_STATUS); + monitor.done(); + } + else { + final Set<Runnable> wait_list = new HashSet<Runnable>(); + for (IRunControl.RunControlContext ctx : set) { + Runnable done = new Runnable() { + public void run() { + wait_list.remove(this); + if (wait_list.isEmpty()) monitor.done(); + } + }; + wait_list.add(done); + execute(monitor, ctx, !model.isInstructionSteppingEnabled(), done); + } + } + } + }; + return true; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/StepIntoCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/StepIntoCommand.java new file mode 100644 index 000000000..4f6c98a67 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/StepIntoCommand.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.commands.IDebugCommandRequest; +import org.eclipse.debug.core.commands.IStepIntoHandler; +import org.eclipse.tm.internal.tcf.debug.actions.TCFActionStepInto; +import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; +import org.eclipse.tm.internal.tcf.debug.model.TCFSourceRef; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeStackFrame; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.util.TCFDataCache; + + +public class StepIntoCommand extends StepCommand implements IStepIntoHandler { + + private static class StepStateMachine extends TCFActionStepInto { + + private final IDebugCommandRequest monitor; + private final Runnable done; + private final TCFNodeExecContext node; + + StepStateMachine(TCFModel model, IDebugCommandRequest monitor, + IRunControl.RunControlContext ctx, boolean src_step, Runnable done) { + super(model.getLaunch(), ctx, src_step, false); + this.monitor = monitor; + this.done = done; + node = (TCFNodeExecContext)model.getNode(ctx.getID()); + } + + @Override + protected TCFDataCache<TCFContextState> getContextState() { + if (node == null) return null; + return node.getState(); + } + + @Override + protected TCFDataCache<TCFSourceRef> getLineInfo() { + TCFNodeStackFrame frame = node.getStackTrace().getTopFrame(); + if (frame == null) return null; + return frame.getLineInfo(); + } + + @Override + protected TCFDataCache<?> getStackTrace() { + return node.getStackTrace(); + } + + @Override + protected void exit(Throwable error) { + if (exited) return; + super.exit(error); + if (error != null && node.getChannel().getState() == IChannel.STATE_OPEN) { + monitor.setStatus(new Status(IStatus.ERROR, + Activator.PLUGIN_ID, 0, "Cannot step: " + error.getLocalizedMessage(), error)); + } + done.run(); + } + } + + public StepIntoCommand(TCFModel model) { + super(model); + } + + @Override + protected boolean canExecute(IRunControl.RunControlContext ctx) { + if (ctx == null) return false; + if (ctx.canResume(IRunControl.RM_STEP_INTO_LINE)) return true; + if (ctx.canResume(IRunControl.RM_STEP_INTO)) return true; + return false; + } + + @Override + protected void execute(final IDebugCommandRequest monitor, final IRunControl.RunControlContext ctx, + boolean src_step, final Runnable done) { + new StepStateMachine(model, monitor, ctx, src_step, done); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/StepOverCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/StepOverCommand.java new file mode 100644 index 000000000..cda698a99 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/StepOverCommand.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.commands.IDebugCommandRequest; +import org.eclipse.debug.core.commands.IStepOverHandler; +import org.eclipse.tm.internal.tcf.debug.actions.TCFActionStepOver; +import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; +import org.eclipse.tm.internal.tcf.debug.model.TCFSourceRef; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeStackFrame; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.services.IBreakpoints; +import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.services.IStackTrace.StackTraceContext; +import org.eclipse.tm.tcf.util.TCFDataCache; + +public class StepOverCommand extends StepCommand implements IStepOverHandler { + + private static class StepStateMachine extends TCFActionStepOver { + + private final IDebugCommandRequest monitor; + private final Runnable done; + private final TCFNodeExecContext node; + private TCFNodeStackFrame frame; + + StepStateMachine(TCFModel model, IDebugCommandRequest monitor, + IRunControl.RunControlContext ctx, + boolean src_step, Runnable done) { + super(model.getLaunch(), ctx, src_step, false); + this.monitor = monitor; + this.done = done; + node = (TCFNodeExecContext)model.getNode(ctx.getID()); + } + + @Override + protected TCFDataCache<TCFContextState> getContextState() { + if (node == null) return null; + return node.getState(); + } + + @Override + protected TCFDataCache<TCFSourceRef> getLineInfo() { + if (frame == null) frame = node.getStackTrace().getTopFrame(); + if (frame == null) return null; + return frame.getLineInfo(); + } + + @Override + protected TCFDataCache<StackTraceContext> getStackFrame() { + if (frame == null) frame = node.getStackTrace().getTopFrame(); + if (frame == null) return null; + return frame.getStackTraceContext(); + } + + @Override + protected int getStackFrameIndex() { + if (frame == null) frame = node.getStackTrace().getTopFrame(); + if (frame == null) return 0; + return frame.getFrameNo(); + } + + @Override + protected TCFDataCache<?> getStackTrace() { + return node.getStackTrace(); + } + + @Override + protected void exit(Throwable error) { + if (exited) return; + super.exit(error); + if (error != null && node.getChannel().getState() == IChannel.STATE_OPEN) { + monitor.setStatus(new Status(IStatus.ERROR, + Activator.PLUGIN_ID, 0, "Cannot step: " + error.getLocalizedMessage(), error)); + } + done.run(); + } + } + + public StepOverCommand(TCFModel model) { + super(model); + } + + @Override + protected boolean canExecute(IRunControl.RunControlContext ctx) { + if (ctx == null) return false; + if (ctx.canResume(IRunControl.RM_STEP_OVER_LINE)) return true; + if (ctx.canResume(IRunControl.RM_STEP_OVER)) return true; + if (ctx.canResume(IRunControl.RM_STEP_INTO) && model.getLaunch().getService(IBreakpoints.class) != null) return true; + return false; + } + + @Override + protected void execute(final IDebugCommandRequest monitor, final IRunControl.RunControlContext ctx, + boolean src_step, final Runnable done) { + new StepStateMachine(model, monitor, ctx, src_step, done); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/StepReturnCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/StepReturnCommand.java new file mode 100644 index 000000000..638be3559 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/StepReturnCommand.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.commands.IDebugCommandRequest; +import org.eclipse.debug.core.commands.IStepReturnHandler; +import org.eclipse.tm.internal.tcf.debug.actions.TCFActionStepOut; +import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeStackFrame; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.services.IBreakpoints; +import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.services.IStackTrace.StackTraceContext; +import org.eclipse.tm.tcf.util.TCFDataCache; + + +public class StepReturnCommand extends StepCommand implements IStepReturnHandler { + + private static class StepStateMachine extends TCFActionStepOut { + + private final IDebugCommandRequest monitor; + private final Runnable done; + private final TCFNodeExecContext node; + private TCFNodeStackFrame frame; + + StepStateMachine(TCFModel model, IDebugCommandRequest monitor, + IRunControl.RunControlContext ctx, Runnable done) { + super(model.getLaunch(), ctx, false); + this.monitor = monitor; + this.done = done; + node = (TCFNodeExecContext)model.getNode(ctx.getID()); + } + + @Override + protected TCFDataCache<TCFContextState> getContextState() { + if (node == null) return null; + return node.getState(); + } + + @Override + protected TCFDataCache<StackTraceContext> getStackFrame() { + if (frame == null) frame = node.getStackTrace().getTopFrame(); + if (frame == null) return null; + return frame.getStackTraceContext(); + } + + @Override + protected int getStackFrameIndex() { + if (frame == null) frame = node.getStackTrace().getTopFrame(); + if (frame == null) return 0; + return frame.getFrameNo(); + } + + @Override + protected TCFDataCache<?> getStackTrace() { + return node.getStackTrace(); + } + + @Override + protected void exit(Throwable error) { + if (exited) return; + super.exit(error); + if (error != null && node.getChannel().getState() == IChannel.STATE_OPEN) { + monitor.setStatus(new Status(IStatus.ERROR, + Activator.PLUGIN_ID, 0, "Cannot step: " + error.getLocalizedMessage(), error)); + } + done.run(); + } + } + + public StepReturnCommand(TCFModel model) { + super(model); + } + + @Override + protected boolean canExecute(IRunControl.RunControlContext ctx) { + if (ctx == null) return false; + if (ctx.canResume(IRunControl.RM_STEP_OUT)) return true; + if (!ctx.hasState()) return false; + if (ctx.canResume(IRunControl.RM_RESUME) && model.getLaunch().getService(IBreakpoints.class) != null) return true; + return false; + } + + @Override + protected void execute(final IDebugCommandRequest monitor, final IRunControl.RunControlContext ctx, + boolean src_step, final Runnable done) { + new StepStateMachine(model, monitor, ctx, done); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/SuspendCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/SuspendCommand.java new file mode 100644 index 000000000..133daf61f --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/SuspendCommand.java @@ -0,0 +1,138 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.commands.IDebugCommandRequest; +import org.eclipse.debug.core.commands.IEnabledStateRequest; +import org.eclipse.debug.core.commands.ISuspendHandler; +import org.eclipse.tm.internal.tcf.debug.actions.TCFAction; +import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFRunnable; +import org.eclipse.tm.tcf.protocol.IToken; +import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.util.TCFDataCache; + + +public class SuspendCommand implements ISuspendHandler { + + private final TCFModel model; + + public SuspendCommand(TCFModel model) { + this.model = model; + } + + public void canExecute(final IEnabledStateRequest monitor) { + new TCFRunnable(monitor) { + public void run() { + if (done) return; + Object[] elements = monitor.getElements(); + boolean res = false; + for (int i = 0; i < elements.length; i++) { + TCFNode node = null; + if (elements[i] instanceof TCFNode) node = (TCFNode)elements[i]; + else node = model.getRootNode(); + while (node != null && !node.isDisposed()) { + IRunControl.RunControlContext ctx = null; + if (node instanceof TCFNodeExecContext) { + TCFDataCache<IRunControl.RunControlContext> cache = ((TCFNodeExecContext)node).getRunContext(); + if (!cache.validate(this)) return; + ctx = cache.getData(); + } + if (ctx == null) { + node = node.getParent(); + } + else if (model.getActiveAction(ctx.getID()) != null) { + res = true; + break; + } + else { + if (!ctx.canSuspend()) break; + if (ctx.isContainer()) { + TCFNodeExecContext.ChildrenStateInfo s = new TCFNodeExecContext.ChildrenStateInfo(); + if (!((TCFNodeExecContext)node).hasSuspendedChildren(s, this)) return; + if (s.running) res = true; + } + if (ctx.hasState()) { + TCFDataCache<TCFContextState> state_cache = ((TCFNodeExecContext)node).getState(); + if (!state_cache.validate(this)) return; + TCFContextState state_data = state_cache.getData(); + if (state_data != null && !state_data.is_suspended && ctx.canSuspend()) res = true; + } + break; + } + } + } + monitor.setEnabled(res); + monitor.setStatus(Status.OK_STATUS); + done(); + } + }; + } + + public boolean execute(final IDebugCommandRequest monitor) { + new TCFRunnable(monitor) { + public void run() { + if (done) return; + Object[] elements = monitor.getElements(); + Set<IRunControl.RunControlContext> set = new HashSet<IRunControl.RunControlContext>(); + for (int i = 0; i < elements.length; i++) { + TCFNode node = null; + if (elements[i] instanceof TCFNode) node = (TCFNode)elements[i]; + else node = model.getRootNode(); + while (node != null && !node.isDisposed()) { + IRunControl.RunControlContext ctx = null; + if (node instanceof TCFNodeExecContext) { + TCFDataCache<IRunControl.RunControlContext> cache = ((TCFNodeExecContext)node).getRunContext(); + if (!cache.validate(this)) return; + ctx = cache.getData(); + } + if (ctx == null) { + node = node.getParent(); + } + else { + set.add(ctx); + break; + } + } + } + final Set<IToken> cmds = new HashSet<IToken>(); + for (Iterator<IRunControl.RunControlContext> i = set.iterator(); i.hasNext();) { + IRunControl.RunControlContext ctx = i.next(); + model.getLaunch().removeContextActions(ctx.getID()); + final TCFAction action = model.getActiveAction(ctx.getID()); + if (action != null) action.abort(); + cmds.add(ctx.suspend(new IRunControl.DoneCommand() { + public void doneCommand(IToken token, Exception error) { + assert cmds.contains(token); + cmds.remove(token); + if (error != null && action == null) { + monitor.setStatus(new Status(IStatus.ERROR, + Activator.PLUGIN_ID, IStatus.OK, "Cannot suspend: " + error.getLocalizedMessage(), error)); + } + if (cmds.isEmpty()) done(); + } + })); + } + } + }; + return true; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/TerminateCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/TerminateCommand.java new file mode 100644 index 000000000..b4cdebc5c --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/TerminateCommand.java @@ -0,0 +1,134 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.commands.IDebugCommandRequest; +import org.eclipse.debug.core.commands.IEnabledStateRequest; +import org.eclipse.debug.core.commands.ITerminateHandler; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFChildren; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFRunnable; +import org.eclipse.tm.tcf.protocol.IToken; +import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.util.TCFDataCache; + + +public class TerminateCommand implements ITerminateHandler { + + public TerminateCommand(TCFModel model) { + } + + public void canExecute(final IEnabledStateRequest monitor) { + new TCFRunnable(monitor) { + public void run() { + if (done) return; + Object[] elements = monitor.getElements(); + boolean res = false; + for (int i = 0; i < elements.length; i++) { + TCFNode node = null; + if (elements[i] instanceof TCFNode) node = (TCFNode)elements[i]; + while (node != null && !node.isDisposed()) { + if (node instanceof TCFNodeExecContext) { + TCFDataCache<IRunControl.RunControlContext> cache = ((TCFNodeExecContext)node).getRunContext(); + if (!cache.validate(this)) return; + IRunControl.RunControlContext ctx = cache.getData(); + if (ctx != null && ctx.canTerminate()) { + res = true; + } + else { + TCFChildren children_cache = ((TCFNodeExecContext)node).getChildren(); + if (!children_cache.validate(this)) return; + for (TCFNode child : children_cache.toArray()) { + cache = ((TCFNodeExecContext)child).getRunContext(); + if (!cache.validate(this)) return; + ctx = cache.getData(); + if (ctx != null && ctx.canTerminate()) { + res = true; + break; + } + } + } + break; + } + node = node.getParent(); + } + } + monitor.setEnabled(res); + monitor.setStatus(Status.OK_STATUS); + done(); + } + }; + } + + public boolean execute(final IDebugCommandRequest monitor) { + new TCFRunnable(monitor) { + public void run() { + if (done) return; + Object[] elements = monitor.getElements(); + Set<IRunControl.RunControlContext> set = new HashSet<IRunControl.RunControlContext>(); + for (int i = 0; i < elements.length; i++) { + TCFNode node = null; + if (elements[i] instanceof TCFNode) node = (TCFNode)elements[i]; + while (node != null && !node.isDisposed()) { + if (node instanceof TCFNodeExecContext) { + TCFDataCache<IRunControl.RunControlContext> cache = ((TCFNodeExecContext)node).getRunContext(); + if (!cache.validate(this)) return; + IRunControl.RunControlContext ctx = cache.getData(); + if (ctx != null && ctx.canTerminate()) { + set.add(ctx); + } + else { + TCFChildren children_cache = ((TCFNodeExecContext)node).getChildren(); + if (!children_cache.validate(this)) return; + for (TCFNode child : children_cache.toArray()) { + cache = ((TCFNodeExecContext)child).getRunContext(); + if (!cache.validate(this)) return; + IRunControl.RunControlContext child_ctx = cache.getData(); + if (child_ctx != null && child_ctx.canTerminate()) { + if (ctx != null) set.add(ctx); + else set.add(child_ctx); + } + } + } + break; + } + node = node.getParent(); + } + } + final Set<IToken> cmds = new HashSet<IToken>(); + for (Iterator<IRunControl.RunControlContext> i = set.iterator(); i.hasNext();) { + IRunControl.RunControlContext ctx = i.next(); + cmds.add(ctx.terminate(new IRunControl.DoneCommand() { + public void doneCommand(IToken token, Exception error) { + assert cmds.contains(token); + cmds.remove(token); + if (error != null) { + monitor.setStatus(new Status(IStatus.ERROR, + Activator.PLUGIN_ID, IStatus.OK, "Cannot resume: " + error.getLocalizedMessage(), error)); + } + if (cmds.isEmpty()) done(); + } + })); + } + } + }; + return false; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/UpdatePolicyMenu.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/UpdatePolicyMenu.java new file mode 100644 index 000000000..80a1d8a78 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/UpdatePolicyMenu.java @@ -0,0 +1,121 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.debug.ui.IDebugView; +import org.eclipse.jface.action.ContributionItem; +import org.eclipse.jface.action.IContributionItem; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.MenuEvent; +import org.eclipse.swt.events.MenuListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.tcf.util.TCFTask; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchPartSite; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.actions.CompoundContributionItem; + +public class UpdatePolicyMenu extends CompoundContributionItem { + + private static final String[] policy_names = { + "Automatic", + "Manual", + "Breakpoint Hit", + }; + + @Override + protected IContributionItem[] getContributionItems() { + IContributionItem[] items = new IContributionItem[policy_names.length]; + for (int i = 0; i < items.length; i++) { + final int n = i; + items[i] = new ContributionItem() { + @Override + public void fill(final Menu menu, int index) { + final MenuItem item = new MenuItem(menu, SWT.RADIO); + item.setText(policy_names[n]); + final MenuListener menu_listener = new MenuListener() { + public void menuShown(MenuEvent e) { + item.setSelection(getPolicy() == n); + } + public void menuHidden(MenuEvent e) { + } + }; + menu.addMenuListener(menu_listener); + item.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + menu.removeMenuListener(menu_listener); + } + }); + item.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + if (item.getSelection()) setPolicy(n); + } + public void widgetDefaultSelected(SelectionEvent e) { + } + }); + } + }; + } + return items; + } + + private IWorkbenchPart getPart() { + return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActivePart(); + } + + private TCFNode getRootNode(IWorkbenchPart part) { + IWorkbenchPartSite site = part.getSite(); + if (site == null || IDebugUIConstants.ID_DEBUG_VIEW.equals(site.getId())) { + return null; + } + if (part instanceof IDebugView) { + Object input = ((IDebugView)part).getViewer().getInput(); + if (input instanceof TCFNode) return (TCFNode)input; + } + return null; + } + + private int getPolicy() { + final IWorkbenchPart part = getPart(); + if (part == null) return 0; + final TCFNode node = getRootNode(part); + if (node == null) return 0; + return new TCFTask<Integer>(node.getChannel()) { + public void run() { + TCFModel model = node.getModel(); + if (!model.isLocked(part)) done(TCFModel.UPDATE_POLICY_AUTOMATIC); + else done(model.getLockPolicy(part)); + } + }.getE(); + } + + private void setPolicy(final int n) { + final IWorkbenchPart part = getPart(); + if (part == null) return; + final TCFNode node = getRootNode(part); + if (node == null) return; + new TCFTask<Object>(node.getChannel()) { + public void run() { + TCFModel model = node.getModel(); + model.setLockPolicy(part, n); + done(null); + } + }.getE(); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/ViewMemoryCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/ViewMemoryCommand.java new file mode 100644 index 000000000..aa189e831 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/ViewMemoryCommand.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import java.util.ArrayList; + +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.debug.core.model.IMemoryBlockRetrievalExtension; +import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExpression; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNumberFormat; +import org.eclipse.tm.tcf.services.IExpressions; +import org.eclipse.tm.tcf.util.TCFDataCache; +import org.eclipse.tm.tcf.util.TCFTask; +import org.eclipse.ui.IWorkbenchPage; + +public class ViewMemoryCommand extends AbstractActionDelegate { + + private static class Block { + long addr; + long size; + } + + @Override + protected void run() { + try { + IWorkbenchPage page = getWindow().getActivePage(); + page.showView(IDebugUIConstants.ID_MEMORY_VIEW, null, IWorkbenchPage.VIEW_ACTIVATE); + final ArrayList<IMemoryBlock> list = new ArrayList<IMemoryBlock>(); + for (final TCFNode node : getSelectedNodes()) { + final IMemoryBlockRetrievalExtension mem_retrieval = (IMemoryBlockRetrievalExtension) + node.getAdapter(IMemoryBlockRetrievalExtension.class); + if (mem_retrieval == null) continue; + Block b = new TCFTask<Block>(node.getChannel()) { + public void run() { + try { + Number addr = null; + long size = -1; + if (node instanceof TCFNodeExpression) { + TCFDataCache<IExpressions.Value> val_cache = ((TCFNodeExpression)node).getValue(); + if (!val_cache.validate(this)) return; + IExpressions.Value val_data = val_cache.getData(); + if (val_data != null) { + addr = val_data.getAddress(); + if (addr != null) { + byte[] bytes = val_data.getValue(); + if (bytes != null) size = bytes.length; + } + else if (val_data.getRegisterID() != null) { + byte[] bytes = val_data.getValue(); + if (bytes != null) { + addr = TCFNumberFormat.toBigInteger(bytes, 0, bytes.length, + val_data.isBigEndian(), false); + } + } + } + } + Block b = null; + if (addr != null) { + b = new Block(); + b.addr = addr.longValue(); + b.size = size; + } + done(b); + } + catch (Exception x) { + error(x); + } + } + }.get(); + if (b != null) list.add(mem_retrieval.getMemoryBlock(b.addr, b.size)); + } + DebugPlugin.getDefault().getMemoryBlockManager().addMemoryBlocks(list.toArray(new IMemoryBlock[list.size()])); + } + catch (Exception x) { + Activator.log("Cannot open memory view", x); + } + } + + @Override + protected void selectionChanged() { + getAction().setEnabled(getSelectedNodes().length > 0); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/WatchInExpressionsCommand.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/WatchInExpressionsCommand.java new file mode 100644 index 000000000..931ac3fa1 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/WatchInExpressionsCommand.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.debug.core.IExpressionManager; +import org.eclipse.debug.core.model.IExpression; +import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.model.IWatchInExpressions; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.tcf.util.TCFDataCache; +import org.eclipse.tm.tcf.util.TCFTask; +import org.eclipse.ui.IWorkbenchPage; + +public class WatchInExpressionsCommand extends AbstractActionDelegate { + + @Override + protected void selectionChanged() { + getAction().setEnabled(getNodes().length > 0); + } + + @Override + protected void run() { + try { + IWorkbenchPage page = getWindow().getActivePage(); + page.showView(IDebugUIConstants.ID_EXPRESSION_VIEW, null, IWorkbenchPage.VIEW_ACTIVATE); + for (final TCFNode node : getNodes()) { + final IExpressionManager manager = node.getModel().getExpressionManager(); + IExpression e = new TCFTask<IExpression>(node.getChannel()) { + public void run() { + try { + IExpression e = null; + if (node instanceof IWatchInExpressions) { + TCFDataCache<String> text_cache = ((IWatchInExpressions)node).getExpressionText(); + if (!text_cache.validate(this)) return; + String text_data = text_cache.getData(); + if (text_data != null) { + for (final IExpression x : manager.getExpressions()) { + if (text_data.equals(x.getExpressionText())) { + done(null); + return; + } + } + e = manager.newWatchExpression(text_data); + } + } + done(e); + } + catch (Exception x) { + error(x); + } + } + }.get(); + if (e != null) manager.addExpression(e); + } + } + catch (Exception x) { + Activator.log("Cannot open expressions view", x); + } + } + + private TCFNode[] getNodes() { + TCFNode[] arr = getSelectedNodes(); + for (TCFNode n : arr) { + if (n instanceof IWatchInExpressions) continue; + return new TCFNode[0]; + } + return arr; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ITCFLaunchContext.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ITCFLaunchContext.java new file mode 100644 index 000000000..a63183ffa --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ITCFLaunchContext.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.ui.ILaunchConfigurationDialog; +import org.eclipse.swt.widgets.Shell; + +/** + * TCF clients can implement ITCFLaunchContext to provide information about + * workspace projects to TCF Launch Configuration. + * + * The information includes default values for launch configuration attributes, + * list of executable binary files, etc. + * + * Since each project type can have its own methods to retrieve relevant information, + * there should be implementation of this interface for each project type that support TCF. + * + * Implementation should be able to examine current IDE state (like active editor input source, + * project explorer selection, etc.) and figure out an "active project". + */ +public interface ITCFLaunchContext { + + /** + * Check if this context is currently active. + * @return true if active. + */ + boolean isActive(); + + /** + * Check if this context recognizes type of a selection. + * @param selection + * @return true if the selection is supported by this context. + */ + boolean isSupportedSelection(Object selection); + + /** + * Get selection project. + * @param selection + * @return selection project or null if selection is not part of a project + */ + IProject getProject(Object selection); + + /** + * Get selection file path. + * @param selection + * @return selection file path or null if selection is not a file + */ + IPath getPath(Object selection); + + /** + * Set launch configuration attributes to default values best suited for current context. + * @param dlg - currently open launch configuration dialog + * @param config - currently open launch configuration + */ + void setDefaults(ILaunchConfigurationDialog dlg, ILaunchConfigurationWorkingCopy config); + + /** + * Get project build configuration ID. + * @param project + * @return build configuration ID. + */ + String getBuildConfigID(IProject project); + + /** + * Show a dialog box that allows user to select executable binary file from a list + * of available file in this context. + * @param project_name + * @param shell + * @return binary file path + */ + String chooseBinary(Shell shell, IProject project); + + /** + * Check if a path represents an executable binary file. + * @param project + * @param path - full path to a file in the project + * @return + * @throws CoreException + */ + boolean isBinary(IProject project, IPath path) throws CoreException; +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/PeerPropsDialog.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/PeerPropsDialog.java new file mode 100644 index 000000000..36b41479d --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/PeerPropsDialog.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch; + +import java.util.Map; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tm.internal.tcf.debug.ui.launch.setup.PeerPropsControl; + +class PeerPropsDialog extends Dialog { + + private final Map<String,String> attrs; + private final boolean enable_editing; + private final Image image; + + private PeerPropsControl props; + + PeerPropsDialog(Shell parent, Image image, Map<String,String> attrs, boolean enable_editing) { + super(parent); + this.image = image; + this.attrs = attrs; + this.enable_editing = enable_editing; + } + + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText("TCF Peer Properties"); + shell.setImage(image); + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + createButton(parent, IDialogConstants.OK_ID, "&OK", true); + updateButtons(); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite)super.createDialogArea(parent); + props = new PeerPropsControl(composite, attrs, enable_editing, new Runnable() { + public void run() { + updateButtons(); + } + }); + composite.setSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); + return composite; + } + + private void updateButtons() { + getButton(IDialogConstants.OK_ID).setEnabled(props.isComplete()); + } + + @Override + protected void okPressed() { + props.okPressed(); + super.okPressed(); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFArgumentsTab.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFArgumentsTab.java new file mode 100644 index 000000000..71baba1d7 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFArgumentsTab.java @@ -0,0 +1,162 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; +import org.eclipse.debug.ui.StringVariableSelectionDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.tm.internal.tcf.debug.launch.TCFLaunchDelegate; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; + + +public class TCFArgumentsTab extends AbstractLaunchConfigurationTab { + + private Text text_arguments; + private Button button_variables; + private Exception init_error; + + public void createControl(Composite parent) { + Font font = parent.getFont(); + Composite comp = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(1, true); + comp.setLayout(layout); + comp.setFont(font); + + GridData gd = new GridData(GridData.FILL_BOTH); + comp.setLayoutData(gd); + setControl(comp); + + createArgumentsGroup(comp); + } + + private void createArgumentsGroup(Composite parent) { + Composite comp = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + comp.setLayout(layout); + GridData gd = new GridData(GridData.FILL_BOTH); + comp.setLayoutData(gd); + + Label label = new Label(comp, SWT.NONE); + label.setText("Program Arguments:"); + gd = new GridData(); + gd.horizontalSpan = 2; + label.setLayoutData(gd); + + text_arguments = new Text(comp, SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.V_SCROLL); + gd = new GridData(GridData.FILL_BOTH); + gd.heightHint = 40; + gd.widthHint = 100; + text_arguments.setLayoutData(gd); + text_arguments.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent evt) { + updateLaunchConfigurationDialog(); + } + }); + button_variables = createPushButton(comp, "Variables", null); + gd = new GridData(GridData.HORIZONTAL_ALIGN_END); + button_variables.setLayoutData(gd); + button_variables.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent arg0) { + handleVariablesButtonSelected(text_arguments); + } + }); + } + + /** + * A variable entry button has been pressed for the given text + * field. Prompt the user for a variable and enter the result + * in the given field. + */ + private void handleVariablesButtonSelected(Text textField) { + String variable = getVariable(); + if (variable != null) textField.append(variable); + } + + /** + * Prompts the user to choose and configure a variable and returns + * the resulting string, suitable to be used as an attribute. + */ + private String getVariable() { + StringVariableSelectionDialog dialog = new StringVariableSelectionDialog(getShell()); + dialog.open(); + return dialog.getVariableExpression(); + } + + public void setDefaults(ILaunchConfigurationWorkingCopy config) { + config.setAttribute(TCFLaunchDelegate.ATTR_PROGRAM_ARGUMENTS, (String)null); + } + + public void initializeFrom(ILaunchConfiguration configuration) { + setErrorMessage(null); + setMessage(null); + try { + text_arguments.setText(configuration.getAttribute(TCFLaunchDelegate.ATTR_PROGRAM_ARGUMENTS, "")); //$NON-NLS-1$ + } + catch (CoreException e) { + init_error = e; + setErrorMessage("Cannot read launch configuration: " + e); + Activator.log(e); + } + } + + public void performApply(ILaunchConfigurationWorkingCopy configuration) { + configuration.setAttribute( + TCFLaunchDelegate.ATTR_PROGRAM_ARGUMENTS, + getAttributeValueFrom(text_arguments)); + } + + @Override + public boolean isValid(ILaunchConfiguration config) { + setErrorMessage(null); + setMessage(null); + + if (init_error != null) { + setErrorMessage("Cannot read launch configuration: " + init_error); + return false; + } + + return true; + } + + protected String getAttributeValueFrom(Text text) { + String content = text.getText().trim(); + content = content.replaceAll("\r\n", "\n"); // eliminate Windows \r line delimiter + if (content.length() > 0) return content; + return null; + } + + public String getName() { + return "Arguments"; + } + + @Override + public Image getImage() { + return ImageCache.getImageDescriptor(ImageCache.IMG_ARGUMENTS_TAB).createImage(); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFLaunchContext.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFLaunchContext.java new file mode 100644 index 000000000..ab0910489 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFLaunchContext.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.Platform; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.osgi.framework.Bundle; + +/** + * TCF clients can implement ITCFLaunchContext to provide information about + * workspace projects to TCF Launch Configuration. + * + * The information includes default values for launch configuration attributes, + * list of executable binary files, etc. + * + * Since each project type can have its own methods to retrieve relevant information, + * there should be implementation of this interface for each project type that support TCF. + * + * Implementation should be able to examine current IDE state (like active editor input source, + * project explorer selection, etc.) and figure out an "active project". + */ +public class TCFLaunchContext { + + public static ITCFLaunchContext getLaunchContext(Object selection) { + try { + IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(Activator.PLUGIN_ID, "launch_context"); + IExtension[] extensions = point.getExtensions(); + for (int i = 0; i < extensions.length; i++) { + try { + Bundle bundle = Platform.getBundle(extensions[i].getNamespaceIdentifier()); + bundle.start(Bundle.START_TRANSIENT); + IConfigurationElement[] e = extensions[i].getConfigurationElements(); + for (int j = 0; j < e.length; j++) { + String nm = e[j].getName(); + if (nm.equals("class")) { //$NON-NLS-1$ + Class<?> c = bundle.loadClass(e[j].getAttribute("name")); //$NON-NLS-1$ + ITCFLaunchContext launch_context = (ITCFLaunchContext)c.newInstance(); + if (selection != null) { + if (launch_context.isSupportedSelection(selection)) return launch_context; + } + else { + if (launch_context.isActive()) return launch_context; + } + } + } + } + catch (Throwable x) { + Activator.log("Cannot access launch context extension points", x); + } + } + } + catch (Exception x) { + Activator.log("Cannot access launch context extension points", x); + } + return null; + } + +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFLaunchShortcut.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFLaunchShortcut.java new file mode 100644 index 000000000..c0f2ad8fc --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFLaunchShortcut.java @@ -0,0 +1,132 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationType; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugModelPresentation; +import org.eclipse.debug.ui.ILaunchShortcut; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tm.internal.tcf.debug.launch.TCFLaunchDelegate; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.dialogs.ElementListSelectionDialog; + +/** + * This class implements extension point that provides support for selection sensitive launching using TCF. + * Extensions register a shortcut which appears in the run and/or debug cascade menus to launch + * the workbench selection or active editor. + */ +public class TCFLaunchShortcut implements ILaunchShortcut { + + private static final String LAUNCH_CONFIGURATION_TYPE_ID = "org.eclipse.tm.tcf.debug.LaunchConfigurationType"; //$NON-NLS-1$ + + public void launch(ISelection selection, String mode) { + if (selection instanceof IStructuredSelection) { + IStructuredSelection ss = (IStructuredSelection)selection; + Object obj = ss.getFirstElement(); + ITCFLaunchContext context = TCFLaunchContext.getLaunchContext(obj); + IProject project = context.getProject(obj); + IPath path = context.getPath(obj); + ILaunchConfiguration config = null; + List<ILaunchConfiguration> list = searchConfigurations(project, path); + if (list != null) { + int count = list.size(); + if (count == 0) { + config = createConfiguration(project, path); + } + else if (count == 1) { + config = list.get(0); + } + else { + config = chooseConfiguration(list); + } + if (config != null) DebugUITools.launch(config, mode); + } + } + } + + public void launch(IEditorPart editor, String mode) { + } + + private List<ILaunchConfiguration> searchConfigurations(IProject project, IPath path) { + try { + List<ILaunchConfiguration> list = new ArrayList<ILaunchConfiguration>(); + ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); + ILaunchConfigurationType type = manager.getLaunchConfigurationType(LAUNCH_CONFIGURATION_TYPE_ID); + ILaunchConfiguration[] configs = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations(type); + for (ILaunchConfiguration config : configs) { + if (config.getAttribute(TCFLaunchDelegate.ATTR_LOCAL_PROGRAM_FILE, "").equals(path.toOSString()) && //$NON-NLS-1$ + config.getAttribute(TCFLaunchDelegate.ATTR_PROJECT_NAME, "").equals(project.getName())) { //$NON-NLS-1$ + list.add(config); + } + } + return list; + } + catch (CoreException x) { + MessageDialog.openError(getShell(), "Error searching available launch configurations", x.getStatus().getMessage()); + return null; + } + } + + private ILaunchConfiguration chooseConfiguration(List<ILaunchConfiguration> list) { + IDebugModelPresentation labelProvider = DebugUITools.newDebugModelPresentation(); + ElementListSelectionDialog dialog= new ElementListSelectionDialog(getShell(), labelProvider); + dialog.setElements(list.toArray()); + dialog.setTitle("TCF Launch Configuration"); + dialog.setMessage("&Select existing configuration:"); + dialog.setMultipleSelection(false); + int result = dialog.open(); + labelProvider.dispose(); + if (result == Window.OK) return (ILaunchConfiguration) dialog.getFirstResult(); + return null; + } + + private ILaunchConfiguration createConfiguration(IProject project, IPath path) { + ILaunchConfiguration config = null; + ILaunchConfigurationWorkingCopy wc = null; + try { + ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); + ILaunchConfigurationType type = manager.getLaunchConfigurationType(LAUNCH_CONFIGURATION_TYPE_ID); + wc = type.newInstance(null, manager.generateUniqueLaunchConfigurationNameFrom("TCF Local Host " + path.lastSegment())); + wc.setAttribute(TCFLaunchDelegate.ATTR_LOCAL_PROGRAM_FILE, path.toOSString()); + wc.setAttribute(TCFLaunchDelegate.ATTR_PROJECT_NAME, project.getName()); + // wc.setMappedResources(new IResource[] { }); + config = wc.doSave(); + } + catch (CoreException x) { + MessageDialog.openError(getShell(), "Cannot create launch configuration", x.getStatus().getMessage()); + } + return config; + } + + private Shell getShell() { + Shell shell = null; + IWorkbenchWindow window = Activator.getDefault().getWorkbench().getActiveWorkbenchWindow(); + if (window != null) shell = window.getShell(); + return shell; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFMainTab.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFMainTab.java new file mode 100644 index 000000000..4a2cfce21 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFMainTab.java @@ -0,0 +1,476 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch; + +import java.io.File; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.tm.internal.tcf.debug.launch.TCFLaunchDelegate; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; +import org.eclipse.ui.dialogs.ElementListSelectionDialog; + +public class TCFMainTab extends AbstractLaunchConfigurationTab { + + private Text project_text; + private Text local_program_text; + private Text remote_program_text; + private Text working_dir_text; + private Button default_dir_button; + private Button attach_children_button; + private Button disconnect_on_ctx_exit; + private Button terminal_button; + private Exception init_error; + + public void createControl(Composite parent) { + Composite comp = new Composite(parent, SWT.NONE); + setControl(comp); + + GridLayout topLayout = new GridLayout(); + comp.setLayout(topLayout); + + createVerticalSpacer(comp, 1); + createProjectGroup(comp); + createApplicationGroup(comp); + createWorkingDirGroup(comp); + createVerticalSpacer(comp, 1); + createOptionButtons(comp, 1); + } + + private void createProjectGroup(Composite parent) { + Group group = new Group(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + group.setLayout(layout); + group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + group.setText("Project"); + + Label label = new Label(group, SWT.NONE); + label.setText("Project Name:"); + GridData gd = new GridData(); + gd.horizontalSpan = 2; + label.setLayoutData(gd); + + project_text = new Text(group, SWT.SINGLE | SWT.BORDER); + gd = new GridData(GridData.FILL_HORIZONTAL); + project_text.setLayoutData(gd); + project_text.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent evt) { + updateLaunchConfigurationDialog(); + } + }); + + Button project_button = createPushButton(group, "Browse...", null); + project_button.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent evt) { + handleProjectButtonSelected(); + updateLaunchConfigurationDialog(); + } + }); + } + + private void createApplicationGroup(Composite parent) { + Group group = new Group(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + group.setLayout(layout); + group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + group.setText("Application"); + + createLocalExeFileGroup(group); + createRemoteExeFileGroup(group); + } + + private void createLocalExeFileGroup(Composite parent) { + Composite comp = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 3; + layout.marginHeight = 0; + layout.marginWidth = 0; + comp.setLayout(layout); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + comp.setLayoutData(gd); + + Label program_label = new Label(comp, SWT.NONE); + program_label.setText("Local File Path:"); + gd = new GridData(); + gd.horizontalSpan = 3; + program_label.setLayoutData(gd); + + local_program_text = new Text(comp, SWT.SINGLE | SWT.BORDER); + local_program_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + local_program_text.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent evt) { + updateLaunchConfigurationDialog(); + } + }); + + Button search_button = createPushButton(comp, "Search...", null); + search_button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent evt) { + handleSearchButtonSelected(); + updateLaunchConfigurationDialog(); + } + }); + + Button browse_button = createPushButton(comp, "Browse...", null); + browse_button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent evt) { + handleBinaryBrowseButtonSelected(); + updateLaunchConfigurationDialog(); + } + }); + } + + private void createRemoteExeFileGroup(Composite parent) { + Composite comp = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + comp.setLayout(layout); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + comp.setLayoutData(gd); + + Label program_label = new Label(comp, SWT.NONE); + program_label.setText("Remote File Path:"); + gd = new GridData(); + gd.horizontalSpan = 3; + program_label.setLayoutData(gd); + + remote_program_text = new Text(comp, SWT.SINGLE | SWT.BORDER); + remote_program_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + remote_program_text.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent evt) { + updateLaunchConfigurationDialog(); + } + }); + } + + private void createWorkingDirGroup(Composite comp) { + Group group = new Group(comp, SWT.NONE); + GridLayout layout = new GridLayout(); + group.setLayout(layout); + group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + group.setText("Working directory"); + + working_dir_text = new Text(group, SWT.SINGLE | SWT.BORDER); + working_dir_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + working_dir_text.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent evt) { + updateLaunchConfigurationDialog(); + } + }); + + default_dir_button = new Button(group, SWT.CHECK); + default_dir_button.setText("Use default"); + default_dir_button.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, true, false)); + default_dir_button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent evt) { + updateLaunchConfigurationDialog(); + } + }); + } + + @Override + protected void updateLaunchConfigurationDialog() { + super.updateLaunchConfigurationDialog(); + working_dir_text.setEnabled(!default_dir_button.getSelection()); + } + + private void createOptionButtons(Composite parent, int col_span) { + Composite terminal_comp = new Composite(parent, SWT.NONE); + GridLayout terminal_layout = new GridLayout(); + terminal_layout.numColumns = 1; + terminal_layout.marginHeight = 0; + terminal_layout.marginWidth = 0; + terminal_comp.setLayout(terminal_layout); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = col_span; + terminal_comp.setLayoutData(gd); + + attach_children_button = createCheckButton(terminal_comp, "Auto-attach process children"); + attach_children_button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent evt) { + updateLaunchConfigurationDialog(); + } + }); + attach_children_button.setEnabled(true); + + disconnect_on_ctx_exit = createCheckButton(terminal_comp, "Disconnect when last debug context exits"); + disconnect_on_ctx_exit.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent evt) { + updateLaunchConfigurationDialog(); + } + }); + disconnect_on_ctx_exit.setEnabled(true); + + terminal_button = createCheckButton(terminal_comp, "Use pseudo-terminal for process standard I/O"); + terminal_button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent evt) { + updateLaunchConfigurationDialog(); + } + }); + terminal_button.setEnabled(true); + } + + public void initializeFrom(ILaunchConfiguration config) { + setErrorMessage(null); + setMessage(null); + try { + project_text.setText(config.getAttribute(TCFLaunchDelegate.ATTR_PROJECT_NAME, "")); + local_program_text.setText(config.getAttribute(TCFLaunchDelegate.ATTR_LOCAL_PROGRAM_FILE, "")); + remote_program_text.setText(config.getAttribute(TCFLaunchDelegate.ATTR_REMOTE_PROGRAM_FILE, "")); + working_dir_text.setText(config.getAttribute(TCFLaunchDelegate.ATTR_WORKING_DIRECTORY, "")); + default_dir_button.setSelection(!config.hasAttribute(TCFLaunchDelegate.ATTR_WORKING_DIRECTORY)); + attach_children_button.setSelection(config.getAttribute(TCFLaunchDelegate.ATTR_ATTACH_CHILDREN, true)); + disconnect_on_ctx_exit.setSelection(config.getAttribute(TCFLaunchDelegate.ATTR_DISCONNECT_ON_CTX_EXIT, true)); + terminal_button.setSelection(config.getAttribute(TCFLaunchDelegate.ATTR_USE_TERMINAL, true)); + working_dir_text.setEnabled(!default_dir_button.getSelection()); + } + catch (Exception e) { + init_error = e; + setErrorMessage("Cannot read launch configuration: " + e); + Activator.log(e); + } + } + + private IProject getProject() { + String name = project_text.getText().trim(); + if (name.length() == 0) return null; + return ResourcesPlugin.getWorkspace().getRoot().getProject(name); + } + + public void performApply(ILaunchConfigurationWorkingCopy config) { + config.setAttribute(TCFLaunchDelegate.ATTR_PROJECT_NAME, project_text.getText()); + config.setAttribute(TCFLaunchDelegate.ATTR_LOCAL_PROGRAM_FILE, local_program_text.getText()); + config.setAttribute(TCFLaunchDelegate.ATTR_REMOTE_PROGRAM_FILE, remote_program_text.getText()); + if (default_dir_button.getSelection()) { + config.removeAttribute(TCFLaunchDelegate.ATTR_WORKING_DIRECTORY); + } + else { + config.setAttribute(TCFLaunchDelegate.ATTR_WORKING_DIRECTORY, working_dir_text.getText()); + } + config.setAttribute(TCFLaunchDelegate.ATTR_ATTACH_CHILDREN, attach_children_button.getSelection()); + config.setAttribute(TCFLaunchDelegate.ATTR_DISCONNECT_ON_CTX_EXIT, disconnect_on_ctx_exit.getSelection()); + config.setAttribute(TCFLaunchDelegate.ATTR_USE_TERMINAL, terminal_button.getSelection()); + } + + /** + * Show a dialog that lists all executable files in currently selected project. + */ + private void handleSearchButtonSelected() { + IProject project = getProject(); + if (project == null) { + MessageDialog.openInformation(getShell(), + "Project required", + "Enter project before searching for program"); + return; + } + ITCFLaunchContext launch_context = TCFLaunchContext.getLaunchContext(project); + if (launch_context == null) return; + String path = launch_context.chooseBinary(getShell(), project); + if (path != null) local_program_text.setText(path); + } + + /** + * Show a dialog that lets the user select a project. This in turn provides context for the main + * type, allowing the user to key a main type name, or constraining the search for main types to + * the specified project. + */ + private void handleBinaryBrowseButtonSelected() { + FileDialog file_dialog = new FileDialog(getShell(), SWT.NONE); + file_dialog.setFileName(local_program_text.getText()); + String path = file_dialog.open(); + if (path != null) local_program_text.setText(path); + } + + /** + * Show a dialog that lets the user select a project. This in turn provides context for the main + * type, allowing the user to key a main type name, or constraining the search for main types to + * the specified project. + */ + private void handleProjectButtonSelected() { + try { + IProject project = chooseProject(); + if (project == null) return; + project_text.setText(project.getName()); + } + catch (Exception e) { + Activator.log("Cannot get project description", e); + } + } + + /** + * Show project list dialog and return the first selected project, or null. + */ + private IProject chooseProject() { + try { + IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); + ILabelProvider label_provider = new LabelProvider() { + + @Override + public String getText(Object element) { + if (element == null) return ""; + return ((IProject)element).getName(); + } + }; + ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), label_provider); + dialog.setTitle("Project Selection"); + dialog.setMessage("Choose project to constrain search for program"); + dialog.setElements(projects); + + IProject cProject = getProject(); + if (cProject != null) dialog.setInitialSelections(new Object[]{cProject}); + if (dialog.open() == Window.OK) return (IProject)dialog.getFirstResult(); + } + catch (Exception e) { + Activator.log("Cannot show project list dialog", e); + } + return null; + } + + @Override + public boolean isValid(ILaunchConfiguration config) { + setErrorMessage(null); + setMessage(null); + + if (init_error != null) { + setErrorMessage("Cannot read launch configuration: " + init_error); + return false; + } + + String project_name = project_text.getText().trim(); + if (project_name.length() != 0) { + IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(project_name); + if (!project.exists()) { + setErrorMessage("Project does not exist"); + return false; + } + if (!project.isOpen()) { + setErrorMessage("Project must be opened"); + return false; + } + } + String local_name = local_program_text.getText().trim(); + if (local_name.equals(".") || local_name.equals("..")) { //$NON-NLS-1$ //$NON-NLS-2$ + setErrorMessage("Invalid local program name"); + return false; + } + String remote_name = remote_program_text.getText().trim(); + if (remote_name.equals(".") || remote_name.equals("..")) { //$NON-NLS-1$ //$NON-NLS-2$ + setErrorMessage("Invalid remote program name"); + return false; + } + if (local_name.length() > 0) { + IProject project = getProject(); + IPath program_path = new Path(local_name); + if (!program_path.isAbsolute()) { + if (project == null) { + File ws = ResourcesPlugin.getWorkspace().getRoot().getLocation().toFile(); + File file = new File(ws, local_name); + if (!file.exists()) { + setErrorMessage("File not found: " + file); + return false; + } + if (file.isDirectory()) { + setErrorMessage("Program path is directory name: " + file); + return false; + } + program_path = new Path(file.getAbsolutePath()); + } + else if (!project.getFile(local_name).exists()) { + setErrorMessage("Program does not exist"); + return false; + } + else { + program_path = project.getFile(local_name).getLocation(); + } + } + else { + File file = program_path.toFile(); + if (!file.exists()) { + setErrorMessage("Program file does not exist"); + return false; + } + if (file.isDirectory()) { + setErrorMessage("Program path is directory name"); + return false; + } + } + if (project != null) { + try { + ITCFLaunchContext launch_context = TCFLaunchContext.getLaunchContext(project); + if (launch_context != null && !launch_context.isBinary(project, program_path)) { + setErrorMessage("Program is not a recongnized executable"); + return false; + } + } + catch (CoreException e) { + Activator.log(e); + setErrorMessage(e.getLocalizedMessage()); + return false; + } + } + } + return true; + } + + public void setDefaults(ILaunchConfigurationWorkingCopy config) { + config.setAttribute(TCFLaunchDelegate.ATTR_PROJECT_NAME, ""); + config.setAttribute(TCFLaunchDelegate.ATTR_ATTACH_CHILDREN, true); + config.setAttribute(TCFLaunchDelegate.ATTR_DISCONNECT_ON_CTX_EXIT, true); + config.setAttribute(TCFLaunchDelegate.ATTR_USE_TERMINAL, true); + config.setAttribute(TCFLaunchDelegate.ATTR_WORKING_DIRECTORY, (String)null); + ITCFLaunchContext launch_context = TCFLaunchContext.getLaunchContext(null); + if (launch_context != null) launch_context.setDefaults(getLaunchConfigurationDialog(), config); + } + + public String getName() { + return "Main"; + } + + @Override + public Image getImage() { + return ImageCache.getImage(ImageCache.IMG_TCF); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFMemoryMapTab.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFMemoryMapTab.java new file mode 100644 index 000000000..0654678f1 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFMemoryMapTab.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; +import org.eclipse.tm.internal.tcf.debug.ui.commands.MemoryMapWidget; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; + +public class TCFMemoryMapTab extends AbstractLaunchConfigurationTab { + + private static final String TAB_ID = "org.eclipse.tm.tcf.launch.memoryMapTab"; + + private MemoryMapWidget widget; + + public void createControl(Composite parent) { + TCFNode node = null; + IAdaptable adaptable = DebugUITools.getDebugContext(); + if (adaptable != null) node = (TCFNode)adaptable.getAdapter(TCFNode.class); + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(1, false); + composite.setFont(parent.getFont()); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 1, 1)); + widget = new MemoryMapWidget(composite, node); + setControl(composite); + } + + public void setDefaults(ILaunchConfigurationWorkingCopy cfg) { + } + + public void initializeFrom(ILaunchConfiguration cfg) { + setErrorMessage(null); + setMessage(null); + widget.loadData(cfg); + } + + public void performApply(ILaunchConfigurationWorkingCopy cfg) { + try { + widget.saveData(cfg); + } + catch (Throwable x) { + setErrorMessage("Cannot update memory map: " + x); + } + } + + public String getName() { + return "Symbol Files"; + } + + @Override + public Image getImage() { + return ImageCache.getImage(ImageCache.IMG_MEMORY_MAP); + } + + @Override + public String getId() { + return TAB_ID; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFPathMapTab.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFPathMapTab.java new file mode 100644 index 000000000..f0e0b638c --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFPathMapTab.java @@ -0,0 +1,285 @@ +/******************************************************************************* + * Copyright (c) 2009, 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.ICellModifier; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TextCellEditor; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Item; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.tm.internal.tcf.debug.launch.TCFLaunchDelegate; +import org.eclipse.tm.internal.tcf.debug.launch.TCFLaunchDelegate.PathMapRule; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; +import org.eclipse.tm.tcf.services.IPathMap; + +// TODO: add source lookup container that represents ATTR_PATH_MAP +public class TCFPathMapTab extends AbstractLaunchConfigurationTab { + + private TableViewer viewer; + private Button button_remove; + private Button button_new; + + private static final String[] column_ids = { + IPathMap.PROP_SOURCE, + IPathMap.PROP_DESTINATION, + IPathMap.PROP_CONTEXT, + }; + + private static final int[] column_size = { + 300, + 300, + 50, + }; + + private static final String TAB_ID = "org.eclipse.tm.tcf.launch.pathMapTab"; + + private ArrayList<PathMapRule> map; + + private class FileMapContentProvider implements IStructuredContentProvider { + + public Object[] getElements(Object input) { + return map.toArray(new PathMapRule[map.size()]); + } + + public void inputChanged(Viewer viewer, Object old_input, Object new_input) { + } + + public void dispose() { + } + } + + private class FileMapLabelProvider extends LabelProvider implements ITableLabelProvider { + + public Image getColumnImage(Object element, int column) { + if (column == 0) return ImageCache.getImage(ImageCache.IMG_ATTRIBUTE); + return null; + } + + public String getColumnText(Object element, int column) { + PathMapRule e = (PathMapRule)element; + Object o = e.getProperties().get(column_ids[column]); + if (o == null) return ""; + return o.toString(); + } + } + + private class FileMapCellModifier implements ICellModifier { + + public boolean canModify(Object element, String property) { + return true; + } + + public Object getValue(Object element, String property) { + if (element instanceof Item) element = ((Item)element).getData(); + PathMapRule a = (PathMapRule)element; + Object o = a.getProperties().get(property); + if (o == null) return ""; + return o.toString(); + } + + public void modify(Object element, String property, Object value) { + if (element instanceof Item) element = ((Item)element).getData(); + PathMapRule a = (PathMapRule)element; + if ("".equals(value)) a.getProperties().remove(property); + else a.getProperties().put(property, value); + viewer.update(element, new String[] { property }); + updateLaunchConfigurationDialog(); + } + } + + private Exception init_error; + + public String getName() { + return "Path Map"; + } + + @Override + public Image getImage() { + return ImageCache.getImage(ImageCache.IMG_PATH); + } + + @Override + public String getId() { + return TAB_ID; + } + + public void createControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(1, false); + composite.setFont(parent.getFont()); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 1, 1)); + createTable(composite); + setControl(composite); + } + + private void createTable(Composite parent) { + Font font = parent.getFont(); + Label map_label = new Label(parent, SWT.WRAP); + map_label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + map_label.setFont(font); + map_label.setText("File path &map rules:"); + + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 1, 1)); + + viewer = new TableViewer(composite, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION); + Table table = viewer.getTable(); + table.setLayoutData(new GridData(GridData.FILL_BOTH)); + table.setHeaderVisible(true); + table.setLinesVisible(true); + table.setFont(font); + viewer.setContentProvider(new FileMapContentProvider()); + viewer.setLabelProvider(new FileMapLabelProvider()); + viewer.setColumnProperties(column_ids); + + CellEditor[] editors = new CellEditor[column_ids.length]; + for (int i = 0; i < column_ids.length; i++) { + TableColumn c = new TableColumn(table, SWT.NONE, i); + c.setText(column_ids[i]); + c.setWidth(column_size[i]); + editors[i] = new TextCellEditor(table); + } + viewer.setCellEditors(editors); + viewer.setCellModifier(new FileMapCellModifier()); + createTableButtons(composite); + viewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + updateLaunchConfigurationDialog(); + } + }); + } + + private void createTableButtons(Composite parent) { + Font font = parent.getFont(); + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL)); + + button_new = new Button(composite, SWT.PUSH); + button_new.setText("&Add"); + button_new.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + button_new.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + PathMapRule a = new PathMapRule(new HashMap<String,Object>()); + a.getProperties().put(IPathMap.PROP_ID, "PR" + System.currentTimeMillis()); + map.add(a); + viewer.add(a); + viewer.setSelection(new StructuredSelection(a), true); + viewer.getTable().setFocus(); + updateLaunchConfigurationDialog(); + } + }); + + button_remove = new Button(composite, SWT.PUSH); + button_remove.setText("&Remove"); + button_remove.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + button_remove.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + for (Iterator<?> i = ((IStructuredSelection)viewer.getSelection()).iterator(); i.hasNext();) { + PathMapRule a = (PathMapRule)i.next(); + map.remove(a); + viewer.remove(a); + } + updateLaunchConfigurationDialog(); + } + }); + } + + List<IPathMap.PathMapRule> getPathMap() { + List<IPathMap.PathMapRule> l = new ArrayList<IPathMap.PathMapRule>(); + for (PathMapRule r : map) l.add(r); + return Collections.unmodifiableList(l); + } + + public void initializeFrom(ILaunchConfiguration config) { + setErrorMessage(null); + setMessage(null); + try { + String s = config.getAttribute(TCFLaunchDelegate.ATTR_PATH_MAP, ""); + map = TCFLaunchDelegate.parsePathMapAttribute(s); + viewer.setInput(config); + button_remove.setEnabled(!viewer.getSelection().isEmpty()); + } + catch (Exception e) { + init_error = e; + setErrorMessage("Cannot read launch configuration: " + e); + Activator.log(e); + } + } + + public void performApply(ILaunchConfigurationWorkingCopy config) { + StringBuffer bf = new StringBuffer(); + for (PathMapRule m : map) bf.append(m.toString()); + if (bf.length() == 0) config.removeAttribute(TCFLaunchDelegate.ATTR_PATH_MAP); + else config.setAttribute(TCFLaunchDelegate.ATTR_PATH_MAP, bf.toString()); + } + + public void setDefaults(ILaunchConfigurationWorkingCopy config) { + config.removeAttribute(TCFLaunchDelegate.ATTR_PATH_MAP); + } + + @Override + protected void updateLaunchConfigurationDialog() { + super.updateLaunchConfigurationDialog(); + button_remove.setEnabled(!viewer.getSelection().isEmpty()); + } + + @Override + public boolean isValid(ILaunchConfiguration config) { + setMessage(null); + + if (init_error != null) { + setErrorMessage("Cannot read launch configuration: " + init_error); + return false; + } + + setErrorMessage(null); + return true; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFPropertyTester.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFPropertyTester.java new file mode 100644 index 000000000..c70096067 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFPropertyTester.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch; + +import org.eclipse.core.expressions.PropertyTester; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IPath; +import org.eclipse.debug.ui.IDebugView; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; + +public class TCFPropertyTester extends PropertyTester { + + public boolean test(Object receiver, String property, Object[] args, Object expected_value) { + if (property.equals("areUpdatePoliciesSupported")) return testUpdatePoliciesSupported(receiver); + if (property.equals("isExecutable")) return testIsExecutable(receiver, expected_value); + return false; + } + + private boolean testUpdatePoliciesSupported(Object receiver) { + return receiver instanceof IDebugView; + } + + private boolean testIsExecutable(Object receiver, Object expected_value) { + Object value = null; + try { + if (receiver instanceof IAdaptable) { + IAdaptable selection = (IAdaptable)receiver; + ITCFLaunchContext context = TCFLaunchContext.getLaunchContext(selection); + if (context != null) { + IProject project = context.getProject(selection); + IPath path = context.getPath(selection); + if (project != null && path != null) { + value = context.isBinary(project, path); + } + } + } + } + catch (Throwable x) { + Activator.log(x); + } + if (expected_value != null) return expected_value.equals(value); + return (value instanceof Boolean) && ((Boolean)value).booleanValue(); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTabGroup.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTabGroup.java new file mode 100644 index 000000000..1db24c9fd --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTabGroup.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch; + +import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup; +import org.eclipse.debug.ui.CommonTab; +import org.eclipse.debug.ui.EnvironmentTab; +import org.eclipse.debug.ui.ILaunchConfigurationDialog; +import org.eclipse.debug.ui.ILaunchConfigurationTab; +import org.eclipse.debug.ui.sourcelookup.SourceLookupTab; + +/** + * Launch configuration dialog tab group for Target Communication Framework + */ +public class TCFTabGroup extends AbstractLaunchConfigurationTabGroup { + + public void createTabs(ILaunchConfigurationDialog dialog, String mode) { + setTabs(new ILaunchConfigurationTab[] { + new TCFMainTab(), + new TCFTargetTab(), + new TCFArgumentsTab(), + new EnvironmentTab(), + new TCFMemoryMapTab(), + new TCFPathMapTab(), + new SourceLookupTab(), + new CommonTab() + }); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTargetTab.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTargetTab.java new file mode 100644 index 000000000..9796f06eb --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTargetTab.java @@ -0,0 +1,1051 @@ +/******************************************************************************* + * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Platform; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; +import org.eclipse.debug.ui.ILaunchConfigurationTab; +import org.eclipse.jface.window.Window; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.TreeEvent; +import org.eclipse.swt.events.TreeListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.ProgressBar; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeColumn; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.tm.internal.tcf.debug.launch.TCFLaunchDelegate; +import org.eclipse.tm.internal.tcf.debug.launch.TCFLocalAgent; +import org.eclipse.tm.internal.tcf.debug.launch.TCFUserDefPeer; +import org.eclipse.tm.internal.tcf.debug.tests.TCFTestSuite; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; +import org.eclipse.tm.internal.tcf.debug.ui.launch.setup.SetupWizardDialog; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IPeer; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.tcf.services.ILocator; +import org.eclipse.tm.tcf.services.IMemoryMap; +import org.eclipse.tm.tcf.services.IPathMap; +import org.eclipse.tm.tcf.util.TCFTask; + + +/** + * Launch configuration dialog tab to specify the Target Communication Framework + * configuration. + */ +public class TCFTargetTab extends AbstractLaunchConfigurationTab { + + private static final String TAB_ID = "org.eclipse.tm.tcf.launch.targetTab"; + + private Button run_local_agent_button; + private Button use_local_agent_button; + private Text peer_id_text; + private Tree peer_tree; + private Runnable update_peer_buttons; + private final PeerInfo peer_info = new PeerInfo(); + private Display display; + private Exception init_error; + private String mem_map_cfg; + + private static class PeerInfo { + PeerInfo parent; + int index; + String id; + Map<String,String> attrs; + PeerInfo[] children; + boolean children_pending; + Throwable children_error; + IPeer peer; + IChannel channel; + ILocator locator; + LocatorListener listener; + } + + private class LocatorListener implements ILocator.LocatorListener { + + private final PeerInfo parent; + + LocatorListener(PeerInfo parent) { + this.parent = parent; + } + + public void peerAdded(final IPeer peer) { + if (display == null) return; + final String id = peer.getID(); + final HashMap<String,String> attrs = new HashMap<String,String>(peer.getAttributes()); + display.asyncExec(new Runnable() { + public void run() { + if (parent.children_error != null) return; + PeerInfo[] arr = parent.children; + for (PeerInfo p : arr) assert !p.id.equals(id); + PeerInfo[] buf = new PeerInfo[arr.length + 1]; + System.arraycopy(arr, 0, buf, 0, arr.length); + PeerInfo info = new PeerInfo(); + info.parent = parent; + info.index = arr.length; + info.id = id; + info.attrs = attrs; + info.peer = peer; + buf[arr.length] = info; + parent.children = buf; + updateItems(parent); + } + }); + } + + public void peerChanged(final IPeer peer) { + if (display == null) return; + final String id = peer.getID(); + final HashMap<String,String> attrs = new HashMap<String,String>(peer.getAttributes()); + display.asyncExec(new Runnable() { + public void run() { + if (parent.children_error != null) return; + PeerInfo[] arr = parent.children; + for (int i = 0; i < arr.length; i++) { + if (arr[i].id.equals(id)) { + arr[i].attrs = attrs; + arr[i].peer = peer; + updateItems(parent); + } + } + } + }); + } + + public void peerRemoved(final String id) { + if (display == null) return; + display.asyncExec(new Runnable() { + public void run() { + if (parent.children_error != null) return; + PeerInfo[] arr = parent.children; + PeerInfo[] buf = new PeerInfo[arr.length - 1]; + int j = 0; + for (int i = 0; i < arr.length; i++) { + if (arr[i].id.equals(id)) { + final PeerInfo info = arr[i]; + Protocol.invokeLater(new Runnable() { + public void run() { + disconnectPeer(info); + } + }); + } + else { + arr[i].index = j; + buf[j++] = arr[i]; + } + } + parent.children = buf; + updateItems(parent); + } + }); + } + + public void peerHeartBeat(final String id) { + if (display == null) return; + display.asyncExec(new Runnable() { + public void run() { + if (parent.children_error != null) return; + PeerInfo[] arr = parent.children; + for (int i = 0; i < arr.length; i++) { + if (arr[i].id.equals(id)) { + if (arr[i].children_error != null) { + TreeItem item = findItem(arr[i]); + boolean visible = item != null; + while (visible && item != null) { + if (!item.getExpanded()) visible = false; + item = item.getParentItem(); + } + if (visible) loadChildren(arr[i]); + } + break; + } + } + } + }); + } + } + + public void createControl(Composite parent) { + display = parent.getDisplay(); + assert display != null; + + Font font = parent.getFont(); + Composite comp = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(1, true); + comp.setLayout(layout); + comp.setFont(font); + + GridData gd = new GridData(GridData.FILL_BOTH); + comp.setLayoutData(gd); + setControl(comp); + createVerticalSpacer(comp, 1); + createLocalAgentButtons(comp); + createVerticalSpacer(comp, 1); + createTargetGroup(comp); + } + + private void createLocalAgentButtons(Composite parent) { + Composite local_agent_comp = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 1; + layout.marginHeight = 0; + layout.marginWidth = 0; + local_agent_comp.setLayout(layout); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + local_agent_comp.setLayoutData(gd); + + run_local_agent_button = createCheckButton(local_agent_comp, "Run instance of TCF agent on the local host"); + run_local_agent_button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent evt) { + updateLaunchConfigurationDialog(); + } + }); + run_local_agent_button.setEnabled(true); + + use_local_agent_button = createCheckButton(local_agent_comp, "Use local host as a target"); + use_local_agent_button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent evt) { + updateLaunchConfigurationDialog(); + } + }); + use_local_agent_button.setEnabled(true); + } + + private void createTargetGroup(Composite parent) { + Font font = parent.getFont(); + + Group group = new Group(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.verticalSpacing = 0; + layout.numColumns = 2; + group.setLayout(layout); + group.setLayoutData(new GridData(GridData.FILL_BOTH)); + group.setFont(font); + group.setText("Target"); + + createVerticalSpacer(group, layout.numColumns); + + Label host_label = new Label(group, SWT.NONE); + host_label.setText("Target ID:"); + host_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + host_label.setFont(font); + + peer_id_text = new Text(group, SWT.SINGLE | SWT.BORDER); + peer_id_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + peer_id_text.setFont(font); + peer_id_text.setEditable(false); + + createVerticalSpacer(group, layout.numColumns); + + Label peer_label = new Label(group, SWT.NONE); + peer_label.setText("&Available targets:"); + peer_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + peer_label.setFont(font); + + loadChildren(peer_info); + createPeerListArea(group); + } + + private void createPeerListArea(Composite parent) { + Font font = parent.getFont(); + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1)); + + peer_tree = new Tree(composite, SWT.VIRTUAL | SWT.BORDER | SWT.SINGLE); + GridData gd = new GridData(GridData.FILL_BOTH); + gd.minimumHeight = 150; + gd.minimumWidth = 470; + peer_tree.setLayoutData(gd); + + for (int i = 0; i < 5; i++) { + TreeColumn column = new TreeColumn(peer_tree, SWT.LEAD, i); + column.setMoveable(true); + switch (i) { + case 0: + column.setText("Name"); + column.setWidth(160); + break; + case 1: + column.setText("OS"); + column.setWidth(100); + break; + case 2: + column.setText("Transport"); + column.setWidth(60); + break; + case 3: + column.setText("Host"); + column.setWidth(100); + break; + case 4: + column.setText("Port"); + column.setWidth(40); + break; + } + } + + peer_tree.setHeaderVisible(true); + peer_tree.setFont(font); + peer_tree.addListener(SWT.SetData, new Listener() { + public void handleEvent(Event event) { + TreeItem item = (TreeItem)event.item; + PeerInfo info = findPeerInfo(item); + if (info == null) { + updateItems(item.getParentItem(), false); + } + else { + fillItem(item, info); + updateLaunchConfigurationDialog(); + } + } + }); + peer_tree.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetDefaultSelected(SelectionEvent e) { + final PeerInfo info = findPeerInfo(peer_id_text.getText()); + if (info == null) return; + new PeerPropsDialog(getShell(), getImage(), info.attrs, + info.peer instanceof TCFUserDefPeer).open(); + if (!(info.peer instanceof TCFUserDefPeer)) return; + Protocol.invokeLater(new Runnable() { + public void run() { + ((TCFUserDefPeer)info.peer).updateAttributes(info.attrs); + TCFUserDefPeer.savePeers(); + } + }); + } + @Override + public void widgetSelected(SelectionEvent e) { + TreeItem[] selections = peer_tree.getSelection(); + if (selections.length > 0) { + assert selections.length == 1; + PeerInfo info = findPeerInfo(selections[0]); + if (info != null) peer_id_text.setText(getPath(info)); + } + updateLaunchConfigurationDialog(); + } + }); + peer_tree.addTreeListener(new TreeListener() { + + public void treeCollapsed(TreeEvent e) { + updateItems((TreeItem)e.item, false); + } + + public void treeExpanded(TreeEvent e) { + updateItems((TreeItem)e.item, true); + } + }); + + createPeerButtons(composite); + } + + private void createPeerButtons(Composite parent) { + Font font = parent.getFont(); + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL)); + Menu menu = new Menu(peer_tree); + SelectionAdapter sel_adapter = null; + + final Button button_new = new Button(composite, SWT.PUSH); + button_new.setText("N&ew..."); + button_new.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + button_new.addSelectionListener(sel_adapter = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + final Map<String,String> attrs = new HashMap<String,String>(); + SetupWizardDialog wizard = new SetupWizardDialog(attrs); + WizardDialog dialog = new WizardDialog(getShell(), wizard); + dialog.create(); + if (dialog.open() != Window.OK) return; + if (attrs.isEmpty()) return; + Protocol.invokeLater(new Runnable() { + public void run() { + new TCFUserDefPeer(attrs); + TCFUserDefPeer.savePeers(); + } + }); + } + }); + final MenuItem item_new = new MenuItem(menu, SWT.PUSH); + item_new.setText("N&ew..."); + item_new.addSelectionListener(sel_adapter); + + final Button button_edit = new Button(composite, SWT.PUSH); + button_edit.setText("E&dit..."); + button_edit.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + button_edit.addSelectionListener(sel_adapter = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + final PeerInfo info = findPeerInfo(peer_id_text.getText()); + if (info == null) return; + if (new PeerPropsDialog(getShell(), getImage(), info.attrs, + info.peer instanceof TCFUserDefPeer).open() != Window.OK) return; + if (!(info.peer instanceof TCFUserDefPeer)) return; + Protocol.invokeLater(new Runnable() { + public void run() { + ((TCFUserDefPeer)info.peer).updateAttributes(info.attrs); + TCFUserDefPeer.savePeers(); + } + }); + } + }); + final MenuItem item_edit = new MenuItem(menu, SWT.PUSH); + item_edit.setText("E&dit..."); + item_edit.addSelectionListener(sel_adapter); + + final Button button_remove = new Button(composite, SWT.PUSH); + button_remove.setText("&Remove"); + button_remove.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + button_remove.addSelectionListener(sel_adapter = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + final PeerInfo info = findPeerInfo(peer_id_text.getText()); + if (info == null) return; + if (!(info.peer instanceof TCFUserDefPeer)) return; + peer_id_text.setText(""); + updateLaunchConfigurationDialog(); + Protocol.invokeAndWait(new Runnable() { + public void run() { + ((TCFUserDefPeer)info.peer).dispose(); + TCFUserDefPeer.savePeers(); + } + }); + } + }); + final MenuItem item_remove = new MenuItem(menu, SWT.PUSH); + item_remove.setText("&Remove"); + item_remove.addSelectionListener(sel_adapter); + + createVerticalSpacer(composite, 20); + new MenuItem(menu, SWT.SEPARATOR); + + final Button button_test = new Button(composite, SWT.PUSH); + button_test.setText("Run &Tests"); + button_test.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + button_test.addSelectionListener(sel_adapter = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + runDiagnostics(false); + } + }); + final MenuItem item_test = new MenuItem(menu, SWT.PUSH); + item_test.setText("Run &Tests"); + item_test.addSelectionListener(sel_adapter); + + final Button button_loop = new Button(composite, SWT.PUSH); + button_loop.setText("Tests &Loop"); + button_loop.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + button_loop.addSelectionListener(sel_adapter = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + runDiagnostics(true); + } + }); + final MenuItem item_loop = new MenuItem(menu, SWT.PUSH); + item_loop.setText("Tests &Loop"); + item_loop.addSelectionListener(sel_adapter); + + peer_tree.setMenu(menu); + + update_peer_buttons = new Runnable() { + + public void run() { + boolean local = use_local_agent_button.getSelection(); + PeerInfo info = findPeerInfo(peer_id_text.getText()); + button_new.setEnabled(!local); + button_edit.setEnabled(info != null && !local); + button_remove.setEnabled(info != null && info.peer instanceof TCFUserDefPeer && !local); + button_test.setEnabled(local || info != null); + button_loop.setEnabled(local || info != null); + item_new.setEnabled(!local); + item_edit.setEnabled(info != null && !local); + item_remove.setEnabled(info != null && info.peer instanceof TCFUserDefPeer && !local); + item_test.setEnabled(info != null); + item_loop.setEnabled(info != null); + } + }; + update_peer_buttons.run(); + } + + @Override + protected void updateLaunchConfigurationDialog() { + if (use_local_agent_button.getSelection()) { + peer_tree.setEnabled(false); + peer_tree.deselectAll(); + String id = TCFLocalAgent.getLocalAgentID(); + if (id == null) id = ""; + peer_id_text.setText(id); + peer_id_text.setEnabled(false); + } + else { + peer_tree.setEnabled(true); + peer_id_text.setEnabled(true); + String id = peer_id_text.getText(); + TreeItem item = findItem(findPeerInfo(id)); + if (item != null) peer_tree.setSelection(item); + else peer_tree.deselectAll(); + } + update_peer_buttons.run(); + super.updateLaunchConfigurationDialog(); + } + + @Override + public void dispose() { + Protocol.invokeAndWait(new Runnable() { + public void run() { + disconnectPeer(peer_info); + display = null; + } + }); + super.dispose(); + } + + public String getName() { + return "Target"; + } + + @Override + public Image getImage() { + return ImageCache.getImage(ImageCache.IMG_TARGET_TAB); + } + + @Override + public String getId() { + return TAB_ID; + } + + public void initializeFrom(ILaunchConfiguration configuration) { + setErrorMessage(null); + setMessage(null); + try { + String id = configuration.getAttribute(TCFLaunchDelegate.ATTR_PEER_ID, ""); + TreeItem item = findItem(findPeerInfo(id)); + if (item != null) peer_tree.setSelection(item); + peer_id_text.setText(id); + run_local_agent_button.setSelection(configuration.getAttribute(TCFLaunchDelegate.ATTR_RUN_LOCAL_AGENT, false)); + use_local_agent_button.setSelection(configuration.getAttribute(TCFLaunchDelegate.ATTR_USE_LOCAL_AGENT, true)); + mem_map_cfg = configuration.getAttribute(TCFLaunchDelegate.ATTR_MEMORY_MAP, "null"); + } + catch (CoreException e) { + init_error = e; + setErrorMessage("Cannot read launch configuration: " + e); + Activator.log(e); + } + updateLaunchConfigurationDialog(); + } + + public void performApply(ILaunchConfigurationWorkingCopy configuration) { + if (use_local_agent_button.getSelection()) { + configuration.removeAttribute(TCFLaunchDelegate.ATTR_PEER_ID); + } + else { + configuration.setAttribute(TCFLaunchDelegate.ATTR_PEER_ID, peer_id_text.getText()); + } + configuration.setAttribute(TCFLaunchDelegate.ATTR_RUN_LOCAL_AGENT, run_local_agent_button.getSelection()); + configuration.setAttribute(TCFLaunchDelegate.ATTR_USE_LOCAL_AGENT, use_local_agent_button.getSelection()); + } + + public void setDefaults(ILaunchConfigurationWorkingCopy configuration) { + configuration.setAttribute(TCFLaunchDelegate.ATTR_RUN_LOCAL_AGENT, false); + configuration.setAttribute(TCFLaunchDelegate.ATTR_USE_LOCAL_AGENT, true); + configuration.removeAttribute(TCFLaunchDelegate.ATTR_PEER_ID); + } + + @Override + public boolean isValid(ILaunchConfiguration config) { + setErrorMessage(null); + setMessage(null); + + if (init_error != null) { + setErrorMessage("Cannot read launch configuration: " + init_error); + return false; + } + + return true; + } + + private void disconnectPeer(final PeerInfo info) { + assert Protocol.isDispatchThread(); + if (info.children != null) { + for (PeerInfo p : info.children) disconnectPeer(p); + } + if (info.listener != null) { + info.locator.removeListener(info.listener); + info.listener = null; + info.locator = null; + } + if (info.channel != null) { + info.channel.close(); + } + } + + private boolean canHaveChildren(PeerInfo parent) { + return parent == peer_info || parent.attrs.get(IPeer.ATTR_PROXY) != null; + } + + private void loadChildren(final PeerInfo parent) { + assert Thread.currentThread() == display.getThread(); + if (parent.children_pending) return; + assert parent.children == null; + parent.children_pending = true; + parent.children_error = null; + Protocol.invokeAndWait(new Runnable() { + public void run() { + assert parent.listener == null; + assert parent.channel == null; + if (!canHaveChildren(parent)) { + doneLoadChildren(parent, null, new PeerInfo[0]); + } + else if (parent == peer_info) { + peer_info.locator = Protocol.getLocator(); + doneLoadChildren(parent, null, createLocatorListener(peer_info)); + } + else { + final IChannel channel = parent.peer.openChannel(); + parent.channel = channel; + parent.channel.addChannelListener(new IChannel.IChannelListener() { + boolean opened = false; + boolean closed = false; + public void congestionLevel(int level) { + } + public void onChannelClosed(final Throwable error) { + assert !closed; + if (parent.channel != channel) return; + if (!opened) { + doneLoadChildren(parent, error, null); + } + else { + if (display != null) { + display.asyncExec(new Runnable() { + public void run() { + if (parent.children_pending) return; + parent.children = null; + parent.children_error = error; + updateItems(parent); + } + }); + } + } + closed = true; + parent.channel = null; + parent.locator = null; + parent.listener = null; + } + public void onChannelOpened() { + assert !opened; + assert !closed; + if (parent.channel != channel) return; + opened = true; + parent.locator = parent.channel.getRemoteService(ILocator.class); + if (parent.locator == null) { + parent.channel.terminate(new Exception("Service not supported: " + ILocator.NAME)); + } + else { + doneLoadChildren(parent, null, createLocatorListener(parent)); + } + } + }); + } + } + }); + } + + private PeerInfo[] createLocatorListener(PeerInfo peer) { + assert Protocol.isDispatchThread(); + Map<String,IPeer> map = peer.locator.getPeers(); + PeerInfo[] buf = new PeerInfo[map.size()]; + int n = 0; + for (IPeer p : map.values()) { + PeerInfo info = new PeerInfo(); + info.parent = peer; + info.index = n; + info.id = p.getID(); + info.attrs = new HashMap<String,String>(p.getAttributes()); + info.peer = p; + buf[n++] = info; + } + peer.listener = new LocatorListener(peer); + peer.locator.addListener(peer.listener); + return buf; + } + + private void doneLoadChildren(final PeerInfo parent, final Throwable error, final PeerInfo[] children) { + assert Protocol.isDispatchThread(); + assert error == null || children == null; + if (display == null) return; + display.asyncExec(new Runnable() { + public void run() { + assert parent.children_pending; + assert parent.children == null; + parent.children_pending = false; + parent.children = children; + parent.children_error = error; + updateItems(parent); + } + }); + } + + private void updateItems(TreeItem parent_item, boolean reload) { + final PeerInfo parent_info = findPeerInfo(parent_item); + if (parent_info == null) { + parent_item.setText("Invalid"); + } + else { + if (reload && parent_info.children_error != null) { + loadChildren(parent_info); + } + display.asyncExec(new Runnable() { + public void run() { + updateItems(parent_info); + } + }); + } + } + + private void updateItems(final PeerInfo parent) { + if (display == null) return; + assert Thread.currentThread() == display.getThread(); + TreeItem[] items = null; + boolean expanded = true; + if (parent.children == null || parent.children_error != null) { + if (parent == peer_info) { + peer_tree.setItemCount(1); + items = peer_tree.getItems(); + } + else { + TreeItem item = findItem(parent); + if (item == null) return; + expanded = item.getExpanded(); + item.setItemCount(1); + items = item.getItems(); + } + assert items.length == 1; + items[0].removeAll(); + if (parent.children_pending) { + items[0].setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); + items[0].setText("Connecting..."); + } + else if (parent.children_error != null) { + String msg = parent.children_error.getMessage(); + if (msg == null) msg = parent.children_error.getClass().getName(); + else msg = msg.replace('\n', ' '); + items[0].setForeground(display.getSystemColor(SWT.COLOR_RED)); + items[0].setText(msg); + } + else if (expanded) { + loadChildren(parent); + items[0].setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); + items[0].setText("Connecting..."); + } + else { + Protocol.invokeAndWait(new Runnable() { + public void run() { + disconnectPeer(parent); + } + }); + items[0].setText(""); + } + int n = peer_tree.getColumnCount(); + for (int i = 1; i < n; i++) items[0].setText(i, ""); + items[0].setImage((Image)null); + } + else { + PeerInfo[] arr = parent.children; + if (parent == peer_info) { + peer_tree.setItemCount(arr.length); + items = peer_tree.getItems(); + } + else { + TreeItem item = findItem(parent); + if (item == null) return; + expanded = item.getExpanded(); + item.setItemCount(expanded ? arr.length : 1); + items = item.getItems(); + } + if (expanded) { + assert items.length == arr.length; + for (int i = 0; i < items.length; i++) fillItem(items[i], arr[i]); + } + else { + Protocol.invokeAndWait(new Runnable() { + public void run() { + disconnectPeer(parent); + } + }); + items[0].setText(""); + int n = peer_tree.getColumnCount(); + for (int i = 1; i < n; i++) items[0].setText(i, ""); + } + } + updateLaunchConfigurationDialog(); + } + + private PeerInfo findPeerInfo(TreeItem item) { + assert Thread.currentThread() == display.getThread(); + if (item == null) return peer_info; + TreeItem parent = item.getParentItem(); + PeerInfo info = findPeerInfo(parent); + if (info == null) return null; + if (info.children == null) return null; + if (info.children_error != null) return null; + int i = parent == null ? peer_tree.indexOf(item) : parent.indexOf(item); + if (i < 0 || i >= info.children.length) return null; + assert info.children[i].index == i; + return info.children[i]; + } + + private PeerInfo findPeerInfo(String path) { + assert Thread.currentThread() == display.getThread(); + if (path == null) return null; + int i = path.lastIndexOf('/'); + String id = null; + PeerInfo[] arr = null; + if (i < 0) { + arr = peer_info.children; + if (arr == null) return null; + id = path; + } + else { + PeerInfo p = findPeerInfo(path.substring(0, i)); + if (p == null) return null; + arr = p.children; + if (arr == null) { + TreeItem item = findItem(p); + item.setExpanded(true); + return null; + } + id = path.substring(i + 1); + } + for (int n = 0; n < arr.length; n++) { + if (arr[n].id.equals(id)) return arr[n]; + } + return null; + } + + private TreeItem findItem(PeerInfo info) { + if (info == null) return null; + assert info.parent != null; + if (info.parent == peer_info) { + int n = peer_tree.getItemCount(); + if (info.index >= n) return null; + return peer_tree.getItem(info.index); + } + TreeItem i = findItem(info.parent); + if (i == null) return null; + int n = i.getItemCount(); + if (info.index >= n) return null; + return i.getItem(info.index); + } + + private void runDiagnostics(boolean loop) { + IPeer peer = null; + if (use_local_agent_button.getSelection()) { + try { + if (run_local_agent_button.getSelection()) TCFLocalAgent.runLocalAgent(); + final String id = TCFLocalAgent.getLocalAgentID(); + peer = new TCFTask<IPeer>() { + public void run() { + done(Protocol.getLocator().getPeers().get(id)); + } + }.get(); + } + catch (Throwable err) { + String msg = err.getLocalizedMessage(); + if (msg == null || msg.length() == 0) msg = err.getClass().getName(); + MessageBox mb = new MessageBox(getShell(), SWT.ICON_ERROR | SWT.OK); + mb.setText("Error"); + mb.setMessage("Cannot start agent:\n" + msg); + mb.open(); + } + } + else { + PeerInfo info = findPeerInfo(peer_id_text.getText()); + if (info == null) return; + peer = info.peer; + } + if (peer == null) return; + final Shell shell = new Shell(getShell(), SWT.TITLE | SWT.PRIMARY_MODAL); + GridLayout layout = new GridLayout(); + layout.verticalSpacing = 0; + layout.numColumns = 2; + shell.setLayout(layout); + shell.setText("Running Diagnostics..."); + CLabel label = new CLabel(shell, SWT.NONE); + label.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false)); + label.setText("Running Diagnostics..."); + final TCFTestSuite[] test = new TCFTestSuite[1]; + Button button_cancel = new Button(shell, SWT.PUSH); + button_cancel.setText("&Cancel"); + button_cancel.setLayoutData(new GridData(GridData.END, GridData.CENTER, false, false)); + button_cancel.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + Protocol.invokeLater(new Runnable() { + public void run() { + if (test[0] != null) test[0].cancel(); + } + }); + } + }); + createVerticalSpacer(shell, 0); + ProgressBar bar = new ProgressBar(shell, SWT.HORIZONTAL); + bar.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 2, 1)); + shell.setDefaultButton(button_cancel); + shell.pack(); + shell.setSize(483, shell.getSize().y); + Rectangle rc0 = getShell().getBounds(); + Rectangle rc1 = shell.getBounds(); + shell.setLocation(rc0.x + (rc0.width - rc1.width) / 2, rc0.y + (rc0.height - rc1.height) / 2); + shell.setVisible(true); + runDiagnostics(peer, loop, test, shell, label, bar); + } + + private void runDiagnostics(final IPeer peer, final boolean loop, final TCFTestSuite[] test, + final Shell shell, final CLabel label, final ProgressBar bar) { + final TCFTestSuite.TestListener done = new TCFTestSuite.TestListener() { + private String last_text = ""; + private int last_count = 0; + private int last_total = 0; + public void progress(final String label_text, final int count_done, final int count_total) { + assert test[0] != null; + if ((label_text == null || last_text.equals(label_text)) && + last_total == count_total && + (count_done - last_count) / (float)count_total < 0.02f) return; + if (label_text != null) last_text = label_text; + last_total = count_total; + last_count = count_done; + display.asyncExec(new Runnable() { + public void run() { + label.setText(last_text); + bar.setMinimum(0); + bar.setMaximum(last_total); + bar.setSelection(last_count); + } + }); + } + public void done(final Collection<Throwable> errors) { + assert test[0] != null; + final boolean b = test[0].isCanceled(); + test[0] = null; + display.asyncExec(new Runnable() { + public void run() { + if (errors.size() > 0) { + shell.dispose(); + new TestErrorsDialog(getControl().getShell(), + ImageCache.getImage(ImageCache.IMG_TCF), errors).open(); + } + else if (loop && !b && display != null) { + runDiagnostics(peer, true, test, shell, label, bar); + } + else { + shell.dispose(); + } + } + }); + } + }; + Protocol.invokeLater(new Runnable() { + public void run() { + try { + List<IPathMap.PathMapRule> path_map = null; + for (ILaunchConfigurationTab t : getLaunchConfigurationDialog().getTabs()) { + if (t instanceof TCFPathMapTab) path_map = ((TCFPathMapTab)t).getPathMap(); + } + HashMap<String,ArrayList<IMemoryMap.MemoryRegion>> mem_map = null; + if (mem_map_cfg != null) { + mem_map = new HashMap<String,ArrayList<IMemoryMap.MemoryRegion>>(); + TCFLaunchDelegate.parseMemMapsAttribute(mem_map, mem_map_cfg); + } + boolean enable_tracing = + "true".equals(Platform.getDebugOption("org.eclipse.tm.tcf.debug/debug")) && + "true".equals(Platform.getDebugOption("org.eclipse.tm.tcf.debug/debug/tests/runcontrol")); + if (enable_tracing) System.setProperty("org.eclipse.tm.tcf.debug.tracing.tests.runcontrol", "true"); + test[0] = new TCFTestSuite(peer, done, path_map, mem_map); + } + catch (Throwable x) { + ArrayList<Throwable> errors = new ArrayList<Throwable>(); + errors.add(x); + done.done(errors); + } + } + }); + } + + private void fillItem(TreeItem item, PeerInfo info) { + assert Thread.currentThread() == display.getThread(); + Object data = item.getData("TCFPeerInfo"); + if (data != null && data != info) item.removeAll(); + item.setData("TCFPeerInfo", info); + String text[] = new String[5]; + text[0] = info.attrs.get(IPeer.ATTR_NAME); + text[1] = info.attrs.get(IPeer.ATTR_OS_NAME); + text[2] = info.attrs.get(IPeer.ATTR_TRANSPORT_NAME); + text[3] = info.attrs.get(IPeer.ATTR_IP_HOST); + text[4] = info.attrs.get(IPeer.ATTR_IP_PORT); + for (int i = 0; i < text.length; i++) { + if (text[i] == null) text[i] = ""; + } + item.setText(text); + item.setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); + item.setImage(ImageCache.getImage(getImageName(info))); + if (!canHaveChildren(info)) item.setItemCount(0); + else if (info.children == null || info.children_error != null) item.setItemCount(1); + else item.setItemCount(info.children.length); + } + + private String getPath(PeerInfo info) { + if (info == peer_info) return ""; + if (info.parent == peer_info) return info.id; + return getPath(info.parent) + "/" + info.id; + } + + private String getImageName(PeerInfo info) { + return ImageCache.IMG_TARGET_TAB; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TestErrorsDialog.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TestErrorsDialog.java new file mode 100644 index 000000000..e1b0ac463 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TestErrorsDialog.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.Collection; +import java.util.Iterator; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +class TestErrorsDialog extends Dialog { + + private static final int + SIZING_TEXT_WIDTH = 600, + SIZING_TEXT_HEIGHT = 400; + + private Collection<Throwable> errors; + private Image image; + private Text text; + + TestErrorsDialog(Shell parent, Image image, Collection<Throwable> errors) { + super(parent); + this.image = image; + this.errors = errors; + } + + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText("Connection Diagnostic errors"); + shell.setImage(image); + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + createButton(parent, IDialogConstants.OK_ID, "&OK", true); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite)super.createDialogArea(parent); + composite.setSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); + + Label label = new Label(composite, SWT.WRAP); + label.setFont(JFaceResources.getFontRegistry().get(JFaceResources.BANNER_FONT)); + label.setText("Connection diagnostics ended with errors:"); + + text = new Text(composite, SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); + text.setFont(JFaceResources.getFontRegistry().get(JFaceResources.TEXT_FONT)); + text.setEditable(false); + text.setText(createText()); + GridData data = new GridData(GridData.FILL_BOTH); + data.widthHint = SIZING_TEXT_WIDTH; + data.heightHint = SIZING_TEXT_HEIGHT; + text.setLayoutData(data); + + return composite; + } + + private String createText() { + StringWriter buf = new StringWriter(); + PrintWriter pwr = new PrintWriter(buf); + for (Iterator<Throwable> i = errors.iterator(); i.hasNext();) { + i.next().printStackTrace(pwr); + pwr.println(); + } + pwr.flush(); + return buf.toString(); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/AbstractRemoteShell.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/AbstractRemoteShell.java new file mode 100644 index 000000000..066ab0630 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/AbstractRemoteShell.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch.setup; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.PrintWriter; + +abstract class AbstractRemoteShell implements IRemoteShell { + + protected boolean debug; + protected BufferedReader inp; + protected PrintWriter out; + + public void setDebug(boolean debug) { + this.debug = debug; + } + + public synchronized void write(String s) { + out.write(s); + } + + public synchronized void expect(String s) throws IOException { + expect(new String[]{ s }); + } + + public synchronized int expect(String s[]) throws IOException { + out.flush(); + int[] pos = new int[s.length]; + for (int i = 0; i < pos.length; i++) pos[i] = 0; + StringBuffer buf = new StringBuffer(); + try { + for (;;) { + int ch = inp.read(); + if (ch < 0) throw new IOException("Unexpected EOF"); + if (ch == '\r') continue; + if (debug) System.out.write(ch); + for (int i = 0; i < pos.length; i++) { + String p = s[i]; + if (ch == p.charAt(pos[i])) { + pos[i]++; + if (pos[i] == p.length()) return i; + } + else { + int nps = pos[i]; + while (nps > 0) { + if (ch == p.charAt(nps - 1)) { + int j = nps - 2; + int k = pos[i] - 1; + while (j >= 0 && p.charAt(j) == p.charAt(k)) { + j--; + k--; + } + if (j < 0) break; + } + nps--; + } + pos[i] = nps; + } + } + buf.append((char)ch); + if (ch == '\n') buf.setLength(0); + } + } + catch (IOException x) { + if (buf.length() == 0) throw x; + IOException y = new IOException("I/O error, last text received: " + buf); + y.initCause(x); + throw y; + } + finally { + if (debug) System.out.flush(); + } + } + + public synchronized String waitPrompt() throws IOException { + StringBuffer res = new StringBuffer(); + StringBuffer buf = new StringBuffer(); + out.flush(); + try { + for (;;) { + int ch = inp.read(); + if (ch < 0) throw new IOException("Unexpected EOF"); + if (ch == '\r') continue; + if (debug) System.out.write(ch); + buf.append((char)ch); + if (buf.length() == PROMPT.length() && buf.toString().equals(PROMPT)) break; + if (ch == '\n') { + res.append(buf); + buf.setLength(0); + } + } + return res.toString(); + } + catch (IOException x) { + if (buf.length() == 0) throw x; + IOException y = new IOException("I/O error, last text received: " + buf); + y.initCause(x); + throw y; + } + finally { + if (debug) System.out.flush(); + } + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/IRemoteShell.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/IRemoteShell.java new file mode 100644 index 000000000..4e052a6b4 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/IRemoteShell.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch.setup; + +import java.io.IOException; + +interface IRemoteShell { + + /** + * String that is used as shell prompt. + */ + static final String PROMPT = "***SHELL***>"; + + /** + * Send text to remote shell. + * @param s - a string for shell input. + * @throws IOException + */ + void write(String s) throws IOException; + + /** + * Read shell output until given string if found. + * @param s - a string to search in shell output. + * @throws IOException + */ + void expect(String s) throws IOException; + + /** + * Read and collect shell output until shell prompt is found. + * @return shell output, not including the prompt. + * @throws IOException + */ + String waitPrompt() throws IOException; + + /** + * Exit shell and close communication channel. + * @throws IOException + */ + void close() throws IOException; + + /** + * Enable/disable debug output to System.out. + */ + void setDebug(boolean debug); +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/PeerPropsControl.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/PeerPropsControl.java new file mode 100644 index 000000000..ad4fee038 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/PeerPropsControl.java @@ -0,0 +1,333 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch.setup; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Map; + +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.ICellModifier; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TextCellEditor; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Item; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.Text; +import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; +import org.eclipse.tm.tcf.protocol.IPeer; + +public class PeerPropsControl { + + private static final int + SIZING_TABLE_WIDTH = 400, + SIZING_TABLE_HEIGHT = 200; + + private static final String[] column_names = { "Name", "Value" }; + + private final Map<String,String> attrs; + private final ArrayList<Attribute> attr_table_data; + private final boolean create_new; + private final boolean enable_editing; + private final Runnable listener; + + private Text id_text; + private Text name_text; + private Table attr_table; + private TableViewer table_viewer; + private Image attr_image; + + private class Attribute { + String name; + String value; + } + + private class AttributeLabelProvider extends LabelProvider implements ITableLabelProvider { + + public Image getColumnImage(Object element, int column) { + if (column == 0) return attr_image; + return null; + } + + public String getColumnText(Object element, int column) { + Attribute a = (Attribute)element; + return column == 0 ? a.name : a.value; + } + + public String getText(Object element) { + TableColumn column = attr_table.getSortColumn(); + if (column == null) return ""; + return getColumnText(element, attr_table.indexOf(column)); + } + } + + public PeerPropsControl(Composite parent, Map<String,String> attrs, boolean enable_editing, Runnable listener) { + this.attrs = attrs; + this.enable_editing = enable_editing; + this.listener = listener; + create_new = attrs.isEmpty(); + attr_table_data = new ArrayList<Attribute>(); + + createTextFields(parent); + createAttrTable(parent); + } + + private void createTextFields(Composite parent) { + Font font = parent.getFont(); + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Label id_label = new Label(composite, SWT.WRAP); + id_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + id_label.setFont(font); + id_label.setText("Peer &ID:"); + + id_text = new Text(composite, SWT.SINGLE | SWT.BORDER); + id_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + id_text.setFont(font); + id_text.setEditable(false); + + Label name_label = new Label(composite, SWT.WRAP); + name_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + name_label.setFont(font); + name_label.setText("Peer &name:"); + + name_text = new Text(composite, SWT.SINGLE | SWT.BORDER); + name_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + name_text.setFont(font); + name_text.setEditable(enable_editing); + name_text.addListener(SWT.KeyUp, new Listener() { + public void handleEvent(Event event) { + listener.run(); + } + }); + } + + private void createAttrTable(Composite parent) { + Font font = parent.getFont(); + Label props_label = new Label(parent, SWT.WRAP); + props_label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + props_label.setFont(font); + props_label.setText("Peer &properties:"); + + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1)); + + attr_table = new Table(composite, SWT.SINGLE | SWT.BORDER | + SWT.H_SCROLL | SWT.V_SCROLL | + SWT.FULL_SELECTION | SWT.HIDE_SELECTION); + attr_table.setFont(font); + GridData data = new GridData(GridData.FILL_BOTH); + data.widthHint = SIZING_TABLE_WIDTH; + data.heightHint = SIZING_TABLE_HEIGHT; + attr_table.setLayoutData(data); + + for (int i = 0; i < column_names.length; i++) { + final TableColumn column = new TableColumn(attr_table, SWT.LEAD, i); + column.setMoveable(false); + column.setText(column_names[i]); + column.setWidth(SIZING_TABLE_WIDTH / column_names.length); + column.addSelectionListener(new SelectionAdapter() { + + public void widgetSelected(SelectionEvent e) { + if (column == attr_table.getSortColumn()) { + switch (attr_table.getSortDirection()) { + case SWT.NONE: + attr_table.setSortDirection(SWT.DOWN); + break; + case SWT.DOWN: + attr_table.setSortDirection(SWT.UP); + break; + case SWT.UP: + attr_table.setSortDirection(SWT.NONE); + break; + } + } + else { + attr_table.setSortColumn(column); + attr_table.setSortDirection(SWT.DOWN); + } + table_viewer.refresh(); + } + }); + } + attr_table.setHeaderVisible(true); + attr_table.setLinesVisible(true); + + attr_image = ImageCache.getImage(ImageCache.IMG_ATTRIBUTE); + + table_viewer = new TableViewer(attr_table); + table_viewer.setUseHashlookup(true); + table_viewer.setColumnProperties(column_names); + + CellEditor[] editors = new CellEditor[column_names.length]; + for (int i = 0; i < column_names.length; i++) { + TextCellEditor editor = new TextCellEditor(attr_table); + ((Text)editor.getControl()).setTextLimit(250); + editors[i] = editor; + } + table_viewer.setCellEditors(editors); + + table_viewer.setCellModifier(new ICellModifier() { + + public boolean canModify(Object element, String property) { + return enable_editing; + } + + public Object getValue(Object element, String property) { + if (element instanceof Item) element = ((Item)element).getData(); + Attribute a = (Attribute)element; + return property.equals(column_names[0]) ? a.name : a.value; + } + + public void modify(Object element, String property, Object value) { + if (element instanceof Item) element = ((Item)element).getData(); + Attribute a = (Attribute)element; + if (property.equals(column_names[0])) { + a.name = (String)value; + } + else { + a.value = (String)value; + } + table_viewer.update(element, new String[] { property }); + } + }); + + String[] keys = attrs.keySet().toArray(new String[attrs.size()]); + Arrays.sort(keys); + for (String key : keys) { + if (key.equals(IPeer.ATTR_ID)) { + id_text.setText(attrs.get(key)); + } + else if (key.equals(IPeer.ATTR_NAME)) { + name_text.setText(attrs.get(key)); + } + else { + Attribute a = new Attribute(); + a.name = key; + a.value = attrs.get(key); + attr_table_data.add(a); + } + } + if (create_new) id_text.setText("USR:" + System.currentTimeMillis()); + + table_viewer.setContentProvider(new IStructuredContentProvider() { + + public Object[] getElements(Object input) { + assert input == attr_table_data; + return attr_table_data.toArray(); + } + + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + }); + + table_viewer.setLabelProvider(new AttributeLabelProvider()); + table_viewer.setInput(attr_table_data); + table_viewer.setComparator(new ViewerComparator() { + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + switch (attr_table.getSortDirection()) { + case SWT.UP : return -super.compare(viewer, e1, e2); + case SWT.DOWN: return +super.compare(viewer, e1, e2); + } + return 0; + } + }); + + createTableButtons(composite); + } + + private void createTableButtons(Composite parent) { + Font font = parent.getFont(); + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL)); + + final Button button_new = new Button(composite, SWT.PUSH); + button_new.setText("&Add"); + button_new.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + button_new.setEnabled(enable_editing); + button_new.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + Attribute a = new Attribute(); + a.name = ""; + a.value = ""; + attr_table_data.add(a); + table_viewer.add(a); + table_viewer.setSelection(new StructuredSelection(a), true); + attr_table.setFocus(); + } + }); + + final Button button_remove = new Button(composite, SWT.PUSH); + button_remove.setText("&Remove"); + button_remove.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + button_remove.setEnabled(enable_editing); + button_remove.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + Attribute a = (Attribute) ((IStructuredSelection) + table_viewer.getSelection()).getFirstElement(); + if (a == null) return; + attr_table_data.remove(a); + table_viewer.remove(a); + } + }); + } + + public boolean isComplete() { + return name_text.getText().length() > 0; + } + + public void okPressed() { + if (enable_editing) { + if (create_new) attrs.put(IPeer.ATTR_ID, id_text.getText()); + String id = attrs.get(IPeer.ATTR_ID); + String nm = name_text.getText(); + attrs.clear(); + for (Attribute a : attr_table_data) attrs.put(a.name, a.value); + attrs.put(IPeer.ATTR_ID, id); + attrs.put(IPeer.ATTR_NAME, nm); + } + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/SSHClient.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/SSHClient.java new file mode 100644 index 000000000..3b5427f91 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/SSHClient.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch.setup; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.io.PrintWriter; + +import org.eclipse.jsch.core.IJSchService; +import org.eclipse.jsch.ui.UserInfoPrompter; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; + +import com.jcraft.jsch.Channel; +import com.jcraft.jsch.Session; + +class SSHClient extends AbstractRemoteShell { + + private final Session session; + private final Channel channel; + + private static class Pipe { + + final PipedOutputStream out = new PipedOutputStream(); + final PipedInputStream inp = new PipedInputStream(); + + Pipe() throws IOException { + inp.connect(out); + } + } + + SSHClient(final Shell parent, String host, String user, final String password) throws Exception { + BundleContext ctx = Activator.getDefault().getBundle().getBundleContext(); + ServiceReference ref = ctx.getServiceReference(IJSchService.class.getName()); + IJSchService s = (IJSchService)ctx.getService(ref); + session = s.createSession(host, 22, user); + session.setPassword(password); + new UserInfoPrompter(session); + session.connect(30000); + channel = session.openChannel("shell"); + Pipe inp = new Pipe(); + Pipe out = new Pipe(); + channel.setInputStream(inp.inp); + channel.setOutputStream(out.out); + this.out = new PrintWriter(inp.out, true); + this.inp = new BufferedReader(new InputStreamReader(new TimeOutInputStream(out.inp, 512, 60000), "UTF-8")); + channel.connect(30000); + write("export PS1=\"" + PROMPT + "\"\n"); + expect(PROMPT + "\"\n"); + waitPrompt(); + } + + public void close() throws IOException { + channel.disconnect(); + session.disconnect(); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/SetupWizardDialog.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/SetupWizardDialog.java new file mode 100644 index 000000000..04facc944 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/SetupWizardDialog.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch.setup; + +import java.util.Map; + +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.swt.graphics.Image; +import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; + +public class SetupWizardDialog extends Wizard { + + private final Map<String,String> peer_attrs; + + public SetupWizardDialog(Map<String,String> peer_attrs) { + this.peer_attrs = peer_attrs; + setWindowTitle("TCF Debug Target Setup"); + } + + @Override + public void addPages() { + addPage(new WizardFirstPage(this)); + addPage(new WizardLoginPage(this)); + addPage(new WizardLogPage(this)); + addPage(new WizardLocalPage(this)); + addPage(new WizardPropsPage(this, peer_attrs)); + } + + @Override + public Image getDefaultPageImage() { + return ImageCache.getImage(ImageCache.IMG_TARGET_WIZARD); + } + + @Override + public boolean canFinish() { + IWizardPage page = getContainer().getCurrentPage(); + if (page instanceof WizardLogPage) return ((WizardLogPage)page).canFinish(); + if (page instanceof WizardPropsPage) return ((WizardPropsPage)page).canFinish(); + return false; + } + + @Override + public boolean performFinish() { + if (!canFinish()) return false; + IWizardPage page = getContainer().getCurrentPage(); + if (page instanceof WizardPropsPage) { + if (!((WizardPropsPage)page).performFinish()) return false;; + } + return true; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/TelnetClient.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/TelnetClient.java new file mode 100644 index 000000000..3c31506b5 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/TelnetClient.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch.setup; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.net.InetAddress; +import java.net.Socket; +import java.net.SocketException; + +class TelnetClient extends AbstractRemoteShell { + + private Socket socket; + private boolean logged; + + TelnetClient(InetAddress address, int port, + String user, String password) throws Exception { + socket = new Socket(address, port); + socket.setTcpNoDelay(true); + InputStream ist = new BufferedInputStream(socket.getInputStream()); + OutputStream ost = new BufferedOutputStream(socket.getOutputStream()); + ist = new TelnetInputStream(ist, ost, true, PROMPT); + ist = new TimeOutInputStream(ist, 512, 30000); + out = new PrintWriter(ost, true); + inp = new BufferedReader(new InputStreamReader(ist, "UTF-8")); + expect("ogin: "); + write(user + "\n"); + expect("assword: "); + write(password + "\n"); + int i = expect(new String[]{"incorrect", PROMPT, "$ ", "# ", "> "}); + if (i == 0) { + close(); + throw new Exception("Login incorrect"); + } + logged = true; + write("export PS1=\"" + PROMPT + "\"\n"); + expect(PROMPT + "\"\n"); + waitPrompt(); + } + + public synchronized void close() throws IOException { + if (socket == null) return; + if (logged) { + write("exit\n"); + logged = false; + } + out.close(); + try { + char[] buf = new char[0x100]; + while (inp.read(buf) >= 0) {} + } + catch (SocketException x) { + if (!x.getMessage().startsWith("Socket closed")) throw x; + } + inp.close(); + socket.close(); + socket = null; + inp = null; + out = null; + } + + public void finalize() throws Throwable { + close(); + super.finalize(); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/TelnetInputStream.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/TelnetInputStream.java new file mode 100644 index 000000000..6554dd9e0 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/TelnetInputStream.java @@ -0,0 +1,328 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch.setup; + +import java.io.*; +import java.net.*; +import java.util.ArrayList; + +class TelnetInputStream extends FilterInputStream { + + public interface TelnetTraceListener { + void command(String s); + } + + private final boolean echo; + private final String prompt; + + private final InputStream inp; + private final OutputStream out; + private final boolean mode_rem[] = new boolean[256]; + private final int mode_cnt[] = new int[256]; + private final Reader reader = new Reader(); + private final byte buf[] = new byte[512]; + private int buf_inp = 0; + private int buf_out = 0; + private boolean eof; + private IOException err; + private boolean closed; + + private final ArrayList<TelnetTraceListener> trace_listeners = new ArrayList<TelnetTraceListener>(); + + private static final int + cm_IAC = 255, + cm_WILL = 251, + cm_WONT = 252, + cm_DO = 253, + cm_DONT = 254, + cm_SB = 250, + cm_SE = 240, + cm_DataMark = 242; + + private static final int + co_ECHO = 1, + co_SUPPRESS_GO_AHEAD = 3, + co_STATUS = 5, + co_TERMINAL_TYPE = 24, + co_NAWS = 31, // Negotiate About Window Size + co_TERMINAL_SPEED = 32, + co_TOGGLE_FLOW_CONTROL = 33, + co_X_DISPLAY_LOCATION = 35, + co_ENVIRON = 36, + co_NEW_ENVIRON = 39; + + @SuppressWarnings("unused") + private static final int + sp_VAR = 0, + sp_VALUE = 1, + sp_ESC = 2, + sp_USERVAR = 3; + + @SuppressWarnings("unused") + private static final int + ac_IS = 0, + ac_SEND = 1, + ac_INFO = 2; + + private class Reader extends Thread { + + private void logCommand(int cmd, int opt) { + String s = "" + cmd; + switch (cmd) { + case cm_WILL: + s = "WILL"; + break; + case cm_WONT: + s = "WONT"; + break; + case cm_DO: + s = "DO"; + break; + case cm_DONT: + s = "DONT"; + break; + case cm_SB: + s = "SB"; + break; + } + s += " "; + switch (opt) { + case co_ECHO: + s += "ECHO"; + break; + case co_SUPPRESS_GO_AHEAD: + s += "SUPPRESS_GO_AHEAD"; + break; + case co_STATUS: + s += "STATUS"; + break; + case co_TERMINAL_TYPE: + s += "TERMINAL_TYPE"; + break; + case co_NAWS: + s += "NAWS"; + break; + case co_TERMINAL_SPEED: + s += "TERMINAL_SPEED"; + break; + case co_TOGGLE_FLOW_CONTROL: + s += "TOGGLE_FLOW_CONTROL"; + break; + case co_X_DISPLAY_LOCATION: + s += "X_DISPLAY_LOCATION"; + break; + case co_ENVIRON: + s += "ENVIRON"; + break; + case co_NEW_ENVIRON: + s += "NEW_ENVIRON"; + break; + default: + s += opt; + break; + } + for (TelnetTraceListener l : trace_listeners) l.command(s); + } + + private int read_ch() throws IOException { + try { + return inp.read(); + } + catch (SocketException x) { + String s = x.getMessage(); + if (s.startsWith("Socket closed")) return -1; + if (s.startsWith("socket closed")) return -1; + throw x; + } + } + + public void run() { + try { + synchronized (out) { + out.write(cm_IAC); + out.write(echo ? cm_DO : cm_DONT); + out.write(co_ECHO); + out.flush(); + } + for (;;) { + int rd = read_ch(); + if (rd < 0) break; + if (rd == cm_IAC) { + int cm = read_ch(); + if (cm < 0) break; + if (cm != cm_IAC) { + int co = read_ch(); + if (co < 0) break; + if (co == cm_DataMark) continue; + logCommand(cm, co); + synchronized (out) { + if (mode_cnt[co] >= 5) continue; + switch (cm) { + case cm_WILL: + mode_rem[co] = true; + break; + case cm_WONT: + mode_rem[co] = false; + break; + case cm_DO: + out.write(cm_IAC); + if (co == co_SUPPRESS_GO_AHEAD) { + out.write(cm_WILL); + } + else if (co == co_NEW_ENVIRON && prompt != null) { + out.write(cm_WILL); + } + else { + out.write(cm_WONT); + } + out.write(co); + break; + case cm_DONT: + out.write(cm_IAC); + out.write(cm_WONT); + out.write(co); + break; + case cm_SB: + int ac = read_ch(); + if (ac < 0) break; + if (ac == ac_SEND) { + if (co == co_NEW_ENVIRON) { + out.write(cm_IAC); + out.write(cm_SB); + out.write(co_NEW_ENVIRON); + out.write(ac_IS); + if (prompt != null) { + out.write(sp_VAR); + out.write('P'); + out.write('S'); + out.write('1'); + out.write(sp_VALUE); + for (int k = 0; k < prompt.length(); k++) out.write(prompt.charAt(k)); + } + out.write(cm_IAC); + out.write(cm_SE); + } + } + int c0 = 0; + for (;;) { + int c1 = read_ch(); + if (c0 == cm_IAC && c1 == cm_SE) break; + if (c0 == cm_IAC && c1 == cm_IAC) c1 = 0; + c0 = c1; + } + break; + default: + throw new IOException("Invalid command: " + cm); + } + out.flush(); + mode_cnt[co]++; + } + continue; + } + } + synchronized (TelnetInputStream.this) { + int new_inp = (buf_inp + 1) % buf.length; + while (new_inp == buf_out) TelnetInputStream.this.wait(); + buf[buf_inp] = (byte)rd; + buf_inp = new_inp; + TelnetInputStream.this.notify(); + } + } + } + catch (InterruptedException x) { + err = new InterruptedIOException(); + } + catch (IOException x) { + if (!closed) err = x; + } + finally { + synchronized (TelnetInputStream.this) { + eof = true; + TelnetInputStream.this.notify(); + } + } + } + } + + TelnetInputStream(InputStream inp, OutputStream out, boolean echo, String prompt) { + super(inp); + if (!(inp instanceof BufferedInputStream)) inp = new BufferedInputStream(inp); + this.inp = inp; + this.out = out; + this.echo = echo; + this.prompt = prompt; + reader.start(); + } + + public synchronized void addTraceListener(TelnetTraceListener l) { + trace_listeners.add(l); + } + + public synchronized void removeTraceListener(TelnetTraceListener l) { + trace_listeners.remove(l); + } + + public synchronized int read() throws IOException { + try { + while (buf_out == buf_inp) { + if (err != null) throw new IOException(err.getMessage()); + if (eof) return -1; + wait(); + } + int res = buf[buf_out] & 0xff; + buf_out = (buf_out + 1) % buf.length; + notify(); + return res; + } + catch (InterruptedException x) { + throw new InterruptedIOException(); + } + } + + public synchronized int read(byte b[], int off, int len) throws IOException { + boolean nfy = false; + try { + int cnt = 0; + while (cnt < len) { + while (buf_out == buf_inp) { + if (cnt > 0) return cnt; + if (err != null) throw new IOException(err.getMessage()); + if (eof) return -1; + if (nfy) { + notify(); + nfy = false; + } + wait(); + } + b[off++] = buf[buf_out]; + buf_out = (buf_out + 1) % buf.length; + nfy = true; + cnt++; + } + return cnt; + } + catch (InterruptedException x) { + throw new InterruptedIOException(); + } + finally { + if (nfy) notify(); + } + } + + public synchronized int available() throws IOException { + return (buf_inp + buf.length - buf_out) % buf.length; + } + + public synchronized void close() throws IOException { + closed = true; + super.close(); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/TimeOutInputStream.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/TimeOutInputStream.java new file mode 100644 index 000000000..e8bb3ab4f --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/TimeOutInputStream.java @@ -0,0 +1,157 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch.setup; + +import java.io.*; + +class TimeOutInputStream extends FilterInputStream { + + private byte buf[]; + private int buf_inp = 0; + private int buf_out = 0; + private boolean eof = false; + private IOException err; + private InputStream inp; + private long time = 0; + private Thread thread; + + private class Prefetch extends Thread { + + public void run() { + try { + for (;;) { + int rd = inp.read(); + if (rd < 0) break; + synchronized (TimeOutInputStream.this) { + int new_inp = (buf_inp + 1) % buf.length; + while (new_inp == buf_out) TimeOutInputStream.this.wait(); + buf[buf_inp] = (byte)rd; + buf_inp = new_inp; + TimeOutInputStream.this.notify(); + } + } + } + catch (InterruptedException x) { + err = new InterruptedIOException(); + } + catch (InterruptedIOException x) { + err = x; + } + catch (IOException x) { + err = x; + } + finally { + synchronized (TimeOutInputStream.this) { + eof = true; + TimeOutInputStream.this.notify(); + } + } + } + } + + TimeOutInputStream(InputStream in, long time) { + this(in, 0x1000, time); + } + + TimeOutInputStream(InputStream in, int size, long time) { + super(in); + inp = in; + buf = new byte[size]; + this.time = time; + thread = new Prefetch(); + thread.start(); + } + + public void setTimeOut(long time) { + this.time = time; + } + + public synchronized int read() throws IOException { + try { + int cnt = 0; + while (buf_inp == buf_out) { + if (err != null) throw new IOException(err.getMessage()); + if (eof) return -1; + if (time != 0) { + if (cnt > 0) throw new IOException("Time Out"); + wait(time); + cnt++; + } + else { + wait(); + } + } + int res = buf[buf_out] & 0xff; + buf_out = (buf_out + 1) % buf.length; + notify(); + return res; + } + catch (InterruptedException x) { + throw new InterruptedIOException(); + } + } + + public synchronized int read(byte b[], int off, int len) throws IOException { + boolean nfy = false; + try { + int res = 0; + while (res < len) { + int cnt = 0; + while (buf_inp == buf_out) { + if (res > 0) return res; + if (err != null) throw new IOException(err.getMessage()); + if (eof) return -1; + if (nfy) { + notify(); + nfy = false; + } + if (time != 0) { + if (cnt > 0) throw new IOException("Time Out"); + wait(time); + cnt++; + } + else { + wait(); + } + } + b[off++] = buf[buf_out]; + buf_out = (buf_out + 1) % buf.length; + nfy = true; + res++; + } + return res; + } + catch (InterruptedException x) { + throw new InterruptedIOException(); + } + finally { + if (nfy) notify(); + } + } + + public synchronized int available() throws IOException { + return (buf_inp - buf_out + buf.length) % buf.length; + } + + public synchronized void close() throws IOException { + super.close(); + if (thread != null) { + try { + thread.interrupt(); + while (!eof) wait(); + thread = null; + } + catch (InterruptedException x) { + throw new InterruptedIOException(); + } + } + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/WizardFirstPage.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/WizardFirstPage.java new file mode 100644 index 000000000..c83842cb1 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/WizardFirstPage.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch.setup; + +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; + +class WizardFirstPage extends WizardPage implements Listener { + + private final SetupWizardDialog wizard; + + private Button button_props; + private Button button_local; + private Button button_login; + + WizardFirstPage(SetupWizardDialog wizard) { + super("FirstPage"); + this.wizard = wizard; + setTitle("Select a task"); + setDescription("Select an option that describes the task you want the wizard to perform"); + } + + public void createControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NULL); + GridLayout gl = new GridLayout(); + gl.numColumns = 1; + composite.setLayout(gl); + + button_props = new Button(composite, SWT.RADIO | SWT.WRAP | SWT.MULTI); + button_props.addListener(SWT.Selection, this); + button_props.setText("Manual setup of TCF connection properties."); + + button_local = new Button(composite, SWT.RADIO | SWT.WRAP | SWT.MULTI); + button_local.addListener(SWT.Selection, this); + button_local.setText("Setup TCF agent on local host."); + + button_login = new Button(composite, SWT.RADIO | SWT.WRAP | SWT.MULTI); + button_login.addListener(SWT.Selection, this); + button_login.setText("Setup TCF agent on remote host over Telnet or SSH."); + + setControl(composite); + } + + public void handleEvent(Event event) { + getContainer().updateButtons(); + } + + @Override + public IWizardPage getNextPage() { + if (button_props.getSelection()) return wizard.getPage("PropsPage"); + if (button_local.getSelection()) return wizard.getPage("LocalPage"); + if (button_login.getSelection()) return wizard.getPage("LoginPage"); + return null; + } +}
\ No newline at end of file diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/WizardLocalPage.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/WizardLocalPage.java new file mode 100644 index 000000000..1ec8cadff --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/WizardLocalPage.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch.setup; + +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; + +class WizardLocalPage extends WizardPage implements Listener { + + WizardLocalPage(SetupWizardDialog wizard) { + super("LocalPage"); + setTitle("Local TCF agent configuration"); + } + + public void handleEvent(Event event) { + getContainer().updateButtons(); + } + + public void createControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NULL); + GridLayout gl = new GridLayout(); + gl.numColumns = 1; + composite.setLayout(gl); + + new Label(composite, SWT.WRAP).setText("Under construction..."); + + setControl(composite); + } + + @Override + public IWizardPage getNextPage() { + return null; + } +}
\ No newline at end of file diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/WizardLogPage.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/WizardLogPage.java new file mode 100644 index 000000000..9d9ee9b62 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/WizardLogPage.java @@ -0,0 +1,400 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch.setup; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.InetAddress; +import java.net.URL; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.dialogs.IPageChangingListener; +import org.eclipse.jface.dialogs.PageChangingEvent; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.tcf.core.Base64; +import org.eclipse.tm.tcf.ssl.TCFSecurityManager; +import org.osgi.framework.Bundle; + +class WizardLogPage extends WizardPage implements Runnable { + + private final SetupWizardDialog wizard; + + private Thread thread; + private String protocol; + private String host; + private String user; + private String user_password; + private String root_password; + + private Text log_text; + + private Display display; + private Shell parent; + private IRemoteShell shell; + + WizardLogPage(SetupWizardDialog wizard) { + super("LogPage"); + this.wizard = wizard; + setTitle("Remote host login"); + setDescription(""); + } + + public void createControl(Composite parent) { + display = parent.getDisplay(); + this.parent = parent.getShell(); + ((WizardDialog)getContainer()).addPageChangingListener(new IPageChangingListener() { + public void handlePageChanging(PageChangingEvent event) { + if (event.getCurrentPage() instanceof WizardLoginPage && event.getTargetPage() == WizardLogPage.this) { + runSetupJob((WizardLoginPage)event.getCurrentPage()); + } + } + }); + + Composite composite = new Composite(parent, SWT.NULL); + GridLayout gl = new GridLayout(); + gl.numColumns = 1; + composite.setLayout(gl); + + new Label(composite, SWT.WRAP).setText("Agent installation log:"); + + log_text = new Text(composite, SWT.BORDER | SWT.MULTI | SWT.READ_ONLY | SWT.H_SCROLL | SWT.V_SCROLL); + GridData gd = new GridData(GridData.FILL_BOTH); + log_text.setLayoutData(gd); + + setControl(composite); + } + + private void runSetupJob(WizardLoginPage login) { + assert display != null; + assert display.getThread() == Thread.currentThread(); + if (thread != null) return; + setErrorMessage(null); + protocol = login.protocol.getText(); + host = login.host.getText(); + user = login.user.getText(); + user_password = login.user_password.getText(); + root_password = login.root_password.getText(); + log_text.setText("Connect to " + host + "\n"); + thread = new Thread(this); + thread.start(); + } + + public void run() { + Throwable error = null; + try { + if ("Telnet".equals(protocol)) { + shell = new TelnetClient(InetAddress.getByName(host), 23, user, user_password); + } + else if ("SSH".equals(protocol)) { + shell = new SSHClient(parent, host, user, user_password); + } + else { + throw new Exception("Invalid protocol name: " + protocol); + } + + String s; + + if (!user.equals("root")) { + send("su", true); + expect("Password: ", true); + send(root_password, false); + s = waitPrompt(); + if (s.length() > 0) throw new Exception(s); + } + exec("cd /tmp"); + send("uname -o", true); + String os = waitPrompt().replace('\n', ' ').trim(); + send("uname -m", true); + String machine = waitPrompt().replace('\n', ' ').trim(); + String version = "0.5.0"; + Bundle bundle = Platform.getBundle(Activator.PLUGIN_ID); + + URL url = FileLocator.find(bundle, new Path("agent/get-os-tag"), null); + if (url == null) throw new Exception("Cannot find get-os-tag script"); + send("cat >get-os-tag", true); + InputStream inp = url.openStream(); + byte[] buf = new byte[0x100]; + for (;;) { + int len = inp.read(buf); + if (len < 0) break; + shell.write(new String(buf, 0, len, "ASCII")); + for (int i = 0; i < len; i++) { + if (buf[i] == '\n') shell.expect("\n"); + } + } + inp.close(); + shell.write("\004"); + s = waitPrompt(); + if (s.length() > 0) throw new Exception(s); + + exec("chmod u+x get-os-tag"); + + send("./get-os-tag", true); + String os_tag = waitPrompt().replace('\n', ' ').trim(); + + exec("rm -f get-os-tag"); + + url = null; + String fnm = null; + String machine0 = machine; + for (;;) { + for (int release = 16; url == null && release > 0; release--) { + fnm = "tcf-agent-" + version + "-" + release + "." + os_tag + "." + machine + ".rpm"; + url = FileLocator.find(bundle, new Path("agent/" + os + "/" + machine + "/" + fnm), null); + } + if (url != null) break; + if (machine.equals("i686")) machine = "i586"; + else if (machine.equals("i586")) machine = "i486"; + else if (machine.equals("i486")) machine = "i386"; + else { + machine = machine0; + if (os_tag.startsWith("fc")) { + int n = Integer.parseInt(os_tag.substring(2)) - 1; + if (n <= 0) break; + os_tag = "fc" + n; + } + else if (os_tag.startsWith("rh")) { + int n = Integer.parseInt(os_tag.substring(2)) - 1; + if (n <= 0) break; + os_tag = "rh" + n; + } + else break; + } + } + if (url == null) throw new Exception("Unsupported target OS or CPU"); + + inp = url.openStream(); + send("which base64", true); + s = waitPrompt(); + if (s.indexOf(':') < 0) { + send("base64 -di >" + fnm, true); + sendBase64(inp); + shell.write("\004"); + s = waitPrompt(); + if (s.length() > 0) throw new Exception(s); + } + else { + send("which uudecode", true); + s = waitPrompt(); + if (s.indexOf(':') < 0) { + send("uudecode", true); + send("begin-base64 644 " + fnm, true); + sendBase64(inp); + send("====", true); + s = waitPrompt(); + if (s.length() > 0) throw new Exception(s); + } + else { + throw new Exception("No base64 or uudecode commands available"); + } + } + inp.close(); + + send("rpm -e --quiet tcf-agent", true); + waitPrompt(); + exec("rm -f /etc/init.d/tcf-agent*"); + exec("rpm -i --quiet " + fnm); + exec("rm -f " + fnm); + + File certs = TCFSecurityManager.getCertificatesDirectory(); + + File local_cert = new File(certs, "local.cert"); + File local_priv = new File(certs, "local.priv"); + + if (!local_cert.exists() || !local_priv.exists()) { + copyRemoteSecret("local.cert", local_cert); + copyRemoteSecret("local.priv", local_priv); + exec("/usr/sbin/tcf-agent -c"); + } + + copyRemoteSecret("local.cert", new File(certs, host + ".cert")); + copyLocalSecret(local_cert, InetAddress.getLocalHost().getHostName() + ".cert"); + + if (!user.equals("root")) { + send("exit", true); + waitPrompt(); + } + } + catch (Throwable x) { + error = x; + } + if (shell != null) { + try { + shell.close(); + shell = null; + } + catch (Throwable x) { + if (error != null) error = x; + } + } + done(error); + } + + private void sendBase64(InputStream inp) throws Exception { + byte[] buf = new byte[0x100 * 3]; + for (;;) { + int len = 0; + while (len < buf.length) { + int rd = inp.read(buf, len, buf.length - len); + if (rd < 0) break; + len += rd; + } + if (len == 0) break; + send(new String(Base64.toBase64(buf, 0, len)), false); + } + } + + private void copyRemoteSecret(String from, File to) throws Exception { + send("cat /etc/tcf/ssl/" + from, true); + String s = waitPrompt(); + if (s.indexOf("-----BEGIN ") != 0) throw new Exception(s); + BufferedWriter wr = new BufferedWriter(new OutputStreamWriter( + new FileOutputStream(to), "ASCII")); + wr.write(s); + wr.close(); + } + + private void copyLocalSecret(File from, String to) throws Exception { + send("cat >/etc/tcf/ssl/" + to, true); + BufferedReader rd = new BufferedReader(new InputStreamReader( + new FileInputStream(from), "ASCII")); + for (;;) { + String s = rd.readLine(); + if (s == null) break; + send(s, true); + } + shell.write("\004"); + String s = waitPrompt(); + if (s.length() > 0) throw new Exception(s); + } + + private void send(final String s, boolean log) throws IOException { + if (log) { + display.asyncExec(new Runnable() { + public void run() { + if (log_text.isDisposed()) return; + log_text.append("Send: "); + log_text.append(s); + if (!s.endsWith("\n")) log_text.append("\n"); + } + }); + } + shell.write(s); + shell.write("\n"); + if (log) shell.expect(s); + shell.expect("\n"); + } + + private void expect(final String s, boolean log) throws IOException { + if (log) { + display.asyncExec(new Runnable() { + public void run() { + if (log_text.isDisposed()) return; + log_text.append("Expect: "); + log_text.append(s); + if (!s.endsWith("\n")) log_text.append("\n"); + } + }); + } + shell.expect(s); + } + + private String waitPrompt() throws IOException { + display.asyncExec(new Runnable() { + public void run() { + if (log_text.isDisposed()) return; + log_text.append("Wait for shell prompt\n"); + } + }); + final String s = shell.waitPrompt(); + if (s.length() > 0) { + display.asyncExec(new Runnable() { + public void run() { + if (log_text.isDisposed()) return; + log_text.append("Got: "); + log_text.append(s); + if (!s.endsWith("\n")) log_text.append("\n"); + } + }); + } + return s; + } + + private void exec(String cmd) throws Exception { + send(cmd, true); + String s = waitPrompt(); + if (s.length() > 0) throw new Exception(s); + } + + private void done(final Throwable error) { + display.asyncExec(new Runnable() { + public void run() { + thread = null; + protocol = null; + host = null; + user = null; + user_password = null; + root_password = null; + if (log_text.isDisposed()) return; + if (error != null) { + StringWriter buf = new StringWriter(); + PrintWriter pwr = new PrintWriter(buf); + error.printStackTrace(pwr); + pwr.flush(); + log_text.append(buf.toString()); + setErrorMessage(error.getClass().getName() + ": " + error.getLocalizedMessage()); + } + else { + log_text.append("Done\n"); + setErrorMessage(null); + } + getContainer().updateButtons(); + } + }); + } + + @Override + public IWizardPage getPreviousPage() { + if (thread != null) return null; + return wizard.getPage("LoginPage"); + } + + @Override + public IWizardPage getNextPage() { + return null; + } + + public boolean canFinish() { + return thread == null && getErrorMessage() == null; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/WizardLoginPage.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/WizardLoginPage.java new file mode 100644 index 000000000..313ef8389 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/WizardLoginPage.java @@ -0,0 +1,209 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch.setup; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.preferences.DefaultScope; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.IPreferencesService; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.jface.preference.IPreferencePage; +import org.eclipse.jface.preference.PreferenceDialog; +import org.eclipse.jface.preference.PreferenceManager; +import org.eclipse.jface.preference.PreferenceNode; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.osgi.framework.Bundle; + +class WizardLoginPage extends WizardPage implements Listener { + + private static final String + PREF_PROTOCOL = "setup.login.protocol", + PREF_HOST = "setup.login.host", + PREF_USER = "setup.login.user"; + + private final SetupWizardDialog wizard; + + final String[] protocols = { "Telnet", "SSH" }; + + Combo protocol; + Button prefs; + Text host; + Text user; + Text user_password; + Text root_password; + + WizardLoginPage(SetupWizardDialog wizard) { + super("LoginPage"); + this.wizard = wizard; + setTitle("Remote TCF agent configuration"); + setDescription("Enter remote host login data"); + } + + public void handleEvent(Event event) { + getContainer().updateButtons(); + + IEclipsePreferences n = new InstanceScope().getNode(Activator.PLUGIN_ID); + n.put(PREF_PROTOCOL, protocol.getText()); + n.put(PREF_HOST, host.getText()); + n.put(PREF_USER, user.getText()); + + root_password.setEnabled(!user.getText().equals("root")); + prefs.setEnabled(protocol.getText().equals(protocols[1])); + } + + public void createControl(final Composite parent) { + GridData gd; + Composite composite = new Composite(parent, SWT.NULL); + GridLayout gl = new GridLayout(); + gl.numColumns = 3; + composite.setLayout(gl); + + new Label(composite, SWT.NONE).setText("Protocol:"); + protocol = new Combo(composite, SWT.BORDER | SWT.READ_ONLY); + gd = new GridData(); + gd.horizontalAlignment = GridData.BEGINNING; + protocol.setLayoutData(gd); + protocol.setItems(protocols); + protocol.addListener(SWT.Selection, this); + + prefs = new Button(composite, SWT.PUSH); + prefs.setText("Preferences"); + gd = new GridData(); + gd.horizontalAlignment = GridData.BEGINNING; + gd.widthHint = 100; + prefs.setLayoutData(gd); + prefs.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent n) { + openProtocolPreferences(parent.getShell(), prefs.getText()); + } + }); + + new Label(composite, SWT.NONE).setText("Host:"); + host = new Text(composite, SWT.BORDER); + gd = new GridData(); + gd.horizontalSpan = 2; + gd.horizontalAlignment = GridData.BEGINNING; + gd.widthHint = 200; + host.setLayoutData(gd); + host.addListener(SWT.KeyUp, this); + + new Label(composite, SWT.NONE).setText("User:"); + user = new Text(composite, SWT.BORDER); + gd = new GridData(); + gd.horizontalSpan = 2; + gd.horizontalAlignment = GridData.BEGINNING; + gd.widthHint = 200; + user.setLayoutData(gd); + user.addListener(SWT.KeyUp, this); + + new Label(composite, SWT.NONE).setText("Password:"); + user_password = new Text(composite, SWT.BORDER | SWT.PASSWORD); + gd = new GridData(); + gd.horizontalSpan = 2; + gd.horizontalAlignment = GridData.BEGINNING; + gd.widthHint = 200; + user_password.setLayoutData(gd); + user_password.addListener(SWT.KeyUp, this); + + new Label(composite, SWT.NONE).setText("Root password:"); + root_password = new Text(composite, SWT.BORDER | SWT.PASSWORD); + gd = new GridData(); + gd.horizontalSpan = 2; + gd.horizontalAlignment = GridData.BEGINNING; + gd.widthHint = 200; + root_password.setLayoutData(gd); + root_password.addListener(SWT.KeyUp, this); + + IEclipsePreferences d = new DefaultScope().getNode(Activator.PLUGIN_ID); + d.put(PREF_PROTOCOL, protocols[0]); + + IEclipsePreferences[] n = { new InstanceScope().getNode(Activator.PLUGIN_ID) }; + IPreferencesService s = Platform.getPreferencesService(); + protocol.setText(s.get(PREF_PROTOCOL, "", n)); + host.setText(s.get(PREF_HOST, "", n)); + user.setText(s.get(PREF_USER, "", n)); + + root_password.setEnabled(!user.getText().equals("root")); + prefs.setEnabled(protocol.getText().equals(protocols[1])); + + setControl(composite); + } + + private void openProtocolPreferences(Shell shell, String title) { + try { + PreferenceManager mgr = new PreferenceManager(); + IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint("org.eclipse.ui", "preferencePages"); + IExtension[] extensions = point.getExtensions(); + for (int i = 0; i < extensions.length; i++) { + IConfigurationElement[] e = extensions[i].getConfigurationElements(); + for (int j = 0; j < e.length; j++) { + String nm = e[j].getName(); + if (nm.equals("page")) { //$NON-NLS-1$ + String cnm = e[j].getAttribute("class"); //$NON-NLS-1$ + if (cnm == null) continue; + if (!cnm.startsWith("org.eclipse.jsch.")) continue; + String id = e[j].getAttribute("id"); //$NON-NLS-1$ + if (id == null) id = cnm; + Bundle bundle = Platform.getBundle(extensions[i].getNamespaceIdentifier()); + Class<?> c = bundle.loadClass(cnm); + IPreferencePage page = (IPreferencePage)c.newInstance(); + String pnm = e[j].getAttribute("name"); //$NON-NLS-1$ + if (pnm != null) page.setTitle(pnm); + mgr.addToRoot(new PreferenceNode(id, page)); + } + } + } + PreferenceDialog dialog = new PreferenceDialog(shell, mgr); + dialog.create(); + dialog.setMessage(title); + dialog.open(); + } + catch (Throwable err) { + String msg = err.getLocalizedMessage(); + if (msg == null || msg.length() == 0) msg = err.getClass().getName(); + MessageBox mb = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK); + mb.setText("Error"); + mb.setMessage("Cannot open preferences dialog:\n" + msg); + mb.open(); + } + } + + @Override + public IWizardPage getNextPage() { + if (host.getText().length() > 0 && + user.getText().length() > 0 && + (user_password.getText().length() > 0 || protocol.getText().equals("SSH")) && + (!root_password.isEnabled() || root_password.getText().length() > 0)) + return wizard.getPage("LogPage"); + return null; + } +}
\ No newline at end of file diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/WizardPropsPage.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/WizardPropsPage.java new file mode 100644 index 000000000..af1ab7711 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/setup/WizardPropsPage.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.launch.setup; + +import java.util.Map; + +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; + +class WizardPropsPage extends WizardPage { + + private final Map<String,String> attrs; + + private PeerPropsControl props; + + protected WizardPropsPage(SetupWizardDialog wizard, Map<String,String> attrs) { + super("PropsPage"); + this.attrs = attrs; + setTitle("Manual client configuration"); + } + + public void createControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NULL); + GridLayout gl = new GridLayout(); + gl.numColumns = 1; + composite.setLayout(gl); + props = new PeerPropsControl(composite, attrs, true, new Runnable() { + public void run() { + getContainer().updateButtons(); + } + }); + setControl(composite); + } + + public IWizardPage getNextPage() { + return null; + } + + public boolean canFinish() { + return props.isComplete(); + } + + public boolean performFinish() { + props.okPressed(); + return true; + } +}
\ No newline at end of file diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/ICastToType.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/ICastToType.java new file mode 100644 index 000000000..5d79636f0 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/ICastToType.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import org.eclipse.tm.tcf.services.ISymbols; +import org.eclipse.tm.tcf.util.TCFDataCache; + +public interface ICastToType { + + void onCastToTypeChanged(); + + TCFDataCache<ISymbols.Symbol> getType(); +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/IDetailsProvider.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/IDetailsProvider.java new file mode 100644 index 000000000..24104eb1d --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/IDetailsProvider.java @@ -0,0 +1,16 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +public interface IDetailsProvider { + + boolean getDetailText(StyledStringBuffer buf, Runnable done); +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/ISourceNotFoundPresentation.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/ISourceNotFoundPresentation.java new file mode 100644 index 000000000..ce0a7aac8 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/ISourceNotFoundPresentation.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.ui.IEditorInput; + +/** + * Adapter to customize source presentation for the source-not-found case. + */ +public interface ISourceNotFoundPresentation { + + /** + * Returns an editor input that should be used to display a source-not-found editor + * for the given object or <code>null</code> if unable to provide an editor input + * for the given object. + * + * @param element a debug model element + * @param cfg the launch configuration of the debug element + * @param file unresolved source file path + * @return an editor input, or <code>null</code> if none + */ + public IEditorInput getEditorInput(Object element, ILaunchConfiguration cfg, String file); + + /** + * Returns the id of the source-not-found editor to use to display the + * given editor input and object, or <code>null</code> if + * unable to provide an editor id. + * + * @param input an editor input that was previously retrieved from this + * presentation's <code>getEditorInput</code> method + * @param element the object that was used in the call to + * <code>getEditorInput</code>, that corresponds to the given editor + * input + * @return an editor id, or <code>null</code> if none + */ + public String getEditorId(IEditorInput input, Object element); + +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/ISymbolOwner.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/ISymbolOwner.java new file mode 100644 index 000000000..2d3a6100c --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/ISymbolOwner.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +public interface ISymbolOwner { + + void addSymbol(TCFNodeSymbol s); + + void removeSymbol(TCFNodeSymbol s); +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/IWatchInExpressions.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/IWatchInExpressions.java new file mode 100644 index 000000000..9fee2ceb9 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/IWatchInExpressions.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import org.eclipse.tm.tcf.util.TCFDataCache; + +public interface IWatchInExpressions { + + TCFDataCache<String> getExpressionText(); +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/StyledStringBuffer.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/StyledStringBuffer.java new file mode 100644 index 000000000..7be54744f --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/StyledStringBuffer.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import java.util.ArrayList; +import java.util.Collection; + +import org.eclipse.swt.graphics.RGB; + +class StyledStringBuffer { + + private final StringBuffer bf = new StringBuffer(); + private final ArrayList<Style> styles = new ArrayList<Style>(); + + static class Style { + int pos; + int len; + int font; + RGB bg; + RGB fg; + } + + StyledStringBuffer append(int pos, int font, RGB bg, RGB fg) { + Style x = new Style(); + x.pos = pos; + x.len = bf.length() - pos; + x.font = font; + x.bg = bg; + x.fg = fg; + styles.add(x); + return this; + } + + StyledStringBuffer append(String s) { + bf.append(s); + return this; + } + + StyledStringBuffer append(char ch) { + bf.append(ch); + return this; + } + + StyledStringBuffer append(int i) { + bf.append(i); + return this; + } + + StyledStringBuffer append(String s, int font) { + Style x = new Style(); + x.pos = bf.length(); + x.len = s.length(); + x.font = font; + styles.add(x); + bf.append(s); + return this; + } + + StyledStringBuffer append(String s, int font, RGB bg, RGB fg) { + Style x = new Style(); + x.pos = bf.length(); + x.len = s.length(); + x.font = font; + x.bg = bg; + x.fg = fg; + styles.add(x); + bf.append(s); + return this; + } + + StyledStringBuffer append(StyledStringBuffer s) { + int offs = bf.length(); + for (Style y : s.styles) { + Style x = new Style(); + x.pos = y.pos + offs; + x.len = y.len; + x.font = y.font; + x.bg = y.bg; + x.fg = y.fg; + styles.add(x); + } + bf.append(s.bf); + return this; + } + + StringBuffer getStringBuffer() { + return bf; + } + + Collection<Style> getStyle() { + return styles; + } + + int length() { + return bf.length(); + } + + @Override + public String toString() { + return bf.toString(); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFAnnotationImageProvider.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFAnnotationImageProvider.java new file mode 100644 index 000000000..486d70222 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFAnnotationImageProvider.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.texteditor.IAnnotationImageProvider; + +public class TCFAnnotationImageProvider implements IAnnotationImageProvider { + + public Image getManagedImage(Annotation annotation) { + return ((TCFAnnotationManager.TCFAnnotation)annotation).image; + } + + public String getImageDescriptorId(Annotation annotation) { + return null; + } + + public ImageDescriptor getImageDescriptor(String imageDescritporId) { + return null; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFAnnotationManager.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFAnnotationManager.java new file mode 100644 index 000000000..21c09020d --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFAnnotationManager.java @@ -0,0 +1,624 @@ +/******************************************************************************* + * Copyright (c) 2008, 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationListener; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.debug.core.model.IBreakpoint; +import org.eclipse.debug.core.model.ISourceLocator; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.debug.ui.ISourcePresentation; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.graphics.Device; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Display; +import org.eclipse.tm.internal.tcf.debug.launch.TCFSourceLookupDirector; +import org.eclipse.tm.internal.tcf.debug.model.ITCFBreakpointListener; +import org.eclipse.tm.internal.tcf.debug.model.TCFBreakpointsStatus; +import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; +import org.eclipse.tm.internal.tcf.debug.model.TCFLaunch; +import org.eclipse.tm.internal.tcf.debug.model.TCFSourceRef; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; +import org.eclipse.tm.tcf.protocol.JSON; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.tcf.services.IBreakpoints; +import org.eclipse.tm.tcf.services.ILineNumbers; +import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.util.TCFDataCache; +import org.eclipse.tm.tcf.util.TCFTask; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IEditorReference; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWindowListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; + +public class TCFAnnotationManager { + + private static final String + TYPE_BP_INSTANCE = "org.eclipse.tm.tcf.debug.breakpoint_instance", + TYPE_TOP_FRAME = "org.eclipse.tm.tcf.debug.top_frame", + TYPE_STACK_FRAME = "org.eclipse.tm.tcf.debug.stack_frame"; + + class TCFAnnotation extends Annotation { + + final ILineNumbers.CodeArea area; + final Image image; + final String text; + final String type; + final int hash_code; + + IAnnotationModel model; + + TCFAnnotation(ILineNumbers.CodeArea area, Image image, String text, String type) { + this.area = area; + this.image = image; + this.text = text; + this.type = type; + hash_code = area.hashCode() + image.hashCode() + text.hashCode() + type.hashCode(); + setText(text); + setType(type); + } + + protected Image getImage() { + return image; + } + + void dispose() { + assert Thread.currentThread() == display.getThread(); + if (model != null) { + model.removeAnnotation(this); + model = null; + } + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof TCFAnnotation)) return false; + TCFAnnotation a = (TCFAnnotation)o; + if (!area.equals(a.area)) return false; + if (!image.equals(a.image)) return false; + if (!text.equals(a.text)) return false; + if (!type.equals(a.type)) return false; + return true; + } + + @Override + public int hashCode() { + return hash_code; + } + } + + private class WorkbenchWindowInfo { + final LinkedList<TCFAnnotation> annotations = new LinkedList<TCFAnnotation>(); + + void dispose() { + for (TCFAnnotation a : annotations) a.dispose(); + annotations.clear(); + } + } + + private final HashMap<IWorkbenchWindow,WorkbenchWindowInfo> windows = + new HashMap<IWorkbenchWindow,WorkbenchWindowInfo>(); + + private final HashSet<IWorkbenchWindow> dirty_windows = new HashSet<IWorkbenchWindow>(); + private final HashSet<TCFLaunch> dirty_launches = new HashSet<TCFLaunch>(); + private final HashSet<TCFLaunch> changed_launch_cfgs = new HashSet<TCFLaunch>(); + + private final TCFLaunch.LaunchListener launch_listener = new TCFLaunch.LaunchListener() { + + public void onCreated(TCFLaunch launch) { + } + + public void onConnected(final TCFLaunch launch) { + updateAnnotations(null, launch); + TCFBreakpointsStatus bps = launch.getBreakpointsStatus(); + if (bps == null) return; + bps.addListener(new ITCFBreakpointListener() { + + public void breakpointStatusChanged(String id) { + updateAnnotations(null, launch); + } + + public void breakpointRemoved(String id) { + updateAnnotations(null, launch); + } + + public void breakpointChanged(String id) { + } + }); + } + + public void onDisconnected(final TCFLaunch launch) { + assert Protocol.isDispatchThread(); + updateAnnotations(null, launch); + } + + public void onProcessOutput(TCFLaunch launch, String process_id, int stream_id, byte[] data) { + } + + public void onProcessStreamError(TCFLaunch launch, String process_id, + int stream_id, Exception error, int lost_size) { + } + }; + + private final ISelectionListener selection_listener = new ISelectionListener() { + + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + updateAnnotations(part.getSite().getWorkbenchWindow(), (TCFLaunch)null); + if (selection instanceof IStructuredSelection) { + final Object obj = ((IStructuredSelection)selection).getFirstElement(); + if (obj instanceof TCFNodeStackFrame && ((TCFNodeStackFrame)obj).isTraceLimit()) { + Protocol.invokeLater(new Runnable() { + public void run() { + ((TCFNodeStackFrame)obj).riseTraceLimit(); + } + }); + } + } + } + }; + + private final IWindowListener window_listener = new IWindowListener() { + + public void windowActivated(IWorkbenchWindow window) { + } + + public void windowClosed(IWorkbenchWindow window) { + assert windows.get(window) != null; + window.getSelectionService().removeSelectionListener( + IDebugUIConstants.ID_DEBUG_VIEW, selection_listener); + windows.remove(window).dispose(); + } + + public void windowDeactivated(IWorkbenchWindow window) { + } + + public void windowOpened(IWorkbenchWindow window) { + if (windows.get(window) != null) return; + window.getSelectionService().addSelectionListener( + IDebugUIConstants.ID_DEBUG_VIEW, selection_listener); + windows.put(window, new WorkbenchWindowInfo()); + updateAnnotations(window, (TCFLaunch)null); + } + }; + + private final ILaunchConfigurationListener launch_conf_listener = new ILaunchConfigurationListener() { + + public void launchConfigurationAdded(ILaunchConfiguration cfg) { + } + + public void launchConfigurationChanged(final ILaunchConfiguration cfg) { + displayExec(new Runnable() { + public void run() { + ILaunch[] arr = launch_manager.getLaunches(); + for (ILaunch l : arr) { + if (l instanceof TCFLaunch) { + TCFLaunch t = (TCFLaunch)l; + if (cfg.equals(t.getLaunchConfiguration())) { + changed_launch_cfgs.add(t); + updateAnnotations(null, t); + } + } + } + } + }); + } + + public void launchConfigurationRemoved(ILaunchConfiguration cfg) { + } + }; + + private final Display display = Display.getDefault(); + private final ILaunchManager launch_manager = DebugPlugin.getDefault().getLaunchManager(); + private int update_unnotations_cnt = 0; + private boolean started; + private boolean disposed; + + public TCFAnnotationManager() { + assert Protocol.isDispatchThread(); + TCFLaunch.addListener(launch_listener); + launch_manager.addLaunchConfigurationListener(launch_conf_listener); + displayExec(new Runnable() { + public void run() { + if (!PlatformUI.isWorkbenchRunning() || PlatformUI.getWorkbench().isStarting()) { + display.timerExec(200, this); + } + else if (!PlatformUI.getWorkbench().isClosing()) { + started = true; + PlatformUI.getWorkbench().addWindowListener(window_listener); + for (IWorkbenchWindow window : PlatformUI.getWorkbench().getWorkbenchWindows()) { + window_listener.windowOpened(window); + } + IWorkbenchWindow w = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (w != null) window_listener.windowActivated(w); + } + } + }); + } + + public void dispose() { + if (disposed) return; + assert Protocol.isDispatchThread(); + disposed = true; + launch_manager.removeLaunchConfigurationListener(launch_conf_listener); + TCFLaunch.removeListener(launch_listener); + displayExec(new Runnable() { + public void run() { + if (!started) return; + PlatformUI.getWorkbench().removeWindowListener(window_listener); + for (IWorkbenchWindow window : windows.keySet()) { + window.getSelectionService().removeSelectionListener( + IDebugUIConstants.ID_DEBUG_VIEW, selection_listener); + windows.get(window).dispose(); + } + windows.clear(); + } + }); + } + + private void displayExec(Runnable r) { + synchronized (Device.class) { + if (!display.isDisposed()) { + display.asyncExec(r); + } + } + } + + /** + * Return breakpoint status info for all active TCF debug sessions. + * @param breakpoint + * @return breakpoint status as defined by TCF Breakpoints service. + */ + Map<TCFLaunch,Map<String,Object>> getBreakpointStatus(IBreakpoint breakpoint) { + assert Protocol.isDispatchThread(); + Map<TCFLaunch,Map<String,Object>> map = new HashMap<TCFLaunch,Map<String,Object>>(); + if (disposed) return null; + ILaunch[] launches = DebugPlugin.getDefault().getLaunchManager().getLaunches(); + for (ILaunch l : launches) { + if (l instanceof TCFLaunch) { + TCFLaunch launch = (TCFLaunch)l; + TCFBreakpointsStatus bs = launch.getBreakpointsStatus(); + if (bs != null) map.put(launch, bs.getStatus(breakpoint)); + } + } + return map; + } + + /** + * Return breakpoint status text for all active TCF debug sessions. + * @param breakpoint + * @return breakpoint status as a string. + */ + @SuppressWarnings("unchecked") + String getBreakpointStatusText(IBreakpoint breakpoint) { + assert Protocol.isDispatchThread(); + String error = null; + for (Map<String,Object> map : getBreakpointStatus(breakpoint).values()) { + if (map != null) { + String s = (String)map.get(IBreakpoints.STATUS_ERROR); + if (s != null && error == null) error = s; + Object planted = map.get(IBreakpoints.STATUS_INSTANCES); + if (planted != null) { + Collection<Map<String,Object>> list = (Collection<Map<String,Object>>)planted; + for (Map<String,Object> m : list) { + if (m.get(IBreakpoints.INSTANCE_ERROR) == null) { + return "Planted"; + } + } + } + } + } + return error; + } + + @SuppressWarnings("unchecked") + private Object[] toObjectArray(Object o) { + if (o == null) return null; + Collection<Object> c = (Collection<Object>)o; + return (Object[])c.toArray(new Object[c.size()]); + } + + @SuppressWarnings("unchecked") + private Map<String,Object> toObjectMap(Object o) { + return (Map<String,Object>)o; + } + + private void addBreakpointErrorAnnotation(List<TCFAnnotation> set, TCFLaunch launch, String id, String error) { + Map<String,Object> props = launch.getBreakpointsStatus().getProperties(id); + if (props != null) { + String file = (String)props.get(IBreakpoints.PROP_FILE); + Number line = (Number)props.get(IBreakpoints.PROP_LINE); + if (file != null && line != null) { + ILineNumbers.CodeArea area = new ILineNumbers.CodeArea(null, file, + line.intValue(), 0, line.intValue() + 1, 0, + null, null, 0, false, false, false, false); + TCFAnnotation a = new TCFAnnotation(area, + ImageCache.getImage(ImageCache.IMG_BREAKPOINT_ERROR), + "Cannot plant breakpoint: " + error, + TYPE_BP_INSTANCE); + set.add(a); + } + } + } + + private void updateAnnotations(IWorkbenchWindow window, final TCFNode node) { + if (disposed) return; + assert Thread.currentThread() == display.getThread(); + final WorkbenchWindowInfo win_info = windows.get(window); + if (win_info == null) return; + List<TCFAnnotation> set = null; + if (node != null) { + set = new TCFTask<List<TCFAnnotation>>(node.getChannel()) { + public void run() { + if (node.isDisposed()) { + done(null); + return; + } + TCFNodeExecContext thread = null; + TCFNodeExecContext memory = null; + TCFNodeStackFrame frame = null; + TCFNodeStackFrame last_top_frame = null; + String bp_group = null; + boolean suspended = false; + if (node instanceof TCFNodeStackFrame) { + thread = (TCFNodeExecContext)node.parent; + frame = (TCFNodeStackFrame)node; + } + else if (node instanceof TCFNodeExecContext) { + thread = (TCFNodeExecContext)node; + TCFChildrenStackTrace trace = thread.getStackTrace(); + if (!trace.validate(this)) return; + frame = trace.getTopFrame(); + } + if (thread != null) { + TCFDataCache<IRunControl.RunControlContext> rc_ctx_cache = thread.getRunContext(); + if (!rc_ctx_cache.validate(this)) return; + IRunControl.RunControlContext rc_ctx_data = rc_ctx_cache.getData(); + if (rc_ctx_data != null) bp_group = rc_ctx_data.getBPGroup(); + TCFDataCache<TCFNodeExecContext> mem_cache = thread.getMemoryNode(); + if (!mem_cache.validate(this)) return; + memory = mem_cache.getData(); + if (bp_group == null && memory != null && rc_ctx_data != null && rc_ctx_data.hasState()) bp_group = memory.id; + last_top_frame = thread.getLastTopFrame(); + TCFDataCache<TCFContextState> state_cache = thread.getState(); + if (!state_cache.validate(this)) return; + suspended = state_cache.getData() != null && state_cache.getData().is_suspended; + } + List<TCFAnnotation> set = new ArrayList<TCFAnnotation>(); + if (memory != null) { + TCFLaunch launch = node.launch; + TCFBreakpointsStatus bs = launch.getBreakpointsStatus(); + if (bs != null) { + for (String id : bs.getStatusIDs()) { + Map<String,Object> map = bs.getStatus(id); + if (map == null) continue; + String error = (String)map.get(IBreakpoints.STATUS_ERROR); + if (error != null) addBreakpointErrorAnnotation(set, launch, id, error); + Object[] arr = toObjectArray(map.get(IBreakpoints.STATUS_INSTANCES)); + if (arr == null) continue; + for (Object o : arr) { + Map<String,Object> m = toObjectMap(o); + String ctx_id = (String)m.get(IBreakpoints.INSTANCE_CONTEXT); + if (ctx_id == null) continue; + if (!ctx_id.equals(node.id) && !ctx_id.equals(bp_group)) continue; + error = (String)m.get(IBreakpoints.INSTANCE_ERROR); + BigInteger addr = JSON.toBigInteger((Number)m.get(IBreakpoints.INSTANCE_ADDRESS)); + if (addr != null) { + ILineNumbers.CodeArea area = null; + TCFDataCache<TCFSourceRef> line_cache = memory.getLineInfo(addr); + if (line_cache != null) { + if (!line_cache.validate(this)) return; + TCFSourceRef line_data = line_cache.getData(); + if (line_data != null && line_data.area != null) area = line_data.area; + } + if (area == null) { + Map<String,Object> props = bs.getProperties(id); + if (props != null) { + String file = (String)props.get(IBreakpoints.PROP_FILE); + Number line = (Number)props.get(IBreakpoints.PROP_LINE); + if (file != null && line != null) { + area = new ILineNumbers.CodeArea(null, file, + line.intValue(), 0, line.intValue() + 1, 0, + null, null, 0, false, false, false, false); + } + } + } + if (area != null) { + if (error != null) { + TCFAnnotation a = new TCFAnnotation(area, + ImageCache.getImage(ImageCache.IMG_BREAKPOINT_ERROR), + "Cannot plant breakpoint at 0x" + addr.toString(16) + ": " + error, + TYPE_BP_INSTANCE); + set.add(a); + error = null; + } + else { + TCFAnnotation a = new TCFAnnotation(area, + ImageCache.getImage(ImageCache.IMG_BREAKPOINT_INSTALLED), + "Breakpoint planted at 0x" + addr.toString(16), + TYPE_BP_INSTANCE); + set.add(a); + } + } + } + if (error != null) addBreakpointErrorAnnotation(set, launch, id, error); + } + } + } + } + if (suspended && frame != null && frame.getFrameNo() >= 0) { + TCFDataCache<TCFSourceRef> line_cache = frame.getLineInfo(); + if (!line_cache.validate(this)) return; + TCFSourceRef line_data = line_cache.getData(); + if (line_data != null && line_data.area != null) { + TCFAnnotation a = null; + if (frame.getFrameNo() == 0) { + a = new TCFAnnotation(line_data.area, + DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_INSTRUCTION_POINTER_TOP), + "Current Instruction Pointer", + TYPE_TOP_FRAME); + } + else { + a = new TCFAnnotation(line_data.area, + DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_INSTRUCTION_POINTER), + "Stack Frame", + TYPE_STACK_FRAME); + } + set.add(a); + } + } + if (!suspended && last_top_frame != null) { + TCFDataCache<TCFSourceRef> line_cache = last_top_frame.getLineInfo(); + if (!line_cache.validate(this)) return; + TCFSourceRef line_data = line_cache.getData(); + if (line_data != null && line_data.area != null) { + TCFAnnotation a = new TCFAnnotation(line_data.area, + DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_INSTRUCTION_POINTER), + "Last Instruction Pointer position", + TYPE_STACK_FRAME); + set.add(a); + } + } + done(set); + } + }.getE(); + } + boolean flush_all = node == null || changed_launch_cfgs.contains(node.launch); + Iterator<TCFAnnotation> i = win_info.annotations.iterator(); + while (i.hasNext()) { + TCFAnnotation a = i.next(); + if (!flush_all && set != null && set.remove(a)) continue; + a.dispose(); + i.remove(); + } + if (set == null || set.size() == 0) return; + Map<IEditorInput,ITextEditor> editors = new HashMap<IEditorInput,ITextEditor>(); + for (IEditorReference ref : window.getActivePage().getEditorReferences()) { + IEditorPart part = ref.getEditor(false); + if (!(part instanceof ITextEditor)) continue; + ITextEditor editor = (ITextEditor)part; + editors.put(editor.getEditorInput(), editor); + } + ISourceLocator locator = node.launch.getSourceLocator(); + ISourcePresentation presentation = TCFModelPresentation.getDefault(); + for (TCFAnnotation a : set) { + Object source_element = TCFSourceLookupDirector.lookup(locator, a.area); + if (source_element == null) continue; + IEditorInput editor_input = presentation.getEditorInput(source_element); + ITextEditor editor = editors.get(editor_input); + if (editor == null) continue; + IDocumentProvider doc_provider = editor.getDocumentProvider(); + IAnnotationModel ann_model = doc_provider.getAnnotationModel(editor_input); + if (ann_model == null) continue; + IRegion region = null; + try { + doc_provider.connect(editor_input); + } + catch (CoreException e) { + } + try { + IDocument document = doc_provider.getDocument(editor_input); + if (document != null) region = document.getLineInformation(a.area.start_line - 1); + } + catch (BadLocationException e) { + } + finally { + doc_provider.disconnect(editor_input); + } + if (region == null) continue; + ann_model.addAnnotation(a, new Position(region.getOffset(), region.getLength())); + a.model = ann_model; + win_info.annotations.add(a); + } + } + + private void updateAnnotations(final int cnt) { + displayExec(new Runnable() { + public void run() { + synchronized (TCFAnnotationManager.this) { + if (cnt != update_unnotations_cnt) return; + } + for (IWorkbenchWindow window : windows.keySet()) { + if (dirty_windows.contains(null) || dirty_windows.contains(window)) { + TCFNode node = null; + try { + ISelection active_context = DebugUITools.getDebugContextManager() + .getContextService(window).getActiveContext(); + if (active_context instanceof IStructuredSelection) { + IStructuredSelection selection = (IStructuredSelection)active_context; + if (!selection.isEmpty()) { + Object first_element = selection.getFirstElement(); + if (first_element instanceof IAdaptable) { + node = (TCFNode)((IAdaptable)first_element).getAdapter(TCFNode.class); + } + } + } + if (dirty_launches.contains(null) || node != null && dirty_launches.contains(node.launch)) { + updateAnnotations(window, node); + } + } + catch (Throwable x) { + if (node == null || !node.isDisposed()) { + Activator.log("Cannot update editor annotations", x); + } + } + } + } + for (TCFLaunch launch : dirty_launches) { + if (launch != null) launch.removePendingClient(TCFAnnotationManager.this); + } + changed_launch_cfgs.clear(); + dirty_windows.clear(); + dirty_launches.clear(); + } + }); + } + + synchronized void updateAnnotations(final IWorkbenchWindow window, final TCFLaunch launch) { + final int cnt = ++update_unnotations_cnt; + displayExec(new Runnable() { + public void run() { + dirty_windows.add(window); + dirty_launches.add(launch); + updateAnnotations(cnt); + } + }); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildren.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildren.java new file mode 100644 index 000000000..1953566d3 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildren.java @@ -0,0 +1,226 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; +import org.eclipse.tm.tcf.protocol.IToken; +import org.eclipse.tm.tcf.util.TCFDataCache; + +/** + * TCFChildren is a concrete type of TCF data cache that is used to cache a list of children. + */ +public abstract class TCFChildren extends TCFDataCache<Map<String,TCFNode>> { + + private final int pool_margin; + private final Map<String,TCFNode> node_pool = new LinkedHashMap<String,TCFNode>(32, 0.75f, true); + + protected final TCFNode node; + + private static final TCFNode[] EMPTY_NODE_ARRAY = new TCFNode[0]; + + private TCFNode[] array; + + TCFChildren(TCFNode node) { + super(node.channel); + this.node = node; + pool_margin = 0; + node.addDataCache(this); + } + + TCFChildren(TCFNode node, int pool_margin) { + super(node.channel); + this.node = node; + this.pool_margin = pool_margin; + node.addDataCache(this); + } + + /** + * Dispose the cache and all nodes in the nodes pool. + */ + @Override + public void dispose() { + assert !isDisposed(); + node.removeDataCache(this); + for (TCFNode n : node_pool.values()) n.dispose(); + node_pool.clear(); + super.dispose(); + } + + /** + * Remove a node from cache. + * The method is called every time a node is disposed. + * @param id - node ID + */ + void onNodeDisposed(String id) { + node_pool.remove(id); + if (isValid()) { + array = null; + Map<String,TCFNode> data = getData(); + if (data != null) data.remove(id); + } + } + + private void addToPool(Map<String,TCFNode> data) { + assert !isDisposed(); + for (TCFNode n : data.values()) { + assert data.get(n.id) == n; + assert n.parent == node; + node_pool.put(n.id, n); + } + if (node_pool.size() > data.size() + pool_margin) { + String[] arr = node_pool.keySet().toArray(new String[node_pool.size()]); + for (String id : arr) { + if (data.get(id) == null) { + node_pool.get(id).dispose(); + if (node_pool.size() <= data.size() + pool_margin) break; + } + } + } + } + + /** + * End cache pending state. + * @param token - pending command handle. + * @param error - data retrieval error or null + * @param data - up-to-date map of children nodes + */ + @Override + public void set(IToken token, Throwable error, Map<String,TCFNode> data) { + array = null; + if (isDisposed()) { + // A command can return data after the cache element has been disposed. + // Just ignore the data in such case. + super.set(token, null, null); + assert node_pool.isEmpty(); + } + else if (data != null) { + super.set(token, error, data); + addToPool(data); + } + else { + super.set(token, error, new HashMap<String,TCFNode>()); + } + } + + /** + * Set given data to the cache, mark cache as valid, cancel any pending data retrieval. + * @param data - up-to-date data to store in the cache, null means empty collection of nodes. + */ + @Override + public void reset(Map<String,TCFNode> data) { + assert !isDisposed(); + array = null; + if (data != null) { + super.reset(data); + addToPool(data); + } + else { + super.reset(new HashMap<String,TCFNode>()); + } + } + + /** + * Invalidate the cache. If retrieval is in progress - let it continue. + */ + @Override + public void reset() { + super.reset(); + array = null; + } + + /** + * Force cache to invalid state, cancel pending data retrieval if any. + */ + @Override + public void cancel() { + super.cancel(); + array = null; + } + + /** + * Add a node to collection of children. + * @param n - a node. + */ + void add(TCFNode n) { + assert !isDisposed(); + assert !n.isDisposed(); + assert node_pool.get(n.id) == null; + assert n.parent == node; + node_pool.put(n.id, n); + if (isValid()) { + array = null; + Map<String,TCFNode> data = getData(); + if (data != null) data.put(n.id, n); + } + } + + /** + * Return collection of all nodes, including current children as well as + * currently unused nodes from the pool. + * To get only current children use getData() method. + * @return Collection of nodes. + */ + Collection<TCFNode> getNodes() { + return node_pool.values(); + } + + /** + * Return current number of children. + * The cache must be valid for the method to work. + * @return number of children. + */ + public int size() { + assert isValid(); + Map<String,TCFNode> data = getData(); + return data == null ? 0 : data.size(); + } + + /** + * Return current children nodes as a sorted array. + * @return array of nodes. + */ + public TCFNode[] toArray() { + assert isValid(); + if (array != null) return array; + Map<String,TCFNode> data = getData(); + if (data == null || data.size() == 0) return array = EMPTY_NODE_ARRAY; + array = data.values().toArray(new TCFNode[data.size()]); + Arrays.sort(array); + return array; + } + + /** + * Return current children nodes in IChildrenUpdate object. + * @param update - children update request object. + * @param done - a call-back object, it is called when cache state changes. + * @return true if all done, false if data request is pending. + */ + boolean getData(IChildrenUpdate update, Runnable done) { + if (!validate(done)) return false; + TCFNode[] arr = toArray(); + int offset = 0; + int r_offset = update.getOffset(); + int r_length = update.getLength(); + for (TCFNode n : arr) { + if (offset >= r_offset && offset < r_offset + r_length) { + update.setChild(n, offset); + } + offset++; + } + return true; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenExecContext.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenExecContext.java new file mode 100644 index 000000000..459cd16a2 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenExecContext.java @@ -0,0 +1,157 @@ +/******************************************************************************* + * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.tm.tcf.protocol.IToken; +import org.eclipse.tm.tcf.services.IMemory; +import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.util.TCFDataCache; + + +/** + * This class is used to maintain a dynamic list of both executable contexts and memory spaces + * that are children of a given parent context. The job is slightly complicated by necessity + * to merge results from two independent services. + */ +public class TCFChildrenExecContext extends TCFChildren { + + private final TCFChildren mem_children; + private final TCFChildren run_children; + + TCFChildrenExecContext(final TCFNode node) { + super(node); + mem_children = new TCFChildren(node) { + @Override + protected boolean startDataRetrieval() { + IMemory mem = node.model.getLaunch().getService(IMemory.class); + if (mem == null) { + set(null, null, new HashMap<String,TCFNode>()); + return true; + } + assert command == null; + command = mem.getChildren(node.id, new IMemory.DoneGetChildren() { + public void doneGetChildren(IToken token, Exception error, String[] contexts) { + Map<String,TCFNode> data = null; + if (command == token && error == null) { + int cnt = 0; + data = new HashMap<String,TCFNode>(); + for (String id : contexts) { + TCFNode n = node.model.getNode(id); + if (n == null) n = new TCFNodeExecContext(node, id); + ((TCFNodeExecContext)n).setMemSeqNo(cnt++); + assert n.parent == node; + data.put(id, n); + } + } + set(token, error, data); + } + }); + return false; + } + }; + run_children = new TCFChildren(node) { + @Override + protected boolean startDataRetrieval() { + IRunControl run = node.model.getLaunch().getService(IRunControl.class); + if (run == null) { + set(null, null, new HashMap<String,TCFNode>()); + return true; + } + assert command == null; + command = run.getChildren(node.id, new IRunControl.DoneGetChildren() { + public void doneGetChildren(IToken token, Exception error, String[] contexts) { + Map<String,TCFNode> data = null; + if (command == token && error == null) { + int cnt = 0; + data = new HashMap<String,TCFNode>(); + for (String id : contexts) { + TCFNode n = node.model.getNode(id); + if (n == null) n = new TCFNodeExecContext(node, id); + ((TCFNodeExecContext)n).setExeSeqNo(cnt++); + assert n.parent == node; + data.put(id, n); + } + } + set(token, error, data); + } + }); + return false; + } + }; + } + + @Override + protected boolean startDataRetrieval() { + TCFDataCache<?> pending = null; + if (!mem_children.validate()) pending = mem_children; + if (!run_children.validate()) pending = run_children; + if (pending != null) { + pending.wait(this); + return false; + } + Throwable error = mem_children.getError(); + if (error == null) error = run_children.getError(); + Map<String,TCFNode> data = new HashMap<String,TCFNode>(); + Map<String,TCFNode> m1 = mem_children.getData(); + Map<String,TCFNode> m2 = run_children.getData(); + if (m1 != null) data.putAll(m1); + if (m2 != null) data.putAll(m2); + set(null, error, data); + return true; + } + + void onContextAdded(IRunControl.RunControlContext context) { + // To preserve children order need to reset children list. + reset(); + run_children.reset(); + mem_children.reset(); + assert !node.isDisposed(); + String id = context.getID(); + TCFNodeExecContext n = (TCFNodeExecContext)node.model.getNode(id); + if (n == null) { + n = new TCFNodeExecContext(node, id); + n.postContextAddedDelta(); + add(n); + } + else { + n.postAllChangedDelta(); + } + run_children.add(n); + n.setRunContext(context); + } + + void onContextAdded(IMemory.MemoryContext context) { + // To preserve children order need to reset children list. + reset(); + run_children.reset(); + mem_children.reset(); + assert !node.isDisposed(); + String id = context.getID(); + TCFNodeExecContext n = (TCFNodeExecContext)node.model.getNode(id); + if (n == null) { + n = new TCFNodeExecContext(node, id); + n.postContextAddedDelta(); + add(n); + } + else { + n.postAllChangedDelta(); + } + mem_children.add(n); + n.setMemoryContext(context); + } + + void onAncestorContextChanged() { + for (TCFNode n : getNodes()) ((TCFNodeExecContext)n).onAncestorContextChanged(); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenExpressions.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenExpressions.java new file mode 100644 index 000000000..d3b9339d9 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenExpressions.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import java.util.HashMap; + +import org.eclipse.debug.core.model.IExpression; +import org.eclipse.debug.core.model.IWatchExpression; + +public class TCFChildrenExpressions extends TCFChildren { + + TCFChildrenExpressions(TCFNode node) { + super(node, 128); + } + + void onSuspended() { + for (TCFNode n : getNodes()) ((TCFNodeExpression)n).onSuspended(); + } + + void onRegisterValueChanged() { + for (TCFNode n : getNodes()) ((TCFNodeExpression)n).onRegisterValueChanged(); + } + + void onMemoryChanged() { + for (TCFNode n : getNodes()) ((TCFNodeExpression)n).onMemoryChanged(); + } + + void onMemoryMapChanged() { + for (TCFNode n : getNodes()) ((TCFNodeExpression)n).onMemoryMapChanged(); + } + + private TCFNodeExpression findScript(String text) { + for (TCFNode n : getNodes()) { + TCFNodeExpression e = (TCFNodeExpression)n; + if (text.equals(e.getScript())) return e; + } + return null; + } + + @Override + protected boolean startDataRetrieval() { + int cnt = 0; + HashMap<String,TCFNode> data = new HashMap<String,TCFNode>(); + for (final IExpression e : node.model.getExpressionManager().getExpressions()) { + String text = e.getExpressionText(); + TCFNodeExpression n = findScript(text); + if (n == null) add(n = new TCFNodeExpression(node, text, null, null, null, -1, false)); + n.setSortPosition(cnt++); + if (e instanceof IWatchExpression) n.setEnabled(((IWatchExpression)e).isEnabled()); + data.put(n.id, n); + } + set(null, null, data); + return true; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenHoverExpressions.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenHoverExpressions.java new file mode 100644 index 000000000..705044bd2 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenHoverExpressions.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import java.util.HashMap; + +/** + * Provides the cache of root nodes for the expression hover. + */ +class TCFChildrenHoverExpressions extends TCFChildren { + + TCFChildrenHoverExpressions(TCFNode parent) { + super(parent, 16); + } + + void onSuspended() { + for (TCFNode n : getNodes()) ((TCFNodeExpression)n).onSuspended(); + } + + void onRegisterValueChanged() { + for (TCFNode n : getNodes()) ((TCFNodeExpression)n).onRegisterValueChanged(); + } + + void onMemoryChanged() { + for (TCFNode n : getNodes()) ((TCFNodeExpression)n).onMemoryChanged(); + } + + void onMemoryMapChanged() { + for (TCFNode n : getNodes()) ((TCFNodeExpression)n).onMemoryMapChanged(); + } + + private TCFNodeExpression findScript(String text) { + for (TCFNode n : getNodes()) { + TCFNodeExpression e = (TCFNodeExpression)n; + if (text.equals(e.getScript())) return e; + } + return null; + } + + @Override + protected boolean startDataRetrieval() { + HashMap<String,TCFNode> data = new HashMap<String,TCFNode>(); + String expression_script = null; + if (node instanceof TCFNodeExecContext) { + expression_script = ((TCFNodeExecContext)node).getHoverExpression(); + } + else if (node instanceof TCFNodeStackFrame) { + expression_script = ((TCFNodeStackFrame)node).getHoverExpression(); + } + if (expression_script != null) { + TCFNodeExpression expression_node = findScript(expression_script); + if (expression_node == null) { + add(expression_node = new TCFNodeExpression(node, expression_script, null, null, null, -1, false)); + } + data.put(expression_node.id, expression_node); + } + set(null, null, data); + return true; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenLocalVariables.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenLocalVariables.java new file mode 100644 index 000000000..2320cd4b3 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenLocalVariables.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.tm.tcf.protocol.IToken; +import org.eclipse.tm.tcf.services.IExpressions; + +public class TCFChildrenLocalVariables extends TCFChildren { + + private final TCFNodeStackFrame node; + + TCFChildrenLocalVariables(TCFNodeStackFrame node) { + super(node, 128); + this.node = node; + } + + void onSuspended() { + reset(); + for (TCFNode n : getNodes()) ((TCFNodeExpression)n).onSuspended(); + } + + void onRegisterValueChanged() { + for (TCFNode n : getNodes()) ((TCFNodeExpression)n).onRegisterValueChanged(); + } + + void onMemoryChanged() { + for (TCFNode n : getNodes()) ((TCFNodeExpression)n).onMemoryChanged(); + } + + void onMemoryMapChanged() { + reset(); + for (TCFNode n : getNodes()) ((TCFNodeExpression)n).onMemoryMapChanged(); + } + + @Override + protected boolean startDataRetrieval() { + IExpressions exps = node.model.getLaunch().getService(IExpressions.class); + if (exps == null || node.isEmulated()) { + set(null, null, new HashMap<String,TCFNode>()); + return true; + } + TCFChildrenStackTrace stack_trace_cache = ((TCFNodeExecContext)node.parent).getStackTrace(); + if (!stack_trace_cache.validate(this)) return false; // node.getFrameNo() is not valid + if (node.getFrameNo() < 0) { + set(null, null, new HashMap<String,TCFNode>()); + return true; + } + assert command == null; + command = exps.getChildren(node.id, new IExpressions.DoneGetChildren() { + public void doneGetChildren(IToken token, Exception error, String[] contexts) { + Map<String,TCFNode> data = null; + if (command == token && error == null) { + int cnt = 0; + data = new HashMap<String,TCFNode>(); + for (String id : contexts) { + TCFNodeExpression n = (TCFNodeExpression)node.model.getNode(id); + if (n == null) n = new TCFNodeExpression(node, null, null, id, null, -1, false); + assert n.id.equals(id); + assert n.parent == node; + n.setSortPosition(cnt++); + data.put(n.id, n); + } + } + set(token, error, data); + } + }); + return false; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenLogExpressions.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenLogExpressions.java new file mode 100644 index 000000000..90286a53e --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenLogExpressions.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import java.util.HashMap; +import java.util.HashSet; + +public class TCFChildrenLogExpressions extends TCFChildren { + + private final HashSet<String> scripts = new HashSet<String>(); + + TCFChildrenLogExpressions(TCFNodeExecContext node) { + super(node, 16); + } + + void onSuspended() { + for (TCFNode n : getNodes()) ((TCFNodeExpression)n).onSuspended(); + scripts.clear(); + reset(); + } + + void onRegisterValueChanged() { + for (TCFNode n : getNodes()) ((TCFNodeExpression)n).onRegisterValueChanged(); + } + + void onMemoryChanged() { + for (TCFNode n : getNodes()) ((TCFNodeExpression)n).onMemoryChanged(); + } + + void onMemoryMapChanged() { + for (TCFNode n : getNodes()) ((TCFNodeExpression)n).onMemoryMapChanged(); + } + + public TCFNodeExpression findScript(String script) { + for (TCFNode n : getNodes()) { + TCFNodeExpression e = (TCFNodeExpression)n; + if (script.equals(e.getScript())) return e; + } + return null; + } + + public void addScript(String script) { + if (scripts.add(script)) reset(); + } + + @Override + protected boolean startDataRetrieval() { + HashMap<String,TCFNode> data = new HashMap<String,TCFNode>(); + for (String script : scripts) { + TCFNodeExpression expression_node = findScript(script); + if (expression_node == null) { + add(expression_node = new TCFNodeExpression(node, script, null, null, null, -1, false)); + } + data.put(expression_node.id, expression_node); + } + set(null, null, data); + return true; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenModules.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenModules.java new file mode 100644 index 000000000..c5fd30e26 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenModules.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.tm.tcf.protocol.IToken; +import org.eclipse.tm.tcf.services.IMemoryMap; + +/** + * Provides and caches memory regions (modules) for a context. + */ +public class TCFChildrenModules extends TCFChildren { + + public TCFChildrenModules(TCFNode node) { + super(node, 128); + } + + void onMemoryMapChanged() { + reset(); + } + + @Override + protected boolean startDataRetrieval() { + assert command == null; + IMemoryMap mmap = node.model.getLaunch().getService(IMemoryMap.class); + if (mmap == null) { + set(null, null, null); + return true; + } + command = mmap.get(node.id, new IMemoryMap.DoneGet() { + public void doneGet(IToken token, Exception error, IMemoryMap.MemoryRegion[] map) { + Map<String, TCFNode> data = new HashMap<String, TCFNode>(); + if (map != null) { + for (IMemoryMap.MemoryRegion region : map) { + String id = node.id + ".Module-" + region.getFileName() + '@' + region.getAddress(); + TCFNodeModule module = (TCFNodeModule) node.model.getNode(id); + if (module == null) { + module = new TCFNodeModule(node, id, region); + } + data.put(id, module); + } + } + set(token, error, data); + } + }); + return false; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenRegisters.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenRegisters.java new file mode 100644 index 000000000..86dc0a30c --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenRegisters.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.tm.tcf.protocol.IToken; +import org.eclipse.tm.tcf.services.IRegisters; + + +public class TCFChildrenRegisters extends TCFChildren { + + TCFChildrenRegisters(TCFNode node) { + super(node, 128); + } + + void onSuspended() { + for (TCFNode n : getNodes()) ((TCFNodeRegister)n).onSuspended(); + } + + void onParentValueChanged() { + for (TCFNode n : getNodes()) ((TCFNodeRegister)n).onParentValueChanged(); + } + + void onRegistersChanged() { + for (TCFNode n : getNodes()) ((TCFNodeRegister)n).onRegistersChanged(); + reset(); + } + + @Override + void onNodeDisposed(String id) { + super.onNodeDisposed(id); + if (node instanceof TCFNodeExecContext) { + // CPU register nodes are special case: + // they have executable node as parent, + // but they are also referenced as children of stack frames + for (TCFNode n : ((TCFNodeExecContext)node).getStackTrace().getNodes()) { + ((TCFNodeStackFrame)n).getRegisters().onNodeDisposed(id); + } + } + } + + @Override + protected boolean startDataRetrieval() { + IRegisters regs = node.model.getLaunch().getService(IRegisters.class); + if (regs == null) { + set(null, null, new HashMap<String,TCFNode>()); + return true; + } + if (node instanceof TCFNodeStackFrame) { + TCFChildrenStackTrace stack_trace_cache = ((TCFNodeExecContext)node.parent).getStackTrace(); + if (!stack_trace_cache.validate(this)) return false; // node.getFrameNo() is not valid + final int frame_no = ((TCFNodeStackFrame)node).getFrameNo(); + if (frame_no < 0) { + set(null, null, new HashMap<String,TCFNode>()); + return true; + } + } + assert command == null; + command = regs.getChildren(node.id, new IRegisters.DoneGetChildren() { + public void doneGetChildren(IToken token, Exception error, String[] contexts) { + Map<String,TCFNode> data = null; + if (command == token && error == null) { + int index = 0; + data = new HashMap<String,TCFNode>(); + for (String id : contexts) { + TCFNodeRegister n = (TCFNodeRegister)node.model.getNode(id); + if (n == null) n = new TCFNodeRegister(node, id); + n.setIndex(index++); + data.put(id, n); + } + } + set(token, error, data); + } + }); + return false; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenStackTrace.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenStackTrace.java new file mode 100644 index 000000000..5ebfe41ab --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenStackTrace.java @@ -0,0 +1,161 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; +import org.eclipse.tm.tcf.protocol.IToken; +import org.eclipse.tm.tcf.services.IStackTrace; +import org.eclipse.tm.tcf.util.TCFDataCache; + + +public class TCFChildrenStackTrace extends TCFChildren { + + private final TCFNodeExecContext node; + + private String top_frame_id; + private int limit_factor = 1; + + TCFChildrenStackTrace(TCFNodeExecContext node) { + super(node, 16); + this.node = node; + } + + void onSourceMappingChange() { + for (TCFNode n : getNodes()) ((TCFNodeStackFrame)n).onSourceMappingChange(); + } + + void onExpressionAddedOrRemoved() { + for (TCFNode n : getNodes()) ((TCFNodeStackFrame)n).onExpressionAddedOrRemoved(); + } + + void onSuspended() { + limit_factor = 1; + for (TCFNode n : getNodes()) ((TCFNodeStackFrame)n).onSuspended(); + reset(); + } + + void onRegistersChanged() { + for (TCFNode n : getNodes()) ((TCFNodeStackFrame)n).onRegistersChanged(); + reset(); + } + + void onMemoryMapChanged() { + for (TCFNode n : getNodes()) ((TCFNodeStackFrame)n).onMemoryMapChanged(); + reset(); + } + + void onMemoryChanged() { + for (TCFNode n : getNodes()) ((TCFNodeStackFrame)n).onMemoryChanged(); + reset(); + } + + void onRegisterValueChanged() { + for (TCFNode n : getNodes()) ((TCFNodeStackFrame)n).onRegisterValueChanged(); + reset(); + } + + void onResumed() { + reset(null); + } + + void onPreferencesChanged() { + reset(); + } + + void riseTraceLimit() { + limit_factor++; + reset(); + } + + void postAllChangedDelta() { + for (TCFNode n : getNodes()) ((TCFNodeStackFrame)n).postAllChangedDelta(); + } + + public TCFNodeStackFrame getTopFrame() { + assert isValid(); + return (TCFNodeStackFrame)node.model.getNode(top_frame_id); + } + + @Override + public void set(IToken token, Throwable error, Map<String,TCFNode> data) { + for (TCFNode n : getNodes()) { + if (data == null || data.get(n.id) == null) ((TCFNodeStackFrame)n).setFrameNo(-1); + } + super.set(token, error, data); + } + + private void addEmulatedTopFrame(HashMap<String,TCFNode> data) { + top_frame_id = node.id + "-TF"; + TCFNodeStackFrame n = (TCFNodeStackFrame)node.model.getNode(top_frame_id); + if (n == null) n = new TCFNodeStackFrame(node, top_frame_id, true); + n.setFrameNo(0); + n.setTraceLimit(false); + data.put(n.id, n); + } + + @Override + protected boolean startDataRetrieval() { + TCFDataCache<TCFContextState> state = node.getState(); + if (!state.validate(this)) return false; + if (node.isNotActive()) { + top_frame_id = null; + set(null, null, new HashMap<String,TCFNode>()); + return true; + } + Throwable state_error = state.getError(); + TCFContextState state_data = state.getData(); + if (state_error != null || state_data == null || !state_data.is_suspended) { + set(null, state_error, null); + return true; + } + final HashMap<String,TCFNode> data = new HashMap<String,TCFNode>(); + IStackTrace st = node.model.getLaunch().getService(IStackTrace.class); + if (st == null) { + addEmulatedTopFrame(data); + set(null, null, data); + return true; + } + assert command == null; + command = st.getChildren(node.id, new IStackTrace.DoneGetChildren() { + public void doneGetChildren(IToken token, Exception error, String[] contexts) { + if (command == token) { + if (error == null && contexts != null) { + int limit_value = 0; + boolean limit_enabled = node.model.getStackFramesLimitEnabled(); + if (limit_enabled) { + limit_value = node.model.getStackFramesLimitValue() * limit_factor; + if (limit_value <= 0) limit_value = limit_factor; + } + int cnt = contexts.length; + for (String id : contexts) { + cnt--; + if (!limit_enabled || cnt <= limit_value) { + TCFNodeStackFrame n = (TCFNodeStackFrame)node.model.getNode(id); + if (n == null) n = new TCFNodeStackFrame(node, id, false); + assert n.parent == node; + n.setFrameNo(cnt); + n.setTraceLimit(limit_enabled && cnt == limit_value); + data.put(id, n); + if (cnt == 0) top_frame_id = id; + } + } + } + if (data.size() == 0) addEmulatedTopFrame(data); + } + set(token, error, data); + } + }); + return false; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenSubExpressions.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenSubExpressions.java new file mode 100644 index 000000000..993e5101c --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFChildrenSubExpressions.java @@ -0,0 +1,249 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.tm.tcf.services.IExpressions; +import org.eclipse.tm.tcf.services.ISymbols; +import org.eclipse.tm.tcf.util.TCFDataCache; + +public class TCFChildrenSubExpressions extends TCFChildren { + + private final int par_level; + private final int par_offs; + private final int par_size; + + TCFChildrenSubExpressions(TCFNode node, int par_level, int par_offs, int par_size) { + super(node, 128); + this.par_level = par_level; + this.par_offs = par_offs; + this.par_size = par_size; + } + + void onSuspended() { + reset(); + for (TCFNode n : getNodes()) { + if (n instanceof TCFNodeExpression) ((TCFNodeExpression)n).onSuspended(); + if (n instanceof TCFNodeArrayPartition) ((TCFNodeArrayPartition)n).onSuspended(); + } + } + + void onValueChanged() { + reset(); + for (TCFNode n : getNodes()) { + if (n instanceof TCFNodeExpression) ((TCFNodeExpression)n).onValueChanged(); + if (n instanceof TCFNodeArrayPartition) ((TCFNodeArrayPartition)n).onValueChanged(); + } + } + + void onRegisterValueChanged() { + reset(); + for (TCFNode n : getNodes()) { + if (n instanceof TCFNodeExpression) ((TCFNodeExpression)n).onRegisterValueChanged(); + if (n instanceof TCFNodeArrayPartition) ((TCFNodeArrayPartition)n).onRegisterValueChanged(); + } + } + + void onMemoryChanged() { + reset(); + for (TCFNode n : getNodes()) { + if (n instanceof TCFNodeExpression) ((TCFNodeExpression)n).onMemoryChanged(); + if (n instanceof TCFNodeArrayPartition) ((TCFNodeArrayPartition)n).onMemoryChanged(); + } + } + + void onMemoryMapChanged() { + reset(); + for (TCFNode n : getNodes()) { + if (n instanceof TCFNodeExpression) ((TCFNodeExpression)n).onMemoryMapChanged(); + if (n instanceof TCFNodeArrayPartition) ((TCFNodeArrayPartition)n).onMemoryMapChanged(); + } + } + + void onCastToTypeChanged() { + cancel(); + TCFNode a[] = getNodes().toArray(new TCFNode[getNodes().size()]); + for (int i = 0; i < a.length; i++) a[i].dispose(); + } + + private TCFNodeExpression findField(String field_id, boolean deref) { + assert field_id != null; + for (TCFNode n : getNodes()) { + TCFNodeExpression e = (TCFNodeExpression)n; + if (field_id.equals(e.getFieldID()) && e.isDeref() == deref) return e; + } + return null; + } + + private boolean findFields(ISymbols.Symbol type, Map<String,TCFNode> map, boolean deref) { + TCFDataCache<String[]> children_cache = node.model.getSymbolChildrenCache(type.getID()); + if (children_cache == null) return true; + if (!children_cache.validate(this)) return false; + String[] children = children_cache.getData(); + if (children == null) return true; + TCFDataCache<?> pending = null; + for (String id : children) { + TCFDataCache<ISymbols.Symbol> sym_cache = node.model.getSymbolInfoCache(id); + if (!sym_cache.validate()) { + pending = sym_cache; + } + else { + ISymbols.Symbol sym_data = sym_cache.getData(); + if (sym_data == null) continue; + if (sym_data.getSymbolClass() != ISymbols.SymbolClass.reference) continue; + if (sym_data.getName() == null) { + if (!findFields(sym_data, map, deref)) return false; + } + else { + TCFNodeExpression n = findField(id, deref); + if (n == null) add(n = new TCFNodeExpression(node, null, id, null, null, -1, deref)); + n.setSortPosition(map.size()); + map.put(n.id, n); + } + } + } + if (pending == null) return true; + pending.wait(this); + return false; + } + + private TCFNodeExpression findReg(String reg_id) { + assert reg_id != null; + for (TCFNode n : getNodes()) { + TCFNodeExpression e = (TCFNodeExpression)n; + if (reg_id.equals(e.getRegisterID())) return e; + } + return null; + } + + private boolean findRegs(TCFNodeRegister reg_node, Map<String,TCFNode> map) { + TCFChildren reg_children = reg_node.getChildren(); + if (!reg_children.validate(this)) return false; + for (TCFNode subnode : reg_children.toArray()) { + TCFNodeExpression n = findReg(subnode.id); + if (n == null) add(n = new TCFNodeExpression(node, null, null, null, subnode.id, -1, false)); + n.setSortPosition(map.size()); + map.put(n.id, n); + } + return true; + } + + private TCFNodeExpression findIndex(int index, boolean deref) { + assert index >= 0; + for (TCFNode n : getNodes()) { + TCFNodeExpression e = (TCFNodeExpression)n; + if (e.getIndex() == index && e.isDeref() == deref) return e; + } + return null; + } + + private TCFNodeArrayPartition findPartition(int offs, int size) { + assert offs >= 0; + for (TCFNode n : getNodes()) { + TCFNodeArrayPartition e = (TCFNodeArrayPartition)n; + if (e.getOffset() == offs && e.getSize() == size) return e; + } + return null; + } + + @Override + protected boolean startDataRetrieval() { + assert !isDisposed(); + TCFNode exp = node; + while (!(exp instanceof TCFNodeExpression)) exp = exp.parent; + TCFDataCache<ISymbols.Symbol> type_cache = ((TCFNodeExpression)exp).getType(); + if (!type_cache.validate(this)) return false; + ISymbols.Symbol type_data = type_cache.getData(); + if (type_data == null) { + HashMap<String,TCFNode> data = new HashMap<String,TCFNode>(); + TCFDataCache<IExpressions.Value> val_cache = ((TCFNodeExpression)exp).getValue(); + if (!val_cache.validate(this)) return false; + IExpressions.Value val_data = val_cache.getData(); + if (val_data != null) { + String reg_id = val_data.getRegisterID(); + if (reg_id != null) { + if (!node.model.createNode(reg_id, this)) return false; + if (isValid()) return true; + TCFNodeRegister reg_node = (TCFNodeRegister)node.model.getNode(reg_id); + if (!findRegs(reg_node, data)) return false; + } + } + set(null, null, data); + return true; + } + ISymbols.TypeClass type_class = type_data.getTypeClass(); + Map<String,TCFNode> data = new HashMap<String,TCFNode>(); + if (par_level > 0 && type_class != ISymbols.TypeClass.array) { + // Nothing + } + else if (type_class == ISymbols.TypeClass.composite) { + if (!findFields(type_data, data, false)) return false; + } + else if (type_class == ISymbols.TypeClass.array) { + int offs = par_level > 0 ? par_offs : 0; + int size = par_level > 0 ? par_size : type_data.getLength(); + if (size <= 100) { + for (int i = offs; i < offs + size; i++) { + TCFNodeExpression n = findIndex(i, false); + if (n == null) n = new TCFNodeExpression(node, null, null, null, null, i, false); + n.setSortPosition(i); + data.put(n.id, n); + } + } + else { + int next_size = 100; + while (size / next_size > 100) next_size *= 100; + for (int i = offs; i < offs + size; i += next_size) { + int sz = next_size; + if (i + sz > offs + size) sz = offs + size - i; + TCFNodeArrayPartition n = findPartition(i, sz); + if (n == null) n = new TCFNodeArrayPartition(node, par_level + 1, i, sz); + data.put(n.id, n); + } + } + } + else if (type_class == ISymbols.TypeClass.pointer) { + TCFDataCache<IExpressions.Value> val_cache = ((TCFNodeExpression)exp).getValue(); + if (!val_cache.validate(this)) return false; + IExpressions.Value val_data = val_cache.getData(); + if (val_data != null && !isNull(val_data.getValue())) { + TCFDataCache<ISymbols.Symbol> base_type_cache = node.model.getSymbolInfoCache(type_data.getBaseTypeID()); + if (base_type_cache != null) { + if (!base_type_cache.validate(this)) return false; + ISymbols.Symbol base_type_data = base_type_cache.getData(); + if (base_type_data != null && base_type_data.getTypeClass() != ISymbols.TypeClass.function && base_type_data.getSize() > 0) { + if (base_type_data.getTypeClass() == ISymbols.TypeClass.composite) { + if (!findFields(base_type_data, data, true)) return false; + } + else { + TCFNodeExpression n = findIndex(0, true); + if (n == null) n = new TCFNodeExpression(node, null, null, null, null, 0, true); + n.setSortPosition(0); + data.put(n.id, n); + } + } + } + } + } + set(null, null, data); + return true; + } + + private boolean isNull(byte[] data) { + if (data == null) return true; + for (byte b : data) { + if (b != 0) return false; + } + return true; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFColumnPresentationExpression.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFColumnPresentationExpression.java new file mode 100644 index 000000000..47264d233 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFColumnPresentationExpression.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; +import org.eclipse.jface.resource.ImageDescriptor; + +public class TCFColumnPresentationExpression implements IColumnPresentation { + + public static final String PRESENTATION_ID = "Expressions"; + + /** + * Presentation column IDs. + */ + public static final String + COL_NAME = "Name", + COL_TYPE = "Type", + COL_HEX_VALUE = "HexValue", + COL_DEC_VALUE = "DecValue"; + + private static String[] cols_all = { + COL_NAME, + COL_TYPE, + COL_DEC_VALUE, + COL_HEX_VALUE, + }; + + private static String[] headers = { + "Name", + "Type", + "Decimal", + "Hex", + }; + + private static String[] cols_ini = { + COL_NAME, + COL_DEC_VALUE, + COL_HEX_VALUE, + }; + + public void dispose() { + } + + public String[] getAvailableColumns() { + return cols_all; + } + + public String getHeader(String id) { + for (int i = 0; i < cols_all.length; i++) { + if (id.equals(cols_all[i])) return headers[i]; + } + return null; + } + + public String getId() { + return PRESENTATION_ID; + } + + public ImageDescriptor getImageDescriptor(String id) { + return null; + } + + public String[] getInitialColumns() { + return cols_ini; + } + + public void init(IPresentationContext context) { + } + + public boolean isOptional() { + return false; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFColumnPresentationModules.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFColumnPresentationModules.java new file mode 100644 index 000000000..43fd626ce --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFColumnPresentationModules.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; +import org.eclipse.jface.resource.ImageDescriptor; + +/** + * Column presentation for the Modules view. + */ +public class TCFColumnPresentationModules implements IColumnPresentation { + + public static final String PRESENTATION_ID = "Modules"; + + /** + * Presentation column IDs. + */ + public static final String + COL_NAME = "Name", + COL_ADDRESS = "Address", + COL_SIZE = "Size", + COL_FLAGS = "Flags", + COL_OFFSET = "Offset", + COL_SECTION = "Section"; + + private static String[] cols_all = { + COL_NAME, + COL_ADDRESS, + COL_SIZE, + COL_FLAGS, + COL_OFFSET, + COL_SECTION + }; + + private static String[] headers = { + "File Name", + "Address", + "Size", + "Flags", + "Offset", + "Section" + }; + + private static String[] cols_ini = { + COL_NAME, + COL_ADDRESS, + COL_SIZE + }; + + public void dispose() { + } + + public String[] getAvailableColumns() { + return cols_all; + } + + public String getHeader(String id) { + for (int i = 0; i < cols_all.length; i++) { + if (id.equals(cols_all[i])) return headers[i]; + } + return null; + } + + public String getId() { + return PRESENTATION_ID; + } + + public ImageDescriptor getImageDescriptor(String id) { + return null; + } + + public String[] getInitialColumns() { + return cols_ini; + } + + public void init(IPresentationContext context) { + } + + public boolean isOptional() { + return true; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFColumnPresentationRegister.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFColumnPresentationRegister.java new file mode 100644 index 000000000..929987145 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFColumnPresentationRegister.java @@ -0,0 +1,108 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; +import org.eclipse.jface.resource.ImageDescriptor; + +public class TCFColumnPresentationRegister implements IColumnPresentation { + + public static final String PRESENTATION_ID = "Registers"; + + /** + * Presentation column IDs. + */ + public static final String + COL_NAME = "Name", + COL_HEX_VALUE = "HexValue", + COL_DEC_VALUE = "DecValue", + COL_DESCRIPTION = "Description", + COL_READBLE = "Readable", + COL_READ_ONCE = "ReadOnce", + COL_WRITEABLE = "Writeable", + COL_WRITE_ONCE = "WriteOnce", + COL_SIDE_EFFECTS = "SideEffects", + COL_VOLATILE = "Volatile", + COL_FLOAT = "Float", + COL_MNEMONIC = "Menimonic"; + + private static String[] cols_all = { + COL_NAME, + COL_HEX_VALUE, + COL_DEC_VALUE, + COL_DESCRIPTION, + COL_READBLE, + COL_READ_ONCE, + COL_WRITEABLE, + COL_WRITE_ONCE, + COL_SIDE_EFFECTS, + COL_VOLATILE, + COL_FLOAT, + COL_MNEMONIC + }; + + private static String[] headers = { + "Name", + "Hex", + "Decimal", + "Description", + "Readable", + "Read Once", + "Writable", + "Write Once", + "Side Effects", + "Volatile", + "Float", + "Mnemonic" + }; + + private static String[] cols_ini = { + COL_NAME, + COL_HEX_VALUE, + COL_DEC_VALUE, + COL_DESCRIPTION, + COL_MNEMONIC + }; + + public void dispose() { + } + + public String[] getAvailableColumns() { + return cols_all; + } + + public String getHeader(String id) { + for (int i = 0; i < cols_all.length; i++) { + if (id.equals(cols_all[i])) return headers[i]; + } + return null; + } + + public String getId() { + return PRESENTATION_ID; + } + + public ImageDescriptor getImageDescriptor(String id) { + return null; + } + + public String[] getInitialColumns() { + return cols_ini; + } + + public void init(IPresentationContext context) { + } + + public boolean isOptional() { + return false; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFConsole.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFConsole.java new file mode 100644 index 000000000..225f737f7 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFConsole.java @@ -0,0 +1,197 @@ +/******************************************************************************* + * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import java.io.IOException; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.widgets.Display; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.console.ConsolePlugin; +import org.eclipse.ui.console.IConsole; +import org.eclipse.ui.console.IConsoleConstants; +import org.eclipse.ui.console.IConsoleManager; +import org.eclipse.ui.console.IConsoleView; +import org.eclipse.ui.console.IOConsole; +import org.eclipse.ui.console.IOConsoleInputStream; +import org.eclipse.ui.console.IOConsoleOutputStream; + +class TCFConsole { + private final TCFModel model; + private final IOConsole console; + private final Display display; + + private final LinkedList<Message> out_queue; + + private static class Message { + int stream_id; + byte[] data; + } + + private final Thread inp_thread = new Thread() { + public void run() { + try { + IOConsoleInputStream inp = console.getInputStream(); + final byte[] buf = new byte[0x100]; + for (;;) { + int len = inp.read(buf); + if (len < 0) break; + // TODO: Eclipse Console view has a bad habit of replacing CR with CR/LF + if (len == 2 && buf[0] == '\r' && buf[1] == '\n') len = 1; + final int n = len; + Protocol.invokeAndWait(new Runnable() { + public void run() { + try { + model.getLaunch().writeProcessInputStream(buf, 0, n); + } + catch (Exception x) { + model.onProcessStreamError(null, 0, x, 0); + } + } + }); + } + } + catch (Throwable x) { + Activator.log("Cannot read console input", x); + } + } + }; + + private final Thread out_thread = new Thread() { + public void run() { + Map<Integer,IOConsoleOutputStream> out_streams = + new HashMap<Integer,IOConsoleOutputStream>(); + try { + for (;;) { + Message m = null; + synchronized (out_queue) { + while (out_queue.size() == 0) out_queue.wait(); + m = out_queue.removeFirst(); + } + if (m.data == null) break; + IOConsoleOutputStream stream = out_streams.get(m.stream_id); + if (stream == null) { + final int id = m.stream_id; + final IOConsoleOutputStream s = stream = console.newOutputStream(); + display.syncExec(new Runnable() { + public void run() { + try { + int color_id = SWT.COLOR_BLACK; + switch (id) { + case 1: color_id = SWT.COLOR_RED; break; + case 2: color_id = SWT.COLOR_BLUE; break; + case 3: color_id = SWT.COLOR_GREEN; break; + } + s.setColor(display.getSystemColor(color_id)); + } + catch (Throwable x) { + Activator.log("Cannot open console view", x); + } + } + }); + out_streams.put(m.stream_id, stream); + } + stream.write(m.data, 0, m.data.length); + } + } + catch (Throwable x) { + Activator.log("Cannot write console output", x); + } + for (IOConsoleOutputStream stream : out_streams.values()) { + try { + stream.close(); + } + catch (IOException x) { + Activator.log("Cannot close console stream", x); + } + } + try { + console.getInputStream().close(); + } + catch (IOException x) { + Activator.log("Cannot close console stream", x); + } + try { + display.syncExec(new Runnable() { + public void run() { + IConsoleManager manager = ConsolePlugin.getDefault().getConsoleManager(); + manager.removeConsoles(new IOConsole[]{ console }); + } + }); + } + catch (SWTException x) { + if (x.code == SWT.ERROR_DEVICE_DISPOSED) return; + Activator.log("Cannot remove console", x); + } + } + }; + + TCFConsole(final TCFModel model, String process_id) { + this.model = model; + display = model.getDisplay(); + out_queue = new LinkedList<Message>(); + console = new IOConsole("TCF " + process_id, null, + ImageCache.getImageDescriptor(ImageCache.IMG_TCF), "UTF-8", true); + display.asyncExec(new Runnable() { + public void run() { + if (!PlatformUI.isWorkbenchRunning() || PlatformUI.getWorkbench().isStarting()) { + display.timerExec(200, this); + } + else if (!PlatformUI.getWorkbench().isClosing()) { + try { + IConsoleManager manager = ConsolePlugin.getDefault().getConsoleManager(); + manager.addConsoles(new IConsole[]{ console }); + IWorkbenchWindow w = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (w == null) return; + IWorkbenchPage page = w.getActivePage(); + if (page == null) return; + IConsoleView view = (IConsoleView)page.showView(IConsoleConstants.ID_CONSOLE_VIEW); + view.display(console); + } + catch (Throwable x) { + Activator.log("Cannot open console view", x); + } + } + } + }); + inp_thread.setName("TCF Launch Console Input"); + out_thread.setName("TCF Launch Console Output"); + inp_thread.start(); + out_thread.start(); + } + + void write(final int stream_id, byte[] data) { + if (data == null || data.length == 0) return; + synchronized (out_queue) { + Message m = new Message(); + m.stream_id = stream_id; + m.data = data; + out_queue.add(m); + out_queue.notify(); + } + } + + void close() { + synchronized (out_queue) { + out_queue.add(new Message()); + out_queue.notify(); + } + } +}
\ No newline at end of file diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFDebugTask.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFDebugTask.java new file mode 100644 index 000000000..4a4bf37e6 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFDebugTask.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugException; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.tcf.util.TCFTask; + +/** + * An extension of TCFTask class that adds support for throwing DebugException. + */ +public abstract class TCFDebugTask<V> extends TCFTask<V> { + + public TCFDebugTask() { + } + + public TCFDebugTask(IChannel channel) { + super(channel); + } + + public synchronized V getD() throws DebugException { + assert !Protocol.isDispatchThread(); + while (!isDone()) { + try { + wait(); + } + catch (InterruptedException x) { + throw new DebugException(new Status( + IStatus.ERROR, Activator.PLUGIN_ID, DebugException.REQUEST_FAILED, + "Debugger requiest interrupted", x)); + } + } + assert isDone(); + Throwable x = getError(); + if (x instanceof DebugException) throw (DebugException)x; + if (x != null) throw new DebugException(new Status( + IStatus.ERROR, Activator.PLUGIN_ID, DebugException.REQUEST_FAILED, + "Debugger requiest failed", x)); + return getResult(); + } + + public void error(String msg) { + error(new DebugException(new Status( + IStatus.ERROR, Activator.PLUGIN_ID, DebugException.REQUEST_FAILED, + msg, null))); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFDetailPane.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFDetailPane.java new file mode 100644 index 000000000..114ac6907 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFDetailPane.java @@ -0,0 +1,158 @@ +/******************************************************************************* + * Copyright (c) 2008, 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; + +import org.eclipse.debug.ui.IDetailPane; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.ITextPresentationListener; +import org.eclipse.jface.text.TextPresentation; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyleRange; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.ui.IWorkbenchPartSite; + +/** + * This detail pane uses a source viewer to display detailed information about the current + * selection. + */ +public class TCFDetailPane implements IDetailPane { + + public static final String ID = "org.eclipse.tm.tcf.debug.DetailPaneFactory"; + public static final String NAME = "TCF Detail Pane"; + public static final String DESC = "TCF Detail Pane"; + + private SourceViewer source_viewer; + private Display display; + private int generation; + @SuppressWarnings("unused") + private IWorkbenchPartSite part_site; + private final Document document = new Document(); + private final ArrayList<StyleRange> style_ranges = new ArrayList<StyleRange>(); + private final HashMap<RGB,Color> colors = new HashMap<RGB,Color>(); + + private final ITextPresentationListener presentation_listener = new ITextPresentationListener() { + public void applyTextPresentation(TextPresentation presentation) { + for (StyleRange r : style_ranges) presentation.addStyleRange(r); + } + }; + + public Control createControl(Composite parent) { + assert source_viewer == null; + source_viewer = new SourceViewer(parent, null, SWT.V_SCROLL | SWT.H_SCROLL); + source_viewer.configure(new SourceViewerConfiguration()); + source_viewer.setDocument(document); + source_viewer.setEditable(false); + source_viewer.addTextPresentationListener(presentation_listener); + Control control = source_viewer.getControl(); + GridData gd = new GridData(GridData.FILL_BOTH); + control.setLayoutData(gd); + display = control.getDisplay(); + return control; + } + + public void display(IStructuredSelection selection) { + if (source_viewer == null) return; + generation++; + final int g = generation; + final ArrayList<TCFNode> nodes = new ArrayList<TCFNode>(); + if (selection != null) { + Iterator<?> iterator = selection.iterator(); + while (iterator.hasNext()) { + Object next = iterator.next(); + if (next instanceof TCFNode) nodes.add((TCFNode)next); + } + } + Protocol.invokeLater(new Runnable() { + public void run() { + if (g != generation) return; + final StyledStringBuffer s = getDetailText(nodes, this); + if (s == null) return; + display.asyncExec(new Runnable() { + public void run() { + if (g != generation) return; + document.set(getStyleRanges(s)); + } + }); + } + }); + } + + private StyledStringBuffer getDetailText(ArrayList<TCFNode> nodes, Runnable done) { + StyledStringBuffer bf = new StyledStringBuffer(); + for (TCFNode n : nodes) { + if (n instanceof IDetailsProvider) { + if (!((IDetailsProvider)n).getDetailText(bf, done)) return null; + } + } + return bf; + } + + private String getStyleRanges(StyledStringBuffer s) { + style_ranges.clear(); + for (StyledStringBuffer.Style x : s.getStyle()) { + style_ranges.add(new StyleRange(x.pos, x.len, getColor(x.fg), getColor(x.bg), x.font)); + } + return s.toString(); + } + + private Color getColor(RGB rgb) { + if (rgb == null) return null; + Color c = colors.get(rgb); + if (c == null) colors.put(rgb, c = new Color(display, rgb)); + return c; + } + + public void dispose() { + for (Color c : colors.values()) c.dispose(); + colors.clear(); + if (source_viewer == null) return; + generation++; + if (source_viewer.getControl() != null) { + source_viewer.getControl().dispose(); + } + source_viewer = null; + } + + public String getDescription() { + return DESC; + } + + public String getID() { + return ID; + } + + public String getName() { + return NAME; + } + + public void init(IWorkbenchPartSite part_site) { + this.part_site = part_site; + } + + public boolean setFocus() { + if (source_viewer == null) return false; + source_viewer.getTextWidget().setFocus(); + return true; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFDetailPaneFactory.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFDetailPaneFactory.java new file mode 100644 index 000000000..e7a6d4fc5 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFDetailPaneFactory.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.debug.ui.IDetailPane; +import org.eclipse.debug.ui.IDetailPaneFactory; +import org.eclipse.jface.viewers.IStructuredSelection; + +/** + * The TCF detail pane factory is contributed to the <code>org.eclipse.debug.ui.detailPaneFactories</code> + * extension. For any selection that contains TCFNode the factory can produce a <code>IDetailPane</code> object. + */ +public class TCFDetailPaneFactory implements IDetailPaneFactory { + + public IDetailPane createDetailPane(String paneID) { + assert paneID.equals(TCFDetailPane.ID); + return new TCFDetailPane(); + } + + public String getDefaultDetailPane(IStructuredSelection selection) { + return TCFDetailPane.ID; + } + + public String getDetailPaneDescription(String paneID) { + return TCFDetailPane.NAME; + } + + public String getDetailPaneName(String paneID) { + return TCFDetailPane.DESC; + } + + @SuppressWarnings("rawtypes") + public Set getDetailPaneTypes(IStructuredSelection selection) { + HashSet<String> set = new HashSet<String>(); + set.add(TCFDetailPane.ID); + return set; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFMemoryBlockRetrieval.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFMemoryBlockRetrieval.java new file mode 100644 index 000000000..18a3f5704 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFMemoryBlockRetrieval.java @@ -0,0 +1,508 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.debug.core.DebugEvent; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.model.IDebugTarget; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.debug.core.model.IMemoryBlockExtension; +import org.eclipse.debug.core.model.IMemoryBlockRetrieval; +import org.eclipse.debug.core.model.IMemoryBlockRetrievalExtension; +import org.eclipse.debug.core.model.MemoryByte; +import org.eclipse.tm.internal.tcf.debug.model.ITCFConstants; +import org.eclipse.tm.internal.tcf.debug.model.TCFLaunch; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IToken; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.tcf.services.IExpressions; +import org.eclipse.tm.tcf.services.IMemory; +import org.eclipse.tm.tcf.services.ISymbols; +import org.eclipse.tm.tcf.services.IMemory.MemoryError; +import org.eclipse.tm.tcf.util.TCFDataCache; + +/** + * A memory block retrieval allows the user interface to request a memory block from a debugger when needed. + * TCF memory block retrieval is based on TCF Memory service. + */ +class TCFMemoryBlockRetrieval implements IMemoryBlockRetrievalExtension { + + private final TCFNodeExecContext exec_ctx; + private final HashSet<MemoryBlock> mem_blocks = new HashSet<MemoryBlock>(); + + private static class MemData { + final BigInteger addr; + final MemoryByte[] data; + final byte[] bytes; + + MemData(BigInteger addr, MemoryByte[] data) { + int i = 0; + this.addr = addr; + this.data = data; + this.bytes = new byte[data.length]; + for (MemoryByte b : data) bytes[i++] = b.getValue(); + } + } + + private class MemoryBlock extends PlatformObject implements IMemoryBlockExtension { + + private final String expression; + private final long length; + private final Set<Object> connections = new HashSet<Object>(); + private final TCFDataCache<IExpressions.Expression> remote_expression; + private final TCFDataCache<IExpressions.Value> expression_value; + private final TCFDataCache<ISymbols.Symbol> expression_type; + + private boolean disposed; + + private MemData mem_data; // current memory block data + private MemData mem_prev; // previous data - before last suspend + private MemData mem_last; // last retrieved memory block data + + MemoryBlock(final String expression, long length) { + this.expression = expression; + this.length = length; + mem_blocks.add(this); + final TCFLaunch launch = exec_ctx.model.getLaunch(); + final IChannel channel = launch.getChannel(); + remote_expression = new TCFDataCache<IExpressions.Expression>(channel) { + @Override + protected boolean startDataRetrieval() { + IExpressions exps = launch.getService(IExpressions.class); + if (exps == null) { + set(null, new Exception("Expressions service not available"), null); + return true; + } + command = exps.create(exec_ctx.id, null, expression, new IExpressions.DoneCreate() { + public void doneCreate(IToken token, Exception error, IExpressions.Expression context) { + if (disposed) { + IExpressions exps = channel.getRemoteService(IExpressions.class); + exps.dispose(context.getID(), new IExpressions.DoneDispose() { + public void doneDispose(IToken token, Exception error) { + if (error == null) return; + if (channel.getState() != IChannel.STATE_OPEN) return; + Activator.log("Error disposing remote expression evaluator", error); + } + }); + return; + } + set(token, error, context); + } + }); + return false; + } + }; + expression_value = new TCFDataCache<IExpressions.Value>(channel) { + @Override + protected boolean startDataRetrieval() { + if (!remote_expression.validate(this)) return false; + final IExpressions.Expression ctx = remote_expression.getData(); + if (ctx == null) { + set(null, null, null); + return true; + } + IExpressions exps = launch.getService(IExpressions.class); + command = exps.evaluate(ctx.getID(), new IExpressions.DoneEvaluate() { + public void doneEvaluate(IToken token, Exception error, IExpressions.Value value) { + set(token, error, value); + } + }); + return false; + } + }; + expression_type = new TCFDataCache<ISymbols.Symbol>(channel) { + @Override + protected boolean startDataRetrieval() { + if (!expression_value.validate(this)) return false; + IExpressions.Value val = expression_value.getData(); + if (val == null) { + set(null, expression_value.getError(), null); + return true; + } + TCFDataCache<ISymbols.Symbol> type_cache = exec_ctx.model.getSymbolInfoCache(val.getTypeID()); + if (type_cache == null) { + set(null, null, null); + return true; + } + if (!type_cache.validate(this)) return false; + set(null, type_cache.getError(), type_cache.getData()); + return true; + } + }; + } + + public synchronized void connect(Object client) { + connections.add(client); + } + + public synchronized void disconnect(Object client) { + connections.remove(client); + } + + public synchronized Object[] getConnections() { + return connections.toArray(new Object[connections.size()]); + } + + public void dispose() throws DebugException { + new TCFDebugTask<Boolean>(exec_ctx.getChannel()) { + public void run() { + disposed = true; + expression_value.dispose(); + expression_type.dispose(); + if (remote_expression.isValid() && remote_expression.getData() != null) { + final IChannel channel = exec_ctx.channel; + if (channel.getState() == IChannel.STATE_OPEN) { + IExpressions exps = channel.getRemoteService(IExpressions.class); + exps.dispose(remote_expression.getData().getID(), new IExpressions.DoneDispose() { + public void doneDispose(IToken token, Exception error) { + if (error == null) return; + if (channel.getState() != IChannel.STATE_OPEN) return; + Activator.log("Error disposing remote expression evaluator", error); + } + }); + } + } + remote_expression.dispose(); + mem_blocks.remove(MemoryBlock.this); + done(Boolean.TRUE); + } + }.getD(); + } + + public int getAddressSize() throws DebugException { + return new TCFDebugTask<Integer>(exec_ctx.getChannel()) { + public void run() { + if (exec_ctx.isDisposed()) { + error("Context is disposed"); + } + else { + TCFDataCache<IMemory.MemoryContext> cache = exec_ctx.getMemoryContext(); + if (!cache.validate(this)) return; + if (cache.getError() != null) { + error(cache.getError()); + } + else { + IMemory.MemoryContext mem = cache.getData(); + if (mem == null) { + error("Context does not provide memory access"); + } + else { + done(mem.getAddressSize()); + } + } + } + } + }.getD(); + } + + public int getAddressableSize() throws DebugException { + // TODO: support for addressable size other then 1 byte + return 1; + } + + public BigInteger getBigBaseAddress() throws DebugException { + return new TCFDebugTask<BigInteger>(exec_ctx.getChannel()) { + public void run() { + if (!expression_value.validate()) { + expression_value.wait(this); + } + else if (expression_value.getError() != null) { + error(expression_value.getError()); + } + else if (expression_value.getData() == null) { + error("Address expression evaluation failed"); + } + else if (!expression_type.validate()) { + expression_type.wait(this); + } + else if (expression_type.getError() != null) { + error(expression_type.getError()); + } + else { + IExpressions.Value value = expression_value.getData(); + byte[] data = value.getValue(); + if (data == null || data.length == 0) { + error("Address expression value is empty (void)"); + } + else { + ISymbols.Symbol type = expression_type.getData(); + boolean signed = type != null && type.getTypeClass() == ISymbols.TypeClass.integer; + done(TCFNumberFormat.toBigInteger(data, 0, data.length, value.isBigEndian(), signed)); + } + } + } + }.getD(); + } + + public MemoryByte[] getBytesFromAddress(final BigInteger address, final long units) throws DebugException { + return new TCFDebugTask<MemoryByte[]>(exec_ctx.getChannel()) { + int offs = 0; + public void run() { + if (mem_data != null && + address.compareTo(mem_data.addr) >= 0 && + address.add(BigInteger.valueOf(units)).compareTo( + mem_data.addr.add(BigInteger.valueOf(mem_data.data.length))) <= 0) { + offs = address.subtract(mem_data.addr).intValue(); + MemoryByte[] res = mem_data.data; + if (units < mem_data.data.length) { + res = new MemoryByte[(int)units]; + System.arraycopy(mem_data, offs, res, 0, res.length); + } + setHistoryFlags(); + done(res); + return; + } + if (exec_ctx.isDisposed()) { + error("Context is disposed"); + return; + } + TCFDataCache<IMemory.MemoryContext> cache = exec_ctx.getMemoryContext(); + if (!cache.validate(this)) return; + if (cache.getError() != null) { + error(cache.getError()); + return; + } + final IMemory.MemoryContext mem = cache.getData(); + if (mem == null) { + error("Context does not provide memory access"); + return; + } + final int size = (int)units; + final int mode = IMemory.MODE_CONTINUEONERROR | IMemory.MODE_VERIFY; + final byte[] buf = new byte[size]; + final MemoryByte[] res = new MemoryByte[size]; + mem.get(address, 1, buf, 0, size, mode, new IMemory.DoneMemory() { + public void doneMemory(IToken token, MemoryError error) { + int big_endian = 0; + if (mem.getProperties().get(IMemory.PROP_BIG_ENDIAN) != null) { + big_endian |= MemoryByte.ENDIANESS_KNOWN; + if (mem.isBigEndian()) big_endian |= MemoryByte.BIG_ENDIAN; + } + int cnt = 0; + while (offs < size) { + int flags = big_endian; + if (error instanceof IMemory.ErrorOffset) { + IMemory.ErrorOffset ofs = (IMemory.ErrorOffset)error; + int status = ofs.getStatus(cnt); + if (status == IMemory.ErrorOffset.BYTE_VALID) { + flags |= MemoryByte.READABLE | MemoryByte.WRITABLE; + } + else if ((status & IMemory.ErrorOffset.BYTE_UNKNOWN) != 0) { + if (cnt > 0) break; + } + } + else if (error == null) { + flags |= MemoryByte.READABLE | MemoryByte.WRITABLE; + } + res[offs] = new MemoryByte(buf[offs], (byte)flags); + offs++; + cnt++; + } + if (offs < size) { + mem.get(address.add(BigInteger.valueOf(offs)), 1, buf, offs, size - offs, mode, this); + } + else { + mem_last = mem_data = new MemData(address, res); + setHistoryFlags(); + done(res); + } + } + }); + } + }.getD(); + } + + private void setHistoryFlags() { + if (mem_data == null) return; + BigInteger addr = mem_data.addr; + BigInteger his_start = null; + BigInteger his_end = null; + if (mem_prev != null) { + his_start = mem_prev.addr; + his_end = mem_prev.addr.add(BigInteger.valueOf(mem_prev.data.length)); + } + for (MemoryByte b : mem_data.data) { + int flags = b.getFlags(); + if (mem_prev != null && addr.compareTo(his_start) >= 0 && addr.compareTo(his_end) < 0) { + flags |= MemoryByte.HISTORY_KNOWN; + int offs = addr.subtract(his_start).intValue(); + if (b.getValue() != mem_prev.data[offs].getValue()) { + flags |= MemoryByte.CHANGED; + } + } + else { + flags &= ~(MemoryByte.HISTORY_KNOWN | MemoryByte.CHANGED); + } + b.setFlags((byte)flags); + addr = addr.add(BigInteger.valueOf(1)); + } + } + + public MemoryByte[] getBytesFromOffset(BigInteger offset, long units) throws DebugException { + return getBytesFromAddress(getBigBaseAddress().add(offset), units); + } + + public String getExpression() { + return expression; + } + + public IMemoryBlockRetrieval getMemoryBlockRetrieval() { + return TCFMemoryBlockRetrieval.this; + } + + public long getStartAddress() { + return 0; // Unbounded + } + + public long getLength() { + return length; + } + + public BigInteger getMemoryBlockStartAddress() throws DebugException { + return null; // Unbounded + } + + public BigInteger getMemoryBlockEndAddress() throws DebugException { + return null; // Unbounded + } + + public BigInteger getBigLength() throws DebugException { + return BigInteger.valueOf(length); + } + + public void setBaseAddress(BigInteger address) throws DebugException { + } + + public void setValue(BigInteger offset, final byte[] bytes) throws DebugException { + final BigInteger address = getBigBaseAddress().add(offset); + new TCFDebugTask<Object>(exec_ctx.getChannel()) { + public void run() { + if (exec_ctx.isDisposed()) { + error("Context is disposed"); + return; + } + TCFDataCache<IMemory.MemoryContext> cache = exec_ctx.getMemoryContext(); + if (!cache.validate(this)) return; + if (cache.getError() != null) { + error(cache.getError()); + return; + } + final IMemory.MemoryContext mem = cache.getData(); + if (mem == null) { + error("Context does not provide memory access"); + return; + } + final int mode = IMemory.MODE_CONTINUEONERROR | IMemory.MODE_VERIFY; + mem.set(address, 1, bytes, 0, bytes.length, mode, new IMemory.DoneMemory() { + public void doneMemory(IToken token, MemoryError error) { + if (error != null) { + error(error); + } + else { + done(null); + } + } + }); + } + }.getD(); + } + + public boolean supportBaseAddressModification() throws DebugException { + return false; + } + + public boolean supportsChangeManagement() { + return true; + } + + public byte[] getBytes() throws DebugException { + if (mem_data == null) return null; + return mem_data.bytes; + } + + public void setValue(long offset, byte[] bytes) throws DebugException { + setValue(BigInteger.valueOf(offset), bytes); + } + + public boolean supportsValueModification() { + return true; + } + + public IDebugTarget getDebugTarget() { + return null; + } + + public ILaunch getLaunch() { + return exec_ctx.model.getLaunch(); + } + + public String getModelIdentifier() { + return ITCFConstants.ID_TCF_DEBUG_MODEL; + } + + @Override + @SuppressWarnings("rawtypes") + public Object getAdapter(Class adapter) { + if (adapter == IMemoryBlockRetrieval.class) return TCFMemoryBlockRetrieval.this; + if (adapter == IMemoryBlockRetrievalExtension.class) return TCFMemoryBlockRetrieval.this; + return super.getAdapter(adapter); + } + } + + TCFMemoryBlockRetrieval(TCFNodeExecContext exec_ctx) { + this.exec_ctx = exec_ctx; + } + + public IMemoryBlockExtension getExtendedMemoryBlock(final String expression, Object context) throws DebugException { + return new TCFDebugTask<IMemoryBlockExtension>() { + public void run() { + done(new MemoryBlock(expression, -1)); + } + }.getD(); + } + + public IMemoryBlock getMemoryBlock(final long address, final long length) throws DebugException { + return new TCFDebugTask<IMemoryBlockExtension>() { + public void run() { + done(new MemoryBlock("0x" + Long.toHexString(address), length)); + } + }.getD(); + } + + public boolean supportsStorageRetrieval() { + return true; + } + + public String getMemoryID() { + return exec_ctx.id; + } + + void onMemoryChanged(boolean suspended) { + assert Protocol.isDispatchThread(); + if (mem_blocks.size() == 0) return; + ArrayList<DebugEvent> list = new ArrayList<DebugEvent>(); + for (MemoryBlock b : mem_blocks) { + if (suspended) b.mem_prev = b.mem_last; + b.mem_data = null; + list.add(new DebugEvent(b, DebugEvent.CHANGE, DebugEvent.CONTENT)); + } + DebugPlugin.getDefault().fireDebugEventSet(list.toArray(new DebugEvent[list.size()])); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java new file mode 100644 index 000000000..1f8787bd4 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java @@ -0,0 +1,1785 @@ +/******************************************************************************* + * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial AP |