Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'target_explorer/plugins/org.eclipse.tcf.te.tcf.locator')
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/.classpath7
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/.options5
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/.project39
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/.settings/org.eclipse.jdt.core.prefs362
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/.settings/org.eclipse.jdt.ui.prefs4
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/META-INF/MANIFEST.MF30
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/build.properties6
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/plugin.properties12
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/plugin.xml44
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/pom.xml17
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/Scanner.java158
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/ScannerRunnable.java186
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/activator/CoreBundleActivator.java73
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/IModelListener.java42
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/IScanner.java49
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/ITracing.java32
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/nodes/ILocatorModel.java116
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/nodes/IPeerModel.java41
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/nodes/IPeerModelProperties.java79
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/preferences/IPreferenceKeys.java39
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/services/ILocatorModelLookupService.java44
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/services/ILocatorModelRefreshService.java23
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/services/ILocatorModelService.java27
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/services/ILocatorModelUpdateService.java47
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/MyPropertyTester.java92
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/PeersPersistenceDelegate.java122
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/adapters/AdapterFactory.java57
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/adapters/MapPersistableAdapter.java136
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/adapters/PeerModelPersistableAdapter.java96
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/nls/Messages.java73
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/nls/Messages.properties6
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/preferences/PreferencesInitializer.java43
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/listener/ChannelStateChangeListener.java84
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/listener/LocatorListener.java123
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/listener/ModelAdapter.java42
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/nodes/LocatorModel.java438
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/nodes/PeerModel.java275
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/AbstractLocatorModelService.java42
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelLookupService.java126
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelRefreshService.java272
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelUpdateService.java114
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/utils/IPAddressUtil.java403
42 files changed, 4026 insertions, 0 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/.classpath b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/.classpath
new file mode 100644
index 000000000..8a8f1668c
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/.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.locator/.options b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/.options
new file mode 100644
index 000000000..be04c242d
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/.options
@@ -0,0 +1,5 @@
+org.eclipse.tcf.te.tcf.locator/debugmode = 0
+
+org.eclipse.tcf.te.tcf.locator/trace/locatorModel = false
+org.eclipse.tcf.te.tcf.locator/trace/locatorListener = false
+org.eclipse.tcf.te.tcf.locator/trace/channelStateChangeListener = false
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/.project b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/.project
new file mode 100644
index 000000000..6fdbad2f7
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/.project
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.tcf.te.tcf.locator</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+ <filteredResources>
+ <filter>
+ <id>1311579482946</id>
+ <name></name>
+ <type>10</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-target</arguments>
+ </matcher>
+ </filter>
+ </filteredResources>
+</projectDescription>
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/.settings/org.eclipse.jdt.core.prefs b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..579e3b099
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,362 @@
+#Fri Oct 07 16:14:10 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.locator/.settings/org.eclipse.jdt.ui.prefs b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 000000000..974541bce
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,4 @@
+#Fri Oct 07 16:14:10 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.locator/META-INF/MANIFEST.MF b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..90a07ee1b
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/META-INF/MANIFEST.MF
@@ -0,0 +1,30 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.tcf.te.tcf.locator; singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.eclipse.tcf.te.tcf.locator.activator.CoreBundleActivator
+Bundle-Vendor: %providerName
+Require-Bundle: org.eclipse.core.runtime;bundle-version="3.7.0",
+ org.eclipse.core.expressions;bundle-version="3.4.300",
+ org.eclipse.tcf.core;bundle-version="1.0.0",
+ org.eclipse.tcf.te.tcf.core;bundle-version="1.0.0",
+ org.eclipse.tcf.te.runtime;bundle-version="1.0.0",
+ org.eclipse.tcf.te.runtime.persistence;bundle-version="1.0.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ActivationPolicy: lazy
+Bundle-Localization: plugin
+Export-Package: org.eclipse.tcf.te.tcf.locator,
+ org.eclipse.tcf.te.tcf.locator.activator;x-internal:=true,
+ org.eclipse.tcf.te.tcf.locator.interfaces,
+ org.eclipse.tcf.te.tcf.locator.interfaces.nodes,
+ org.eclipse.tcf.te.tcf.locator.interfaces.preferences,
+ org.eclipse.tcf.te.tcf.locator.interfaces.services,
+ org.eclipse.tcf.te.tcf.locator.internal;x-internal:=true,
+ org.eclipse.tcf.te.tcf.locator.internal.adapters;x-internal:=true,
+ org.eclipse.tcf.te.tcf.locator.internal.nls;x-internal:=true,
+ org.eclipse.tcf.te.tcf.locator.internal.preferences;x-internal:=true,
+ org.eclipse.tcf.te.tcf.locator.listener,
+ org.eclipse.tcf.te.tcf.locator.nodes,
+ org.eclipse.tcf.te.tcf.locator.services,
+ org.eclipse.tcf.te.tcf.locator.utils
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/build.properties b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/build.properties
new file mode 100644
index 000000000..30b2fc40b
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/build.properties
@@ -0,0 +1,6 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.properties,\
+ plugin.xml
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/plugin.properties b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/plugin.properties
new file mode 100644
index 000000000..9e5336314
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/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 Locator Extensions
+providerName = Eclipse.org
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/plugin.xml b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/plugin.xml
new file mode 100644
index 000000000..86b397d2c
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/plugin.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+
+<!-- Preference contributions -->
+ <extension point="org.eclipse.core.runtime.preferences">
+ <initializer
+ class="org.eclipse.tcf.te.tcf.locator.internal.preferences.PreferencesInitializer"/>
+ </extension>
+
+<!-- Eclipse core expressions property tester -->
+ <extension point="org.eclipse.core.expressions.propertyTesters">
+ <propertyTester
+ class="org.eclipse.tcf.te.tcf.locator.internal.MyPropertyTester"
+ id="org.eclipse.tcf.te.tcf.locator.LocatorModelPropertyTester"
+ namespace="org.eclipse.tcf.te.tcf.locator"
+ properties="name,hasLocalService,hasRemoteService,isStaticPeer"
+ type="org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel">
+ </propertyTester>
+ </extension>
+
+<!-- Persistence delegate contributions -->
+ <extension point="org.eclipse.tcf.te.runtime.persistence.delegates">
+ <delegate
+ id="org.eclipse.tcf.te.tcf.locator.persistence"
+ class="org.eclipse.tcf.te.tcf.locator.internal.PeersPersistenceDelegate">
+ </delegate>
+ </extension>
+
+<!-- Adapter factory contributions -->
+ <extension point="org.eclipse.core.runtime.adapters">
+ <factory
+ adaptableType="java.util.Map"
+ class="org.eclipse.tcf.te.tcf.locator.internal.adapters.AdapterFactory">
+ <adapter type="org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistable"/>
+ </factory>
+
+ <factory
+ adaptableType="org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel"
+ class="org.eclipse.tcf.te.tcf.locator.internal.adapters.AdapterFactory">
+ <adapter type="org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistable"/>
+ </factory>
+ </extension>
+</plugin>
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/pom.xml b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/pom.xml
new file mode 100644
index 000000000..894615620
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/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.locator</artifactId>
+ <packaging>eclipse-plugin</packaging>
+</project>
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/Scanner.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/Scanner.java
new file mode 100644
index 000000000..112808ea8
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/Scanner.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * 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.locator;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.te.tcf.locator.interfaces.IScanner;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+
+
+/**
+ * Locator model scanner implementation.
+ */
+public class Scanner extends Job implements IScanner {
+ // Reference to the parent model instance.
+ private final ILocatorModel parentModel;
+
+ // Reference to the scanner configuration
+ private final Map<String, Object> configuration = new HashMap<String, Object>();
+
+ // Flag to mark if the scanner is terminated
+ private AtomicBoolean terminated = new AtomicBoolean(false);
+
+ /**
+ * Constructor.
+ *
+ * @param parentModel The parent model instance. Must not be <code>null</code>.
+ */
+ public Scanner(ILocatorModel parentModel) {
+ super(Scanner.class.getName());
+ Assert.isNotNull(parentModel);
+ this.parentModel = parentModel;
+ }
+
+ /**
+ * Returns the parent model instance.
+ *
+ * @return The parent model instance.
+ */
+ protected ILocatorModel getParentModel() {
+ return parentModel;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.IScanner#setConfiguration(java.util.Map)
+ */
+ @Override
+ public void setConfiguration(Map<String, Object> configuration) {
+ Assert.isNotNull(configuration);
+ this.configuration.clear();
+ this.configuration.putAll(configuration);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.IScanner#getConfiguration()
+ */
+ @Override
+ public Map<String, Object> getConfiguration() {
+ return configuration;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ if (monitor == null) monitor = new NullProgressMonitor();
+
+ // Get the current list of peers known to the parent model
+ IPeerModel[] peers = getParentModel().getPeers();
+ // Do we have something to scan at all
+ if (peers.length > 0) {
+ // The first runnable is setting the thread which will finish
+ // the job at the end
+ Protocol.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ Scanner.this.setThread(Thread.currentThread());
+ }
+ });
+ // Loop the nodes and try to get an channel
+ for (IPeerModel peer : peers) {
+ // Check for the progress monitor getting canceled
+ if (monitor.isCanceled() || isTerminated()) break;
+ // Create the scanner runnable
+ Runnable runnable = new ScannerRunnable(this, peer);
+ // Submit for execution
+ Protocol.invokeLater(runnable);
+ }
+ // The last runnable will terminate the job as soon all
+ // scanner runnable's are processed and will reschedule the job
+ final IStatus result = monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS;
+ Protocol.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ Scanner.this.done(result);
+
+ Long delay = (Long)getConfiguration().get(IScanner.PROP_SCHEDULE);
+ if (delay != null) {
+ Scanner.this.schedule(delay.longValue());
+ }
+ }
+ });
+ }
+
+ return peers.length > 0 ? ASYNC_FINISH : Status.OK_STATUS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.IScanner#terminate()
+ */
+ @Override
+ public void terminate() {
+ terminated.set(true);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.IScanner#isTerminated()
+ */
+ @Override
+ public final boolean isTerminated() {
+ return terminated.get();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.jobs.Job#shouldRun()
+ */
+ @Override
+ public boolean shouldRun() {
+ return Platform.isRunning() && !getParentModel().isDisposed() && !isTerminated();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.jobs.Job#shouldSchedule()
+ */
+ @Override
+ public boolean shouldSchedule() {
+ return Platform.isRunning() && !getParentModel().isDisposed() && !isTerminated();
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/ScannerRunnable.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/ScannerRunnable.java
new file mode 100644
index 000000000..b004a70ef
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/ScannerRunnable.java
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * 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.locator;
+
+import java.net.SocketTimeoutException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.tcf.core.ChannelTCP;
+import org.eclipse.tcf.protocol.IChannel;
+import org.eclipse.tcf.protocol.IPeer;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.services.ILocator;
+import org.eclipse.tcf.te.tcf.locator.interfaces.IScanner;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModelProperties;
+import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelLookupService;
+import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelUpdateService;
+import org.eclipse.tcf.te.tcf.locator.nodes.PeerModel;
+
+
+/**
+ * Scanner runnable to be executed for each peer to probe within the
+ * TCF event dispatch thread.
+ */
+public class ScannerRunnable implements Runnable, IChannel.IChannelListener {
+ /**
+ * The default socket connect timeout in milliseconds.
+ */
+ private static final int DEFAULT_SOCKET_CONNECT_TIMEOUT = 10000;
+
+ // Reference to the parent model scanner
+ private final IScanner parentScanner;
+ // Reference to the peer model node to update
+ private final IPeerModel peerNode;
+ // Reference to the channel
+ private IChannel channel = null;
+
+ /**
+ * Constructor.
+ *
+ * @param scanner The parent model scanner or <code>null</code> if the runnable is constructed from outside a scanner.
+ * @param peerNode The peer model instance. Must not be <code>null</code>.
+ */
+ public ScannerRunnable(IScanner scanner, IPeerModel peerNode) {
+ super();
+
+ parentScanner = scanner;
+
+ Assert.isNotNull(peerNode);
+ this.peerNode = peerNode;
+ }
+
+ /**
+ * Returns the parent scanner instance.
+ *
+ * @return The parent scanner instance or <code>null</code>.
+ */
+ protected final IScanner getParentScanner() {
+ return parentScanner;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Runnable#run()
+ */
+ @Override
+ public void run() {
+ if (peerNode != null && peerNode.getPeer() != null) {
+ // Open the channel
+ channel = peerNode.getPeer().openChannel();
+ // Configure the connect timeout
+ if (channel instanceof ChannelTCP) {
+ int timeout = peerNode.getIntProperty(IPeerModelProperties.PROP_CONNECT_TIMEOUT);
+ if (timeout == -1) timeout = DEFAULT_SOCKET_CONNECT_TIMEOUT;
+ ((ChannelTCP)channel).setConnectTimeout(timeout);
+ }
+ // Add ourself as channel listener
+ channel.addChannelListener(this);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.protocol.IChannel.IChannelListener#onChannelOpened()
+ */
+ @Override
+ public void onChannelOpened() {
+ // Peer is reachable
+ if (channel != null) {
+ // Remove ourself as channel listener
+ channel.removeChannelListener(this);
+ }
+
+ // Set the peer state property
+ if (peerNode != null) {
+ int counter = peerNode.getIntProperty(IPeerModelProperties.PROP_CHANNEL_REF_COUNTER);
+ peerNode.setProperty(IPeerModelProperties.PROP_STATE, counter > 0 ? IPeerModelProperties.STATE_CONNECTED : IPeerModelProperties.STATE_REACHABLE);
+ peerNode.setProperty(IPeerModelProperties.PROP_LAST_SCANNER_ERROR, null);
+ }
+
+ if (channel != null && channel.getState() == IChannel.STATE_OPEN) {
+ // Get the parent model from the model mode
+ final ILocatorModel model = (ILocatorModel)peerNode.getAdapter(ILocatorModel.class);
+ if (model != null) {
+ // Get the local service
+ Collection<String> localServices = new ArrayList<String>(channel.getLocalServices());
+ // Get the remote services
+ Collection<String> remoteServices = new ArrayList<String>(channel.getRemoteServices());
+
+ // Get the update service
+ ILocatorModelUpdateService updateService = model.getService(ILocatorModelUpdateService.class);
+ if (updateService != null) {
+ // Update the services nodes
+ updateService.updatePeerServices(peerNode, localServices, remoteServices);
+ }
+
+ // Use the open channel to ask the remote peer what other
+ // peers it knows
+ ILocator locator = channel.getRemoteService(ILocator.class);
+ if (locator != null) {
+ final Map<String, IPeer> peers = locator.getPeers();
+ if (peers != null && !peers.isEmpty()) {
+ // Execute asynchronously within the TCF dispatch thread
+ Protocol.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ for (String peerId : peers.keySet()) {
+ // Try to find an existing peer node first
+ IPeerModel peerNode = model.getService(ILocatorModelLookupService.class).lkupPeerModelById(peerId);
+ if (peerNode == null) peerNode = new PeerModel(model, peers.get(peerId));
+ // Add the peer node to model
+ model.getService(ILocatorModelUpdateService.class).add(peerNode);
+ // And schedule for immediate status update
+ Runnable runnable = new ScannerRunnable(getParentScanner(), peerNode);
+ Protocol.invokeLater(runnable);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ // And close the channel
+ channel.close();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.protocol.IChannel.IChannelListener#onChannelClosed(java.lang.Throwable)
+ */
+ @Override
+ public void onChannelClosed(Throwable error) {
+ // Peer is not reachable
+
+ if (channel != null) {
+ // Remove ourself as channel listener
+ channel.removeChannelListener(this);
+ }
+
+ // Set the peer state property, if the scanner the runnable
+ // has been scheduled from is still active.
+ if (peerNode != null && (parentScanner == null || parentScanner != null && !parentScanner.isTerminated())) {
+ peerNode.setProperty(IPeerModelProperties.PROP_CHANNEL_REF_COUNTER, null);
+ peerNode.setProperty(IPeerModelProperties.PROP_STATE,
+ error instanceof SocketTimeoutException ? IPeerModelProperties.STATE_NOT_REACHABLE : IPeerModelProperties.STATE_ERROR);
+ peerNode.setProperty(IPeerModelProperties.PROP_LAST_SCANNER_ERROR, error instanceof SocketTimeoutException ? null : error);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.protocol.IChannel.IChannelListener#congestionLevel(int)
+ */
+ @Override
+ public void congestionLevel(int level) {
+ }
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/activator/CoreBundleActivator.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/activator/CoreBundleActivator.java
new file mode 100644
index 000000000..8f1ad4dd6
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/activator/CoreBundleActivator.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * 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.locator.activator;
+
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.tcf.te.runtime.tracing.TraceHandler;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class CoreBundleActivator extends Plugin {
+ // The shared instance
+ private static CoreBundleActivator plugin;
+ // The trace handler instance
+ private static TraceHandler traceHandler;
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static CoreBundleActivator getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Convenience method which returns the unique identifier of this plugin.
+ */
+ public static String getUniqueIdentifier() {
+ if (getDefault() != null && getDefault().getBundle() != null) {
+ return getDefault().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.eclipse.core.runtime.Plugin#start(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/IModelListener.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/IModelListener.java
new file mode 100644
index 000000000..779b62aa1
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/IModelListener.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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.locator.interfaces;
+
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+
+/**
+ * Interface for clients to implement that wishes to listen
+ * to changes to the locator model.
+ */
+public interface IModelListener {
+
+ /**
+ * Invoked if a peer is added or removed to/from the locator model.
+ *
+ * @param model The changed locator model.
+ */
+ public void locatorModelChanged(ILocatorModel model);
+
+ /**
+ * Invoked if the locator model is disposed.
+ *
+ * @param model The disposed locator model.
+ */
+ public void locatorModelDisposed(ILocatorModel model);
+
+ /**
+ * Invoked if the peer model properties have changed.
+ *
+ * @param model The parent locator model.
+ * @param peer The changed peer model.
+ */
+ public void peerModelChanged(ILocatorModel model, IPeerModel peer);
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/IScanner.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/IScanner.java
new file mode 100644
index 000000000..784dbedd5
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/IScanner.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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.locator.interfaces;
+
+import java.util.Map;
+
+/**
+ * Locator model scanner.
+ */
+public interface IScanner {
+
+ /**
+ * Scanner configuration property: The time in millisecond between the scanner runs.
+ */
+ public static String PROP_SCHEDULE = "schedule"; //$NON-NLS-1$
+
+ /**
+ * Set or modify the current scanner configuration.
+ *
+ * @param configuration The new scanner configuration. Must not be <code>null</code>.
+ */
+ public void setConfiguration(Map<String, Object> configuration);
+
+ /**
+ * Returns the current scanner configuration.
+ *
+ * @return The current scanner configuration.
+ */
+ public Map<String, Object> getConfiguration();
+
+ /**
+ * Terminate the scanner.
+ */
+ public void terminate();
+
+ /**
+ * Returns if or if not the discovery model scanner has been terminated.
+ *
+ * @return <code>True</code> if the discovery model scanner is terminated, <code>false</code> if still active.
+ */
+ public boolean isTerminated();
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/ITracing.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/ITracing.java
new file mode 100644
index 000000000..7dcb93e83
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/ITracing.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.locator.interfaces;
+
+/**
+ * TCF locator bundle tracing identifiers.
+ */
+public interface ITracing {
+
+
+ /**
+ * If enabled, prints information about locator model method invocations.
+ */
+ public static String ID_TRACE_LOCATOR_MODEL = "trace/locatorModel"; //$NON-NLS-1$
+
+ /**
+ * If enabled, prints information about locator listener method invocations.
+ */
+ public static String ID_TRACE_LOCATOR_LISTENER = "trace/locatorListener"; //$NON-NLS-1$
+
+ /**
+ * If enabled, prints information about channel state change listener method invocations.
+ */
+ public static String ID_TRACE_CHANNEL_STATE_CHANGE_LISTENER = "trace/channelStateChangeListener"; //$NON-NLS-1$
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/nodes/ILocatorModel.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/nodes/ILocatorModel.java
new file mode 100644
index 000000000..cb4818985
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/nodes/ILocatorModel.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * 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.locator.interfaces.nodes;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.tcf.services.ILocator;
+import org.eclipse.tcf.te.tcf.locator.interfaces.IModelListener;
+import org.eclipse.tcf.te.tcf.locator.interfaces.IScanner;
+import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelService;
+
+
+/**
+ * The locator model is an extension to the TCF locator service. The
+ * model allows to store additional properties for each peer, keep
+ * track of peers from different origins.
+ * <p>
+ * <b>Note:</b> Updates to the locator model, and the locator model
+ * children needs to be performed in the TCF dispatch thread. The
+ * locator model and all child model nodes do assert this core
+ * assumption. To maintain consistency, and to avoid any performance
+ * overhead for thread synchronization, the model read access must
+ * happen in the TCF dispatch thread as well.
+ *
+ * @see ILocator
+ */
+public interface ILocatorModel extends IAdaptable {
+
+ /**
+ * Adds the specified listener to the list of model listener.
+ * If the same listener has been added before, the listener will
+ * not be added again.
+ *
+ * @param listener The listener. Must not be <code>null</code>.
+ */
+ public void addListener(IModelListener listener);
+
+ /**
+ * Removes the specified listener from the list of model listener.
+ *
+ * @param listener The listener. Must not be <code>null</code>.
+ */
+ public void removeListener(IModelListener listener);
+
+ /**
+ * Returns the list of registered model listeners.
+ *
+ * @return The list of registered model listeners or an empty list.
+ */
+ public IModelListener[] getListener();
+
+ /**
+ * Dispose the locator model instance.
+ */
+ public void dispose();
+
+ /**
+ * Returns if or if not the locator model instance is disposed.
+ *
+ * @return <code>True</code> if the locator model instance is disposed, <code>false/code> otherwise.
+ */
+ public boolean isDisposed();
+
+ /**
+ * Returns the list of known peers.
+ *
+ * @return The list of known peers or an empty list.
+ */
+ public IPeerModel[] getPeers();
+
+ /**
+ * Returns the scanner instance being associated with the
+ * locator model.
+ *
+ * @return The scanner instance.
+ */
+ public IScanner getScanner();
+
+ /**
+ * Starts the scanner.
+ *
+ * @param delay The delay in millisecond before the scanning starts.
+ * @param schedule The time in millisecond between the scanner runs.
+ */
+ public void startScanner(long delay, long schedule);
+
+ /**
+ * Stops the scanner.
+ */
+ public void stopScanner();
+
+ /**
+ * Returns the locator model service, implementing at least the specified
+ * service interface.
+ *
+ * @param serviceInterface The service interface class. Must not be <code>null</code>.
+ * @return The service instance implementing the specified service interface, or <code>null</code>.
+ */
+ public <V extends ILocatorModelService> V getService(Class<V> serviceInterface);
+
+ /**
+ * Validate the given peer model if or if not it can be added
+ * to the locator model as new peer node.
+ *
+ * @param node The peer model. Must not be <code>null</code>.
+ * @return The peer node if it allowed add it to the model, or <code>null</code> if not.
+ */
+ public IPeerModel validatePeerNodeForAdd(IPeerModel node);
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/nodes/IPeerModel.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/nodes/IPeerModel.java
new file mode 100644
index 000000000..5146c21ab
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/nodes/IPeerModel.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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.locator.interfaces.nodes;
+
+import org.eclipse.tcf.protocol.IPeer;
+import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer;
+
+/**
+ * The peer model is an extension to the TCF target/host representation, implementing the
+ * {@link IPeer} interface. The peer model provides an offline cache for a peers known list of local
+ * and remote services and is the merge point of peer attributes from custom data storages.
+ * <p>
+ * <b>Note:</b> The {@link #getProperty(String)} method provides access both the native peer
+ * attributes and to the custom attributes. Alternatively, the native peer attributes can be access
+ * via <i><code>getPeer().getAttributes()</code></i>.
+ * <p>
+ * <b>Note:</b> Read and write access to the peer model must happen within the TCF dispatch thread.
+ */
+public interface IPeerModel extends IPropertiesContainer {
+
+ /**
+ * Returns the parent locator model instance.
+ *
+ * @return The parent locator model instance.
+ */
+ public ILocatorModel getModel();
+
+ /**
+ * Returns the native {@link IPeer} object.
+ *
+ * @return The native {@link IPeer} instance.
+ */
+ public IPeer getPeer();
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/nodes/IPeerModelProperties.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/nodes/IPeerModelProperties.java
new file mode 100644
index 000000000..cb1ce57d4
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/nodes/IPeerModelProperties.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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.locator.interfaces.nodes;
+
+import org.eclipse.tcf.protocol.IPeer;
+
+/**
+ * Default set of custom peer properties.
+ */
+public interface IPeerModelProperties {
+
+ /**
+ * Property: The peer instance. Object stored here must be
+ * castable to {@link IPeer}.
+ */
+ public static final String PROP_INSTANCE = "instance"; //$NON-NLS-1$
+
+ /**
+ * Property: The list of known local service names.
+ */
+ public static final String PROP_LOCAL_SERVICES = "services.local"; //$NON-NLS-1$
+
+ /**
+ * Property: The list of known remote service names.
+ */
+ public static final String PROP_REMOTE_SERVICES = "services.remote"; //$NON-NLS-1$
+
+ /**
+ * Property: The peer state.
+ */
+ public static String PROP_STATE = "state"; //$NON-NLS-1$
+
+ /**
+ * Peer state: Not determined yet (unknown).
+ */
+ public static int STATE_UNKNOWN = -1;
+
+ /**
+ * Peer state: Peer is reachable, no active communication channel is open.
+ */
+ public static int STATE_REACHABLE = 0;
+
+ /**
+ * Peer state: Peer is reachable and an active communication channel is opened.
+ */
+ public static int STATE_CONNECTED = 1;
+
+ /**
+ * Peer state: Peer is not reachable. Connection attempt timed out.
+ */
+ public static int STATE_NOT_REACHABLE = 2;
+
+ /**
+ * Peer state: Peer is not reachable. Connection attempt terminated with error.
+ */
+ public static int STATE_ERROR = 3;
+
+ /**
+ * Property: The peer connect timeout (for socket based transports)
+ */
+ public static String PROP_CONNECT_TIMEOUT = "connectTimeout"; //$NON-NLS-1$
+
+ /**
+ * Property: Reference counter tracking the active channels for this peer.
+ */
+ public static String PROP_CHANNEL_REF_COUNTER = "channelRefCounter.silent"; //$NON-NLS-1$
+
+ /**
+ * Property: The last error the scanner encounter trying to open a channel to this peer.
+ */
+ public static String PROP_LAST_SCANNER_ERROR = "lastScannerError"; //$NON-NLS-1$
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/preferences/IPreferenceKeys.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/preferences/IPreferenceKeys.java
new file mode 100644
index 000000000..a8601a35e
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/preferences/IPreferenceKeys.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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.locator.interfaces.preferences;
+
+import java.io.File;
+
+/**
+ * The locator model bundle preference key identifiers.
+ */
+public interface IPreferenceKeys {
+ /**
+ * Common prefix for all core preference keys
+ */
+ public final String PREFIX = "tcf.locator.core."; //$NON-NLS-1$
+
+ /**
+ * If set to <code>true</code>, peers having the same agent id are filtered.
+ */
+ public final String PREF_FILTER_BY_AGENT_ID = PREFIX + "model.filter.agentid"; //$NON-NLS-1$
+
+ /**
+ * If set, the preference is defining a list of root locations where
+ * to lookup the static peer definitions. The single entries in the list
+ * are separated by the system dependent path separator character.
+ * <p>
+ * <b>Note:</b> If set, the given list of root locations replaces the default
+ * list of root locations.
+ *
+ * @see File#pathSeparatorChar
+ */
+ public final String PREF_STATIC_PEERS_ROOT_LOCATIONS = PREFIX + "model.peers.rootLocations"; //$NON-NLS-1$
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/services/ILocatorModelLookupService.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/services/ILocatorModelLookupService.java
new file mode 100644
index 000000000..4c46b9523
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/services/ILocatorModelLookupService.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * 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.locator.interfaces.services;
+
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+
+/**
+ * The service to lookup/search in the parent locator model.
+ */
+public interface ILocatorModelLookupService extends ILocatorModelService {
+
+ /**
+ * Lookup the peer model for the given peer id.
+ *
+ * @param id The peer id. Must not be <code>null</code>.
+ * @return The peer model instance, or <code>null</code> if the peer model cannot be found.
+ */
+ public IPeerModel lkupPeerModelById(String id);
+
+ /**
+ * Lookup matching peer model instances for the given agent id.
+ *
+ * @param agentId The agent id. Must not be <code>null</code>.
+ * @return The peer model instances, or an empty list if the given agent id could not be matched.
+ */
+ public IPeerModel[] lkupPeerModelByAgentId(String agentId);
+
+ /**
+ * Lookup matching peer model instances which supports the listed local and remote services.
+ *
+ * @param expectedLocalServices The list of local service names to be supported, or <code>null</code>.
+ * @param expectedRemoteServices The list of remote service names to be supported, or <code>null</code>.
+ *
+ * @return The peer model instances, or an empty list if the listed services are not supported by any of the peers.
+ */
+ public IPeerModel[] lkupPeerModelBySupportedServices(String[] expectedLocalServices, String[] expectedRemoteServices);
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/services/ILocatorModelRefreshService.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/services/ILocatorModelRefreshService.java
new file mode 100644
index 000000000..64a590b95
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/services/ILocatorModelRefreshService.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * 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.locator.interfaces.services;
+
+/**
+ * The service to refresh the parent locator model from remote.
+ */
+public interface ILocatorModelRefreshService extends ILocatorModelService {
+
+ /**
+ * Refreshes the list of known peers from the local locator service
+ * and update the locator model.
+ */
+ public void refresh();
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/services/ILocatorModelService.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/services/ILocatorModelService.java
new file mode 100644
index 000000000..2cb869948
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/services/ILocatorModelService.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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.locator.interfaces.services;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
+
+
+/**
+ * Common parent interface for locator model services.
+ */
+public interface ILocatorModelService extends IAdaptable {
+
+ /**
+ * Returns the parent locator model.
+ *
+ * @return The parent locator model.
+ */
+ public ILocatorModel getLocatorModel();
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/services/ILocatorModelUpdateService.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/services/ILocatorModelUpdateService.java
new file mode 100644
index 000000000..9cc4dd719
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/interfaces/services/ILocatorModelUpdateService.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. and others. All rights reserved.
+ * This program and the accompanying materials are made available under the terms
+ * of the Eclipse Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.tcf.locator.interfaces.services;
+
+import java.util.Collection;
+
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+
+
+/**
+ * The service to update the properties of given locator model nodes.
+ */
+public interface ILocatorModelUpdateService extends ILocatorModelService {
+
+ /**
+ * Adds the given peer to the list of know peers. A previous
+ * mapping to a peer model with the same id as the given
+ * peer model is overwritten.
+ *
+ * @param peer The peer model object. Must not be <code>null</code>.
+ */
+ public void add(IPeerModel peer);
+
+ /**
+ * Removes the given peer from the list of known peers.
+ *
+ * @param peer The peer model object. Must not be <code>null</code.
+ */
+ public void remove(IPeerModel peer);
+
+ /**
+ * Update the service nodes of the given peer node with the new set of
+ * local and/or remote services.
+ *
+ * @param peerNode The peer model instance. Must not be <code>null</code>.
+ * @param localServices The list of local service names or <code>null</code>.
+ * @param remoteServices The list of remote service names or <code>null</code>.
+ */
+ public void updatePeerServices(IPeerModel peerNode, Collection<String> localServices, Collection<String> remoteServices);
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/MyPropertyTester.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/MyPropertyTester.java
new file mode 100644
index 000000000..b1ebe5ced
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/MyPropertyTester.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * 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.locator.internal;
+
+import org.eclipse.core.expressions.PropertyTester;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModelProperties;
+
+
+
+/**
+ * Locator model property tester.
+ */
+public class MyPropertyTester extends PropertyTester {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.expressions.IPropertyTester#test(java.lang.Object, java.lang.String, java.lang.Object[], java.lang.Object)
+ */
+ @Override
+ public boolean test(final Object receiver, final String property, final Object[] args, final Object expectedValue) {
+ // The receiver is expected to be a peer model node
+ if (receiver instanceof IPeerModel) {
+ final Boolean[] result = new Boolean[1];
+ if (Protocol.isDispatchThread()) {
+ result[0] = Boolean.valueOf(testPeerModel((IPeerModel)receiver, property, args, expectedValue));
+ } else {
+ Protocol.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ result[0] = Boolean.valueOf(testPeerModel((IPeerModel)receiver, property, args, expectedValue));
+ }
+ });
+ }
+ if (result[0] != null) return result[0].booleanValue();
+ }
+ return false;
+ }
+
+ /**
+ * Test the specific peer model node properties.
+ *
+ * @param node The model node. Must not be <code>null</code>.
+ * @param property The property to test.
+ * @param args The property arguments.
+ * @param expectedValue The expected value.
+ *
+ * @return <code>True</code> if the property to test has the expected value, <code>false</code> otherwise.
+ */
+ protected boolean testPeerModel(IPeerModel node, String property, Object[] args, Object expectedValue) {
+ Assert.isNotNull(node);
+ Assert.isTrue(Protocol.isDispatchThread());
+
+ if ("name".equals(property)) { //$NON-NLS-1$
+ if (node.getPeer().getName() != null && node.getPeer().getName().equals(expectedValue)) {
+ return true;
+ }
+ }
+
+ if ("hasLocalService".equals(property) || "hasRemoteService".equals(property)) { //$NON-NLS-1$ //$NON-NLS-2$
+ String services = null;
+
+ if ("hasLocalService".equals(property)) services = node.getStringProperty(IPeerModelProperties.PROP_LOCAL_SERVICES); //$NON-NLS-1$
+ if ("hasRemoteService".equals(property)) services = node.getStringProperty(IPeerModelProperties.PROP_REMOTE_SERVICES); //$NON-NLS-1$
+
+ if (services != null) {
+ // Lookup each service individually to avoid "accidental" matching
+ for (String service : services.split(",")) { //$NON-NLS-1$
+ if (service != null && service.trim().equals(expectedValue)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ if ("isStaticPeer".equals(property)) { //$NON-NLS-1$
+ String path = node.getPeer().getAttributes().get("Path"); //$NON-NLS-1$
+ boolean isStaticPeer = path != null && !"".equals(path.trim()); //$NON-NLS-1$
+ if (expectedValue instanceof Boolean) return ((Boolean)expectedValue).booleanValue() == isStaticPeer;
+ }
+
+ return false;
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/PeersPersistenceDelegate.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/PeersPersistenceDelegate.java
new file mode 100644
index 000000000..91112202b
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/PeersPersistenceDelegate.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * 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.locator.internal;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.net.URI;
+import java.util.Map;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.tcf.te.runtime.persistence.AbstractPersistenceDelegate;
+
+/**
+ * Static peers persistence delegate implementation.
+ */
+public class PeersPersistenceDelegate extends AbstractPersistenceDelegate {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistenceDelegate#write(java.net.URI, java.util.Map)
+ */
+ @Override
+ public void write(URI uri, Map<String, Object> data) throws IOException {
+ Assert.isNotNull(uri);
+ Assert.isNotNull(data);
+
+ // Only "file:" URIs are supported
+ if (!"file".equalsIgnoreCase(uri.getScheme())) { //$NON-NLS-1$
+ throw new IOException("Unsupported URI schema '" + uri.getScheme() + "'"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ // Create the file object from the given URI
+ File file = new File(uri.normalize());
+
+ // The file must be absolute
+ if (!file.isAbsolute()) {
+ throw new IOException("URI must denote an absolute file path."); //$NON-NLS-1$
+ }
+
+ // Check if the file extension is "ini" (otherwise it is not picked up)
+ IPath path = new Path(file.getCanonicalPath());
+ if (!"ini".equals(path.getFileExtension())) { //$NON-NLS-1$
+ path = path.addFileExtension("ini"); //$NON-NLS-1$
+ }
+
+ BufferedWriter writer = null;
+ try {
+ writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path.toFile()), "UTF-8")); //$NON-NLS-1$
+ for (String attribute : data.keySet()) {
+ writer.write(attribute);
+ writer.write('=');
+ writer.write(data.get(attribute).toString());
+ writer.newLine();
+ }
+ } finally {
+ writer.close();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistenceDelegate#delete(java.net.URI)
+ */
+ @Override
+ public boolean delete(URI uri) throws IOException {
+ Assert.isNotNull(uri);
+
+ // Only "file:" URIs are supported
+ if (!"file".equalsIgnoreCase(uri.getScheme())) { //$NON-NLS-1$
+ throw new IOException("Unsupported URI schema '" + uri.getScheme() + "'"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ // Create the file object from the given URI
+ File file = new File(uri.normalize());
+
+ // The file must be absolute
+ if (!file.isAbsolute()) {
+ throw new IOException("URI must denote an absolute file path."); //$NON-NLS-1$
+ }
+
+ // Check if the file extension is "ini" (otherwise it is not picked up)
+ IPath path = new Path(file.getCanonicalPath());
+ if (!"ini".equals(path.getFileExtension())) { //$NON-NLS-1$
+ path = path.addFileExtension("ini"); //$NON-NLS-1$
+ }
+
+ return path.toFile().delete();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistenceDelegate#read(java.net.URI)
+ */
+ @Override
+ public Map<String, Object> read(URI uri) throws IOException {
+ Assert.isNotNull(uri);
+
+ // Only "file:" URIs are supported
+ if (!"file".equalsIgnoreCase(uri.getScheme())) { //$NON-NLS-1$
+ throw new IOException("Unsupported URI schema '" + uri.getScheme() + "'"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ // Create the file object from the given URI
+ File file = new File(uri.normalize());
+
+ // The file must be absolute
+ if (!file.isAbsolute()) {
+ throw new IOException("URI must denote an absolute file path."); //$NON-NLS-1$
+ }
+
+ return null;
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/adapters/AdapterFactory.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/adapters/AdapterFactory.java
new file mode 100644
index 000000000..2e337fd41
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/adapters/AdapterFactory.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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.locator.internal.adapters;
+
+import java.util.Map;
+
+import org.eclipse.core.runtime.IAdapterFactory;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+import org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistable;
+
+/**
+ * Static peers adapter factory implementation.
+ */
+public class AdapterFactory implements IAdapterFactory {
+ // The single instance adapter references
+ private final IPersistable mapPersistableAdapter = new MapPersistableAdapter();
+ private final IPersistable peerModelPersistableAdapter = new PeerModelPersistableAdapter();
+
+ private static final Class<?>[] CLASSES = new Class[] {
+ IPersistable.class
+ };
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IAdapterFactory#getAdapter(java.lang.Object, java.lang.Class)
+ */
+ @Override
+ public Object getAdapter(Object adaptableObject, Class adapterType) {
+ if (adaptableObject instanceof Map) {
+ if (IPersistable.class.equals(adapterType)) {
+ return mapPersistableAdapter;
+ }
+ }
+
+ if (adaptableObject instanceof IPeerModel) {
+ if (IPersistable.class.equals(adapterType)) {
+ return peerModelPersistableAdapter;
+ }
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList()
+ */
+ @Override
+ public Class[] getAdapterList() {
+ return CLASSES;
+ }
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/adapters/MapPersistableAdapter.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/adapters/MapPersistableAdapter.java
new file mode 100644
index 000000000..e2695c393
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/adapters/MapPersistableAdapter.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * 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.locator.internal.adapters;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.tcf.protocol.IPeer;
+import org.eclipse.tcf.te.tcf.locator.activator.CoreBundleActivator;
+import org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistable;
+
+/**
+ * Persistable implementation handling peer attributes.
+ */
+public class MapPersistableAdapter implements IPersistable {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistable#getStorageID()
+ */
+ @Override
+ public String getStorageID() {
+ return "org.eclipse.tcf.te.tcf.locator.persistence"; //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistable#getURI(java.lang.Object)
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public URI getURI(final Object data) {
+ Assert.isNotNull(data);
+
+ URI uri = null;
+
+ // Only map objects are supported
+ if (data instanceof Map) {
+ // Get the name of the peer and make it a valid
+ // file system name (no spaces etc).
+ String name = ((Map<String, String>) data).get(IPeer.ATTR_NAME);
+ if (name == null) name = ((Map<String, String>) data).get(IPeer.ATTR_ID);
+ name = makeValidFileSystemName(name);
+ // Get the URI from the name
+ uri = getRoot().append(name).toFile().toURI();
+ }
+
+ return uri;
+ }
+
+ /**
+ * Make a valid file system name from the given name.
+ *
+ * @param name The original name. Must not be <code>null</code>.
+ * @return The valid file system name.
+ */
+ private String makeValidFileSystemName(String name) {
+ Assert.isNotNull(name);
+ return name.replaceAll("\\W", "_"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * Returns the root location of the peers storage.
+ *
+ * @return The root location or <code>null</code> if it cannot be determined.
+ */
+ public IPath getRoot() {
+ IPath location = null;
+
+ // Try the bundles state location first (not available if launched with -data @none).
+ try {
+ IPath path = CoreBundleActivator.getDefault().getStateLocation().append(".peers"); //$NON-NLS-1$
+ if (!path.toFile().exists()) path.toFile().mkdirs();
+ if (path.toFile().canRead() && path.toFile().isDirectory()) {
+ location = path;
+ }
+ } catch (IllegalStateException e) {
+ // Workspace less environments (-data @none)
+ // The users local peers lookup directory is $HOME/.tcf/.peers.
+ IPath path = new Path(System.getProperty("user.home")).append(".tcf/.peers"); //$NON-NLS-1$ //$NON-NLS-2$
+ if (!path.toFile().exists()) path.toFile().mkdirs();
+ if (path.toFile().canRead() && path.toFile().isDirectory()) {
+ location = path;
+ }
+ }
+
+ return location;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistable#exportFrom(java.lang.Object)
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public Map<String, Object> exportFrom(Object data) throws IOException {
+ Assert.isNotNull(data);
+
+ Map<String, Object> result = null;
+
+ // Only map objects are supported
+ if (data instanceof Map) {
+ // Convert into a String/Object map to pass it on to the persistence delegates
+ result = new LinkedHashMap<String, Object>();
+ for (String key : ((Map<String, String>) data).keySet()) result.put(key, ((Map<String, String>) data).get(key));
+ }
+
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistable#importTo(java.lang.Object, java.util.Map)
+ */
+ @Override
+ public void importTo(Object data, Map<String, Object> external) throws IOException {
+ Assert.isNotNull(data);
+ Assert.isNotNull(external);
+
+ // Only map objects are supported
+ if (data instanceof Map) {
+ @SuppressWarnings("unchecked")
+ Map<String, String> map = (Map<String, String>)data;
+ for (String key : external.keySet()) map.put(key, (String)external.get(key));
+ }
+ }
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/adapters/PeerModelPersistableAdapter.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/adapters/PeerModelPersistableAdapter.java
new file mode 100644
index 000000000..fa7ee71ff
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/adapters/PeerModelPersistableAdapter.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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.locator.internal.adapters;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Map;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+import org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistable;
+
+/**
+ * Persistable implementation handling peer attributes.
+ */
+public class PeerModelPersistableAdapter implements IPersistable {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistable#getStorageID()
+ */
+ @Override
+ public String getStorageID() {
+ return "org.eclipse.tcf.te.tcf.locator.persistence"; //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistable#getURI(java.lang.Object)
+ */
+ @Override
+ public URI getURI(final Object data) {
+ Assert.isNotNull(data);
+
+ URI uri = null;
+
+ // Only peer model objects are supported
+ if (data instanceof IPeerModel) {
+ // Get the file path the peer model has been created from
+ final String[] path = new String[1];
+ if (Protocol.isDispatchThread()) {
+ path[0] = ((IPeerModel)data).getPeer().getAttributes().get("Path"); //$NON-NLS-1$
+ } else {
+ Protocol.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ path[0] = ((IPeerModel)data).getPeer().getAttributes().get("Path"); //$NON-NLS-1$
+ }
+ });
+ }
+
+ if (path[0] != null && !"".equals(path[0].trim())) { //$NON-NLS-1$
+ uri = new Path(path[0].trim()).toFile().toURI();
+ }
+ }
+
+ return uri;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistable#exportFrom(java.lang.Object)
+ */
+ @Override
+ public Map<String, Object> exportFrom(Object data) throws IOException {
+ Assert.isNotNull(data);
+
+ Map<String, Object> result = null;
+
+ // Only peer model objects are supported
+ if (data instanceof IPeerModel) {
+ }
+
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistable#importTo(java.lang.Object, java.util.Map)
+ */
+ @Override
+ public void importTo(Object data, Map<String, Object> external) throws IOException {
+ Assert.isNotNull(data);
+ Assert.isNotNull(external);
+
+ // Only peer model objects are supported
+ if (data instanceof IPeerModel) {
+ }
+ }
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/nls/Messages.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/nls/Messages.java
new file mode 100644
index 000000000..7a053e140
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/nls/Messages.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * 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.locator.internal.nls;
+
+import java.lang.reflect.Field;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Target Explorer TCF Locator 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.locator.internal.nls.Messages"; //$NON-NLS-1$
+
+ /**
+ * Static constructor.
+ */
+ static {
+ // Load message values from bundle file
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ /**
+ * Returns if or if not this NLS manager contains a constant for
+ * the given externalized strings key.
+ *
+ * @param key The externalized strings key or <code>null</code>.
+ * @return <code>True</code> if a constant for the given key exists, <code>false</code> otherwise.
+ */
+ public static boolean hasString(String key) {
+ if (key != null) {
+ try {
+ Field field = Messages.class.getDeclaredField(key);
+ return field != null;
+ } catch (NoSuchFieldException e) { /* ignored on purpose */ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the corresponding string for the given externalized strings
+ * key or <code>null</code> if the key does not exist.
+ *
+ * @param key The externalized strings key or <code>null</code>.
+ * @return The corresponding string or <code>null</code>.
+ */
+ public static String getString(String key) {
+ if (key != null) {
+ try {
+ Field field = Messages.class.getDeclaredField(key);
+ if (field != null) {
+ return (String)field.get(null);
+ }
+ } catch (Exception e) { /* ignored on purpose */ }
+ }
+
+ return null;
+ }
+
+ // **** Declare externalized string id's down here *****
+
+ public static String PeersPersistenceDelegate_error_noRootLocation;
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/nls/Messages.properties b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/nls/Messages.properties
new file mode 100644
index 000000000..f694d51aa
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/nls/Messages.properties
@@ -0,0 +1,6 @@
+#
+# org.eclipse.tcf.te.tcf.locator
+# Externalized Strings.
+#
+
+PeersPersistenceDelegate_error_noRootLocation=Failed to determine persistence storage root location
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/preferences/PreferencesInitializer.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/preferences/PreferencesInitializer.java
new file mode 100644
index 000000000..7bc15e465
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/preferences/PreferencesInitializer.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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.locator.internal.preferences;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.tcf.te.tcf.locator.activator.CoreBundleActivator;
+import org.eclipse.tcf.te.tcf.locator.interfaces.preferences.IPreferenceKeys;
+
+
+/**
+ * The locator model bundle preference initializer.
+ */
+public class PreferencesInitializer extends AbstractPreferenceInitializer {
+
+ /**
+ * Constructor.
+ */
+ public PreferencesInitializer() {
+ super();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
+ */
+ @Override
+ public void initializeDefaultPreferences() {
+ // Get the bundles preferences manager
+ IEclipsePreferences prefs = DefaultScope.INSTANCE.getNode(CoreBundleActivator.getUniqueIdentifier());
+ if (prefs != null) {
+ // [Hidden] Filtered by agent id: default on
+ prefs.putBoolean(IPreferenceKeys.PREF_FILTER_BY_AGENT_ID, true);
+ }
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/listener/ChannelStateChangeListener.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/listener/ChannelStateChangeListener.java
new file mode 100644
index 000000000..c5c5264f3
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/listener/ChannelStateChangeListener.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * 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.locator.listener;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.tcf.protocol.IChannel;
+import org.eclipse.tcf.protocol.IPeer;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.te.tcf.locator.activator.CoreBundleActivator;
+import org.eclipse.tcf.te.tcf.locator.interfaces.ITracing;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModelProperties;
+import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelLookupService;
+import org.eclipse.tcf.te.tcf.core.interfaces.listeners.IChannelStateChangeListener;
+
+
+/**
+ * Channel state change listener implementation.
+ */
+public class ChannelStateChangeListener implements IChannelStateChangeListener {
+ // Reference to the parent model
+ private final ILocatorModel model;
+
+ /**
+ * Constructor.
+ *
+ * @param model The parent locator model. Must not be <code>null</code>.
+ */
+ public ChannelStateChangeListener(ILocatorModel model) {
+ Assert.isNotNull(model);
+ this.model = model;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.tcf.core.interfaces.listeners.IChannelStateChangeListener#stateChanged(org.eclipse.tcf.protocol.IChannel, int)
+ */
+ @Override
+ public void stateChanged(IChannel channel, int state) {
+ Assert.isNotNull(channel);
+ Assert.isTrue(Protocol.isDispatchThread());
+
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_CHANNEL_STATE_CHANGE_LISTENER)) {
+ CoreBundleActivator.getTraceHandler().trace("ChannelStateChangeListener.stateChanged( " + channel + ", " + (state == IChannel.STATE_OPEN ? "OPEN" : "CLOSED") + " )", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+ ITracing.ID_TRACE_CHANNEL_STATE_CHANGE_LISTENER, this);
+ }
+
+ switch (state) {
+ case IChannel.STATE_OPEN:
+ IPeer peer = channel.getRemotePeer();
+ // Find the corresponding model node
+ IPeerModel node = model.getService(ILocatorModelLookupService.class).lkupPeerModelById(peer.getID());
+ if (node != null) {
+ // Increase the channel reference counter by 1
+ int counter = node.getIntProperty(IPeerModelProperties.PROP_CHANNEL_REF_COUNTER);
+ if (counter < 0) counter = 0;
+ counter++;
+ node.setProperty(IPeerModelProperties.PROP_CHANNEL_REF_COUNTER, counter);
+ if (counter > 0) node.setProperty(IPeerModelProperties.PROP_STATE, IPeerModelProperties.STATE_CONNECTED);
+ }
+ break;
+ case IChannel.STATE_CLOSED:
+ peer = channel.getRemotePeer();
+ // Find the corresponding model node
+ node = model.getService(ILocatorModelLookupService.class).lkupPeerModelById(peer.getID());
+ if (node != null) {
+ // Decrease the channel reference counter by 1
+ int counter = node.getIntProperty(IPeerModelProperties.PROP_CHANNEL_REF_COUNTER);
+ counter--;
+ if (counter < 0) counter = 0;
+ node.setProperty(IPeerModelProperties.PROP_CHANNEL_REF_COUNTER, counter);
+ if (counter == 0) node.setProperty(IPeerModelProperties.PROP_STATE, IPeerModelProperties.STATE_REACHABLE);
+ }
+ break;
+ }
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/listener/LocatorListener.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/listener/LocatorListener.java
new file mode 100644
index 000000000..f266ee235
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/listener/LocatorListener.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * 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.locator.listener;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.tcf.protocol.IPeer;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.services.ILocator;
+import org.eclipse.tcf.te.tcf.locator.ScannerRunnable;
+import org.eclipse.tcf.te.tcf.locator.activator.CoreBundleActivator;
+import org.eclipse.tcf.te.tcf.locator.interfaces.ITracing;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModelProperties;
+import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelLookupService;
+import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelUpdateService;
+import org.eclipse.tcf.te.tcf.locator.nodes.PeerModel;
+
+
+/**
+ * Locator listener implementation.
+ */
+public class LocatorListener implements ILocator.LocatorListener {
+ // Reference to the parent model
+ private final ILocatorModel model;
+
+ /**
+ * Constructor.
+ *
+ * @param model The parent locator model. Must not be <code>null</code>.
+ */
+ public LocatorListener(ILocatorModel model) {
+ super();
+
+ Assert.isNotNull(model);
+ this.model = model;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.services.ILocator.LocatorListener#peerAdded(org.eclipse.tcf.protocol.IPeer)
+ */
+ @Override
+ public void peerAdded(IPeer peer) {
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_LOCATOR_LISTENER)) {
+ CoreBundleActivator.getTraceHandler().trace("LocatorListener.peerAdded( " + (peer != null ? peer.getID() : null) + " )", ITracing.ID_TRACE_LOCATOR_LISTENER, this); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ if (model != null && peer != null) {
+ // find the corresponding model node to remove (expected to be null)
+ IPeerModel peerNode = model.getService(ILocatorModelLookupService.class).lkupPeerModelById(peer.getID());
+ // If not found, create a new peer node instance
+ if (peerNode == null) {
+ peerNode = new PeerModel(model, peer);
+ // Validate the peer node before adding
+ peerNode = model.validatePeerNodeForAdd(peerNode);
+ // Add the peer node to the model
+ if (peerNode != null) {
+ model.getService(ILocatorModelUpdateService.class).add(peerNode);
+ // And schedule for immediate status update
+ Runnable runnable = new ScannerRunnable(model.getScanner(), peerNode);
+ Protocol.invokeLater(runnable);
+ }
+ } else {
+ // Peer node found, update the peer instance
+ peerNode.setProperty(IPeerModelProperties.PROP_INSTANCE, peer);
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.services.ILocator.LocatorListener#peerChanged(org.eclipse.tcf.protocol.IPeer)
+ */
+ @Override
+ public void peerChanged(IPeer peer) {
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_LOCATOR_LISTENER)) {
+ CoreBundleActivator.getTraceHandler().trace("LocatorListener.peerChanged( " + (peer != null ? peer.getID() : null) + " )", ITracing.ID_TRACE_LOCATOR_LISTENER, this); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ if (model != null && peer != null) {
+ // find the corresponding model node to remove
+ IPeerModel peerNode = model.getService(ILocatorModelLookupService.class).lkupPeerModelById(peer.getID());
+ // Update the peer instance
+ if (peerNode != null) peerNode.setProperty(IPeerModelProperties.PROP_INSTANCE, peer);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.services.ILocator.LocatorListener#peerRemoved(java.lang.String)
+ */
+ @Override
+ public void peerRemoved(String id) {
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_LOCATOR_LISTENER)) {
+ CoreBundleActivator.getTraceHandler().trace("LocatorListener.peerRemoved( " + id + " )", ITracing.ID_TRACE_LOCATOR_LISTENER, this); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ if (model != null && id != null) {
+ // find the corresponding model node to remove
+ IPeerModel peerNode = model.getService(ILocatorModelLookupService.class).lkupPeerModelById(id);
+ if (peerNode != null) {
+ // Remove from the model
+ model.getService(ILocatorModelUpdateService.class).remove(peerNode);
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.services.ILocator.LocatorListener#peerHeartBeat(java.lang.String)
+ */
+ @Override
+ public void peerHeartBeat(String id) {
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_LOCATOR_LISTENER)) {
+ CoreBundleActivator.getTraceHandler().trace("LocatorListener.peerHeartBeat( " + id + " )", ITracing.ID_TRACE_LOCATOR_LISTENER, this); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/listener/ModelAdapter.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/listener/ModelAdapter.java
new file mode 100644
index 000000000..2ebba7e62
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/listener/ModelAdapter.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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.locator.listener;
+
+import org.eclipse.tcf.te.tcf.locator.interfaces.IModelListener;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+
+/**
+ * Default model listener implementation.
+ */
+public class ModelAdapter implements IModelListener {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.IModelListener#locatorModelChanged(org.eclipse.tcf.te.tcf.locator.core.interfaces.nodes.ILocatorModel)
+ */
+ @Override
+ public void locatorModelChanged(ILocatorModel model) {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.IModelListener#locatorModelDisposed(org.eclipse.tcf.te.tcf.locator.core.interfaces.nodes.ILocatorModel)
+ */
+ @Override
+ public void locatorModelDisposed(ILocatorModel model) {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.IModelListener#peerModelChanged(org.eclipse.tcf.te.tcf.locator.core.interfaces.nodes.ILocatorModel, org.eclipse.tcf.te.tcf.locator.core.interfaces.nodes.IPeerModel)
+ */
+ @Override
+ public void peerModelChanged(ILocatorModel model, IPeerModel peer) {
+ }
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/nodes/LocatorModel.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/nodes/LocatorModel.java
new file mode 100644
index 000000000..50564ea14
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/nodes/LocatorModel.java
@@ -0,0 +1,438 @@
+/*******************************************************************************
+ * 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.locator.nodes;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.tcf.protocol.IPeer;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.services.ILocator;
+import org.eclipse.tcf.te.tcf.locator.Scanner;
+import org.eclipse.tcf.te.tcf.locator.activator.CoreBundleActivator;
+import org.eclipse.tcf.te.tcf.locator.interfaces.IModelListener;
+import org.eclipse.tcf.te.tcf.locator.interfaces.IScanner;
+import org.eclipse.tcf.te.tcf.locator.interfaces.ITracing;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.preferences.IPreferenceKeys;
+import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelLookupService;
+import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelRefreshService;
+import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelService;
+import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelUpdateService;
+import org.eclipse.tcf.te.tcf.locator.listener.ChannelStateChangeListener;
+import org.eclipse.tcf.te.tcf.locator.listener.LocatorListener;
+import org.eclipse.tcf.te.tcf.locator.services.LocatorModelLookupService;
+import org.eclipse.tcf.te.tcf.locator.services.LocatorModelRefreshService;
+import org.eclipse.tcf.te.tcf.locator.services.LocatorModelUpdateService;
+import org.eclipse.tcf.te.tcf.locator.utils.IPAddressUtil;
+import org.eclipse.tcf.te.tcf.core.Tcf;
+import org.eclipse.tcf.te.tcf.core.interfaces.listeners.IChannelStateChangeListener;
+
+
+/**
+ * Default locator model implementation.
+ */
+public class LocatorModel extends PlatformObject implements ILocatorModel {
+ // The unique model id
+ private final UUID uniqueId = UUID.randomUUID();
+ // Flag to mark the model disposed
+ private boolean disposed;
+
+ // The list of known peers
+ private final Map<String, IPeerModel> peers = new HashMap<String, IPeerModel>();
+
+ // Reference to the scanner
+ private IScanner scanner = null;
+
+ // Reference to the model locator listener
+ private ILocator.LocatorListener locatorListener = null;
+ // Reference to the model channel state change listener
+ private IChannelStateChangeListener channelStateChangeListener = null;
+
+ // The list of registered model listeners
+ private final List<IModelListener> modelListener = new ArrayList<IModelListener>();
+
+ // Reference to the refresh service
+ private final ILocatorModelRefreshService refreshService = new LocatorModelRefreshService(this);
+ // Reference to the lookup service
+ private final ILocatorModelLookupService lookupService = new LocatorModelLookupService(this);
+ // Reference to the update service
+ private final ILocatorModelUpdateService updateService = new LocatorModelUpdateService(this);
+
+ /**
+ * Constructor.
+ */
+ public LocatorModel() {
+ super();
+ disposed = false;
+
+ channelStateChangeListener = new ChannelStateChangeListener(this);
+ Tcf.addChannelStateChangeListener(channelStateChangeListener);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.nodes.ILocatorModel#addListener(org.eclipse.tcf.te.tcf.locator.core.interfaces.IModelListener)
+ */
+ @Override
+ public void addListener(IModelListener listener) {
+ Assert.isNotNull(listener);
+ Assert.isTrue(Protocol.isDispatchThread());
+
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_LOCATOR_MODEL)) {
+ CoreBundleActivator.getTraceHandler().trace("LocatorModel.addListener( " + listener + " )", ITracing.ID_TRACE_LOCATOR_MODEL, this); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ if (!modelListener.contains(listener)) modelListener.add(listener);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.nodes.ILocatorModel#removeListener(org.eclipse.tcf.te.tcf.locator.core.interfaces.IModelListener)
+ */
+ @Override
+ public void removeListener(IModelListener listener) {
+ Assert.isNotNull(listener);
+ Assert.isTrue(Protocol.isDispatchThread());
+
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_LOCATOR_MODEL)) {
+ CoreBundleActivator.getTraceHandler().trace("LocatorModel.removeListener( " + listener + " )", ITracing.ID_TRACE_LOCATOR_MODEL, this); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ modelListener.remove(listener);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel#getListener()
+ */
+ @Override
+ public IModelListener[] getListener() {
+ return modelListener.toArray(new IModelListener[modelListener.size()]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.nodes.ILocatorModel#dispose()
+ */
+ @Override
+ public void dispose() {
+ Assert.isTrue(Protocol.isDispatchThread());
+
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_LOCATOR_MODEL)) {
+ CoreBundleActivator.getTraceHandler().trace("LocatorModel.dispose()", ITracing.ID_TRACE_LOCATOR_MODEL, this); //$NON-NLS-1$
+ }
+
+ // If already disposed, we are done immediately
+ if (disposed) return;
+
+ disposed = true;
+
+ final IModelListener[] listeners = getListener();
+ if (listeners.length > 0) {
+ Protocol.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ for (IModelListener listener : listeners) {
+ listener.locatorModelDisposed(LocatorModel.this);
+ }
+ }
+ });
+ }
+ modelListener.clear();
+
+ if (locatorListener != null) {
+ Protocol.getLocator().removeListener(locatorListener);
+ locatorListener = null;
+ }
+
+ if (channelStateChangeListener != null) {
+ Tcf.removeChannelStateChangeListener(channelStateChangeListener);
+ channelStateChangeListener = null;
+ }
+
+ if (scanner != null) {
+ stopScanner();
+ scanner = null;
+ }
+
+ peers.clear();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.nodes.ILocatorModel#isDisposed()
+ */
+ @Override
+ public boolean isDisposed() {
+ return disposed;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.nodes.ILocatorModel#getPeers()
+ */
+ @Override
+ public IPeerModel[] getPeers() {
+ return peers.values().toArray(new IPeerModel[peers.values().size()]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.PlatformObject#getAdapter(java.lang.Class)
+ */
+ @Override
+ public Object getAdapter(Class adapter) {
+ if (adapter.isAssignableFrom(ILocator.LocatorListener.class)) {
+ return locatorListener;
+ }
+ if (adapter.isAssignableFrom(IScanner.class)) {
+ return scanner;
+ }
+ if (adapter.isAssignableFrom(ILocatorModelRefreshService.class)) {
+ return refreshService;
+ }
+ if (adapter.isAssignableFrom(ILocatorModelLookupService.class)) {
+ return lookupService;
+ }
+ if (adapter.isAssignableFrom(ILocatorModelUpdateService.class)) {
+ return updateService;
+ }
+ if (adapter.isAssignableFrom(Map.class)) {
+ return peers;
+ }
+
+ return super.getAdapter(adapter);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public final boolean equals(Object obj) {
+ if (obj instanceof LocatorModel) {
+ return uniqueId.equals(((LocatorModel)obj).uniqueId);
+ }
+ return super.equals(obj);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.nodes.ILocatorModel#getService(java.lang.Class)
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ public <V extends ILocatorModelService> V getService(Class<V> serviceInterface) {
+ Assert.isNotNull(serviceInterface);
+ return (V)getAdapter(serviceInterface);
+ }
+
+ /**
+ * Check if the locator listener has been created and registered
+ * to the global locator service.
+ * <p>
+ * <b>Note:</b> This method is not intended to be call from clients.
+ */
+ public void checkLocatorListener() {
+ Assert.isTrue(Protocol.isDispatchThread());
+ Assert.isNotNull(Protocol.getLocator());
+
+ if (locatorListener == null) {
+ locatorListener = doCreateLocatorListener(this);
+ Protocol.getLocator().addListener(locatorListener);
+ }
+ }
+
+ /**
+ * Creates the locator listener instance.
+ *
+ * @param model The parent model. Must not be <code>null</code>.
+ * @return The locator listener instance.
+ */
+ protected ILocator.LocatorListener doCreateLocatorListener(ILocatorModel model) {
+ Assert.isNotNull(model);
+ return new LocatorListener(model);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.nodes.ILocatorModel#getScanner()
+ */
+ @Override
+ public IScanner getScanner() {
+ if (scanner == null) scanner = new Scanner(this);
+ return scanner;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.nodes.ILocatorModel#startScanner(long, long)
+ */
+ @Override
+ public void startScanner(long delay, long schedule) {
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_LOCATOR_MODEL)) {
+ CoreBundleActivator.getTraceHandler().trace("LocatorModel.startScanner( " + delay + ", " + schedule + " )", ITracing.ID_TRACE_LOCATOR_MODEL, this); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ IScanner scanner = getScanner();
+
+ if (scanner != null) {
+ // Pass on the schedule parameter
+ Map<String, Object> config = new HashMap<String, Object>(scanner.getConfiguration());
+ config.put(IScanner.PROP_SCHEDULE, Long.valueOf(schedule));
+ scanner.setConfiguration(config);
+ }
+
+ // The default scanner implementation is a job.
+ // -> schedule here if it is a job
+ if (scanner instanceof Job) {
+ Job job = (Job)scanner;
+ job.setSystem(true);
+ job.setPriority(Job.DECORATE);
+ job.schedule(delay);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.nodes.ILocatorModel#stopScanner()
+ */
+ @Override
+ public void stopScanner() {
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_LOCATOR_MODEL)) {
+ CoreBundleActivator.getTraceHandler().trace("LocatorModel.stopScanner()", ITracing.ID_TRACE_LOCATOR_MODEL, this); //$NON-NLS-1$
+ }
+
+ if (scanner != null) {
+ // Terminate the scanner
+ scanner.terminate();
+ // Reset the scanner reference
+ scanner = null;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.nodes.ILocatorModel#validatePeerNodeForAdd(org.eclipse.tcf.te.tcf.locator.core.interfaces.nodes.IPeerModel)
+ */
+ @Override
+ public IPeerModel validatePeerNodeForAdd(IPeerModel node) {
+ Assert.isNotNull(node);
+ Assert.isTrue(Protocol.isDispatchThread());
+
+ // Get the peer from the peer node
+ IPeer peer = node.getPeer();
+
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_LOCATOR_MODEL)) {
+ CoreBundleActivator.getTraceHandler().trace("LocatorModel.validatePeerNodeForAdd( " + (peer != null ? peer.getID() : null) + " )", ITracing.ID_TRACE_LOCATOR_MODEL, this); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ IPeerModel result = node;
+
+ // Check on the filtered by preference settings what to do
+ boolean isFilterByAgentId = Platform.getPreferencesService().getBoolean(CoreBundleActivator.getUniqueIdentifier(),
+ IPreferenceKeys.PREF_FILTER_BY_AGENT_ID,
+ false, null);
+ if (isFilterByAgentId) {
+ // Peers are filtered by agent id. Don't add the peer node
+ // if we have another peer node already having the same agent id
+ String agentId = peer.getAgentID();
+ IPeerModel[] previousNodes = agentId != null ? getService(ILocatorModelLookupService.class).lkupPeerModelByAgentId(agentId) : new IPeerModel[0];
+
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_LOCATOR_MODEL)) {
+ CoreBundleActivator.getTraceHandler().trace("LocatorModel.validatePeerNodeForAdd: agentId=" + agentId + ", Matching peer nodes " //$NON-NLS-1$ //$NON-NLS-2$
+ + (previousNodes.length > 0 ? "found (" + previousNodes.length +")" : "not found --> DONE") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ , ITracing.ID_TRACE_LOCATOR_MODEL, this);
+ }
+
+ boolean fireListener = false;
+
+ for (IPeerModel previousNode : previousNodes) {
+ // Get the peer for the previous node
+ IPeer previousPeer = previousNode.getPeer();
+ if (previousPeer != null) {
+ // We prefer to use the peer node for the canonical IP address before
+ // the loop back address before any other address.
+ String loopback = IPAddressUtil.getInstance().getIPv4LoopbackAddress();
+ String canonical = IPAddressUtil.getInstance().getCanonicalAddress();
+
+ String peerIP = peer.getAttributes().get(IPeer.ATTR_IP_HOST);
+ String previousPeerIP = previousPeer.getAttributes().get(IPeer.ATTR_IP_HOST);
+
+ String peerPort = peer.getAttributes().get(IPeer.ATTR_IP_PORT);
+ if (peerPort == null || "".equals(peerPort)) peerPort = "1534"; //$NON-NLS-1$ //$NON-NLS-2$
+ String previousPeerPort = previousPeer.getAttributes().get(IPeer.ATTR_IP_PORT);
+ if (previousPeerPort == null || "".equals(previousPeerPort)) previousPeerPort = "1534"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_LOCATOR_MODEL)) {
+ CoreBundleActivator.getTraceHandler().trace("LocatorModel.validatePeerNodeForAdd: loopback=" + loopback + ", canonical=" + canonical //$NON-NLS-1$ //$NON-NLS-2$
+ + ", peerIP=" + peerIP + ", previousPeerIP=" + previousPeerIP //$NON-NLS-1$ //$NON-NLS-2$
+ + ", peerPort=" + peerPort + ", previousPeerPort=" + previousPeerPort //$NON-NLS-1$ //$NON-NLS-2$
+ , ITracing.ID_TRACE_LOCATOR_MODEL, this);
+ }
+
+ // If the ports of the agent instances are identical,
+ // than try to find the best representation of the agent instance
+ if (peerPort.equals(previousPeerPort)) {
+ if (canonical != null && canonical.equals(peerIP) && !canonical.equals(previousPeerIP)) {
+ // Remove the old node and replace it with the new new
+ peers.remove(previousNode.getPeer().getID());
+ fireListener = true;
+
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_LOCATOR_MODEL)) {
+ CoreBundleActivator.getTraceHandler().trace("LocatorModel.validatePeerNodeForAdd: Previous peer node replaced (canonical overwrite)" //$NON-NLS-1$
+ , ITracing.ID_TRACE_LOCATOR_MODEL, this);
+ }
+ } else if (loopback != null && loopback.equals(peerIP) && !loopback.equals(previousPeerIP)
+ && (canonical == null || !canonical.equals(previousPeerIP))) {
+ // Remove the old node and replace it with the new new
+ peers.remove(previousNode.getPeer().getID());
+ fireListener = true;
+
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_LOCATOR_MODEL)) {
+ CoreBundleActivator.getTraceHandler().trace("LocatorModel.validatePeerNodeForAdd: Previous peer node replaced (loopback overwrite)" //$NON-NLS-1$
+ , ITracing.ID_TRACE_LOCATOR_MODEL, this);
+ }
+ } else {
+ // Drop the current node
+ result = null;
+
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_LOCATOR_MODEL)) {
+ CoreBundleActivator.getTraceHandler().trace("LocatorModel.validatePeerNodeForAdd: Previous peer node kept, new peer node dropped" //$NON-NLS-1$
+ , ITracing.ID_TRACE_LOCATOR_MODEL, this);
+ }
+
+ }
+
+ // Break the loop if the ports matched
+ break;
+ }
+
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_LOCATOR_MODEL)) {
+ CoreBundleActivator.getTraceHandler().trace("LocatorModel.validatePeerNodeForAdd: Previous peer node kept, new peer node added (Port mismatch)" //$NON-NLS-1$
+ , ITracing.ID_TRACE_LOCATOR_MODEL, this);
+ }
+ }
+ }
+
+ if (fireListener) {
+ final IModelListener[] listeners = getListener();
+ if (listeners.length > 0) {
+ Protocol.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ for (IModelListener listener : listeners) {
+ listener.locatorModelChanged(LocatorModel.this);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ return result;
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/nodes/PeerModel.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/nodes/PeerModel.java
new file mode 100644
index 000000000..6b77020a4
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/nodes/PeerModel.java
@@ -0,0 +1,275 @@
+/*******************************************************************************
+ * 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.locator.nodes;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.tcf.protocol.IPeer;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.te.tcf.locator.interfaces.IModelListener;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModelProperties;
+import org.eclipse.tcf.te.runtime.interfaces.workingsets.IWorkingSetElement;
+import org.eclipse.tcf.te.runtime.properties.PropertiesContainer;
+
+
+/**
+ * Default peer model implementation.
+ */
+public class PeerModel extends PropertiesContainer implements IPeerModel, IWorkingSetElement {
+ // Reference to the parent locator model
+ private final ILocatorModel parentModel;
+ // Reference to the element id (cached for performance optimization)
+ private String elementId;
+
+ /**
+ * Constructor.
+ *
+ * @param parent The parent locator model. Must not be <code>null</code>.
+ */
+ public PeerModel(ILocatorModel parent) {
+ this(parent, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param parent The parent locator model. Must not be <code>null</code>.
+ * @param peer The peer or <code>null</code>.
+ */
+ public PeerModel(ILocatorModel parent, IPeer peer) {
+ super();
+
+ Assert.isNotNull(parent);
+ parentModel = parent;
+
+ // Set the default properties before enabling the change events.
+ // The properties changed listeners should not be called from the
+ // constructor.
+ setProperty(IPeerModelProperties.PROP_INSTANCE, peer);
+
+ // Initialize the element id
+ elementId = peer.getID();
+ Assert.isNotNull(elementId);
+
+ // Enable change events
+ setChangeEventsEnabled(true);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.properties.PropertiesContainer#checkThreadAccess()
+ */
+ @Override
+ protected final boolean checkThreadAccess() {
+ return Protocol.isDispatchThread();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel#getModel()
+ */
+ @Override
+ public ILocatorModel getModel() {
+ return (ILocatorModel)getAdapter(ILocatorModel.class);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel#getPeer()
+ */
+ @Override
+ public IPeer getPeer() {
+ return (IPeer)getAdapter(IPeer.class);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.workingsets.IWorkingSetElement#getElementId()
+ */
+ @Override
+ public String getElementId() {
+ return elementId;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.PlatformObject#getAdapter(java.lang.Class)
+ */
+ @Override
+ public Object getAdapter(final Class adapter) {
+ // NOTE: The getAdapter(...) method can be invoked from many place and
+ // many threads where we cannot control the calls. Therefore, this
+ // method is allowed be called from any thread.
+ final Object[] object = new Object[1];
+ if (Protocol.isDispatchThread()) {
+ object[0] = doGetAdapter(adapter);
+ } else {
+ Protocol.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ object[0] = doGetAdapter(adapter);
+ }
+ });
+ }
+ return object[0] != null ? object[0] : super.getAdapter(adapter);
+ }
+
+ /**
+ * Returns an object which is an instance of the given class associated with this object.
+ * Returns <code>null</code> if no such object can be found.
+ * <p>
+ * This method must be called within the TCF dispatch thread!
+ *
+ * @param adapter The adapter class to look up.
+ * @return The adapter or <code>null</code>.
+ */
+ protected Object doGetAdapter(Class<?> adapter) {
+ Assert.isTrue(checkThreadAccess(), "Illegal Thread Access"); //$NON-NLS-1$
+
+ if (adapter.isAssignableFrom(ILocatorModel.class)) {
+ return parentModel;
+ }
+
+ Object peer = getProperty(IPeerModelProperties.PROP_INSTANCE);
+ if (peer != null && adapter.isAssignableFrom(peer.getClass())) {
+ return peer;
+ }
+
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.properties.PropertiesContainer#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder buffer = new StringBuilder(getClass().getSimpleName());
+
+ if (Protocol.isDispatchThread()) {
+ IPeer peer = getPeer();
+ buffer.append(": id=" + peer.getID()); //$NON-NLS-1$
+ buffer.append(", name=" + peer.getName()); //$NON-NLS-1$
+ } else {
+ Protocol.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ IPeer peer = getPeer();
+ buffer.append(": id=" + peer.getID()); //$NON-NLS-1$
+ buffer.append(", name=" + peer.getName()); //$NON-NLS-1$
+ }
+ });
+ }
+ buffer.append(", " + super.toString()); //$NON-NLS-1$
+ return buffer.toString();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.properties.PropertiesContainer#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof PeerModel) {
+ return getElementId().equals(((PeerModel)obj).getElementId());
+ }
+ return super.equals(obj);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.properties.PropertiesContainer#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return getElementId().hashCode();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.properties.PropertiesContainer#getProperties()
+ */
+ @Override
+ public Map<String, Object> getProperties() {
+ Map<String, Object> properties = new HashMap<String, Object>(super.getProperties());
+ if (getPeer() != null) properties.putAll(getPeer().getAttributes());
+ return Collections.unmodifiableMap(new HashMap<String, Object>(properties));
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.properties.PropertiesContainer#getProperty(java.lang.String)
+ */
+ @Override
+ public Object getProperty(String key) {
+ Object property = super.getProperty(key);
+ if (property == null && getPeer() != null && getPeer().getAttributes().containsKey(key)) {
+ property = getPeer().getAttributes().get(key);
+ }
+ return property;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.properties.PropertiesContainer#postSetProperties(java.util.Map)
+ */
+ @Override
+ protected void postSetProperties(Map<String, Object> properties) {
+ Assert.isTrue(checkThreadAccess(), "Illegal Thread Access"); //$NON-NLS-1$
+ Assert.isNotNull(properties);
+ Assert.isNotNull(getPeer());
+
+ // New properties applied. Update the element id
+ elementId = getPeer().getID();
+ Assert.isNotNull(elementId);
+
+ if (changeEventsEnabled()) {
+ final IModelListener[] listeners = parentModel.getListener();
+ if (listeners.length > 0) {
+ Protocol.invokeLater(new Runnable() {
+ @Override
+ @SuppressWarnings("synthetic-access")
+ public void run() {
+ for (IModelListener listener : listeners) {
+ listener.peerModelChanged(parentModel, PeerModel.this);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.properties.PropertiesContainer#postSetProperty(java.lang.String, java.lang.Object, java.lang.Object)
+ */
+ @Override
+ public void postSetProperty(String key, Object value, Object oldValue) {
+ Assert.isTrue(checkThreadAccess(), "Illegal Thread Access"); //$NON-NLS-1$
+ Assert.isNotNull(key);
+ Assert.isNotNull(getPeer());
+
+ // If the peer instance changed, update the element id
+ if (IPeerModelProperties.PROP_INSTANCE.equals(key)) {
+ elementId = getPeer().getID();
+ Assert.isNotNull(elementId);
+ }
+
+ // Notify registered listeners that the peer changed. Property
+ // changes for property slots ending with ".silent" are suppressed.
+ if (changeEventsEnabled() && !key.endsWith(".silent")) { //$NON-NLS-1$
+ final IModelListener[] listeners = parentModel.getListener();
+ if (listeners.length > 0) {
+ Protocol.invokeLater(new Runnable() {
+ @Override
+ @SuppressWarnings("synthetic-access")
+ public void run() {
+ for (IModelListener listener : listeners) {
+ listener.peerModelChanged(parentModel, PeerModel.this);
+ }
+ }
+ });
+ }
+ }
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/AbstractLocatorModelService.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/AbstractLocatorModelService.java
new file mode 100644
index 000000000..ea6df29b5
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/AbstractLocatorModelService.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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.locator.services;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelService;
+
+
+/**
+ * Abstract locator model service base implementation.
+ */
+public abstract class AbstractLocatorModelService extends PlatformObject implements ILocatorModelService {
+ // Reference to the parent locator model
+ private final ILocatorModel locatorModel;
+
+ /**
+ * Constructor.
+ *
+ * @param parentModel The parent locator model instance. Must not be <code>null</code>.
+ */
+ public AbstractLocatorModelService(ILocatorModel parentModel) {
+ Assert.isNotNull(parentModel);
+ locatorModel = parentModel;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelService#getLocatorModel()
+ */
+ @Override
+ public final ILocatorModel getLocatorModel() {
+ return locatorModel;
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelLookupService.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelLookupService.java
new file mode 100644
index 000000000..c349127f3
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelLookupService.java
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * 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.locator.services;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.tcf.protocol.IPeer;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModelProperties;
+import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelLookupService;
+
+
+/**
+ * Default locator model lookup service implementation.
+ */
+public class LocatorModelLookupService extends AbstractLocatorModelService implements ILocatorModelLookupService {
+
+ /**
+ * Constructor.
+ *
+ * @param parentModel The parent locator model instance. Must not be <code>null</code>.
+ */
+ public LocatorModelLookupService(ILocatorModel parentModel) {
+ super(parentModel);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.services.ILocatorModelLookupService#lkupPeerModelById(java.lang.String)
+ */
+ @Override
+ public IPeerModel lkupPeerModelById(String id) {
+ Assert.isNotNull(id);
+ Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
+
+ IPeerModel node = null;
+ for (IPeerModel candidate : getLocatorModel().getPeers()) {
+ IPeer peer = candidate.getPeer();
+ if (id.equals(peer.getID())) {
+ node = candidate;
+ break;
+ }
+ }
+
+ return node;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelLookupService#lkupPeerModelByAgentId(java.lang.String)
+ */
+ @Override
+ public IPeerModel[] lkupPeerModelByAgentId(String agentId) {
+ Assert.isNotNull(agentId);
+ Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
+
+ List<IPeerModel> nodes = new ArrayList<IPeerModel>();
+ for (IPeerModel candidate : getLocatorModel().getPeers()) {
+ IPeer peer = candidate.getPeer();
+ if (agentId.equals(peer.getAgentID())) {
+ nodes.add(candidate);
+ }
+ }
+
+ return nodes.toArray(new IPeerModel[nodes.size()]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelLookupService#lkupPeerModelBySupportedServices(java.lang.String[], java.lang.String[])
+ */
+ @Override
+ public IPeerModel[] lkupPeerModelBySupportedServices(String[] expectedLocalServices, String[] expectedRemoteServices) {
+ Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
+
+ List<IPeerModel> nodes = new ArrayList<IPeerModel>();
+ for (IPeerModel candidate : getLocatorModel().getPeers()) {
+ String localServices = candidate.getStringProperty(IPeerModelProperties.PROP_LOCAL_SERVICES);
+ String remoteServices = candidate.getStringProperty(IPeerModelProperties.PROP_REMOTE_SERVICES);
+
+ boolean matchesExpectations = true;
+
+ // Ignore the local services if not expectations are set
+ if (expectedLocalServices != null && expectedLocalServices.length > 0) {
+ if (localServices != null) {
+ for (String service : expectedLocalServices) {
+ if (!localServices.contains(service)) {
+ matchesExpectations = false;
+ break;
+ }
+ }
+ } else {
+ matchesExpectations = false;
+ }
+ }
+
+ if (!matchesExpectations) continue;
+
+ // Ignore the remote services if not expectations are set
+ if (expectedRemoteServices != null && expectedRemoteServices.length > 0) {
+ if (remoteServices != null) {
+ for (String service : expectedRemoteServices) {
+ if (!remoteServices.contains(service)) {
+ matchesExpectations = false;
+ break;
+ }
+ }
+ } else {
+ matchesExpectations = false;
+ }
+ }
+
+ if (matchesExpectations) nodes.add(candidate);
+ }
+
+ return nodes.toArray(new IPeerModel[nodes.size()]);
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelRefreshService.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelRefreshService.java
new file mode 100644
index 000000000..4fb96826c
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelRefreshService.java
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * 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.locator.services;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.tcf.core.TransientPeer;
+import org.eclipse.tcf.protocol.IPeer;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.services.ILocator;
+import org.eclipse.tcf.te.tcf.locator.ScannerRunnable;
+import org.eclipse.tcf.te.tcf.locator.activator.CoreBundleActivator;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.preferences.IPreferenceKeys;
+import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelLookupService;
+import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelRefreshService;
+import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelUpdateService;
+import org.eclipse.tcf.te.tcf.locator.nodes.LocatorModel;
+import org.eclipse.tcf.te.tcf.locator.nodes.PeerModel;
+import org.eclipse.tcf.te.tcf.core.Tcf;
+
+
+/**
+ * Default locator model refresh service implementation.
+ */
+public class LocatorModelRefreshService extends AbstractLocatorModelService implements ILocatorModelRefreshService {
+
+ /**
+ * Constructor.
+ *
+ * @param parentModel The parent locator model instance. Must not be <code>null</code>.
+ */
+ public LocatorModelRefreshService(ILocatorModel parentModel) {
+ super(parentModel);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.services.ILocatorModelRefreshService#refresh()
+ */
+ @Override
+ public void refresh() {
+ Assert.isTrue(Protocol.isDispatchThread());
+
+ // Get the parent locator model
+ ILocatorModel model = getLocatorModel();
+
+ // If the parent model is already disposed, the service will drop out immediately
+ if (model.isDisposed()) return;
+
+ // If the TCF framework isn't initialized yet, the service will drop out immediately
+ if (!Tcf.isRunning()) return;
+
+ // Get the list of old children (update node instances where possible)
+ final List<IPeerModel> oldChildren = new ArrayList<IPeerModel>(Arrays.asList(model.getPeers()));
+
+ // Get the locator service
+ ILocator locatorService = Protocol.getLocator();
+ if (locatorService != null) {
+ // Check for the locator listener to be created and registered
+ if (model instanceof LocatorModel) ((LocatorModel)model).checkLocatorListener();
+ // Get the map of peers known to the locator service.
+ Map<String, IPeer> peers = locatorService.getPeers();
+ // Process the peers
+ processPeers(peers, oldChildren, model);
+ }
+
+ // Refresh the static peer definitions
+ refreshStaticPeers(oldChildren, model);
+
+ // If there are remaining old children, remove them from the model (non-recursive)
+ for (IPeerModel oldChild : oldChildren) model.getService(ILocatorModelUpdateService.class).remove(oldChild);
+ }
+
+ /**
+ * Process the given map of peers and update the given locator model.
+ *
+ * @param peers The map of peers to process. Must not be <code>null</code>.
+ * @param oldChildren The list of old children. Must not be <code>null</code>.
+ * @param model The locator model. Must not be <code>null</code>.
+ */
+ protected void processPeers(Map<String, IPeer> peers, List<IPeerModel> oldChildren, ILocatorModel model) {
+ Assert.isNotNull(peers);
+ Assert.isNotNull(oldChildren);
+ Assert.isNotNull(model);
+
+ for (String peerId : peers.keySet()) {
+ // Get the peer instance for the current peer id
+ IPeer peer = peers.get(peerId);
+ // Try to find an existing peer node first
+ IPeerModel peerNode = model.getService(ILocatorModelLookupService.class).lkupPeerModelById(peerId);
+ // And create a new one if we cannot find it
+ if (peerNode == null) peerNode = new PeerModel(model, peer);
+ else oldChildren.remove(peerNode);
+ // Validate the peer node before adding
+ peerNode = model.validatePeerNodeForAdd(peerNode);
+ if (peerNode != null) {
+ // Add the peer node to model
+ model.getService(ILocatorModelUpdateService.class).add(peerNode);
+ // And schedule for immediate status update
+ Runnable runnable = new ScannerRunnable(model.getScanner(), peerNode);
+ Protocol.invokeLater(runnable);
+ }
+ }
+ }
+
+ /**
+ * Refresh the static peer definitions.
+ *
+ * @param oldChildren The list of old children. Must not be <code>null</code>.
+ * @param model The locator model. Must not be <code>null</code>.
+ */
+ protected void refreshStaticPeers(List<IPeerModel> oldChildren, ILocatorModel model) {
+ Assert.isNotNull(oldChildren);
+ Assert.isNotNull(model);
+
+ // Get the root locations to lookup the static peer definitions
+ File[] roots = getStaticPeerLookupDirectories();
+ if (roots.length > 0) {
+ // The map of peers created from the static definitions
+ Map<String, IPeer> peers = new HashMap<String, IPeer>();
+ // Process the root locations
+ for (File root : roots) {
+ // List all "*.ini" files within the root location
+ File[] candidates = root.listFiles(new FileFilter() {
+ @Override
+ public boolean accept(File pathname) {
+ IPath path = new Path(pathname.getAbsolutePath());
+ return path.getFileExtension() != null && path.getFileExtension().toLowerCase().equals("ini"); //$NON-NLS-1$
+ }
+ });
+ // If there are ini files to read, process them
+ if (candidates != null && candidates.length > 0) {
+
+ for (File candidate : candidates) {
+ try {
+ Properties properties = new Properties();
+
+ // Load the properties found in the candidate file into
+ // the Properties object. The input stream passed to
+ // the Properties.load(...) method needs to be closed
+ // manually afterwards.
+ InputStream is = null;
+ try {
+ is = new FileInputStream(candidate);
+ properties.load(is);
+ } finally {
+ if (is != null) {
+ try { is.close(); } catch (IOException e) { /* ignored on purpose */ }
+ }
+ }
+
+ // Remember the file path within the properties
+ properties.setProperty("Path", candidate.getAbsolutePath()); //$NON-NLS-1$
+
+ // Validate the name attribute. If not set, set
+ // it to the file name without the .ini extension.
+ String name = properties.getProperty(IPeer.ATTR_NAME);
+ if (name == null || "".equals(name.trim())) { //$NON-NLS-1$
+ name = new Path(candidate.getAbsolutePath()).removeFileExtension().lastSegment();
+ properties.setProperty(IPeer.ATTR_NAME, name);
+ }
+
+ // Validate the id attribute. If not set, generate one.
+ String id = properties.getProperty(IPeer.ATTR_ID);
+ if (id == null || "".equals(id.trim()) || "USR:".equals(id.trim())) { //$NON-NLS-1$ //$NON-NLS-2$
+ String transport = properties.getProperty(IPeer.ATTR_TRANSPORT_NAME);
+ String host = properties.getProperty(IPeer.ATTR_IP_HOST);
+ String port = properties.getProperty(IPeer.ATTR_IP_PORT);
+
+ if (transport != null && host != null && !(id != null && "USR:".equals(id.trim()))) { //$NON-NLS-1$
+ id = transport.trim() + ":" + host.trim(); //$NON-NLS-1$
+ id += port != null ? ":" + port.trim() : ":1534"; //$NON-NLS-1$ //$NON-NLS-2$
+ } else {
+ id = "USR:" + System.currentTimeMillis(); //$NON-NLS-1$
+ // If the key is not unique, we have to wait a little bit an try again
+ while (peers.containsKey(id)) {
+ try { Thread.sleep(20); } catch (InterruptedException e) { /* ignored on purpose */ }
+ id = "USR:" + System.currentTimeMillis(); //$NON-NLS-1$
+ }
+ }
+ properties.put(IPeer.ATTR_ID, id);
+ }
+
+ // Copy all string attributes
+ Map<String, String> attrs = new HashMap<String, String>();
+ for (Object key : properties.keySet()) {
+ if (key instanceof String && properties.get(key) instanceof String) {
+ attrs.put((String)key, (String)properties.get(key));
+ }
+ }
+
+ // Construct the peer from the attributes
+ IPeer peer = new TransientPeer(attrs);
+ // Add the constructed peer to the peers map
+ peers.put(peer.getID(), peer);
+ } catch (IOException e) {
+ /* ignored on purpose */
+ }
+ }
+ }
+ }
+ // Process the read peers
+ if (!peers.isEmpty()) processPeers(peers, oldChildren, model);
+ }
+ }
+
+ /**
+ * Returns the list of root locations to lookup for static peers definitions.
+ *
+ * @return The list of root locations or an empty list.
+ */
+ protected File[] getStaticPeerLookupDirectories() {
+ // The list defining the root locations
+ List<File> rootLocations = new ArrayList<File>();
+
+ // Check on the peers root locations preference setting
+ String roots = Platform.getPreferencesService().getString(CoreBundleActivator.getUniqueIdentifier(),
+ IPreferenceKeys.PREF_STATIC_PEERS_ROOT_LOCATIONS,
+ null, null);
+ // If set, split it in its single components
+ if (roots != null) {
+ String[] candidates = roots.split(File.pathSeparator);
+ // Check on each candidate to denote an existing directory
+ for (String candidate : candidates) {
+ File file = new File(candidate);
+ if (file.canRead() && file.isDirectory() && !rootLocations.contains(file)) {
+ rootLocations.add(file);
+ }
+ }
+ } else {
+ // Try the bundles state location first (not available if launched with -data @none).
+ try {
+ File file = CoreBundleActivator.getDefault().getStateLocation().append(".peers").toFile(); //$NON-NLS-1$
+ if (file.canRead() && file.isDirectory() && !rootLocations.contains(file)) {
+ rootLocations.add(file);
+ }
+ } catch (IllegalStateException e) {
+ /* ignored on purpose */
+ }
+
+ // The users local peers lookup directory is $HOME/.tcf/.peers.
+ File file = new Path(System.getProperty("user.home")).append(".tcf/.peers").toFile(); //$NON-NLS-1$ //$NON-NLS-2$
+ if (file.canRead() && file.isDirectory() && !rootLocations.contains(file)) {
+ rootLocations.add(file);
+ }
+ }
+
+ return rootLocations.toArray(new File[rootLocations.size()]);
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelUpdateService.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelUpdateService.java
new file mode 100644
index 000000000..839a282c5
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelUpdateService.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * 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.locator.services;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.te.tcf.locator.interfaces.IModelListener;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModelProperties;
+import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelUpdateService;
+
+
+/**
+ * Default locator model update service implementation.
+ */
+public class LocatorModelUpdateService extends AbstractLocatorModelService implements ILocatorModelUpdateService {
+
+ /**
+ * Constructor.
+ *
+ * @param parentModel The parent locator model instance. Must not be <code>null</code>.
+ */
+ public LocatorModelUpdateService(ILocatorModel parentModel) {
+ super(parentModel);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.services.ILocatorModelUpdateService#add(org.eclipse.tcf.te.tcf.locator.core.interfaces.nodes.IPeerModel)
+ */
+ @Override
+ public void add(IPeerModel peer) {
+ Assert.isNotNull(peer);
+ Assert.isTrue(Protocol.isDispatchThread());
+
+ Map<String, IPeerModel> peers = (Map<String, IPeerModel>)getLocatorModel().getAdapter(Map.class);
+ Assert.isNotNull(peers);
+ peers.put(peer.getPeer().getID(), peer);
+
+ final IModelListener[] listeners = getLocatorModel().getListener();
+ if (listeners.length > 0) {
+ Protocol.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ for (IModelListener listener : listeners) {
+ listener.locatorModelChanged(getLocatorModel());
+ }
+ }
+ });
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.services.ILocatorModelUpdateService#remove(org.eclipse.tcf.te.tcf.locator.core.interfaces.nodes.IPeerModel)
+ */
+ @Override
+ public void remove(IPeerModel peer) {
+ Assert.isNotNull(peer);
+ Assert.isTrue(Protocol.isDispatchThread());
+
+ Map<String, IPeerModel> peers = (Map<String, IPeerModel>)getLocatorModel().getAdapter(Map.class);
+ Assert.isNotNull(peers);
+ peers.remove(peer.getPeer().getID());
+
+ final IModelListener[] listeners = getLocatorModel().getListener();
+ if (listeners.length > 0) {
+ Protocol.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ for (IModelListener listener : listeners) {
+ listener.locatorModelChanged(getLocatorModel());
+ }
+ }
+ });
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.core.interfaces.services.ILocatorModelUpdateService#updatePeerServices(org.eclipse.tcf.te.tcf.locator.core.interfaces.nodes.IPeerModel, java.util.Collection, java.util.Collection)
+ */
+ @Override
+ public void updatePeerServices(IPeerModel peerNode, Collection<String> localServices, Collection<String> remoteServices) {
+ Assert.isNotNull(peerNode);
+ Assert.isTrue(Protocol.isDispatchThread());
+
+ peerNode.setProperty(IPeerModelProperties.PROP_LOCAL_SERVICES, localServices != null ? makeString(localServices) : null);
+ peerNode.setProperty(IPeerModelProperties.PROP_REMOTE_SERVICES, remoteServices != null ? makeString(remoteServices) : null);
+ }
+
+ /**
+ * Transform the given collection into a plain string.
+ *
+ * @param collection The collection. Must not be <code>null</code>.
+ * @return The plain string.
+ */
+ protected String makeString(Collection<String> collection) {
+ Assert.isNotNull(collection);
+
+ String buffer = collection.toString();
+ buffer = buffer.replaceAll("\\[", "").replaceAll("\\]", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ return buffer.trim();
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/utils/IPAddressUtil.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/utils/IPAddressUtil.java
new file mode 100644
index 000000000..79b9cb9be
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/utils/IPAddressUtil.java
@@ -0,0 +1,403 @@
+/*******************************************************************************
+ * 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.locator.utils;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * The IP address utility provides a safe method to get all local IP addresses,
+ * check if any given address refers to the local host, and compare IP addresses.
+ */
+public class IPAddressUtil {
+
+ /**
+ * Constants for address types. They are sorted by "quality", i.e. the higher the total value of all flags is, the
+ * "better" or "more canonical" an address is assumed to be. Any "global" address type is better than all other
+ * addresses; among address types, the canonical name is better than the address which is better than a plain name;
+ * IPv4 is better than IPv6.
+ */
+ public final static int HOSTMAP_IPV6 = 0x01;
+ public final static int HOSTMAP_IPV4 = 0x02;
+
+ public final static int HOSTMAP_NAME = 0x04;
+ public final static int HOSTMAP_ADDR = 0x08;
+ public final static int HOSTMAP_CANONICALNAME = 0x10;
+ public final static int HOSTMAP_CANONICALADDR = 0x20;
+
+ public final static int HOSTMAP_MULTICAST = 0x40;
+ public final static int HOSTMAP_LOOPBACK = 0x80;
+ public final static int HOSTMAP_LINKLOCAL = 0x100;
+ public final static int HOSTMAP_SITELOCAL = 0x200;
+ public final static int HOSTMAP_GLOBAL = 0x400;
+
+ // shortcuts
+ public final static int HOSTMAP_ANY_UNICAST = HOSTMAP_LOOPBACK | HOSTMAP_LINKLOCAL | HOSTMAP_SITELOCAL | HOSTMAP_GLOBAL;
+
+ private final Map<String, Integer> fLocalHostAddresses = new HashMap<String, Integer>();
+ private final Set<String> fNonLocalHostAddresses = new HashSet<String>();
+ private String fCanonicalAddress = null;
+
+ IPAddressUtil() {
+ initializeHostCache();
+ }
+
+ private synchronized void initializeHostCache() {
+ // first, add the known interfaces. This is the only safe method to get
+ // the _real_ IP addresses, and get _all_ of them.
+ addLocalAddressesByInterface();
+ try {
+ // Add what Java thinks is the local host.
+ InetAddress localHostJava = InetAddress.getLocalHost();
+ // Do _not_ add the address that Java thinks the local host has,
+ // since it may be wrong! This is due to the method Java uses:
+ // it takes the host _name_ and does a reverse name lookup
+ // to get the address. This may be _wrong_ in case the DNS server
+ // points to a different (or outdated) address for the name.
+ // In reality, _only_ the addresses given by our own interfaces
+ // are correct! (As obtained by addLocalAddressesByInterface()).
+ // addLocalAddress(localHostJava);
+
+ // Add what Java thinks is the local host name.
+ // The local host name correct in the sense that it is configured
+ // locally and thus known locally. Note that in case of DNS inconsistency,
+ // DNS servers will return a _different_ address for the name than the
+ // local one, in this case the host name will be added as non-local.
+ addHostName(localHostJava.getHostName());
+ } catch (UnknownHostException e) {
+ /* no error */
+ }
+ // finally, add the "localhost" special host name since it might not be covered
+ // by the methods above (we cannot get all names for a given address, only the other way round).
+ addHostName("localhost"); //$NON-NLS-1$
+ // and initialize the "canonical hostname" cache.
+ getCanonicalAddress();
+ }
+
+ /**
+ * Iterate over local interfaces and add IP-addresses. This is the only safe method to get all local IP-addresses,
+ * since InetAddr.getAllByName() may fail to get the local IP address in case the local hostname is configured to be
+ * resolved to the loopback adapter (in this case, only the loopback adapter's address is returned). When this
+ * method has run, we know that we have all IP addresses of this machine. We can not know all the names of this
+ * machine since there s no method to query all name servers for all addresses. Therefore, new names may be added
+ * later by @see addHostName(String).
+ */
+ private synchronized void addLocalAddressesByInterface() {
+ Enumeration<NetworkInterface> interfaces = null;
+ try {
+ interfaces = NetworkInterface.getNetworkInterfaces();
+ } catch (SocketException e) {
+ /* no error, try other method */
+ }
+ while (interfaces != null && interfaces.hasMoreElements()) {
+ NetworkInterface iface = interfaces.nextElement();
+ Enumeration<InetAddress> addresses = iface.getInetAddresses();
+ while (addresses.hasMoreElements()) {
+ InetAddress addr = addresses.nextElement();
+ addLocalAddress(addr);
+ }
+ }
+ }
+
+ private synchronized void addLocalAddress(InetAddress addr) {
+ int addrtype;
+ if (addr.isLoopbackAddress()) {
+ addrtype = HOSTMAP_LOOPBACK;
+ } else if (addr.isLinkLocalAddress()) {
+ addrtype = HOSTMAP_LINKLOCAL;
+ } else if (addr.isSiteLocalAddress()) {
+ addrtype = HOSTMAP_SITELOCAL;
+ } else if (addr.isMulticastAddress()) {
+ addrtype = HOSTMAP_MULTICAST;
+ } else {
+ addrtype = HOSTMAP_GLOBAL;
+ }
+ if (addr.getAddress().length == 4) {
+ addrtype |= HOSTMAP_IPV4;
+ } else {
+ addrtype |= HOSTMAP_IPV6;
+ }
+ String addrAsString = addr.getHostAddress();
+ fLocalHostAddresses.put(addrAsString, new Integer(addrtype | HOSTMAP_ADDR));
+ if (0 == (addrtype & (HOSTMAP_LINKLOCAL | HOSTMAP_SITELOCAL | HOSTMAP_MULTICAST))) {
+ // Don't do DNS Reverse Loopkup's for non-routable addresses.
+ // They won't be known to the Name Server anyway, and they
+ // make startup _much_ slower.
+ String addrAsNameCan = addr.getCanonicalHostName().toLowerCase();
+ // query the name after the canonical name, it will re-use
+ // cached canonical name (if the name was not explicitly set)
+ String addrAsName = addr.getHostName().toLowerCase();
+ if (!addrAsNameCan.equals(addrAsString)) {
+ // We must check if we really got a name, since InetAddress.getHostName()
+ // returns the original address in case it thinks the name is spoofed!
+ if (0 == (addrtype & HOSTMAP_LOOPBACK)) {
+ // Not loopback --> found a Canonical Name.
+ fLocalHostAddresses.put(addrAsNameCan, new Integer(addrtype | HOSTMAP_NAME | HOSTMAP_CANONICALNAME));
+ // override the address as canonical-address
+ fLocalHostAddresses.put(addrAsString, new Integer(addrtype | HOSTMAP_ADDR | HOSTMAP_CANONICALADDR));
+ } else {
+ // Loopback --> add the found name as non-canonical.
+ fLocalHostAddresses.put(addrAsNameCan, new Integer(addrtype | HOSTMAP_NAME));
+ }
+ }
+ if (!addrAsName.equals(addrAsString) && !addrAsName.equals(addrAsNameCan)) {
+ // don't override the canonical name by the name.
+ fLocalHostAddresses.put(addrAsName, new Integer(addrtype | HOSTMAP_NAME));
+ }
+ }
+ }
+
+ private synchronized boolean addHostAddress(InetAddress addr, String hostName) {
+ if (addr == null) {
+ // Address for host name could not be resolved --> add to non-local-addresses
+ fNonLocalHostAddresses.add(hostName);
+ return false;
+ }
+
+ // Get the host address
+ String hostAddr = addr.getHostAddress();
+
+ // Newly discovered loopback addresses are added
+ // to the local host address list first
+ if (!fLocalHostAddresses.containsKey(hostAddr) && addr.isLoopbackAddress()) {
+ addLocalAddress(addr);
+ }
+
+ Integer entryType = fLocalHostAddresses.get(hostAddr);
+ if (entryType != null) {
+ // found a new name for a known local address ?
+ if (!fLocalHostAddresses.containsKey(hostName)) {
+ int addrtype = entryType.intValue() & (~(HOSTMAP_ADDR | HOSTMAP_CANONICALADDR));
+ fLocalHostAddresses.put(hostName, new Integer(addrtype | HOSTMAP_NAME));
+ }
+ return true;
+ }
+
+ fNonLocalHostAddresses.add(hostName);
+ fNonLocalHostAddresses.add(hostAddr);
+ return false;
+ }
+
+ /**
+ * Add a host name to internal caching tables.
+ *
+ * @param hostName String host name or address as String
+ * @return <code>true</code> if the added Host was considered "local", false otherwise.
+ */
+ public boolean addHostName(String hostName) {
+ hostName = hostName.toLowerCase();
+ try {
+ // Only take the first address: in case of multiple addresses
+ // on the remote host, some of them could be on different
+ // subnetworks and thus be non-local although they match one
+ // of our local addresses!
+ //
+ // Make sure that the name service resolving (probably time-consuming!)
+ // is outside our synchronized block.
+ InetAddress addr = InetAddress.getByName(hostName);
+ return addHostAddress(addr, hostName);
+ } catch (UnknownHostException e) {
+ /* got an illegal name --> add as non-local. */
+ return addHostAddress(null, hostName);
+ }
+ }
+
+ /**
+ * Return a list of hostnames or addresses for the local host. In case loopback addresses were asked for, these will
+ * appear first in the list. Example: String[] addresses =
+ * getLocalHostAddresses(HOSTMAP_ADDR|HOSTMAP_LOOPBACK|HOSTMAP_IPV4);
+ *
+ * @param typesToGet an integer bitmask of the types to get, uses the HOSTMAP constants declared in this class:
+ * HOSTMAP_NAME - get hostnames HOSTMAP_ADDR - get IP-addresses HOSTMAP_CANONICALNAME - get the
+ * "canonical" hostnames for each interface HOSTMAP_CANONICALADDR - get the "canonical" addresses for each
+ * interface HOSTMAP_LOOPBACK - get names/addresses for the loopback interface HOSTMAP_LINKLOCAL - get
+ * names/addresses for link-local non-routable interfaces HOSTMAP_SITELOCAL - get names/addresses for
+ * site-local non-routable interfaces HOSTMAP_MULTICAST - get multicast names/addresses HOSTMAP_GLOBAL -
+ * get names/addresses that are globally valid HOSTMAP_ANY_UNICAST - get names/addresses for any local
+ * non-unicast address HOSTMAP_IPV4 - get IPv4 names/addresses HOSTMAP_IPV6 - get IPv6 names/addresses
+ * @return String[] array of IP-addresses in String representation.
+ */
+ public synchronized String[] getLocalHostAddresses(int typesToGet) {
+ if ((typesToGet & HOSTMAP_ADDR) != 0) {
+ typesToGet |= HOSTMAP_CANONICALADDR; // plain address query includes the canonical address
+ }
+ if ((typesToGet & HOSTMAP_NAME) != 0) {
+ typesToGet |= HOSTMAP_CANONICALNAME; // plain name query includes the canonical name
+ }
+ List<String> addresses = new ArrayList<String>(fLocalHostAddresses.size());
+ Iterator<Entry<String, Integer>> it = fLocalHostAddresses.entrySet().iterator();
+ while (it.hasNext()) {
+ Entry<String, Integer> entry = it.next();
+ int addrtype = entry.getValue().intValue();
+ if ((addrtype & typesToGet) == addrtype) {
+ if ((addrtype & HOSTMAP_LOOPBACK) != 0) {
+ addresses.add(0, entry.getKey()); // add loopback addresses first
+ } else {
+ addresses.add(entry.getKey());
+ }
+ }
+ }
+ return addresses.toArray(new String[addresses.size()]);
+ }
+
+ /**
+ * Returns an IPv4 address to safely connect to the local host. This method works around limitations in the Java
+ * library's provisions for obtaining the local host address: - InetAddress.getByName("localhost") might be IPv6,
+ * and it might be mapped to a non-local host by the name service - InetAddress.getByName(null) might fail due to
+ * disabled loopback adapter (ifconfig lo down) - InetAddress.getLocalHost() returns non-loopback-address which is
+ * not optimal (slower than loopback, may disappear when removing a network cable or disconnecting from dial-up
+ * network connection) Therefore, the method below relies on information obtained from Enumeration
+ * NetworkInterface.getNetworkInterfaces() to know if an address is local.
+ *
+ * @return String representation of IPv4 address referring to the local host, or <code>null</code> if no address is
+ * found that allows to connect to the local host via IPv4.
+ */
+ public synchronized String getIPv4LoopbackAddress() {
+ // first, try the official IPv4 loopback address as per Internet RFC.
+ // This can fail only in case of disabled loopback adapter ("ifconfig lo down").
+ // Should perhaps be removed here in order to allow configuring preferred
+ // localhost connection from the outside.
+ if (isLocalHost("127.0.0.1")) { //$NON-NLS-1$
+ return "127.0.0.1"; //$NON-NLS-1$
+ }
+ // next, check if "localhost" is configured as an IPv4 address:
+ // if yes, it can be used directly. This allows to configure
+ // the preferred method for local host connections from the outside.
+ Integer key = fLocalHostAddresses.get("localhost"); //$NON-NLS-1$
+ if (key != null && (key.intValue() & HOSTMAP_IPV4) != 0) { return "localhost"; //$NON-NLS-1$
+ }
+ // finally ("localhost" mis-configured), obtain an address from NetworkInterfaces.
+ // loopback addresses are sorted first, so they are preferred
+ int typemask = HOSTMAP_ADDR | HOSTMAP_IPV4 | HOSTMAP_ANY_UNICAST;
+ String[] candidates = getLocalHostAddresses(typemask);
+ if (candidates.length == 0) {
+ // re-initialize the cache, perhaps some interfaces were brought up
+ // in the meantime (e.g. hot-plug network cards)
+ addLocalAddressesByInterface();
+ candidates = getLocalHostAddresses(typemask);
+ }
+ return candidates.length > 0 ? candidates[0] : null;
+ }
+
+ /**
+ * Returns the canonical name or address of this host. A "best effort" is made to return the address that is assumed
+ * to be "most canonical". A global IP address is considered better than a host name, since name service
+ * configuration might not be global.
+ *
+ * @return String IP address of the local host as it should be reachable from the outside.
+ */
+ public synchronized String getCanonicalAddress() {
+ if (fCanonicalAddress == null) {
+ Iterator<Entry<String, Integer>> it = fLocalHostAddresses.entrySet().iterator();
+ String bestAddress = null;
+ int bestAddrType = 0;
+ while (it.hasNext()) {
+ Entry<String, Integer> curEntry = it.next();
+ int curAddrType = curEntry.getValue().intValue();
+ if (curAddrType > bestAddrType) {
+ bestAddress = curEntry.getKey();
+ bestAddrType = curAddrType;
+ }
+ }
+ // fCanonicalAddress = InetAddress.getByName(bestAddress);
+ fCanonicalAddress = bestAddress;
+ }
+ return fCanonicalAddress;
+ }
+
+ /**
+ * Returns a list of host names that are considered "most canonical" on this host. The names are guaranteed to refer
+ * to global IP addresses of this machine. The list may be empty if no proper name is configured.
+ *
+ * @return String[] host names, may be empty
+ */
+ public synchronized String[] getCanonicalHostNames() {
+ int typeMask = IPAddressUtil.HOSTMAP_CANONICALNAME | IPAddressUtil.HOSTMAP_GLOBAL | IPAddressUtil.HOSTMAP_IPV4;
+ String canonicalNames[] = IPAddressUtil.getInstance().getLocalHostAddresses(typeMask);
+ if (canonicalNames.length == 0) {
+ typeMask |= IPAddressUtil.HOSTMAP_NAME;
+ canonicalNames = IPAddressUtil.getInstance().getLocalHostAddresses(typeMask);
+ }
+ return canonicalNames;
+ }
+
+ /**
+ * Find out if the given host name is the local host.
+ *
+ * @param host String hostname or IP address
+ * @return <code>true</code> if the given host refers to the local host.
+ */
+ public boolean isLocalHost(String host) {
+ if (host == null) { return false; }
+ String hostLower = host.toLowerCase();
+ // Don't trim, perhaps it is possible to have addresses ended by space
+ // hostLower = hostLower.trim();
+ synchronized (this) {
+ if (fLocalHostAddresses.containsKey(hostLower)) {
+ return true;
+ } else if (fNonLocalHostAddresses.contains(hostLower)) { return false; }
+ }
+ // Make sure that the name service lookup (probably time consuming!)
+ // is outside the synchronized block.
+ return addHostName(hostLower);
+ }
+
+ /**
+ * Find out if two IP Addresses refer to the same host.
+ *
+ * @param h1 host name or IP address
+ * @param h2 host name or IP address
+ * @return
+ */
+ public boolean isSameHost(String h1, String h2) {
+ if (h1 == null) {
+ return (h2 == null);
+ } else if (h2 == null) { return false; }
+ h1 = h1.trim();
+ h2 = h2.trim();
+ if (h1.equalsIgnoreCase(h2)) { return true; }
+ // The local host can be referred to by several methods...
+ if (isLocalHost(h1) && isLocalHost(h2)) { return true; }
+ // Compare IP-addresses? How to know if two hosts are the same?
+ // Only the first IP-Address we get should be checked. But what if
+ // h1 and h2 are different IP-Addresses referring to the same host?
+ // The check would be complex and probably slow since name service
+ // must be invoked. So we do not do it for now.
+ return false;
+ }
+
+ // Initialize-On-Demand Holder Class idiom:
+ // Lazy initialization and thread-safe single instance.
+ // See http://www-106.ibm.com/developerworks/java/library/j-jtp03304/
+ private static class LazyHolder {
+ public static IPAddressUtil instance = new IPAddressUtil();
+ }
+
+ /**
+ * Return the singleton instance.
+ */
+ public static IPAddressUtil getInstance() {
+ // LazyRegistryHolder class will be loaded in thread-safe manner
+ // the first time it is used.
+ return LazyHolder.instance;
+ }
+
+}

Back to the top