diff options
author | Uwe Stieber | 2011-11-16 08:59:51 +0000 |
---|---|---|
committer | Uwe Stieber | 2011-11-16 08:59:51 +0000 |
commit | 8706fb04b6c1417ed8d5ece83bc9fca64ddfc3ce (patch) | |
tree | 35ff2855e92a05029eb1a01455c6018c573c7175 /target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core | |
parent | 67449886c09c8ec4da4f39082373ab62ccc3d978 (diff) | |
download | org.eclipse.tcf-8706fb04b6c1417ed8d5ece83bc9fca64ddfc3ce.tar.gz org.eclipse.tcf-8706fb04b6c1417ed8d5ece83bc9fca64ddfc3ce.tar.xz org.eclipse.tcf-8706fb04b6c1417ed8d5ece83bc9fca64ddfc3ce.zip |
Target Explorer: Refactor name space from org.eclipse.tm.te.* to org.eclipse.tcf.te.*
Diffstat (limited to 'target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core')
20 files changed, 2747 insertions, 0 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/.classpath b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/.classpath new file mode 100644 index 000000000..8a8f1668c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/.options b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/.options new file mode 100644 index 000000000..01b4a8797 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/.options @@ -0,0 +1,4 @@ +org.eclipse.tcf.te.tcf.terminals.core/debugmode = 0 +org.eclipse.tcf.te.tcf.terminals.core/trace/terminalsLauncher = false +org.eclipse.tcf.te.tcf.terminals.core/trace/terminalsListener = false +org.eclipse.tcf.te.tcf.processes.core/trace/streamsListener = false diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/.project b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/.project new file mode 100644 index 000000000..78c0c754d --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.tcf.te.tcf.terminals.core</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/.settings/org.eclipse.jdt.core.prefs b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..5f9d30b9a --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,362 @@ +#Sat Oct 15 08:44:04 CEST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=warning
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=enabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=enabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=0
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=0
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=0
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=0
+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=0
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+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=true
+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=do not insert
+org.eclipse.jdt.core.formatter.comment.line_length=100
+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=4
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4
+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=4
+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=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_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=100
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true
+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
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/.settings/org.eclipse.jdt.ui.prefs b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 000000000..20cb663f8 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,4 @@ +#Sat Oct 15 08:44:04 CEST 2011
+eclipse.preferences.version=1
+formatter_profile=_Target Explorer Java STD
+formatter_settings_version=12
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/META-INF/MANIFEST.MF b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/META-INF/MANIFEST.MF new file mode 100644 index 000000000..ff3c831c4 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/META-INF/MANIFEST.MF @@ -0,0 +1,21 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.tcf.te.tcf.terminals.core;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: org.eclipse.tcf.te.tcf.terminals.core.activator.CoreBundleActivator +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.7.0", + org.eclipse.tcf.te.runtime;bundle-version="1.0.0", + org.eclipse.tcf.te.runtime.services;bundle-version="1.0.0", + org.eclipse.tcf.te.core;bundle-version="1.0.0", + org.eclipse.tcf.core;bundle-version="1.0.0", + org.eclipse.tcf.te.tcf.core;bundle-version="1.0.0" +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-ActivationPolicy: lazy +Bundle-Localization: plugin +Export-Package: org.eclipse.tcf.te.tcf.terminals.core.activator;x-internal:=true, + org.eclipse.tcf.te.tcf.terminals.core.interfaces.launcher, + org.eclipse.tcf.te.tcf.terminals.core.internal.tracing;x-internal:=true, + org.eclipse.tcf.te.tcf.terminals.core.launcher, + org.eclipse.tcf.te.tcf.terminals.core.nls;x-internal:=true diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/build.properties b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/build.properties new file mode 100644 index 000000000..f4ae97015 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/build.properties @@ -0,0 +1,5 @@ +source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.properties
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/plugin.properties b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/plugin.properties new file mode 100644 index 000000000..9969ab30d --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/plugin.properties @@ -0,0 +1,12 @@ +################################################################################## +# 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 +################################################################################## + +pluginName = Target Explorer, TCF Terminals Extensions Core +providerName = Eclipse.org diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/pom.xml b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/pom.xml new file mode 100644 index 000000000..e4d4dcb0c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/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>1.0.0-SNAPSHOT</version> + <relativePath>../../../pom.xml</relativePath> + </parent> + + <version>1.0.0.qualifier</version> + <artifactId>org.eclipse.tcf.te.tcf.terminals.core</artifactId> + <packaging>eclipse-plugin</packaging> +</project> diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/activator/CoreBundleActivator.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/activator/CoreBundleActivator.java new file mode 100644 index 000000000..3d5711ba7 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/activator/CoreBundleActivator.java @@ -0,0 +1,71 @@ +/*******************************************************************************
+ * 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.tcf.te.tcf.terminals.core.activator;
+
+import org.eclipse.tcf.te.runtime.tracing.TraceHandler;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class CoreBundleActivator implements BundleActivator {
+ // The bundle context
+ private static BundleContext context;
+ // The trace handler instance
+ private static TraceHandler traceHandler;
+
+ /**
+ * Returns the bundle context
+ *
+ * @return the bundle context
+ */
+ public static BundleContext getContext() {
+ return context;
+ }
+
+ /**
+ * Convenience method which returns the unique identifier of this plugin.
+ */
+ public static String getUniqueIdentifier() {
+ if (getContext() != null && getContext().getBundle() != null) {
+ return getContext().getBundle().getSymbolicName();
+ }
+ return null;
+ }
+
+ /**
+ * Returns the bundles trace handler.
+ *
+ * @return The bundles trace handler.
+ */
+ public static TraceHandler getTraceHandler() {
+ if (traceHandler == null) {
+ traceHandler = new TraceHandler(getUniqueIdentifier());
+ }
+ return traceHandler;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void start(BundleContext bundleContext) throws Exception {
+ CoreBundleActivator.context = bundleContext;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void stop(BundleContext bundleContext) throws Exception {
+ CoreBundleActivator.context = null;
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/interfaces/launcher/ITerminalsContextAwareListener.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/interfaces/launcher/ITerminalsContextAwareListener.java new file mode 100644 index 000000000..131104f6a --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/interfaces/launcher/ITerminalsContextAwareListener.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * 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.tcf.te.tcf.terminals.core.interfaces.launcher; + +import org.eclipse.tcf.services.ITerminals; + +/** + * Remote terminal context aware listener. + */ +public interface ITerminalsContextAwareListener { + + /** + * Sets the terminals context. + * + * @param context The terminals context. Must not be <code>null</code>. + */ + public void setTerminalsContext(ITerminals.TerminalContext context); + + /** + * Returns the terminals context. + * + * @return The terminals context. + */ + public ITerminals.TerminalContext getTerminalsContext(); +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/interfaces/launcher/ITerminalsLauncher.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/interfaces/launcher/ITerminalsLauncher.java new file mode 100644 index 000000000..7d5fc33b3 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/interfaces/launcher/ITerminalsLauncher.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * 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.tcf.te.tcf.terminals.core.interfaces.launcher; + +import java.util.Map; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.tcf.protocol.IPeer; +import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback; +import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer; + +/** + * Interface to be implemented by classes providing a remote terminals launcher. + */ +public interface ITerminalsLauncher extends IAdaptable { + + /** + * Property denoting the terminal PTY type. + * <p> + * <b>Note:</b> If not explicitly specified, the terminal type defaults to "ansi". + * <p> + * The property type is {@link String}. + */ + public static String PROP_TERMINAL_TYPE = "terminals.type"; //$NON-NLS-1$ + + /** + * Property denoting the terminal encoding. + * <p> + * The property type is {@link String}. + */ + public static String PROP_TERMINAL_ENCODING = "terminals.cwd"; //$NON-NLS-1$ + + /** + * Property denoting the terminal environment. + * <p> + * The property type is {@link Map}< {@link String}, {@link String} >. + */ + public static String PROP_TERMINAL_ENV = "terminals.env"; //$NON-NLS-1$ + + /** + * Property denoting if the terminal is redirecting it's output to an file. + * <p> + * The property type is {@link String}. + */ + public static String PROP_TERMINAL_OUTPUT_REDIRECT_TO_FILE = "terminal.redirectToFile"; //$NON-NLS-1$ + + /** + * Property denoting the full name of the connection the launcher got invoked for. + * <p> + * The property type is {@link String}. + */ + public static String PROP_CONNECTION_NAME = "connection.name"; //$NON-NLS-1$ + + /** + * Launch a remote terminal defined by the given launch properties at the target specified by the + * given peer. + * + * @param peer The peer. Must not be <code>null</code>. + * @param params The remote terminal properties. Must not be <code>null</code>. + * @param callback The callback or <code>null</code>. + */ + public void launch(IPeer peer, IPropertiesContainer properties, ICallback callback); + + /** + * Disposes the remote terminals launcher instance. + */ + public void dispose(); + + /** + * Exit the launched terminal (if still running). + */ + public void exit(); +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/internal/tracing/ITraceIds.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/internal/tracing/ITraceIds.java new file mode 100644 index 000000000..30e9e559b --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/internal/tracing/ITraceIds.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * 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.tcf.te.tcf.terminals.core.internal.tracing; + +/** + * Core plug-in trace slot identifiers. + */ +public interface ITraceIds { + + /** + * If activated, tracing information about the remote terminals launcher is printed out. + */ + public static final String TRACE_TERMINALS_LAUNCHER = "trace/terminalsLauncher"; //$NON-NLS-1$ + + /** + * If activated, tracing information about the remote terminals listener is printed out. + */ + public static final String TRACE_TERMINALS_LISTENER = "trace/terminalsListener"; //$NON-NLS-1$ + + /** + * If activated, tracing information about the remote terminals streams listener is printed out. + */ + public static final String TRACE_STREAMS_LISTENER = "trace/streamsListener"; //$NON-NLS-1$ +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsLauncher.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsLauncher.java new file mode 100644 index 000000000..bed8c1f93 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsLauncher.java @@ -0,0 +1,825 @@ +/******************************************************************************* + * 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.tcf.te.tcf.terminals.core.launcher; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.core.runtime.Status; +import org.eclipse.osgi.util.NLS; +import org.eclipse.tcf.protocol.IChannel; +import org.eclipse.tcf.protocol.IChannel.IChannelListener; +import org.eclipse.tcf.protocol.IPeer; +import org.eclipse.tcf.protocol.IToken; +import org.eclipse.tcf.protocol.Protocol; +import org.eclipse.tcf.services.IStreams; +import org.eclipse.tcf.services.ITerminals; +import org.eclipse.tcf.services.ITerminals.TerminalContext; +import org.eclipse.tcf.te.tcf.terminals.core.activator.CoreBundleActivator; +import org.eclipse.tcf.te.tcf.terminals.core.interfaces.launcher.ITerminalsContextAwareListener; +import org.eclipse.tcf.te.tcf.terminals.core.interfaces.launcher.ITerminalsLauncher; +import org.eclipse.tcf.te.tcf.terminals.core.internal.tracing.ITraceIds; +import org.eclipse.tcf.te.tcf.terminals.core.nls.Messages; +import org.eclipse.tcf.te.core.async.AsyncCallbackCollector; +import org.eclipse.tcf.te.runtime.callback.Callback; +import org.eclipse.tcf.te.runtime.events.DisposedEvent; +import org.eclipse.tcf.te.runtime.events.EventManager; +import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback; +import org.eclipse.tcf.te.runtime.interfaces.events.IEventListener; +import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer; +import org.eclipse.tcf.te.runtime.properties.PropertiesContainer; +import org.eclipse.tcf.te.runtime.services.ServiceManager; +import org.eclipse.tcf.te.runtime.services.interfaces.ITerminalService; +import org.eclipse.tcf.te.runtime.services.interfaces.constants.ITerminalsConnectorConstants; +import org.eclipse.tcf.te.tcf.core.Tcf; +import org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager; +import org.eclipse.tcf.te.tcf.core.streams.StreamsDataProvider; +import org.eclipse.tcf.te.tcf.core.streams.StreamsDataReceiver; + +/** + * Remote terminals launcher. + * <p> + * The terminals launcher is implemented fully asynchronous. + */ +public class TerminalsLauncher extends PlatformObject implements ITerminalsLauncher { + // The channel instance + /* default */ IChannel channel; + // The terminals properties instance + private IPropertiesContainer properties; + + // The terminals service instance + /* default */ ITerminals svcTerminals; + // The streams service instance + /* default */ IStreams svcStreams; + // The remote terminals context + /* default */ ITerminals.TerminalContext terminalContext; + + // The callback instance + private ICallback callback; + + // The streams listener instance + private IStreams.StreamsListener streamsListener = null; + // The terminals listener instance + private ITerminals.TerminalsListener terminalsListener = null; + // The event listener instance + private IEventListener eventListener = null; + + /** + * Constructor. + */ + public TerminalsLauncher() { + super(); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.terminals.core.interfaces.launcher.ITerminalsLauncher#dispose() + */ + @Override + public void dispose() { + // Unlink the terminal context + terminalContext = null; + + // Store a final reference to the channel instance + final IChannel finChannel = channel; + + // Remove the notification listener + if (eventListener != null) { + EventManager.getInstance().removeEventListener(eventListener); + eventListener = null; + } + + // Create the callback invocation delegate + AsyncCallbackCollector.ICallbackInvocationDelegate delegate = new AsyncCallbackCollector.ICallbackInvocationDelegate() { + @Override + public void invoke(Runnable runnable) { + Assert.isNotNull(runnable); + if (Protocol.isDispatchThread()) runnable.run(); + else Protocol.invokeLater(runnable); + } + }; + + // Create the callback collector + final AsyncCallbackCollector collector = new AsyncCallbackCollector(new Callback() { + @Override + protected void internalDone(Object caller, IStatus status) { + Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$ + // Close the channel as all disposal is done + if (finChannel != null) finChannel.close(); + } + }, delegate); + + if (streamsListener != null) { + // Dispose the streams listener + if (streamsListener instanceof TerminalsStreamsListener) { + ((TerminalsStreamsListener)streamsListener).dispose(new AsyncCallbackCollector.SimpleCollectorCallback(collector)); + } + streamsListener = null; + } + + // Dispose the terminals listener if created + if (terminalsListener != null) { + // Dispose the terminals listener + if (terminalsListener instanceof TerminalsListener) { + ((TerminalsListener)terminalsListener).dispose(new AsyncCallbackCollector.SimpleCollectorCallback(collector)); + } + terminalsListener = null; + // Remove the terminals listener from the terminals service + getSvcTerminals().removeListener(terminalsListener); + } + + // Mark the collector initialization as done + collector.initDone(); + + // Dissociate the channel + channel = null; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.terminals.core.interfaces.launcher.ITerminalsLauncher#exit() + */ + @Override + public void exit() { + Runnable runnable = new Runnable() { + @Override + public void run() { + if (terminalContext != null) { + // Exit the terminal + terminalContext.exit(new ITerminals.DoneCommand() { + @Override + public void doneCommand(IToken token, Exception error) { + onExitDone(terminalContext, error); + } + }); + } + + } + }; + + if (Protocol.isDispatchThread()) runnable.run(); + else Protocol.invokeAndWait(runnable); + } + + /** + * Check if the terminal context really exited. + * <p> + * Called from {@link #exit()}. + * + * @param context The terminal context. Must not be <code>null</code>. + * @param error The exception in case {@link #exit()} returned with an error or <code>null</code>. + */ + protected void onExitDone(ITerminals.TerminalContext context, Exception error) { + Assert.isNotNull(context); + + // If the exit of the remote terminal context failed, give a warning to the user + if (error != null) { + String message = NLS.bind(Messages.TerminalsLauncher_error_terminalExitFailed, context.getProcessID()); + message += NLS.bind(Messages.TerminalsLauncher_error_possibleCause, error.getLocalizedMessage()); + + IStatus status = new Status(IStatus.WARNING, CoreBundleActivator.getUniqueIdentifier(), message, error); + Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status); + + // Dispose the launcher directly + dispose(); + } + // No error from exit -> double-check. + else { + final ITerminals.TerminalContext finContext = context; + // Let's see if we can still get information about the context + getSvcTerminals().getContext(context.getID(), new ITerminals.DoneGetContext() { + @Override + public void doneGetContext(IToken token, Exception error, TerminalContext context) { + // In case there is no error and we do get back an terminal context, + // the terminal must be still running, having ignored the exit. + if (error == null && context != null && context.getID().equals(finContext.getID())) { + String message = NLS.bind(Messages.TerminalsLauncher_error_terminalExitFailed, context.getProcessID()); + message += Messages.TerminalsLauncher_error_possibleCauseUnknown; + + IStatus status = new Status(IStatus.WARNING, CoreBundleActivator.getUniqueIdentifier(), message, error); + Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status); + + // Dispose the launcher directly + dispose(); + } + } + }); + } + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.terminals.core.interfaces.launcher.ITerminalsLauncher#launch(org.eclipse.tcf.protocol.IPeer, org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer, org.eclipse.tcf.te.runtime.interfaces.callback.ICallback) + */ + @Override + public void launch(final IPeer peer, final IPropertiesContainer properties, final ICallback callback) { + Assert.isNotNull(peer); + Assert.isNotNull(properties); + + // Normalize the callback + if (callback == null) { + this.callback = new Callback() { + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.callback.Callback#internalDone(java.lang.Object, org.eclipse.core.runtime.IStatus) + */ + @Override + public void internalDone(Object caller, IStatus status) { + } + }; + } + else { + this.callback = callback; + } + + // Remember the terminal properties + this.properties = properties; + + // Open a channel to the given peer + Tcf.getChannelManager().openChannel(peer, new IChannelManager.DoneOpenChannel() { + /* (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.DoneOpenChannel#doneOpenChannel(java.lang.Throwable, org.eclipse.tcf.protocol.IChannel) + */ + @Override + public void doneOpenChannel(Throwable error, IChannel channel) { + if (error == null) { + TerminalsLauncher.this.channel = channel; + + // Attach a channel listener so we can dispose ourself if the channel + // is closed from the remote side. + channel.addChannelListener(new IChannelListener() { + /* (non-Javadoc) + * @see org.eclipse.tcf.protocol.IChannel.IChannelListener#onChannelOpened() + */ + @Override + public void onChannelOpened() { + } + /* (non-Javadoc) + * @see org.eclipse.tcf.protocol.IChannel.IChannelListener#onChannelClosed(java.lang.Throwable) + */ + @Override + public void onChannelClosed(Throwable error) { + if (error != null) { + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), + NLS.bind(Messages.TerminalsLauncher_error_channelConnectFailed, peer.getID(), error.getLocalizedMessage()), + error); + invokeCallback(status, null); + } + } + /* (non-Javadoc) + * @see org.eclipse.tcf.protocol.IChannel.IChannelListener#congestionLevel(int) + */ + @Override + public void congestionLevel(int level) { + } + }); + + + // Check if the channel is in connected state + if (channel.getState() != IChannel.STATE_OPEN) { + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), + Messages.TerminalsLauncher_error_channelNotConnected, + new IllegalStateException()); + invokeCallback(status, null); + return; + } + + // Get the terminals and streams services + svcTerminals = channel.getRemoteService(ITerminals.class); + if (svcTerminals == null) { + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), + NLS.bind(Messages.TerminalsLauncher_error_missingRequiredService, ITerminals.class.getName()), + null); + + invokeCallback(status, null); + return; + } + + svcStreams = channel.getRemoteService(IStreams.class); + if (svcStreams == null) { + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), + NLS.bind(Messages.TerminalsLauncher_error_missingRequiredService, IStreams.class.getName()), + null); + invokeCallback(status, null); + return; + } + + // Execute the launch now + executeLaunch(); + } else { + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), + NLS.bind(Messages.TerminalsLauncher_error_channelConnectFailed, peer.getID(), error.getLocalizedMessage()), + error); + invokeCallback(status, null); + } + } + }); + } + + /** + * Executes the launch of the remote terminal. + */ + protected void executeLaunch() { + // Get the properties container + final IPropertiesContainer properties = getProperties(); + if (properties == null) { + // This is an illegal argument. Properties must be set + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), + NLS.bind(Messages.TerminalsLauncher_error_illegalNullArgument, "properties"), //$NON-NLS-1$ + new IllegalArgumentException()); + invokeCallback(status, null); + return; + } + + // Create the streams listener + streamsListener = createStreamsListener(); + // If available, we need to subscribe to the streams. + if (streamsListener != null) { + getSvcStreams().subscribe(ITerminals.NAME, streamsListener, new IStreams.DoneSubscribe() { + @Override + public void doneSubscribe(IToken token, Exception error) { + // In case the subscribe to the stream fails, we pass on + // the error to the user and stop the launch + if (error != null) { + // Construct the error message to show to the user + String message = NLS.bind(Messages.TerminalsLauncher_error_terminalLaunchFailed, + properties.getStringProperty(ITerminalsLauncher.PROP_CONNECTION_NAME)); + message += NLS.bind(Messages.TerminalsLauncher_error_possibleCause, Messages.TerminalsLauncher_cause_subscribeFailed); + + // Construct the status object + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), message, error); + invokeCallback(status, null); + } else { + // Initialize the console or output file + onSubscribeStreamsDone(); + } + } + }); + } else { + // No streams to attach to -> go directly to the terminals launch + onAttachStreamsDone(); + } + } + + /** + * Initialize and attach the output console and/or the output file. + * <p> + * Called from {@link IStreams#subscribe(String, org.eclipse.tcf.services.IStreams.StreamsListener, org.eclipse.tcf.services.IStreams.DoneSubscribe)}. + */ + protected void onSubscribeStreamsDone() { + // Get the properties container + IPropertiesContainer properties = getProperties(); + if (properties == null) { + // This is an illegal argument. Properties must be set + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), + NLS.bind(Messages.TerminalsLauncher_error_illegalNullArgument, "properties"), //$NON-NLS-1$ + new IllegalArgumentException()); + invokeCallback(status, null); + return; + } + + // Register the notification listener to listen to the console disposal + eventListener = new TerminalsLauncherEventListener(this); + EventManager.getInstance().addEventListener(eventListener, DisposedEvent.class); + + // Get the terminal service + ITerminalService terminal = ServiceManager.getInstance().getService(ITerminalService.class); + // If not available, we cannot fulfill this request + if (terminal != null) { + // Create the terminal streams settings + PropertiesContainer props = new PropertiesContainer(); + props.setProperty(ITerminalsConnectorConstants.PROP_CONNECTOR_TYPE_ID, "org.eclipse.tcf.te.ui.terminals.type.terminals"); //$NON-NLS-1$ + props.setProperty(ITerminalsConnectorConstants.PROP_ID, "org.eclipse.tcf.te.ui.terminals.TerminalsView"); //$NON-NLS-1$ + // Set the terminal tab title + String terminalTitle = getTerminalTitle(); + if (terminalTitle != null) { + props.setProperty(ITerminalsConnectorConstants.PROP_TITLE, terminalTitle); + } + + // Create and store the streams which will be connected to the terminals stdin + props.setProperty(ITerminalsConnectorConstants.PROP_STREAMS_STDIN, connectRemoteOutputStream(getStreamsListener(), new String[] { ITerminals.PROP_STDIN_ID })); + // Create and store the streams the terminal will see as stdout + props.setProperty(ITerminalsConnectorConstants.PROP_STREAMS_STDOUT, connectRemoteInputStream(getStreamsListener(), new String[] { ITerminals.PROP_STDOUT_ID })); + // Create and store the streams the terminal will see as stderr + props.setProperty(ITerminalsConnectorConstants.PROP_STREAMS_STDERR, connectRemoteInputStream(getStreamsListener(), new String[] { ITerminals.PROP_STDERR_ID })); + + // Copy the terminal properties + props.setProperty(ITerminalsConnectorConstants.PROP_LOCAL_ECHO, properties.getBooleanProperty(ITerminalsConnectorConstants.PROP_LOCAL_ECHO)); + props.setProperty(ITerminalsConnectorConstants.PROP_LINE_SEPARATOR, properties.getStringProperty(ITerminalsConnectorConstants.PROP_LINE_SEPARATOR)); + + // The custom data object is the terminal launcher itself + props.setProperty(ITerminalsConnectorConstants.PROP_DATA, this); + + // Open the console + terminal.openConsole(props, null); + } + + // The streams got subscribed, check if we shall configure the output redirection to a file + if (properties.getStringProperty(ITerminalsLauncher.PROP_TERMINAL_OUTPUT_REDIRECT_TO_FILE) != null) { + // Get the file name where to redirect the terminal output to + String filename = properties.getStringProperty(ITerminalsLauncher.PROP_TERMINAL_OUTPUT_REDIRECT_TO_FILE); + try { + // Create the receiver instance. If the file already exist, we + // overwrite the file content. + StreamsDataReceiver receiver = new StreamsDataReceiver(new BufferedWriter(new FileWriter(filename)), + new String[] { ITerminals.PROP_STDOUT_ID, ITerminals.PROP_STDERR_ID }); + // Register the receiver to the streams listener + if (getStreamsListener() instanceof TerminalsStreamsListener) { + ((TerminalsStreamsListener)getStreamsListener()).registerDataReceiver(receiver); + } + } catch (IOException e) { + // Construct the error message to show to the user + String message = NLS.bind(Messages.TerminalsLauncher_error_terminalLaunchFailed, + properties.getStringProperty(ITerminalsLauncher.PROP_CONNECTION_NAME)); + message += NLS.bind(Messages.TerminalsLauncher_error_possibleCause, + e.getLocalizedMessage() != null ? e.getLocalizedMessage() : Messages.TerminalsLauncher_cause_ioexception); + + // Construct the status object + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), message, e); + invokeCallback(status, null); + } + } + + // Launch the terminal + onAttachStreamsDone(); + } + + /** + * Returns the terminal title string. + * <p> + * The default implementation constructs a title like "[peer name] (Start time) ". + * + * @return The terminal title string or <code>null</code>. + */ + protected String getTerminalTitle() { + if (properties == null) { + return null; + } + + StringBuilder title = new StringBuilder(); + + // Get the peer name + final AtomicReference<String> peerName = new AtomicReference<String>(getProperties().getStringProperty(ITerminalsLauncher.PROP_CONNECTION_NAME)); + if (peerName.get() == null) { + // Query the peer from the open channel + Runnable runnable = new Runnable() { + @Override + public void run() { + if (channel != null) { + peerName.set(channel.getRemotePeer().getName()); + } + } + }; + + if (Protocol.isDispatchThread()) runnable.run(); + else Protocol.invokeAndWait(runnable); + } + + if (peerName.get() != null) { + title.append("[").append(peerName.get()).append("]"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + DateFormat format = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); + String date = format.format(new Date(System.currentTimeMillis())); + title.append(" (").append(date).append(")"); //$NON-NLS-1$ //$NON-NLS-2$ + + return title.toString(); + } + + /** + * Connects the given stream id's to a local {@link InputStream} instance. + * + * @param streamsListener The streams listener. Must not be <code>null</code>. + * @param streamIds The stream id's. Must not be <code>null</code>. + * + * @return The local input stream instance or <code>null</code>. + */ + protected InputStream connectRemoteInputStream(IStreams.StreamsListener streamsListener, String[] streamIds) { + Assert.isNotNull(streamsListener); + Assert.isNotNull(streamIds); + + InputStream stream = null; + + // Create the output stream receiving the data from remote + PipedOutputStream remoteStreamDataReceiverStream = new PipedOutputStream(); + // Create the piped input stream instance + try { stream = new PipedInputStream(remoteStreamDataReceiverStream); } catch (IOException e) { /* ignored on purpose */ } + + // If the input stream creation succeeded, connect the data receiver + if (stream != null) { + StreamsDataReceiver receiver = new StreamsDataReceiver(new OutputStreamWriter(remoteStreamDataReceiverStream), streamIds); + // Register the data receiver to the streams listener + if (getStreamsListener() instanceof TerminalsStreamsListener) { + ((TerminalsStreamsListener)getStreamsListener()).registerDataReceiver(receiver); + } + } + + return stream; + } + + /** + * Connects the given stream id's to a local {@link OutputStream} instance. + * + * @param streamsListener The streams listener. Must not be <code>null</code>. + * @param streamIds The stream id's. Must not be <code>null</code>. + * + * @return The local output stream instance or <code>null</code>. + */ + protected OutputStream connectRemoteOutputStream(IStreams.StreamsListener streamsListener, String[] streamIds) { + Assert.isNotNull(streamsListener); + Assert.isNotNull(streamIds); + + PipedInputStream inStream = null; + + // Create the output stream receiving the data from local + PipedOutputStream stream = new PipedOutputStream(); + // Create the piped input stream instance + try { inStream = new PipedInputStream(stream); } catch (IOException e) { stream = null; } + + // If the stream creation succeeded, connect the data provider + if (stream != null && inStream != null) { + StreamsDataProvider provider = new StreamsDataProvider(new InputStreamReader(inStream), streamIds); + // Register the data provider to the streams listener + if (getStreamsListener() instanceof TerminalsStreamsListener) { + ((TerminalsStreamsListener)getStreamsListener()).setDataProvider(provider); + } + } + + return stream; + } + + /** + * Initiate the terminal launch. + * <p> + * Called from {@link #executeLaunch()} or {@link #onAttachStreamsDone()}. + */ + protected void onAttachStreamsDone() { + // Get the properties container + final IPropertiesContainer properties = getProperties(); + if (properties == null) { + // This is an illegal argument. Properties must be set + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), + NLS.bind(Messages.TerminalsLauncher_error_illegalNullArgument, "properties"), //$NON-NLS-1$ + new IllegalArgumentException()); + invokeCallback(status, null); + return; + } + + // Create the terminal listener + terminalsListener = createTerminalsListener(); + if (terminalsListener != null) { + getSvcTerminals().addListener(terminalsListener); + } + + // Get the terminal attributes + + // Terminal Type: Default to "ansi" if not explicitly specified + String type = properties.getStringProperty(ITerminalsLauncher.PROP_TERMINAL_TYPE); + if (type == null || "".equals(type.trim())) type = "ansi"; //$NON-NLS-1$ //$NON-NLS-2$ + + // Terminal Encoding: Default to "null" if not explicitly specified + String encoding = properties.getStringProperty(ITerminalsLauncher.PROP_TERMINAL_ENCODING); + + // Environment: Default to "null" if not explicitly specified + Map<String, String> env = (Map<String, String>)properties.getProperty(ITerminalsLauncher.PROP_TERMINAL_ENV); + + // Launch the remote terminal + getSvcTerminals().launch(type, encoding, makeEnvironmentArray(env), new ITerminals.DoneLaunch() { + @Override + public void doneLaunch(IToken token, Exception error, ITerminals.TerminalContext terminal) { + if (error != null) { + // Construct the error message to show to the user + String message = NLS.bind(Messages.TerminalsLauncher_error_terminalLaunchFailed, + properties.getStringProperty(ITerminalsLauncher.PROP_CONNECTION_NAME)); + message += NLS.bind(Messages.TerminalsLauncher_error_possibleCause, + error.getLocalizedMessage() != null ? error.getLocalizedMessage() : Messages.TerminalsLauncher_cause_startFailed); + + // Construct the status object + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), message, error); + invokeCallback(status, null); + } else { + // Register the terminal context to the listener + onTerminalLaunchDone(terminal); + } + } + }); + } + + /** + * Register the terminals context to the listeners. + * + * @param terminal The terminals context or <code>null</code>. + */ + protected void onTerminalLaunchDone(ITerminals.TerminalContext terminal) { + // Register the terminal context with the listeners + if (terminal != null) { + if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_TERMINALS_LAUNCHER)) { + CoreBundleActivator.getTraceHandler().trace("Terminal context created: id='" + terminal.getID() + "', PTY type='" + terminal.getPtyType() + "'", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + 0, ITraceIds.TRACE_TERMINALS_LAUNCHER, IStatus.INFO, getClass()); + } + + // Remember the terminal context + terminalContext = terminal; + + // Push the terminals context to the listeners + if (getStreamsListener() instanceof ITerminalsContextAwareListener) { + ((ITerminalsContextAwareListener)getStreamsListener()).setTerminalsContext(terminal); + } + if (getTerminalsListener() instanceof ITerminalsContextAwareListener) { + ((ITerminalsContextAwareListener)getTerminalsListener()).setTerminalsContext(terminal); + } + + // Send a notification + TerminalsStateChangeEvent event = createRemoteTerminalsStateChangeEvent(terminal); + if (event != null) EventManager.getInstance().fireEvent(event); + } + + // Invoke the callback to signal that we are done + invokeCallback(Status.OK_STATUS, terminal); + } + + /** + * Creates a new remote terminals state change event instance. + * + * @param context The terminals context. Must not be <code>null</code>. + * @return The event instance or <code>null</code>. + */ + protected TerminalsStateChangeEvent createRemoteTerminalsStateChangeEvent(ITerminals.TerminalContext context) { + Assert.isNotNull(context); + return new TerminalsStateChangeEvent(context, TerminalsStateChangeEvent.EVENT_TERMINAL_CREATED, Boolean.FALSE, Boolean.TRUE, -1); + } + + /** + * Invoke the callback with the given parameters. If the given status severity + * is {@link IStatus#ERROR}, the terminals launcher object is disposed automatically. + * + * @param status The status. Must not be <code>null</code>. + * @param result The result object or <code>null</code>. + */ + protected void invokeCallback(IStatus status, Object result) { + // Dispose the terminal launcher if we report an error + if (status.getSeverity() == IStatus.ERROR) { + dispose(); + } + + // Invoke the callback + ICallback callback = getCallback(); + if (callback != null) { + callback.setResult(result); + callback.done(this, status); + } + } + + /** + * Returns the channel instance. + * + * @return The channel instance or <code>null</code> if none. + */ + public final IChannel getChannel() { + return channel; + } + + /** + * Returns the terminals properties container. + * + * @return The terminals properties container or <code>null</code> if none. + */ + public final IPropertiesContainer getProperties() { + return properties; + } + + /** + * Returns the terminals service instance. + * + * @return The terminals service instance or <code>null</code> if none. + */ + public final ITerminals getSvcTerminals() { + return svcTerminals; + } + + /** + * Returns the streams service instance. + * + * @return The streams service instance or <code>null</code> if none. + */ + public final IStreams getSvcStreams() { + return svcStreams; + } + + /** + * Returns the callback instance. + * + * @return The callback instance or <code>null</code> if none. + */ + protected final ICallback getCallback() { + return callback; + } + + /** + * Create the streams listener instance. + * + * @return The streams listener instance or <code>null</code> if none. + */ + protected IStreams.StreamsListener createStreamsListener() { + return new TerminalsStreamsListener(this); + } + + /** + * Returns the streams listener instance. + * + * @return The streams listener instance or <code>null</code>. + */ + protected final IStreams.StreamsListener getStreamsListener() { + return streamsListener; + } + + /** + * Create the terminals listener instance. + * + * @return The terminals listener instance or <code>null</code> if none. + */ + protected ITerminals.TerminalsListener createTerminalsListener() { + return new TerminalsListener(this); + } + + /** + * Returns the terminals listener instance. + * + * @return The terminals listener instance or <code>null</code> if none. + */ + protected final ITerminals.TerminalsListener getTerminalsListener() { + return terminalsListener; + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.PlatformObject#getAdapter(java.lang.Class) + */ + @Override + public Object getAdapter(Class adapter) { + if (adapter.isAssignableFrom(ITerminals.TerminalsListener.class)) { + return terminalsListener; + } + else if (adapter.isAssignableFrom(IStreams.StreamsListener.class)) { + return streamsListener; + } + else if (adapter.isAssignableFrom(IStreams.class)) { + return svcStreams; + } + else if (adapter.isAssignableFrom(ITerminals.class)) { + return svcTerminals; + } + else if (adapter.isAssignableFrom(IChannel.class)) { + return channel; + } + else if (adapter.isAssignableFrom(IPropertiesContainer.class)) { + return properties; + } + else if (adapter.isAssignableFrom(ITerminals.TerminalContext.class)) { + return terminalContext; + } + else if (adapter.isAssignableFrom(this.getClass())) { + return this; + } + + + return super.getAdapter(adapter); + } + + /** + * Makes an environment array out of the given map. + * + * @param env The environment map or <code>null</code>. + * @return The string. + */ + private String[] makeEnvironmentArray(Map<String, String> env) { + if (env == null) return null; + + List<String> envList = new ArrayList<String>(); + for (String key : env.keySet()) { + String entry = key.trim() + "=" + env.get(key).trim(); //$NON-NLS-1$ + envList.add(entry); + } + + return envList.toArray(new String[envList.size()]); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsLauncherEventListener.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsLauncherEventListener.java new file mode 100644 index 000000000..b663b8a47 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsLauncherEventListener.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * 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.tcf.te.tcf.terminals.core.launcher; + +import java.util.EventObject; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.tcf.te.runtime.events.DisposedEvent; +import org.eclipse.tcf.te.runtime.interfaces.events.IEventListener; + +/** + * Remote terminals launcher default notification listener implementation. + * <p> + * <b>Note:</b> The notifications may occur in every thread! + */ +public class TerminalsLauncherEventListener extends PlatformObject implements IEventListener { + // Reference to the parent launcher + private final TerminalsLauncher parent; + + /** + * Constructor. + * + * @param parent The parent launcher. Must not be <code>null</code>. + */ + public TerminalsLauncherEventListener(TerminalsLauncher parent) { + super(); + + Assert.isNotNull(parent); + this.parent = parent; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.interfaces.events.IEventListener#eventFired(java.util.EventObject) + */ + @Override + public void eventFired(EventObject event) { + if (event instanceof DisposedEvent) { + // Get the custom data object from the disposed event + Object data = ((DisposedEvent)event).getData(); + // The custom data object must be of type TerminalsLauncher and match the parent launcher + if (data instanceof TerminalsLauncher && parent.equals(data)) { + // Terminate the remote terminal (leads to the disposal of the parent) + parent.exit(); + } + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsListener.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsListener.java new file mode 100644 index 000000000..ec70d4fda --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsListener.java @@ -0,0 +1,143 @@ +/******************************************************************************* + * 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.tcf.te.tcf.terminals.core.launcher; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.tcf.services.ITerminals; +import org.eclipse.tcf.services.ITerminals.TerminalContext; +import org.eclipse.tcf.te.tcf.terminals.core.activator.CoreBundleActivator; +import org.eclipse.tcf.te.tcf.terminals.core.interfaces.launcher.ITerminalsContextAwareListener; +import org.eclipse.tcf.te.tcf.terminals.core.internal.tracing.ITraceIds; +import org.eclipse.tcf.te.runtime.events.EventManager; +import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback; + +/** + * Remote process processes listener implementation. + */ +public class TerminalsListener implements ITerminals.TerminalsListener, ITerminalsContextAwareListener { + // The parent terminals launcher instance + private final TerminalsLauncher parent; + // The remote terminals context + private ITerminals.TerminalContext context; + // A flag to remember if exited(...) got called + private boolean exitedCalled = false; + + /** + * Constructor. + * + * @param parent The parent terminals launcher instance. Must not be <code>null</code> + */ + public TerminalsListener(TerminalsLauncher parent) { + Assert.isNotNull(parent); + this.parent = parent; + } + + /** + * Returns the parent terminals launcher instance. + * + * @return The parent terminals launcher instance. + */ + protected final TerminalsLauncher getParent() { + return parent; + } + + /** + * Dispose the terminals listener instance. + * <p> + * <b>Note:</b> The terminals listener is removed from the terminals service by the parent remote terminals launcher. + * + * @param callback The callback to invoke if the dispose finished or <code>null</code>. + */ + public void dispose(ICallback callback) { + // If exited(...) hasn't been called yet, but dispose is invoked, + // send a ... event to signal listeners that a terminated event won't come. + if (!exitedCalled && context != null) { + TerminalsStateChangeEvent event = new TerminalsStateChangeEvent(context, TerminalsStateChangeEvent.EVENT_LOST_COMMUNICATION, Boolean.FALSE, Boolean.TRUE, -1); + EventManager.getInstance().fireEvent(event); + } + // Invoke the callback + if (callback != null) callback.done(this, Status.OK_STATUS); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.terminals.core.interfaces.launcher.ITerminalsContextAwareListener#setTerminalsContext(org.eclipse.tcf.services.ITerminals.TerminalContext) + */ + @Override + public void setTerminalsContext(TerminalContext context) { + Assert.isNotNull(context); + this.context = context; + + if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_TERMINALS_LISTENER)) { + CoreBundleActivator.getTraceHandler().trace("Terminals context set to: id='" + context.getID() + "', PTY type='" + context.getPtyType() + "'", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + 0, ITraceIds.TRACE_TERMINALS_LISTENER, + IStatus.INFO, getClass()); + } + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.terminals.core.interfaces.launcher.ITerminalsContextAwareListener#getTerminalsContext() + */ + @Override + public TerminalContext getTerminalsContext() { + return context; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.services.ITerminals.TerminalsListener#exited(java.lang.String, int) + */ + @Override + public void exited(String terminalId, int exitCode) { + if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_TERMINALS_LISTENER)) { + CoreBundleActivator.getTraceHandler().trace("Terminals context terminated: id='" + terminalId + "', exitCode='" + exitCode + "'", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + 0, ITraceIds.TRACE_TERMINALS_LISTENER, + IStatus.INFO, getClass()); + } + + // If the exited terminal is the one we are monitoring, + // --> initiate the disposal of the parent remote terminal launcher + ITerminals.TerminalContext context = getTerminalsContext(); + if (context != null && terminalId != null && terminalId.equals(context.getID())) { + // Exited got called for the associated terminal context + exitedCalled = true; + // Send a notification + TerminalsStateChangeEvent event = createRemoteTerminalStateChangeEvent(context, exitCode); + EventManager.getInstance().fireEvent(event); + // Dispose the parent remote process launcher + getParent().dispose(); + } + } + + /** + * Creates a new remote terminal state change event instance. + * + * @param context The terminal context. Must not be <code>null</code>. + * @return The event instance or <code>null</code>. + */ + protected TerminalsStateChangeEvent createRemoteTerminalStateChangeEvent(ITerminals.TerminalContext context, int exitCode) { + Assert.isNotNull(context); + return new TerminalsStateChangeEvent(context, TerminalsStateChangeEvent.EVENT_TERMINAL_TERMINATED, Boolean.FALSE, Boolean.TRUE, exitCode); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.services.ITerminals.TerminalsListener#winSizeChanged(java.lang.String, int, int) + */ + @Override + public void winSizeChanged(String terminalId, int newWidth, int newHeight) { + if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_TERMINALS_LISTENER)) { + CoreBundleActivator.getTraceHandler().trace("Terminals context window size changed: id='" + terminalId + "', newWidth='" + newWidth + "', newHeight='" + newHeight + "'", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + 0, ITraceIds.TRACE_TERMINALS_LISTENER, + IStatus.INFO, getClass()); + } + + // Pass on to the terminal widget + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsStateChangeEvent.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsStateChangeEvent.java new file mode 100644 index 000000000..f95c9aadb --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsStateChangeEvent.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * 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.tcf.te.tcf.terminals.core.launcher; + +import org.eclipse.tcf.te.runtime.events.ChangeEvent; + +/** + * Remote terminals state change event implementation. + */ +public class TerminalsStateChangeEvent extends ChangeEvent { + private static final long serialVersionUID = -2119193125420935279L; + + /** + * Event id signaling if a remote terminal got created. + */ + public static final String EVENT_TERMINAL_CREATED = "created"; //$NON-NLS-1$ + + /** + * Event id signaling if a remote terminal terminated. + */ + public static final String EVENT_TERMINAL_TERMINATED = "terminated"; //$NON-NLS-1$ + + /** + * Event id signaling that the communication with the terminal got lost, probably because of a + * channel closed event. Any listener waiting for a terminal termination event should react on + * this event and stop waiting. + */ + public static final String EVENT_LOST_COMMUNICATION = "lostCommunication"; //$NON-NLS-1$ + + // Exit code of the remote process + private final int exitCode; + + /** + * Constructor. + * + * @param source The event source. Must not be <code>null</code>. + * @param eventId The event id. Must not be <code>null</code>. + * @param oldValue The old value or <code>null</code>. + * @param newValue The new value or <code>null</code>. + */ + public TerminalsStateChangeEvent(Object source, Object eventId, Object oldValue, Object newValue) { + this(source, eventId, oldValue, newValue, -1); + } + + /** + * Constructor. + * + * @param source The event source. Must not be <code>null</code>. + * @param eventId The event id. Must not be <code>null</code>. + * @param oldValue The old value or <code>null</code>. + * @param newValue The new value or <code>null</code>. + * @param exitCode The process exit code or <code>-1</code> if not applicable. + */ + public TerminalsStateChangeEvent(Object source, Object eventId, Object oldValue, Object newValue, int exitCode) { + super(source, eventId, oldValue, newValue); + this.exitCode = exitCode; + } + + /** + * Returns the remote process exit code. The exit code is only applicable if the set event id is + * {@link #EVENT_TERMINAL_TERMINATED}. + * + * @return The remote process exit code or <code>-1</code> if not applicable. + */ + public final int getExitCode() { + return exitCode; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsStreamsListener.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsStreamsListener.java new file mode 100644 index 000000000..79ac2fcab --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsStreamsListener.java @@ -0,0 +1,907 @@ +/******************************************************************************* + * 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.tcf.te.tcf.terminals.core.launcher; + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.CancellationException; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.osgi.util.NLS; +import org.eclipse.tcf.protocol.IToken; +import org.eclipse.tcf.protocol.Protocol; +import org.eclipse.tcf.services.IStreams; +import org.eclipse.tcf.services.ITerminals; +import org.eclipse.tcf.services.ITerminals.TerminalContext; +import org.eclipse.tcf.te.tcf.terminals.core.activator.CoreBundleActivator; +import org.eclipse.tcf.te.tcf.terminals.core.interfaces.launcher.ITerminalsContextAwareListener; +import org.eclipse.tcf.te.tcf.terminals.core.internal.tracing.ITraceIds; +import org.eclipse.tcf.te.tcf.terminals.core.nls.Messages; +import org.eclipse.tcf.util.TCFTask; +import org.eclipse.tcf.te.core.async.AsyncCallbackCollector; +import org.eclipse.tcf.te.runtime.callback.Callback; +import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback; +import org.eclipse.tcf.te.tcf.core.streams.StreamsDataProvider; +import org.eclipse.tcf.te.tcf.core.streams.StreamsDataReceiver; +import org.eclipse.tcf.te.tcf.core.utils.ExceptionUtils; + +/** + * Remote terminal streams listener implementation. + */ +public class TerminalsStreamsListener implements IStreams.StreamsListener, ITerminalsContextAwareListener { + // The parent terminals launcher instance + private final TerminalsLauncher parent; + // The remote terminal context + private ITerminals.TerminalContext context; + // The list of registered stream data receivers + private final List<StreamsDataReceiver> dataReceiver = new ArrayList<StreamsDataReceiver>(); + // The stream data provider + private StreamsDataProvider dataProvider; + // The list of delayed stream created events + private final List<StreamCreatedEvent> delayedCreatedEvents = new ArrayList<StreamCreatedEvent>(); + // The list of created runnable's + private final List<Runnable> runnables = new ArrayList<Runnable>(); + + /** + * Immutable stream created event. + */ + private final static class StreamCreatedEvent { + /** + * The stream type. + */ + public final String streamType; + /** + * The stream id. + */ + public final String streamId; + /** + * The context id. + */ + public final String contextId; + + // As the class is immutable, we do not need to build the toString + // value again and again. Build it once in the constructor and reuse it later. + private final String toString; + + /** + * Constructor. + * + * @param streamType The stream type. + * @param streamId The stream id. + * @param contextId The context id. + */ + public StreamCreatedEvent(String streamType, String streamId, String contextId) { + this.streamType = streamType; + this.streamId = streamId; + this.contextId = contextId; + + toString = toString(); + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + return obj instanceof StreamCreatedEvent + && toString().equals(((StreamCreatedEvent)obj).toString()); + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return toString().hashCode(); + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + if (toString != null) return toString; + + StringBuilder builder = new StringBuilder(getClass().getSimpleName()); + builder.append(": streamType = "); //$NON-NLS-1$ + builder.append(streamType); + builder.append("; streamId = "); //$NON-NLS-1$ + builder.append(streamId); + builder.append("; contextId = "); //$NON-NLS-1$ + builder.append(contextId); + + return builder.toString(); + } + } + + /** + * Remote stream reader runnable implementation. + * <p> + * The runnable will be executed within a thread and is responsible to read the + * incoming data from the associated stream and forward them to the registered receivers. + */ + protected class StreamReaderRunnable implements Runnable { + // The associated stream id + private final String streamId; + // The associated stream type id + private final String streamTypeId; + // The list of receivers applicable for the associated stream type id + private final List<StreamsDataReceiver> receivers = new ArrayList<StreamsDataReceiver>(); + // The currently active read task + private TCFTask<ReadData> activeTask; + // The callback to invoke if the runnable stopped + private ICallback callback; + + // Flag to stop the runnable + private boolean stopped = false; + + /** + * Immutable class describing the result returned by {@link StreamReaderRunnable#read(IStreams, String, int)}. + */ + protected class ReadData { + /** + * The number of lost bytes in case of a buffer overflow. If <code>-1</code>, + * an unknown number of bytes were lost. If non-zero and <code>data.length</code> is + * non-zero, the lost bytes are considered located right before the read bytes. + */ + public final int lostBytes; + /** + * The read data as byte array. + */ + public final byte[] data; + /** + * Flag to signal if the end of the stream has been reached. + */ + public final boolean eos; + + /** + * Constructor. + */ + public ReadData(int lostBytes, byte[] data, boolean eos) { + this.lostBytes = lostBytes; + this.data = data; + this.eos = eos; + } + } + + /** + * Constructor. + * + * @param streamId The associated stream id. Must not be <code>null</code>. + * @param streamTypeId The associated stream type id. Must not be <code>null</code>. + * @param receivers The list of registered data receivers. Must not be <code>null</code>. + */ + public StreamReaderRunnable(String streamId, String streamTypeId, StreamsDataReceiver[] receivers) { + Assert.isNotNull(streamId); + Assert.isNotNull(streamTypeId); + Assert.isNotNull(receivers); + + this.streamId = streamId; + this.streamTypeId = streamTypeId; + + // Loop the list of receivers and filter out the applicable ones + for (StreamsDataReceiver receiver : receivers) { + if (receiver.isApplicable(this.streamTypeId)) + this.receivers.add(receiver); + } + } + + /** + * Returns the associated stream id. + * + * @return The associated stream id. + */ + public final String getStreamId() { + return streamId; + } + + /** + * Returns if or if not the list of applicable receivers is empty. + * + * @return <code>True</code> if the list of applicable receivers is empty, <code>false</code> otherwise. + */ + public final boolean isEmpty() { + return receivers.isEmpty(); + } + + /** + * Stop the runnable. + * + * @param callback The callback to invoke if the runnable stopped. + */ + public final synchronized void stop(ICallback callback) { + // If the runnable is stopped already, invoke the callback directly + if (stopped) { + if (callback != null) callback.done(this, Status.OK_STATUS); + return; + } + + // Store the callback instance + this.callback = callback; + // Mark the runnable as stopped + stopped = true; + } + + /** + * Returns if the runnable should stop. + */ + protected final synchronized boolean isStopped() { + return stopped; + } + + /** + * Sets the currently active reader task. + * + * @param task The currently active reader task or <code>null</code>. + */ + protected final synchronized void setActiveTask(TCFTask<ReadData> task) { + activeTask = task; + } + + /** + * Returns the currently active reader task. + * + * @return The currently active reader task or <code>null</code>. + */ + protected final TCFTask<ReadData> getActiveTask() { + return activeTask; + } + + /** + * Returns the callback instance to invoke. + * + * @return The callback instance or <code>null</code>. + */ + protected final ICallback getCallback() { + return callback; + } + + /* (non-Javadoc) + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + // Create a snapshot of the receivers + final StreamsDataReceiver[] receivers = this.receivers.toArray(new StreamsDataReceiver[this.receivers.size()]); + // Get the service instance from the parent + final IStreams svcStreams = getParent().getSvcStreams(); + + // Run until stopped and the streams service is available + while (!isStopped() && svcStreams != null) { + try { + ReadData streamData = read(svcStreams, streamId, 1024); + if (streamData != null) { + // Check if the received data contains some stream data + if (streamData.data != null) { + // Notify the data receivers about the new received data + notifyReceiver(new String(streamData.data), receivers); + } + // If the end of the stream have been reached --> break out + if (streamData.eos) break; + } + } catch (Exception e) { + // An error occurred -> Dump to the error log + e = ExceptionUtils.checkAndUnwrapException(e); + // Check if the blocking read task got canceled + if (!(e instanceof CancellationException)) { + // Log the error to the user, might be something serious + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), + NLS.bind(Messages.TerminalsStreamReaderRunnable_error_readFailed, streamId, e.getLocalizedMessage()), + e); + Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status); + } + // break out of the loop + break; + } + } + + // Disconnect from the stream + if (svcStreams != null) { + svcStreams.disconnect(streamId, new IStreams.DoneDisconnect() { + @Override + @SuppressWarnings("synthetic-access") + public void doneDisconnect(IToken token, Exception error) { + // Disconnect is done, ignore any error, invoke the callback + synchronized (this) { + if (getCallback() != null) getCallback().done(this, Status.OK_STATUS); + } + // Mark the runnable definitely stopped + stopped = true; + } + }); + } else { + // Invoke the callback directly, if any + synchronized (this) { + if (callback != null) callback.done(this, Status.OK_STATUS); + } + // Mark the runnable definitely stopped + stopped = true; + } + } + + /** + * Reads data from the stream and blocks until some data has been received. + * + * @param service The streams service. Must not be <code>null</code>. + * @param streamId The stream id. Must not be <code>null</code>. + * @param size The size of the data to read. + * + * @return The read data. + * + * @throws Exception In case the read fails. + */ + protected final ReadData read(final IStreams service, final String streamId, final int size) throws Exception { + Assert.isNotNull(service); + Assert.isNotNull(streamId); + Assert.isTrue(!Protocol.isDispatchThread()); + + // Create the task object + TCFTask<ReadData> task = new TCFTask<ReadData>(getParent().getChannel()) { + @Override + public void run() { + service.read(streamId, size, new IStreams.DoneRead() { + /* (non-Javadoc) + * @see org.eclipse.tcf.services.IStreams.DoneRead#doneRead(org.eclipse.tcf.protocol.IToken, java.lang.Exception, int, byte[], boolean) + */ + @Override + public void doneRead(IToken token, Exception error, int lostSize, byte[] data, boolean eos) { + if (error == null) done(new ReadData(lostSize, data, eos)); + else error(error); + } + }); + } + }; + + // Push the task object to the runnable instance + setActiveTask(task); + + // Block until some data is received + return task.get(); + } + + /** + * Notify the data receiver that some data has been received. + * + * @param data The data or <code>null</code>. + */ + protected final void notifyReceiver(final String data, final StreamsDataReceiver[] receivers) { + if (data == null) return; + // Notify the data receiver + for (StreamsDataReceiver receiver : receivers) { + try { + // Get the writer + Writer writer = receiver.getWriter(); + // Append the data + writer.append(data); + // And flush it + writer.flush(); + } catch (IOException e) { + if (CoreBundleActivator.getTraceHandler().isSlotEnabled(1, null)) { + IStatus status = new Status(IStatus.WARNING, CoreBundleActivator.getUniqueIdentifier(), + NLS.bind(Messages.TerminalsStreamReaderRunnable_error_appendFailed, streamId, data), + e); + Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status); + } + } + } + } + } + + /** + * Remote stream writer runnable implementation. + * <p> + * The runnable will be executed within a thread and is responsible to read the + * incoming data from the registered providers and forward them to the associated stream. + */ + protected class StreamWriterRunnable implements Runnable { + // The associated stream id + /* default */ final String streamId; + // The associated stream type id + @SuppressWarnings("unused") + private final String streamTypeId; + // The data provider applicable for the associated stream type id + private final StreamsDataProvider provider; + // The currently active write task + private TCFTask<Object> activeTask; + // The callback to invoke if the runnable stopped + private ICallback callback; + + // Flag to stop the runnable + private boolean stopped = false; + + /** + * Constructor. + * + * @param streamId The associated stream id. Must not be <code>null</code>. + * @param streamTypeId The associated stream type id. Must not be <code>null</code>. + * @param provider The data provider. Must not be <code>null</code> and must be applicable for the stream type. + */ + public StreamWriterRunnable(String streamId, String streamTypeId, StreamsDataProvider provider) { + Assert.isNotNull(streamId); + Assert.isNotNull(streamTypeId); + Assert.isNotNull(provider); + Assert.isTrue(provider.isApplicable(streamTypeId)); + + this.streamId = streamId; + this.streamTypeId = streamTypeId; + this.provider = provider; + } + + /** + * Returns the associated stream id. + * + * @return The associated stream id. + */ + public final String getStreamId() { + return streamId; + } + + /** + * Stop the runnable. + * + * @param callback The callback to invoke if the runnable stopped. + */ + public final synchronized void stop(ICallback callback) { + // If the runnable is stopped already, invoke the callback directly + if (stopped) { + if (callback != null) callback.done(this, Status.OK_STATUS); + return; + } + + // Store the callback instance + this.callback = callback; + // Mark the runnable as stopped + stopped = true; + } + + /** + * Returns if the runnable should stop. + */ + protected final synchronized boolean isStopped() { + return stopped; + } + + /** + * Sets the currently active writer task. + * + * @param task The currently active writer task or <code>null</code>. + */ + protected final synchronized void setActiveTask(TCFTask<Object> task) { + activeTask = task; + } + + /** + * Returns the currently active writer task. + * + * @return The currently active writer task or <code>null</code>. + */ + protected final TCFTask<Object> getActiveTask() { + return activeTask; + } + + /** + * Returns the callback instance to invoke. + * + * @return The callback instance or <code>null</code>. + */ + protected final ICallback getCallback() { + return callback; + } + + /* (non-Javadoc) + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + // If not data provider is set, we are done here immediately + if (provider == null) { + // Invoke the callback directly, if any + synchronized (this) { + if (callback != null) callback.done(this, Status.OK_STATUS); + } + // Mark the runnable definitely stopped + stopped = true; + + return; + } + + // Get the service instance from the parent + final IStreams svcStreams = getParent().getSvcStreams(); + + // Create the data buffer instance + final char[] buffer = new char[1024]; + + // Run until stopped and the streams service is available + while (!isStopped() && svcStreams != null) { + try { + // Read available data from the data provider + int charactersRead = provider.getReader().read(buffer, 0, 1024); + // Have we reached the end of the stream -> break out + if (charactersRead == -1) break; + // If we read some data from the provider, write it to the stream + if (charactersRead > 0) write(svcStreams, streamId, new String(buffer).getBytes(), charactersRead); + } catch (Exception e) { + // An error occurred -> Dump to the error log + e = ExceptionUtils.checkAndUnwrapException(e); + // Check if the blocking read task got canceled + if (!(e instanceof CancellationException)) { + // Log the error to the user, might be something serious + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), + NLS.bind(Messages.TerminalsStreamWriterRunnable_error_writeFailed, streamId, e.getLocalizedMessage()), + e); + Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status); + } + // break out of the loop + break; + } + } + + // Disconnect from the stream + if (svcStreams != null) { + // Write EOS first + svcStreams.eos(streamId, new IStreams.DoneEOS() { + @Override + public void doneEOS(IToken token, Exception error) { + // Disconnect now + svcStreams.disconnect(streamId, new IStreams.DoneDisconnect() { + @Override + @SuppressWarnings("synthetic-access") + public void doneDisconnect(IToken token, Exception error) { + // Disconnect is done, ignore any error, invoke the callback + synchronized (this) { + if (getCallback() != null) getCallback().done(this, Status.OK_STATUS); + } + // Mark the runnable definitely stopped + stopped = true; + } + }); + } + }); + } else { + // Invoke the callback directly, if any + synchronized (this) { + if (callback != null) callback.done(this, Status.OK_STATUS); + } + // Mark the runnable definitely stopped + stopped = true; + } + } + + /** + * Writes data to the stream. + * + * @param service The streams service. Must not be <code>null</code>. + * @param streamId The stream id. Must not be <code>null</code>. + * @param data The data buffer. Must not be <code>null</code>. + * @param size The size of the data to write. + * + * @throws Exception In case the write fails. + */ + protected final void write(final IStreams service, final String streamId, final byte[] data, final int size) throws Exception { + Assert.isNotNull(service); + Assert.isNotNull(streamId); + Assert.isTrue(!Protocol.isDispatchThread()); + + // Create the task object + TCFTask<Object> task = new TCFTask<Object>() { + @Override + public void run() { + service.write(streamId, data, 0, size, new IStreams.DoneWrite() { + /* (non-Javadoc) + * @see org.eclipse.tcf.services.IStreams.DoneWrite#doneWrite(org.eclipse.tcf.protocol.IToken, java.lang.Exception) + */ + @Override + public void doneWrite(IToken token, Exception error) { + if (error == null) done(null); + else error(error); + } + }); + } + }; + task.get(); + + // Push the task object to the runnable instance + setActiveTask(task); + + // Execute the write + task.get(); + } + } + + /** + * Constructor. + * + * @param parent The parent terminals launcher instance. Must not be <code>null</code> + */ + public TerminalsStreamsListener(TerminalsLauncher parent) { + Assert.isNotNull(parent); + this.parent = parent; + } + + /** + * Returns the parent terminals launcher instance. + * + * @return The parent terminals launcher instance. + */ + protected final TerminalsLauncher getParent() { + return parent; + } + + /** + * Dispose the streams listener instance. + * + * @param callback The callback to invoke if the dispose finished or <code>null</code>. + */ + public void dispose(final ICallback callback) { + // Store a final reference to the streams listener instance + final IStreams.StreamsListener finStreamsListener = this; + + // Store a final reference to the data receivers list + final List<StreamsDataReceiver> finDataReceivers; + synchronized (dataReceiver) { + finDataReceivers = new ArrayList<StreamsDataReceiver>(dataReceiver); + dataReceiver.clear(); + } + + // Create the callback invocation delegate + AsyncCallbackCollector.ICallbackInvocationDelegate delegate = new AsyncCallbackCollector.ICallbackInvocationDelegate() { + @Override + public void invoke(Runnable runnable) { + Assert.isNotNull(runnable); + if (Protocol.isDispatchThread()) runnable.run(); + else Protocol.invokeLater(runnable); + } + }; + + // Create a new collector to catch all runnable stop callback's + AsyncCallbackCollector collector = new AsyncCallbackCollector(new Callback() { + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.callback.Callback#internalDone(java.lang.Object, org.eclipse.core.runtime.IStatus) + */ + @Override + protected void internalDone(final Object caller, final IStatus status) { + Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$ + // Get the service instance from the parent + IStreams svcStreams = getParent().getSvcStreams(); + // Unsubscribe the streams listener from the service + svcStreams.unsubscribe(ITerminals.NAME, finStreamsListener, new IStreams.DoneUnsubscribe() { + @Override + public void doneUnsubscribe(IToken token, Exception error) { + // Loop all registered listeners and close them + for (StreamsDataReceiver receiver : finDataReceivers) receiver.dispose(); + // Call the original outer callback + if (callback != null) callback.done(caller, status); + } + }); + } + }, delegate); + + // Loop all runnable's and force them to stop + synchronized (runnables) { + for (Runnable runnable : runnables) { + if (runnable instanceof StreamReaderRunnable) { + ((StreamReaderRunnable)runnable).stop(new AsyncCallbackCollector.SimpleCollectorCallback(collector)); + } + } + runnables.clear(); + } + + // Mark the collector initialization done + collector.initDone(); + } + + /** + * Adds the given receiver to the stream data receiver list. + * + * @param receiver The data receiver. Must not be <code>null</code>. + */ + public void registerDataReceiver(StreamsDataReceiver receiver) { + Assert.isNotNull(receiver); + synchronized (dataReceiver) { + if (!dataReceiver.contains(receiver)) dataReceiver.add(receiver); + } + } + + /** + * Removes the given receiver from the stream data receiver list. + * + * @param receiver The data receiver. Must not be <code>null</code>. + */ + public void unregisterDataReceiver(StreamsDataReceiver receiver) { + Assert.isNotNull(receiver); + synchronized (dataReceiver) { + dataReceiver.remove(receiver); + } + } + + /** + * Sets the stream data provider instance. + * + * @param provider The stream data provider instance or <code>null</code>. + */ + public void setDataProvider(StreamsDataProvider provider) { + dataProvider = provider; + } + + /** + * Returns the stream data provider instance. + * + * @return The stream data provider instance or <code>null</code>. + */ + public StreamsDataProvider getDataProvider() { + return dataProvider; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.terminals.core.interfaces.launcher.ITerminalsContextAwareListener#setTerminalsContext(org.eclipse.tcf.services.ITerminals.TerminalContext) + */ + @Override + public void setTerminalsContext(TerminalContext context) { + Assert.isNotNull(context); + this.context = context; + + if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER)) { + CoreBundleActivator.getTraceHandler().trace("Terminals context set to: id='" + context.getID() + "', PTY type='" + context.getPtyType() + "'", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + 0, ITraceIds.TRACE_STREAMS_LISTENER, + IStatus.INFO, getClass()); + } + + // Loop all delayed create events and look for the streams for our context + synchronized (delayedCreatedEvents) { + Iterator<StreamCreatedEvent> iterator = delayedCreatedEvents.iterator(); + while (iterator.hasNext()) { + StreamCreatedEvent event = iterator.next(); + if (context.getID().equals(event.contextId) || context.getProcessID().equals(event.contextId) || event.contextId == null) { + // Re-dispatch the event + created(event.streamType, event.streamId, event.contextId); + } + } + // Clear all events + delayedCreatedEvents.clear(); + } + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.terminals.core.interfaces.launcher.ITerminalsContextAwareListener#getTerminalsContext() + */ + @Override + public TerminalContext getTerminalsContext() { + return context; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.services.IStreams.StreamsListener#created(java.lang.String, java.lang.String, java.lang.String) + */ + @Override + public void created(String streamType, String streamId, String contextId) { + // We ignore any other stream type than ITerminals.NAME + if (!ITerminals.NAME.equals(streamType)) return; + + if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER)) { + CoreBundleActivator.getTraceHandler().trace("New remote terminals stream created: streamId='" + streamId + "', contextId='" + contextId + "'", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + 0, ITraceIds.TRACE_STREAMS_LISTENER, + IStatus.INFO, getClass()); + } + + // If a terminals context is set, check if the created event is for the + // monitored terminals context + final ITerminals.TerminalContext context = getTerminalsContext(); + // The contextId is null if used with an older TCF agent not sending the third parameter + // + // 2011-10-18: Since the unification of terminals and processes service, the + // context id of the streams events is the process context id, not + // the terminal context id as before. So check for both here to support + // both the older and the newer version of the terminals service. + if (context != null && (context.getID().equals(contextId) || context.getProcessID().equals(contextId) || contextId == null)) { + // Create a snapshot of the registered data receivers + StreamsDataReceiver[] receivers; + synchronized (dataReceiver) { + receivers = dataReceiver.toArray(new StreamsDataReceiver[dataReceiver.size()]); + } + // The created event is for the monitored terminals context + // --> Create the stream reader thread(s) + if (streamId != null && streamId.equals(context.getProperties().get(ITerminals.PROP_STDIN_ID))) { + // Data provider set? + if (dataProvider != null) { + // Create the stdin stream writer runnable + StreamWriterRunnable runnable = new StreamWriterRunnable(streamId, ITerminals.PROP_STDIN_ID, dataProvider); + // Add to the list of created runnable's + synchronized (runnables) { runnables.add(runnable); } + // And create and start the thread + Thread thread = new Thread(runnable, "Thread-" + ITerminals.PROP_STDIN_ID + "-" + streamId); //$NON-NLS-1$ //$NON-NLS-2$ + thread.start(); + } + } + if (streamId != null && streamId.equals(context.getProperties().get(ITerminals.PROP_STDOUT_ID))) { + // Create the stdout stream reader runnable + StreamReaderRunnable runnable = new StreamReaderRunnable(streamId, ITerminals.PROP_STDOUT_ID, receivers); + // If not empty, create the thread + if (!runnable.isEmpty()) { + // Add to the list of created runnable's + synchronized (runnables) { runnables.add(runnable); } + // And create and start the thread + Thread thread = new Thread(runnable, "Thread-" + ITerminals.PROP_STDOUT_ID + "-" + streamId); //$NON-NLS-1$ //$NON-NLS-2$ + thread.start(); + } + } + if (streamId != null && streamId.equals(context.getProperties().get(ITerminals.PROP_STDERR_ID))) { + // Create the stdout stream reader runnable + StreamReaderRunnable runnable = new StreamReaderRunnable(streamId, ITerminals.PROP_STDERR_ID, receivers); + // If not empty, create the thread + if (!runnable.isEmpty()) { + // Add to the list of created runnable's + synchronized (runnables) { runnables.add(runnable); } + // And create and start the thread + Thread thread = new Thread(runnable, "Thread-" + ITerminals.PROP_STDERR_ID + "-" + streamId); //$NON-NLS-1$ //$NON-NLS-2$ + thread.start(); + } + } + } else if (context == null) { + // Context not set yet --> add to the delayed list + StreamCreatedEvent event = new StreamCreatedEvent(streamType, streamId, contextId); + synchronized (delayedCreatedEvents) { + if (!delayedCreatedEvents.contains(event)) delayedCreatedEvents.add(event); + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.services.IStreams.StreamsListener#disposed(java.lang.String, java.lang.String) + */ + @Override + public void disposed(String streamType, String streamId) { + // We ignore any other stream type than ITerminals.NAME + if (!ITerminals.NAME.equals(streamType)) return; + + if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER)) { + CoreBundleActivator.getTraceHandler().trace("Remote terminals stream disposed: streamId='" + streamId + "'", //$NON-NLS-1$ //$NON-NLS-2$ + 0, ITraceIds.TRACE_STREAMS_LISTENER, + IStatus.INFO, getClass()); + } + + // If the delayed created events list is not empty, we have + // to check if one of the delayed create events got disposed + synchronized (delayedCreatedEvents) { + Iterator<StreamCreatedEvent> iterator = delayedCreatedEvents.iterator(); + while (iterator.hasNext()) { + StreamCreatedEvent event = iterator.next(); + if (event.streamType != null && event.streamType.equals(streamType) + && event.streamId != null && event.streamId.equals(streamId)) { + // Remove the create event from the list + iterator.remove(); + } + } + } + + // Stop the thread(s) if the disposed event is for the active + // monitored stream id(s). + synchronized (runnables) { + Iterator<Runnable> iterator = runnables.iterator(); + while (iterator.hasNext()) { + Runnable runnable = iterator.next(); + if (runnable instanceof StreamReaderRunnable) { + StreamReaderRunnable myRunnable = (StreamReaderRunnable)runnable; + if (myRunnable.getStreamId().equals(streamId)) { + // This method is called within the TCF event dispatch thread, so + // we cannot wait for a callback here + myRunnable.stop(null); + iterator.remove(); + } + } + } + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/nls/Messages.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/nls/Messages.java new file mode 100644 index 000000000..55e16741c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/nls/Messages.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * 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.tcf.te.tcf.terminals.core.nls; + +import org.eclipse.osgi.util.NLS; + +/** + * Target Explorer TCF terminals extensions core plug-in externalized strings management. + */ +public class Messages extends NLS { + + // The plug-in resource bundle name + private static final String BUNDLE_NAME = "org.eclipse.tcf.te.tcf.terminals.core.nls.Messages"; //$NON-NLS-1$ + + /** + * Static constructor. + */ + static { + // Load message values from bundle file + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + // **** Declare externalized string id's down here ***** + + public static String TerminalsLauncher_error_channelConnectFailed; + public static String TerminalsLauncher_error_channelNotConnected; + public static String TerminalsLauncher_error_missingProcessPath; + public static String TerminalsLauncher_error_missingRequiredService; + public static String TerminalsLauncher_error_illegalNullArgument; + public static String TerminalsLauncher_error_terminalLaunchFailed; + public static String TerminalsLauncher_error_terminalExitFailed; + public static String TerminalsLauncher_error_possibleCause; + public static String TerminalsLauncher_error_possibleCauseUnknown; + public static String TerminalsLauncher_cause_subscribeFailed; + public static String TerminalsLauncher_cause_startFailed; + public static String TerminalsLauncher_cause_ioexception; + + public static String TerminalsStreamReaderRunnable_error_readFailed; + public static String TerminalsStreamWriterRunnable_error_writeFailed; + public static String TerminalsStreamReaderRunnable_error_appendFailed; +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/nls/Messages.properties b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/nls/Messages.properties new file mode 100644 index 000000000..23a7994c4 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/nls/Messages.properties @@ -0,0 +1,20 @@ +# +# org.eclipse.tcf.te.tcf.terminals.core +# Externalized Strings. +# + +TerminalsLauncher_error_channelConnectFailed=Failed to connect channel for peer ''{0}''.\n\nPossible Cause:\n{1} +TerminalsLauncher_error_channelNotConnected=Channel is not connected! +TerminalsLauncher_error_missingRequiredService=Failed to get required service: {0}! +TerminalsLauncher_error_illegalNullArgument=Illegal argument: ''{0}'' has to be not null. +TerminalsLauncher_error_terminalLaunchFailed=Failed to launch remote terminal.\n\Peer: {0} +TerminalsLauncher_error_terminalExitFailed=Failed to exit remote terminal.\n\nTerminal process id: {0} +TerminalsLauncher_error_possibleCause=\n\nPossible Cause:\n{0} +TerminalsLauncher_error_possibleCauseUnknown=\n\nPossible Cause:\nTerminal did not exit for unknown reasons. +TerminalsLauncher_cause_subscribeFailed=Failed to subscribe to the remote terminal streams service. +TerminalsLauncher_cause_startFailed=Failed to start remote terminal. +TerminalsLauncher_cause_ioexception=An IOException occurred. + +TerminalsStreamReaderRunnable_error_readFailed=Failed to read data from stream with id ''{0}''.\n\nPossible Cause:\n{1} +TerminalsStreamWriterRunnable_error_writeFailed=Failed to write data to stream with id ''{0}''.\n\nPossible Cause:\n{1} +TerminalsStreamReaderRunnable_error_appendFailed=Failed to append data from stream with id ''{0}'' to data receiver.\n\nLost data:\n{1}. |